6

I'm working with a file which is zero-indexed. Using M-x linum-mode, I can get emacs to display line numbers. How can I get emacs to start counting from 0 instead of 1?

2 Answers 2

8

This is a cleaner solution:

;; paste this in your init file
(eval-when-compile (require 'cl-lib))
(defun nadvice/linum-update-window (old-fun &rest args)
  (cl-letf* ((old-count-lines (symbol-function #'count-lines))
             ((symbol-function #'count-lines)
              (lambda (&rest args) (1- (apply old-count-lines args)))))
    (apply old-fun args)))

(defun linum-toggle-zero-indexing ()
  (interactive)
  (if (advice-member-p #'nadvice/linum-update-window 'linum-update-window)
      (advice-remove 'linum-update-window #'nadvice/linum-update-window)
    (advice-add 'linum-update-window :around #'nadvice/linum-update-window)))

Use M-x linum-toggle-zero-indexing RET to toggle the zero-indexing.

0
2

Add a 1- to line-number-at-pos and count-lines.

(require 'linum)

(defun linum-update-window (win)
  "Update line numbers for the portion visible in window WIN."
  (goto-char (window-start win))
  (let ((line (1- (line-number-at-pos)))
        (limit (window-end win t))
        (fmt (cond ((stringp linum-format) linum-format)
                   ((eq linum-format 'dynamic)
                    (let ((w (length (number-to-string
                                      (1- (count-lines (point-min) (point-max)))))))
                      (concat "%" (number-to-string w) "d")))))
        (width 0))
    (run-hooks 'linum-before-numbering-hook)
    ;; Create an overlay (or reuse an existing one) for each
    ;; line visible in this window, if necessary.
    (while (and (not (eobp)) (< (point) limit))
      (let* ((str (if fmt
                      (propertize (format fmt line) 'face 'linum)
                    (funcall linum-format line)))
             (visited (catch 'visited
                        (dolist (o (overlays-in (point) (point)))
                          (when (equal-including-properties
                                 (overlay-get o 'linum-str) str)
                            (unless (memq o linum-overlays)
                              (push o linum-overlays))
                            (setq linum-available (delq o linum-available))
                            (throw 'visited t))))))
        (setq width (max width (length str)))
        (unless visited
          (let ((ov (if (null linum-available)
                        (make-overlay (point) (point))
                      (move-overlay (pop linum-available) (point) (point)))))
            (push ov linum-overlays)
            (overlay-put ov 'before-string
                         (propertize " " 'display `((margin left-margin) ,str)))
            (overlay-put ov 'linum-str str))))
      ;; Text may contain those nasty intangible properties, but that
      ;; shouldn't prevent us from counting those lines.
      (let ((inhibit-point-motion-hooks t))
        (forward-line))
      (setq line (1+ line)))
    (when (display-graphic-p)
      (setq width (ceiling
                   (/ (* width 1.0 (linum--face-width 'linum))
                      (frame-char-width)))))
    ;; open up space in the left margin, if needed, and record that
    ;; fact as the window-parameter `linum--set-margins'
    (let ((existing-margins (window-margins win)))
      (when (> width (or (car existing-margins) 0))
        (set-window-margins win width (cdr existing-margins))
        (set-window-parameter win 'linum--set-margins (window-margins win))))))
2
  • Thank you very much. Since I'm new to emacs, could you explain how I can use that function in emacs? I think I have to add something like add-hook in my .emacs.el file?, but I don't really know how to do that.
    – shimao
    Commented Feb 2, 2016 at 5:00
  • Just stuff it all inside your .emacs file, save, and restart Emacs. :) All I did was add 1- in two places -- 1- is a function that essentially subtracts 1. Here is the doc-string: "1- is a built-in function in 'C source code'. (1- NUMBER) Return NUMBER minus one. NUMBER may be a number or a marker. Markers are converted to integers." The require statement ensures that the library is loaded, before you essentially re-define one of its functions.
    – lawlist
    Commented Feb 2, 2016 at 5:14

Your Answer

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

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