Always default to avy-keys but allow for per-command overrides

Using the new `avy-keys-alist` one can override the default `avy-keys`
on a per-command basis.  That's much better than hard-coding ?a-?z for
some commands and using the defaults for some others.

Fixes #20
This commit is contained in:
Tassilo Horn 2015-05-08 22:56:33 +02:00 committed by Oleh Krehel
parent a55858540b
commit 0e049bbc44

View File

@ -36,8 +36,30 @@
:prefix "avy-") :prefix "avy-")
(defcustom avy-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l) (defcustom avy-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)
"Keys for jumping." "Default keys for jumping."
:type '(repeat character)) :type '(repeat :tag "Keys" character))
(defcustom avy-keys-alist nil
"Alist of avy-jump commands to avy-keys overriding the default avy-keys."
:type '(alist :key-type (choice :tag "Command"
(const avy-goto-char)
(const avy-goto-char-2)
(const avy-isearch)
(const avy-goto-line)
(const avy-goto-subword-0)
(const avy-goto-subword-1)
(const avy-goto-word-0)
(const avy-goto-word-1)
(const avy-copy-line)
(const avy-copy-region)
(const avy-move-line))
:value-type (repeat :tag "Keys" character)))
(defmacro avy--with-avy-keys (command &rest body)
(declare (indent 1))
`(let ((avy-keys (or (cdr (assq ',command avy-keys-alist))
avy-keys)))
,@body))
(defcustom avy-background nil (defcustom avy-background nil
"When non-nil, a gray background will be added during the selection." "When non-nil, a gray background will be added during the selection."
@ -269,44 +291,47 @@ STYLE determines the leading char overlay style."
"Read one char and jump to it. "Read one char and jump to it.
The window scope is determined by `avy-all-windows' (ARG negates it)." The window scope is determined by `avy-all-windows' (ARG negates it)."
(interactive "P") (interactive "P")
(avy--generic-jump (avy--with-avy-keys avy-goto-char
(let ((c (read-char "char: "))) (avy--generic-jump
(if (= 13 c) (let ((c (read-char "char: ")))
"\n" (if (= 13 c)
(regexp-quote (string c)))) "\n"
arg (regexp-quote (string c))))
avy-goto-char-style)) arg
avy-goto-char-style)))
;;;###autoload ;;;###autoload
(defun avy-goto-char-2 (&optional arg) (defun avy-goto-char-2 (&optional arg)
"Read two consecutive chars and jump to the first one. "Read two consecutive chars and jump to the first one.
The window scope is determined by `avy-all-windows' (ARG negates it)." The window scope is determined by `avy-all-windows' (ARG negates it)."
(interactive "P") (interactive "P")
(avy--generic-jump (avy--with-avy-keys avy-goto-char-2
(regexp-quote (string (avy--generic-jump
(read-char "char 1: ") (regexp-quote (string
(read-char "char 2: "))) (read-char "char 1: ")
arg (read-char "char 2: ")))
avy-goto-char-style)) arg
avy-goto-char-style)))
;;;###autoload ;;;###autoload
(defun avy-isearch () (defun avy-isearch ()
"Jump to one of the current isearch candidates." "Jump to one of the current isearch candidates."
(interactive) (interactive)
(let* ((candidates (avy--with-avy-keys avy-isearch
(avy--regex-candidates isearch-string)) (let* ((candidates
(avy-background nil) (avy--regex-candidates isearch-string))
(candidate (avy-background nil)
(avy--process candidates #'avy--overlay-post))) (candidate
(isearch-done) (avy--process candidates #'avy--overlay-post)))
(avy--goto candidate))) (isearch-done)
(avy--goto candidate))))
;;;###autoload ;;;###autoload
(defun avy-goto-word-0 (arg) (defun avy-goto-word-0 (arg)
"Jump to a word start. "Jump to a word start.
The window scope is determined by `avy-all-windows' (ARG negates it)." The window scope is determined by `avy-all-windows' (ARG negates it)."
(interactive "P") (interactive "P")
(let ((avy-keys (number-sequence ?a ?z))) (avy--with-avy-keys avy-goto-word-0
(avy--generic-jump "\\b\\sw" arg avy-goto-word-style))) (avy--generic-jump "\\b\\sw" arg avy-goto-word-style)))
;;;###autoload ;;;###autoload
@ -314,17 +339,18 @@ The window scope is determined by `avy-all-windows' (ARG negates it)."
"Read one char at word start and jump there. "Read one char at word start and jump there.
The window scope is determined by `avy-all-windows' (ARG negates it)." The window scope is determined by `avy-all-windows' (ARG negates it)."
(interactive "P") (interactive "P")
(let* ((str (string (read-char "char: "))) (avy--with-avy-keys avy-goto-word-1
(regex (cond ((string= str ".") (let* ((str (string (read-char "char: ")))
"\\.") (regex (cond ((string= str ".")
((and avy-word-punc-regexp "\\.")
(string-match avy-word-punc-regexp str)) ((and avy-word-punc-regexp
str) (string-match avy-word-punc-regexp str))
(t str)
(concat (t
"\\b" (concat
str))))) "\\b"
(avy--generic-jump regex arg avy-goto-word-style))) str)))))
(avy--generic-jump regex arg avy-goto-word-style))))
(declare-function subword-backward "subword") (declare-function subword-backward "subword")
@ -338,23 +364,21 @@ When PREDICATE is non-nil it's a function of zero parameters that
should return true." should return true."
(interactive "P") (interactive "P")
(require 'subword) (require 'subword)
(let ((avy-keys (if predicate (avy--with-avy-keys avy-goto-subword-0
avy-keys (let ((case-fold-search nil)
(number-sequence ?a ?z))) candidates)
(case-fold-search nil) (avy-dowindows arg
candidates) (let ((ws (window-start)))
(avy-dowindows arg (save-excursion
(let ((ws (window-start))) (goto-char (window-end (selected-window) t))
(save-excursion (subword-backward)
(goto-char (window-end (selected-window) t)) (while (> (point) ws)
(subword-backward) (when (or (null predicate)
(while (> (point) ws) (and predicate (funcall predicate)))
(when (or (null predicate) (push (cons (point) (selected-window)) candidates))
(and predicate (funcall predicate))) (subword-backward)))))
(push (cons (point) (selected-window)) candidates)) (avy--goto
(subword-backward))))) (avy--process candidates (avy--style-fn avy-goto-word-style))))))
(avy--goto
(avy--process candidates (avy--style-fn avy-goto-word-style)))))
;;;###autoload ;;;###autoload
(defun avy-goto-subword-1 (&optional arg) (defun avy-goto-subword-1 (&optional arg)
@ -362,9 +386,10 @@ should return true."
The window scope is determined by `avy-all-windows' (ARG negates it). The window scope is determined by `avy-all-windows' (ARG negates it).
The case is ignored." The case is ignored."
(interactive "P") (interactive "P")
(let ((char (downcase (read-char "char: ")))) (avy--with-avy-keys avy-goto-subword-1
(avy-goto-subword-0 (let ((char (downcase (read-char "char: "))))
arg (lambda () (eq (downcase (char-after)) char))))) (avy-goto-subword-0
arg (lambda () (eq (downcase (char-after)) char))))))
(defun avy--line (&optional arg) (defun avy--line (&optional arg)
"Select line in current window." "Select line in current window."
@ -387,57 +412,61 @@ The case is ignored."
(defun avy-goto-line (&optional arg) (defun avy-goto-line (&optional arg)
"Jump to a line start in current buffer." "Jump to a line start in current buffer."
(interactive "P") (interactive "P")
(avy--goto (avy--line arg))) (avy--with-avy-keys avy-goto-line
(avy--goto (avy--line arg))))
;;;###autoload ;;;###autoload
(defun avy-copy-line (arg) (defun avy-copy-line (arg)
"Copy a selected line above the current line. "Copy a selected line above the current line.
ARG lines can be used." ARG lines can be used."
(interactive "p") (interactive "p")
(let ((start (car (avy--line)))) (avy--with-avy-keys avy-copy-line
(move-beginning-of-line nil) (let ((start (car (avy--line))))
(save-excursion (move-beginning-of-line nil)
(insert (save-excursion
(buffer-substring-no-properties (insert
start (buffer-substring-no-properties
(save-excursion start
(goto-char start) (save-excursion
(move-end-of-line arg) (goto-char start)
(point))) (move-end-of-line arg)
"\n")))) (point)))
"\n")))))
;;;###autoload ;;;###autoload
(defun avy-move-line (arg) (defun avy-move-line (arg)
"Move a selected line above the current line. "Move a selected line above the current line.
ARG lines can be used." ARG lines can be used."
(interactive "p") (interactive "p")
(let ((start (car (avy--line)))) (avy--with-avy-keys avy-move-line
(move-beginning-of-line nil) (let ((start (car (avy--line))))
(save-excursion (move-beginning-of-line nil)
(save-excursion (save-excursion
(goto-char start) (save-excursion
(move-end-of-line arg) (goto-char start)
(kill-region start (point))) (move-end-of-line arg)
(insert (kill-region start (point)))
(current-kill 0) (insert
"\n")))) (current-kill 0)
"\n")))))
;;;###autoload ;;;###autoload
(defun avy-copy-region () (defun avy-copy-region ()
"Select two lines and copy the text between them here." "Select two lines and copy the text between them here."
(interactive) (interactive)
(let ((beg (car (avy--line))) (avy--with-avy-keys avy-copy-region
(end (car (avy--line))) (let ((beg (car (avy--line)))
(pad (if (bolp) "" "\n"))) (end (car (avy--line)))
(move-beginning-of-line nil) (pad (if (bolp) "" "\n")))
(save-excursion (move-beginning-of-line nil)
(insert (save-excursion
(buffer-substring-no-properties (insert
beg (buffer-substring-no-properties
(save-excursion beg
(goto-char end) (save-excursion
(line-end-position))) (goto-char end)
pad)))) (line-end-position)))
pad)))))
;;;###autoload ;;;###autoload
(defun avy-setup-default () (defun avy-setup-default ()