For me, the clearest measure for the size of a file is its number of lines. So, I want this information in my mode line. I am using Doom emacs and, even I could define my own mode line, for such a minor change I would prefer to follow the recommended way: add the information to global-mode-string (see point 4 in doom-mode-line)

I ended up with the following code, which works very well except for one thing. When I open a file, the displayed number of total lines is not the actual number of lines. I tried different ways to set correctly brust-buffer-total-lines when opening a file, but none of them worked. The two versions of the function brust-buffer-total-lines-activate summarise all my ideas so far. (Of course, comments on any part of the code are very well come.)

My questions: - Why these function do not work when they are called from the hook text-mode-hookor find-file-hook? - How could I set correctly the variable brust-buffer-total-lines when opening a file?

;; Variable to buffer-locally store the total number of lines.

(defvar-local brust-buffer-total-lines ""
  "Show the numbers of total lines in modeline")

;; Funtion to update the number of lines after every command modifying the buffer (it will be hooked in `post-command-hook`).

(defun brust-buffer-update-total-lines nil
  (when (buffer-modified-p) ;; lighten up post-command hook
    (setq brust-buffer-total-lines
          (save-excursion (goto-char (point-max)) (format-mode-line "/%l/")))))

;; Version 1 of the function to buffer-locally initiate the whole process.  

(defun brust-buffer-total-lines-activate nil
  (let* ((curr-file (buffer-file-name))
            (insert-file-contents curr-file) 
            (line-number-at-pos (point-max)))))
    (setq brust-buffer-total-lines num-total-lines))
  (add-hook 'post-command-hook #'brust-buffer-update-total-lines nil t))

;; Version 2 of the function to buffer-locally initiate the whole process.  

(defun brust-buffer-total-lines-activate nil
  (setq brust-buffer-total-lines
        (save-excursion (goto-char (point-max)) (format-mode-line "/%l/")))
  (add-hook 'post-command-hook #'brust-buffer-update-total-lines nil t))

;; Final steps:

;; (add-hook 'text-mode-hook #'brust-buffer-total-lines-activate)
(add-hook 'find-file-hook #'brust-buffer-total-lines-activate)
(setq global-mode-string '("" brust-buffer-total-lines)))

This strange behaviour can be reproduced in vanilla emacs, just init emacs with emacs -Q load the previous code and open a file. You will see that the total number of lines is wrong and it is corrected after modifying the buffer.


Not sure it is the right answer to your question.

You can know the number of lines in a buffer with M-x count-lines-page (C-x l) with the default key-binding Regarding the `mode-line you can modify it as you wish

See on of my configuration below just the strick necessary. Notice that you can call any function you like. For my part I've add the multiple cursors counts.

(require 'multiple-cursors-core)
;; *** implementation
(setenv "HOST"  "gnu")
(setq *my-mode-line-format*
      (list " -"
        " "
     (let ((host-name
            (or (file-remote-p default-directory 'host)
       (if (string-match "^[^0-9][^.]*\\(\\..*\\)" host-name)
           (substring host-name 0 (match-beginning 1))
        "   "
        "%n "
        "(%m) "
        '(vc-mode vc-mode)
        '(which-func-mode ("" which-func-format "--"))      
        '(:eval  (if (>  (mc/num-cursors) 1) (format (propertize " mc %d" 'face 'font-lock-warning-face) (mc/num-cursors))))
(setq-default mode-line-format *my-mode-line-format*)

You don't have to be as radical as me though. I would suggest diminish mode https://www.emacswiki.org/emacs/DiminishedModes. A few more info I would suggest C-h v mode-line-format and C-h v 'mode-line-percent-position

| improve this answer | |
  • Thank you very much, but related to my question, sorry. Getting the total number of lines in an alredy open buffer is not a problem and I want to not modify mode-line-format. The problem is to obtain the right number of lines at the moment to open a file. For example, I've tried calling a function in the hooks text-mode-hook or find-file-hook. That is one of the goals of the function brust-buffer-total-lines-activate. Actually, when it is called from an already open buffer it works, but when called from these hooks it gives a wrong number of lines. – MonLau Apr 10 at 14:55

Here there is a workaround.

(defun brust-buffer-total-lines-activate nil
  (setq brust-buffer-total-lines
    (let ((curr-file (buffer-file-name)))
         (insert-file-contents curr-file) 
         (concat "/" (number-to-string (line-number-at-pos (point-max))) "/"))))
  (add-hook 'post-command-hook #'brust-buffer-update-total-lines nil t))

The explanation I have found so far.

  • The file contents is not inserted when emacs calls the funtions in the hooks find-file-hook or text-mode-hook. I think this is the reason "version 2" does not work.
  • A temporary buffer has no mode-line. This is the reason we need to use line-numer-at-pos instead of the much more efficient (format-mode-line "%l"). (It is not important, it just one time opening the file).
  • Version 1 works, it is just I was passing the number of lines as an actual number and it needs to be a string, which is done in this new version.

Well, that is all!

| improve this answer | |

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.