Add avy-linum-mode

* avy.el (avy--linum-strings): New defun.
(avy--linum-update-window): New defun. This is a copy-paste of
`linum-update-window' with just a few lines added.
(avy-linum-mode): New minor mode. Currently, only works with
`avy-all-windows' set to nil.
(avy--line): When `avy-linum-mode' is on, don't display
overlays. Instead, display a simple message.

Fixes #155
This commit is contained in:
Oleh Krehel 2016-06-13 22:53:06 +02:00
parent 430d75085f
commit 4e4c488eef

82
avy.el
View File

@ -1160,6 +1160,83 @@ Which one depends on variable `subword-mode'."
(forward-line 1)))))))
(nreverse candidates)))
(defun avy--linum-strings ()
(let* ((lines (mapcar #'car (avy--line-cands)))
(line-tree (avy-tree lines avy-keys))
(line-list nil))
(avy-traverse
line-tree
(lambda (path _leaf)
(let ((str (propertize (apply #'string (reverse path))
'face 'avy-lead-face)))
(when (> (length str) 1)
(set-text-properties 0 1 '(face avy-lead-face-0) str))
(push str line-list))))
(nreverse line-list)))
(defun avy--linum-update-window (_ win)
"Update line numbers for the portion visible in window WIN."
(goto-char (window-start win))
(let ((line (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
(count-lines (point-min) (point-max))))))
(concat "%" (number-to-string w) "d")))))
(width 0)
(avy-strs (when avy-linum-mode
(avy--linum-strings))))
(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
(cond (avy-linum-mode
(pop avy-strs))
(fmt
(propertize (format fmt line) 'face 'linum))
(t
(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)))))
(set-window-margins win width (cdr (window-margins win)))))
(define-minor-mode avy-linum-mode
"Minor mode that uses avy hints for `linum-mode'."
:group 'avy
(if avy-linum-mode
(progn
(require 'linum)
(advice-add 'linum-update-window :around 'avy--linum-update-window)
(linum-mode 1))
(advice-remove 'linum-update-window 'avy--linum-update-window)
(linum-mode -1)))
(defun avy--line (&optional arg beg end)
"Select a line.
The window scope is determined by `avy-all-windows' (ARG negates it).
@ -1167,7 +1244,10 @@ Narrow the scope to BEG END."
(let ((avy-action #'identity))
(avy--process
(avy--line-cands arg beg end)
(avy--style-fn avy-style))))
(if avy-linum-mode
(progn (message "Goto line:")
'ignore)
(avy--style-fn avy-style)))))
;;;###autoload
(defun avy-goto-line (&optional arg)