4

If a file lies in a directory backed by a Subversion repo ending with either trunk or branches/X how do I make the trunk or X show up in the mode-line as SVN-trunk or SVN-X similar to what is shown in Git-backed files typically as Git-master.

Nordlöw
  • 11,838
  • 10
  • 52
  • 99

2 Answers2

5

Determining SVN status

I am not aware of any built-in way to do this, but you can write your own code for this purpose.

Based on vc-svn-repository-name and vc-backend you can write a function that returns a custom mode text for SVN, and falls back to the default for all other VC systems:

(defun lunaryorn-vc-mode-line ()
  (let ((backend (vc-backend (buffer-file-name))))
    (if (eq backend 'SVN)
        (let ((url (vc-svn-repository-hostname (buffer-file-name))))
          (cond
           ((string-match-p "/trunk/" url) "SVN-trunk")
           ((string-match "/branches/\\([^/]+\\)/" url)
            (concat "SVN-" (match-string 1 url)))
           (t vc-mode)))
      ;; Use default mode text for other backends
      vc-mode)))

If the current file is under SVN, we check its repo URL according to your convention and compile a corresponding mode text. Don't be confused by the name of vc-svn-repository-hostname, the function actually returns the complete repo URL of the given file.

For all other backends, or if the URL does not match any pattern, we fall back to the default VC status text as in vc-mode.

Adding to the mode line

You can then use this function in the mode line, by adding a corresponding mode line construct to mode-line-format:

(setq-default mode-line-format
              '(…
                (vc-mode (" " (:eval (lunaryorn-vc-mode-line))))
                …))

Since mode-line-format is buffer-local, we use setq-default to change its global value. Our new mode line construct checks whether vc-mode is active, that is, whether the file is under version control, and evaluates our function in this case, to obtain our custom status text. See Mode Line Data for more information about mode line constructs.

The ellipsis stand for the other content of the mode line, which you may also customize to your liking. I'd suggest, though, that you simply copy the default value of mode-line-format, and replace (vc-mode vc-mode) with our new construct. That will simply replace the old VC information with our custom status text, and leaves everything else as before.

  • Superb answer! Only one thing: Can I programmatically replace `(vc-mode vc-mode)` with `(vc-mode (" " :eval (lunaryorn-vc-mode-line)))` in `mode-line-format`? I don't want to hard-code my mode-line format in this package `svn-mode-line`. IMHO that's too intrusive. – Nordlöw Aug 14 '14 at 22:51
  • I get the feeling that this could be made more elegant. Shouldn't the definition of `vc-mode-line` or some of its sub-logic be overridden somehow? Hmm, it seems as if the defintion of `vc-mode-line` lacks a bit of flexibility that could be implemented using by hooks or function variables. – Nordlöw Aug 14 '14 at 22:58
  • 1
    @Nordlöw If you'd like to put this in a proper package and distribute it, you should not touch `mode-line-format` at all. Packages shouldn't mess with user customization. Instead, just instruct users how to setup your package. –  Aug 15 '14 at 09:21
  • 1
    @Nordlöw Well, you could also define the `vc-svn-mode-line-string` function like Stefan suggested. VC Mode will call this function to get a mode line string for SVN. That's probably also more efficient than re-evaluating VC state on every mode line update. –  Aug 15 '14 at 09:27
  • Great! I'll try that later on. Thx. – Nordlöw Aug 15 '14 at 11:28
  • Is there an Emacs function to modify only `(vc-mode vc-mode)` part in `mode-line-format` typically to `(vc-mode (" " :eval (lunaryorn-vc-mode-line)))`? I know I can extra it with `(assoc 'vc-mode mode-line-format)`. – Nordlöw Aug 19 '14 at 12:59
  • 1
    @Nordlöw `(setcdr (assq 'vc-mode mode-line-format) (whatever-you-want)`. –  Aug 19 '14 at 13:06
  • Doesn't work. When I do `(setcdr (assq 'vc-mode mode-line-format) '(vc-fancy-mode-line-string))` the vc information in mode-line disappears in all buffers. So far I have https://github.com/nordlow/elisp/blob/master/mine/svn-mode-line.el – Nordlöw Aug 19 '14 at 13:23
  • @Nordlöw `'(vc-fancy-mode-line-string)` is an invalid mode line construct. You'll need `'(:eval (vc-fancy-mode-line-string))`. Please read [Mode Line Data](http://www.gnu.org/software/emacs/manual/html_node/elisp/Mode-Line-Data.html#Mode-Line-Data). –  Aug 19 '14 at 13:31
  • @Nordlöw By the way, I saw that you defined `vc-svn-mode-line-string`. You don't need to change `vc-mode` anymore then. VC automatically calls that function to get status text for SVN. –  Aug 19 '14 at 13:32
  • My definition of `vc-svn-mode-line-string` is not run. I dont' know why. This when I have `vc-mode` set to `vc-mode` in `mode-line-format`. – Nordlöw Aug 19 '14 at 14:22
  • Ok, now it works with using eval at https://github.com/nordlow/elisp/blob/master/mine/svn-mode-line.el. Thanks. Added some coloring of the SVN version. – Nordlöw Aug 19 '14 at 14:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/59616/discussion-between-nordlow-and-lunaryorn). – Nordlöw Aug 19 '14 at 21:09
2

You could define a function:

(defun vc-svn-mode-line-string (file)
  (format "SVN-%s" (vc-svn-current-branch-name file)))

Of course, you'd also have to define vc-svn-current-branch-name because that one doesn't exist yet. I guess it would have to do something like

(defun vc-svn-current-branch-name (file)
  (with-temp-buffer
    (setq default-directory (file-name-directory file))
    (vc-svn-command t t file "info")
    ...extract the branch name from the info in current buffer..
    ))
Stefan
  • 27,908
  • 4
  • 53
  • 82
  • Defining function `vc-svn-mode-line-string` has no effect in my Emacs (git master). – Nordlöw Aug 19 '14 at 13:28
  • 1
    There's some caching going on, so make sure you define it before you load vc-svn.el (e.g. put it in your .emacs and then restart). Try `(defun vc-svn-mode-line-string (file) "TEST")` for a start. – Stefan Aug 20 '14 at 13:58