1

Currently in the mode-line the filename %f, is absolute.

I would like to have the path relative to the version-control root, without having to find this every redraw.

How could this be cached, allowing for changes to the buffers filename to be refreshed?


Current code for reference.

(defvar-local buffer-file-name--vc-root-relative nil "
Use to cache the VC relative path.

- nil: Unset.
- t: No VC root, use regular filename.
- Otherwise this is the VC relative path.
")

(defun buffer-file-name-vc-root-relative-fn (filepath) "
Cache the vc-root relative name of the buffer,
return this, or a mode-line formatting character.
"
  (if filepath
    (progn
      ;; lazy initialize.
      (when (eq buffer-file-name--vc-root-relative nil)
        (let
          ((base-path
             (vc-call-backend
               (vc-responsible-backend filepath) 'root filepath)))
          (setq buffer-file-name--vc-root-relative
            (if base-path
              ;; Account for possibility of filepath containing a '%'.
              (replace-regexp-in-string "%" "%%"
                (file-relative-name filepath base-path)))
            t)))
      (if (eq buffer-file-name--vc-root-relative t)
        "%f"
        buffer-file-name--vc-root-relative))
    ;; No filepath, return buffer name.
    "%8b"))
0

after-set-visited-file-name-hook is a reliable way to detect changes to the filename.

This clears the cached value when a new filename if set.

;; Clear cached relative file name when saving under a new name,
(add-hook
  'after-set-visited-file-name-hook
  (lambda ()
    (setq buffer-file-name--vc-root-relative nil)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.