7

I use vc-mode to show information about the current VC state in my mode line, like this:

(setq mode-line-format '(… (vc-mode vc-mode) …))

However, I find the default format of vc-mode pretty verbose. Notably, it includes the name of the current VC backend, which is not particularly interesting to me—I usually know which VCS the current buffer as, and I don’t really use any VCS other than Git anyway.

How can I customize the appearance of vc-mode? Ideally, I’d hide the name of the backend, and show just the name of the current branch (or probably something similar to git describe).

Alternatively, if vc-mode can’t be customized, can I somehow get the current branch name from VC, for use in a custom (:eval …) construct?

5

How can I customize the appearance of vc-mode? Ideally, I’d hide the name of the backend, and show just the name of the current branch.

That's pretty much what smart-mode-line does. You can give it a try, or you can just copy the advice that it uses:

(defadvice vc-mode-line (after strip-backend () activate)
  (when (stringp vc-mode)
    (let ((noback (replace-regexp-in-string 
                   (format "^ %s" (vc-backend buffer-file-name))
                   " " vc-mode)))
      (setq vc-mode noback))))

Note that this is a streamlined version of it. You can find the full code for the advice here, which also applies different faces depending on the state of the branch.


As an alternative, here's an even more streamlined version that doesn't use an advice.

(setcdr (assq 'vc-mode mode-line-format)
        '((:eval (replace-regexp-in-string "^ Git" " " vc-mode))))
  • That would work—though I'd prefer to use an :eval construct instead of an advice—but it's not exactly what I'd call "customising". It's a dirty hack, isn't it? I'd treacly prefer a cleaner way… – lunaryorn Apr 27 '15 at 14:29
  • 1
    @lunaryorn Yes, it's a hack. vc-mode is not highly customizable in this aspect (that I can tell). I would prefer a cleaner way too. :-) – Malabarba Apr 27 '15 at 15:22
  • 2
    @lunaryorn I've edited the answer to use the :eval construct. – Malabarba Apr 27 '15 at 16:35
3

I was not happy with the default behavior either. I could never keep the vc info characters straight— ":" for edited, "@" for added, etc. You can feel free to use my method.

I defined several custom faces to display the statuses in various colors. Then I wrote a function to translate the default vc info into a string to insert into the mode line. Then I added a :eval line in my mode line definition to show it.

;; Define faces.

(defface my/mode:vc-added
  `(
     (  ((class color))
        (:background "#FFAA55"  :foreground "black")  )
     (  t
        (:weight bold :underline t)  )
   )
  "VC status tag face for files that have just been added to
version-control."
  :group 'MY/mode)

(defface my/mode:vc-edited
  `(
     (  ((class color))
        (:background "#F05B80"  :foreground "black")  )   ; "#F04040" maybe?
     (  t
        (:weight bold :underline t)  )
   )
  "VC status tag face for files that are under version control
but which have been edited."
  :group 'MY/mode)

(defface my/mode:vc-in-sync
  `(
     (  ((class color))
        (:background "#60CC60"  :foreground "black")  )
     (  t
        (:weight bold :underline t)  )
   )
  "VC status tag face for files that are under version control
and which are in sync with the respository."
  :group 'MY/mode)

(defface my/mode:vc-none
  `(
     (  ((class color))
        (:background "#70A0D0"  :foreground "black")  )
     (  t
        (:weight bold :underline t)  )
   )
  "VC status tag face for files that are not under version
control"
  :group 'MY/mode)

(defface my/mode:vc-unknown
  `(
     (  ((class color))
        (:background "#FF0000"  :foreground "white")  )
     (  t
        (:weight bold :underline t)  )
   )
  "VC status tag face for files whose version-control status
cannot be determined."
  :group 'MY/mode)

(defvar my-vc-mode-attrs
  '((""  . (" NoVC "  my/mode:vc-none))
    ("-" . (" VC = "  my/mode:vc-in-sync))
    (":" . (" VC > "  my/mode:vc-edited))
    ("@" . (" VC + "  my/mode:vc-added))
    ("?" . (" ?VC? "  my/mode:vc-unknown))
    )
  "Lookup table to translate vc-mode character into another string/face."
)


;; This function helps me understand the version-control status.
(defun my-mode-line-vc-info ()
  "Return version-control status information about the file in
the current buffer, as a fontified string.

The mode-line variable `vc-mode' is nil if the file is not under
version control, and displays a hyphen or a colon depending on whether
the file has been modified since check-in.  I can never keep those
straight.

This function returns \"NoVC\" if the file is not under version 
control.  It displays a string with an = sign if the file is in sync
with its version control, and a string with a > sign if the file has
been modified since its last check-in."
  (let* ((class
          (cond
           ;; If not under version-control
           ((not vc-mode)
            "")

           ;; If under version-control decode the -:@ character
           ((string-match "\\` ?\\(?:CVS\\|Git\\)\\([-:@]\\)\\([^^:~ \x00-\x1F\\\\/]+\\)?" vc-mode)
            (match-string-no-properties 1 vc-mode))

           ;; Otherwise, indicate confusion
           (t
            "?")
           ))

         (branch
          (if (any class '("-" ":" "@"))
              (concat " " (match-string-no-properties 2 vc-mode))
            ""))

         ;; Fetch properties list for the class character above
         (props (cdr (assoc class my-vc-mode-attrs)))
         )

    (concat (propertize (car props) 'face (cadr props))
            branch)))

(set-default 'mode-line-format
   '(
     ...
        (:eval (my-mode-line-vc-info))
     ...))
  • Thanks. This looks like something I really need to copy into my own configuration :) – lunaryorn Apr 28 '15 at 9:43

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.