6

I want to customize mode-line-format using if or cond etc., to let it show different text conditionally.

Here is a demo that I tried:

(setq-default
 mode-line-format
 (quote
  (
   (:eval
    (cond
     (buffer-read-only
      (propertize " ⚑ "
                  'face (:foreground "red" :weight 'bold)
                  'help-echo "buffer is read-only!!!"))
     ;; (overwrite-mode
     ;;  (propertize "??"))
     (buffer-modified-p
      (propertize " ☡ "
                  'face (:foreground "orange")
                  'help-echo "buffer modified."))
     ))

   (:eval (if (or (eq (buffer-local-value 'major-mode (current-buffer)) 'ruby-mode)
                 (eq (buffer-local-value 'major-mode (current-buffer)) 'enh-ruby-mode))
              (:propertize "Ruby"
                           face (:foreground "green"))
            (:propertize "Not Ruby"
                         face (:foreground "orange"))))
   )))

But it does not show anything, I don't know where is wrong. Need help.

BTW:

I googled this, And got two good results:

And I saw two different code:

(setq-default
 mode-line-format
 '(
   (:propertize var
                'face (:foreground "green"))
   ))

(setq-default
 mode-line-format
 (list
   '(:eval (if ...))
   ))

I don't know what's the difference.

---------------- UPDATE ---------------------

I found I can't put multiple (propertize ...) in one (progn ...). Is there any solution to solve this?

(setq-default
 mode-line-format
'(
  (:eval
    (if (memq (buffer-local-value 'major-mode (current-buffer))
              '(ruby-mode enh-ruby-mode))
        (progn
          (propertize " ("
                      'face '(:foreground "#444444"))
          (propertize "Ruby: "
                      'face '(:family "Segoe Print"
                                      :height 80
                                      :foreground "red2"))
          (propertize (rbenv--active-ruby-version) ; `rbenv--modestring'
                      'face '(:foreground "cyan")
                      'help-echo '(concat "\nCurrent Ruby version: " (rbenv--active-ruby-version)
                                          "\nmouse-1: switch Ruby version menu")
                      ;; 'local-map
                      )
          (propertize ")"
                      'face '(:foreground "#444444"))
          )
      ;; (propertize "Not Ruby"
      ;;             'face '(:foreground "red2"))
      ))
))

This is solved, use (list (propertize ...) (propertize ...).

1
  • I love the flag!
    – lawlist
    Jul 3, 2015 at 2:21

1 Answer 1

7

If you want something that changes according to conditions then you pretty much need to use :eval, as in the second borrowed-code snippet.

There are several things wrong with your code. buffer-modified-p is a function, not a variable; you forgot to quote some things; etc. Try this, and then compare it carefully with your code:

(setq-default mode-line-format
              '((:eval
                 (cond
                   (buffer-read-only
                    (propertize " ⚑ "
                                'face '(:foreground "red" :weight 'bold)
                                'help-echo "buffer is read-only!!!"))
                   ((buffer-modified-p)
                    (propertize " ☡ "
                                'face '(:foreground "orange")
                                'help-echo "buffer modified."))))
                (:eval (if (memq (buffer-local-value 'major-mode (current-buffer))
                                 '(ruby-mode enh-ruby-mode))
                           (propertize "Ruby" 'face '(:foreground "green"))
                         (propertize "Not Ruby" 'face '(:foreground "orange")))))) 
4
  • Why need to quote those things, I'm confused. Can you tell me why? Or just give me some hints. Jul 3, 2015 at 3:36
  • What if I want to display a symbol like mode-line-process, I use (propertize 'mode-line-process 'face '(:foreground "orange")) does not work. Why? Jul 3, 2015 at 4:22
  • 1
    You need to quote things like the symbol face because :eval will try to evaluate them. You can try it yourself: Select the sexp in your code that is inside the :eval, and use M-: to evaluate it (after turning on debug-on-error. You will see the error raised. That is generally a good way to debug mode-line-format stuff.
    – Drew
    Jul 3, 2015 at 14:59
  • 2
    You don't want to propertize the symbol mode-line-process (presumably). You want to propertize its value, which is a string (presumably). You need to spend some time with the Emacs doc (including the manual Intro to Emacs Lisp) and spend some time experimenting with evaluating simple sexps. mode-line-format, especially with the use of :eval, is probably not the best place to start.
    – Drew
    Jul 3, 2015 at 15:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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