How to Call a Function in Emacs Mode Line Format

898 Views Asked by At

I want to call some methods in the Emacs mode-line format. For example count-words to see how many characters are selected or what's the class/method name cursor is on.

This is my current mode-line format, but calling count-words, it shows *invalid* as a result and also I'm not sure that it will be invoked in any changes.

(setq-default mode-line-format
      (list "---File:[%b%+] Line:[%l] Size:[%i] "
        (count-words (point-min) (point-max))
        ))

I want to call some custom methods in the mode-line area which are updating frequently. For example, how many characters I've selected, who changed this line (git blame), what is the current class name which the cursor is on now, and so on.

2

There are 2 best solutions below

3
Realraptor On

The answer to the question you have asked is:

(setq mode-line-format
  (list "---File:[%b%+] Line:[%l] Size:[%i] %d"
    (format "count: %d" (count-words (point-min) (point-max)))))

But I don't think that is the question you meant to ask, because the value won't update. Let's fix that.

I've chosen to have it update after you save the file because the counting the words in buffer is going to get v slow at some buffer size if you are doing it frequently.

(setq mode-line-format
      (list "---File:[%b%+] Line:[%l] Size:[%i] %d"
        'count-words-string))

(defun update-count-words-string-for-modeline ()
  (interactive)
  (setq count-words-string 
        (format "word count: %d" (count-words (point-min) (point-max))))
  (force-mode-line-update))

(add-hook 'after-save-hook 'update-count-words-string-for-modeline)

(It might equally suit your purposes to simply call message with the word count after saving.)

2
phils On
‘(:eval FORM)’
     A list whose first element is the symbol ‘:eval’ says to evaluate
     FORM, and use the result as a string to display.  Make sure this
     evaluation cannot load any files, as doing so could cause infinite
     recursion.

-- C-hig (elisp)Mode Line Data

In general, avoid using :eval if you don't need to. In many cases it will be more efficient to display the value of a variable in the mode line, and arrange elsewhere for that variable to be updated whenever necessary (which may be far less frequently than the mode line is redisplayed).

Your example of calling count-words on the entire buffer might cause performance issues in large buffers.

Example:

(setq-default mode-line-format '(:eval (count-words--buffer-message)))