X-Git-Url: https://code.delx.au/gnu-emacs-elpa/blobdiff_plain/c45346a3c823eaafc09b96d2c33ba945a287346a..c828ee6d19b57256e1fa2321dc830fe5a6cf8af1:/packages/nlinum/nlinum.el diff --git a/packages/nlinum/nlinum.el b/packages/nlinum/nlinum.el index 1c9e4e832..8719e92f6 100644 --- a/packages/nlinum/nlinum.el +++ b/packages/nlinum/nlinum.el @@ -1,10 +1,10 @@ ;;; nlinum.el --- Show line numbers in the margin -*- lexical-binding: t -*- -;; Copyright (C) 2012 Free Software Foundation, Inc. +;; Copyright (C) 2012, 2014 Free Software Foundation, Inc. ;; Author: Stefan Monnier ;; Keywords: convenience -;; Version: 1.1 +;; Version: 1.4 ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -24,6 +24,16 @@ ;; This is like linum-mode, but uses jit-lock to be (hopefully) ;; more efficient. +;;; News: + +;; v1.3: +;; - New custom variable `nlinum-format'. +;; - Change in calling convention of `nlinum-format-function'. + +;; v1.2: +;; - New global mode `global-nlinum-mode'. +;; - New config var `nlinum-format-function'. + ;;; Code: (require 'linum) ;For its face. @@ -44,26 +54,38 @@ Linum mode is a buffer-local minor mode." :lighter nil ;; (" NLinum" nlinum--desc) (jit-lock-unregister #'nlinum--region) (remove-hook 'window-configuration-change-hook #'nlinum--setup-window t) - (remove-hook 'after-change-functions #'nlinum--after-change) + (remove-hook 'after-change-functions #'nlinum--after-change t) (kill-local-variable 'nlinum--line-number-cache) (remove-overlays (point-min) (point-max) 'nlinum t) ;; (kill-local-variable 'nlinum--ol-counter) (kill-local-variable 'nlinum--width) (when nlinum-mode + ;; FIXME: Another approach would be to make the mode permanent-local, + ;; which might indeed be preferable. + (add-hook 'change-major-mode-hook (lambda () (nlinum-mode -1))) (add-hook 'window-configuration-change-hook #'nlinum--setup-window nil t) (add-hook 'after-change-functions #'nlinum--after-change nil t) (jit-lock-register #'nlinum--region t)) (nlinum--setup-windows)) +(defun nlinum--face-height (face) + (aref (font-info (face-font face)) 2)) + (defun nlinum--setup-window () - (set-window-margins nil (if nlinum-mode nlinum--width) - (cdr (window-margins)))) + (let ((width (ceiling + ;; We'd really want to check the widths rather than the + ;; heights, but it's a start. + (/ (* nlinum--width 1.0 + (nlinum--face-height 'linum)) + (frame-char-height))))) + (set-window-margins nil (if nlinum-mode width) + (cdr (window-margins))))) (defun nlinum--setup-windows () (dolist (win (get-buffer-window-list nil nil t)) (with-selected-window win (nlinum--setup-window)))) -(defun nlinum--new-width () +(defun nlinum--flush () (nlinum--setup-windows) ;; (kill-local-variable 'nlinum--ol-counter) (remove-overlays (point-min) (point-max) 'nlinum t) @@ -71,6 +93,8 @@ Linum mode is a buffer-local minor mode." (lambda (buf) (with-current-buffer buf (with-silent-modifications + ;; FIXME: only remove `fontified' on those parts of the + ;; buffer that had an nlinum overlay! (remove-text-properties (point-min) (point-max) '(fontified))))) (current-buffer))) @@ -124,6 +148,14 @@ Linum mode is a buffer-local minor mode." (defvar nlinum--line-number-cache nil) (make-variable-buffer-local 'nlinum--line-number-cache) +;; We could try and avoid flushing the cache at every change, e.g. with: +;; (defun nlinum--before-change (start _end) +;; (if (and nlinum--line-number-cache +;; (< start (car nlinum--line-number-cache))) +;; (save-excursion (goto-char start) (nlinum--line-number-at-pos)))) +;; But it's far from clear that it's worth the trouble. The current simplistic +;; approach seems to be good enough in practice. + (defun nlinum--after-change (&rest _args) (setq nlinum--line-number-cache nil)) @@ -143,6 +175,25 @@ Linum mode is a buffer-local minor mode." (setq nlinum--line-number-cache (cons (point) pos)) pos)) +(defcustom nlinum-format "%d" + "Format of the line numbers. +Used by the default `nlinum-format-function'." + :type 'string + :group 'linum) + +(defvar nlinum-format-function + (lambda (line width) + (let ((str (format nlinum-format line))) + (when (< (length str) width) + ;; Left pad to try and right-align the line-numbers. + (setq str (concat (make-string (- width (length str)) ?\ ) str))) + (put-text-property 0 width 'face 'linum str) + str)) + "Function to build the string representing the line number. +Takes 2 arguments LINE and WIDTH, both of them numbers, and should return +a string. WIDTH is the ideal width of the result. If the result is larger, +it may cause the margin to be resized and line numbers to be recomputed.") + (defun nlinum--region (start limit) (save-excursion ;; Text may contain those nasty intangible properties, but @@ -151,23 +202,21 @@ Linum mode is a buffer-local minor mode." (goto-char start) (unless (bolp) (forward-line 1)) (remove-overlays (point) limit 'nlinum t) - (let ((line (nlinum--line-number-at-pos)) - (fmt (format "%%%dd" nlinum--width))) + (let ((line (nlinum--line-number-at-pos))) (while (and (not (eobp)) (< (point) limit) (let* ((ol (make-overlay (point) (1+ (point)))) - (str (format fmt line)) + (str (funcall nlinum-format-function + line nlinum--width)) (width (string-width str))) (when (< nlinum--width width) (setq nlinum--width width) - (nlinum--new-width)) + (nlinum--flush)) (overlay-put ol 'nlinum t) (overlay-put ol 'evaporate t) (overlay-put ol 'before-string (propertize " " 'display - `((margin left-margin) - ,(propertize str - 'face 'linum)))) + `((margin left-margin) ,str))) ;; (setq nlinum--ol-counter (1- nlinum--ol-counter)) ;; (when (= nlinum--ol-counter 0) ;; (run-with-idle-timer 0.5 nil #'nlinum--flush-overlays @@ -176,7 +225,10 @@ Linum mode is a buffer-local minor mode." (zerop (forward-line 1)))))))) ;; (setq nlinum--desc (format "-%d" (nlinum--ol-count))) nil) - - + +;;;###autoload +(define-globalized-minor-mode global-nlinum-mode nlinum-mode + (lambda () (unless (minibufferp) (nlinum-mode)))) + (provide 'nlinum) ;;; nlinum.el ends here