5

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?

shimao
  • 163
  • 5

2 Answers2

7

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.

PythonNut
  • 10,243
  • 2
  • 29
  • 75
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))))))
lawlist
  • 18,826
  • 5
  • 37
  • 118
  • 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 Feb 02 '16 at 05: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 Feb 02 '16 at 05:14