0

I've this code in my init.el

(setq-default mode-line-format (list
                                (propertize " %b " 'face 'bufname)
                                (propertize (concat " " vc-mode " ") 'face 'gitmode)))

This evaluates vc-mode to ""

undesired behaviour

while evaluating the same thing with setq instead of setq-default results in the desired string "Git:nixos".

desired behaviour

But I need to use setq-default here to modify the mode-line-format. Why does this happen and how to fix it?

3
  • You shouldn’t ask two questions at the same time; move the second one to its own Question.
    – db48x
    Sep 13 at 23:26
  • edited, the second one wasn't that important anyway
    – natto
    Sep 13 at 23:28
  • You're not using a good value for mode-line-format. Read the Elisp manual about it. For one thing, you need to quote a variable such as vc-mode. For another you should use :propertize (see Properties in Mode). You can look this up as easily as anyone who might want to provide an answer - just check what the manual tells you.
    – Drew
    Sep 14 at 3:06
2

When the code in your init file runs, there are no open files at all. vc-mode is only set when a file is finally opened and determined to be in version–controlled. This means that when it runs your init file and evaluates vc-mode, it puts the nil value into the list that goes into mode-line-format. That nil is then skipped whenever the mode line is displayed.

Instead, you should put the symbol 'vc-mode into the mode-line-format. Then, when the mode line is displayed, it will know to put the current value of the variable named by that symbol into the mode line instead. Like this:

(setq-default mode-line-format
              (list
               (propertize " %b " 'face 'bufname)
               (propertize " " 'face 'gitmode)
               (propertize 'vc-mode 'face 'gitmode)
               (propertize " " 'face 'gitmode)))

The ' in front of the name is called a quote, and it quotes whatever lisp form follows it so that it is treated literally instead of evaluated. The propertize function, for example, wants the symbol 'face rather than the value of a variable that happens to be called face, so it too is quoted.

It also doesn’t matter whether you use setq or setq-default in your init file, since at that point there are no open buffers and so setting any variable will set the default value of that variable rather than the buffer–local value.

Finally, the mode line machinery has a lot of useful things that can simplify your code quite a bit, like this:

(setq mode-line-format
      '((:propertize " %b " face bufname)
        (:propertize (" " vc-mode " ") face gitmode)))

You should read chapter 23.4.2 The Data Structure of the Mode Line of the Emacs Lisp manual, which details everything that can go into the mode line. This manual is also available inside of Emacs. You can open the Info viewer with C-h i; this starts you out at a menu of all the manuals installed on your system.

2
  • +1 - nice answer!
    – NickD
    Sep 14 at 1:42
  • 1
    thanks, the referenced chapter saved me a lot of time with some other stuff too
    – natto
    Sep 14 at 1:49

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.