mirror of
https://github.com/abo-abo/avy.git
synced 2025-10-13 13:33:03 +00:00
Compare commits
36 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
933d1f36cc | ||
![]() |
be612110cb | ||
![]() |
d9634efe26 | ||
![]() |
8576155193 | ||
![]() |
955c8dedd6 | ||
![]() |
6f9eefadc9 | ||
![]() |
fd7b02f556 | ||
![]() |
ba5f035be3 | ||
![]() |
6b53033883 | ||
![]() |
e92cb37457 | ||
![]() |
bbf1e7339e | ||
![]() |
2dde8b71a0 | ||
![]() |
f34ff764aa | ||
![]() |
36a48baa2c | ||
![]() |
acf553cae2 | ||
![]() |
509471bad0 | ||
![]() |
aa35412375 | ||
![]() |
954774d6e9 | ||
![]() |
3bf83140fa | ||
![]() |
cf95ba9582 | ||
![]() |
f9c15c573c | ||
![]() |
87394c9a88 | ||
![]() |
5f2eba5f59 | ||
![]() |
455ebec6f3 | ||
![]() |
5127f993f9 | ||
![]() |
034de4c0e9 | ||
![]() |
27d1af3fa6 | ||
![]() |
01a311ca6a | ||
![]() |
66886e265c | ||
![]() |
343fc42de1 | ||
![]() |
9ae059deaa | ||
![]() |
aadca9308a | ||
![]() |
f91ae613a8 | ||
![]() |
8686845ed9 | ||
![]() |
0e59474430 | ||
![]() |
b408f76e3d |
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
liberapay: abo-abo
|
||||
patreon: abo_abo
|
@ -1,3 +1,4 @@
|
||||
[](https://elpa.gnu.org/packages/avy.html)
|
||||
[](https://melpa.org/#/avy)
|
||||
[](https://stable.melpa.org/#/avy)
|
||||
|
||||
|
334
avy.el
334
avy.el
@ -1,6 +1,6 @@
|
||||
;;; avy.el --- Jump to arbitrary positions in visible text and select text quickly. -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2015-2019 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2015-2020 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Oleh Krehel <ohwoeowho@gmail.com>
|
||||
;; URL: https://github.com/abo-abo/avy
|
||||
@ -26,22 +26,22 @@
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; With Avy, you can move point to any position in Emacs – even in a
|
||||
;; different window – using very few keystrokes. For this, you look at
|
||||
;; different window – using very few keystrokes. For this, you look at
|
||||
;; the position where you want point to be, invoke Avy, and then enter
|
||||
;; the sequence of characters displayed at that position.
|
||||
;;
|
||||
;; If the position you want to jump to can be determined after only
|
||||
;; issuing a single keystroke, point is moved to the desired position
|
||||
;; immediately after that keystroke. In case this isn't possible, the
|
||||
;; immediately after that keystroke. In case this isn't possible, the
|
||||
;; sequence of keystrokes you need to enter is comprised of more than
|
||||
;; one character. Avy uses a decision tree where each candidate position
|
||||
;; one character. Avy uses a decision tree where each candidate position
|
||||
;; is a leaf and each edge is described by a character which is distinct
|
||||
;; per level of the tree. By entering those characters, you navigate the
|
||||
;; per level of the tree. By entering those characters, you navigate the
|
||||
;; tree, quickly arriving at the desired candidate position, such that
|
||||
;; Avy can move point to it.
|
||||
;;
|
||||
;; Note that this only makes sense for positions you are able to see
|
||||
;; when invoking Avy. These kinds of positions are supported:
|
||||
;; when invoking Avy. These kinds of positions are supported:
|
||||
;;
|
||||
;; * character positions
|
||||
;; * word or subword start positions
|
||||
@ -99,7 +99,7 @@ keys different than the following: a, e, i, o, u, y"
|
||||
(function :tag "Other command")))
|
||||
|
||||
(defcustom avy-keys-alist nil
|
||||
"Alist of avy-jump commands to `avy-keys' overriding the default `avy-keys'."
|
||||
"Alist of `avy-jump' commands to `avy-keys' overriding the default `avy-keys'."
|
||||
:type `(alist
|
||||
:key-type ,avy--key-type
|
||||
:value-type (repeat :tag "Keys" character)))
|
||||
@ -156,27 +156,27 @@ Use `avy-styles-alist' to customize this per-command."
|
||||
(const :tag "Words" words)))
|
||||
|
||||
(defcustom avy-styles-alist nil
|
||||
"Alist of avy-jump commands to the style for each command.
|
||||
"Alist of `avy-jump' commands to the style for each command.
|
||||
If the commands isn't on the list, `avy-style' is used."
|
||||
: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)
|
||||
(const avy-move-region)
|
||||
(const avy-kill-whole-line)
|
||||
(const avy-kill-region)
|
||||
(const avy-kill-ring-save-whole-line)
|
||||
(const avy-kill-ring-save-region)
|
||||
(function :tag "Other 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)
|
||||
(const avy-move-region)
|
||||
(const avy-kill-whole-line)
|
||||
(const avy-kill-region)
|
||||
(const avy-kill-ring-save-whole-line)
|
||||
(const avy-kill-ring-save-region)
|
||||
(function :tag "Other command"))
|
||||
:value-type (choice
|
||||
(const :tag "Pre" pre)
|
||||
(const :tag "At" at)
|
||||
@ -192,6 +192,7 @@ If the commands isn't on the list, `avy-style' is used."
|
||||
(?m . avy-action-mark)
|
||||
(?n . avy-action-copy)
|
||||
(?y . avy-action-yank)
|
||||
(?Y . avy-action-yank-line)
|
||||
(?i . avy-action-ispell)
|
||||
(?z . avy-action-zap-to-char))
|
||||
"List of actions for `avy-handler-default'.
|
||||
@ -248,12 +249,16 @@ Typically, these modes don't use the text representation."
|
||||
"In case there is only one candidate jumps directly to it."
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom avy-del-last-char-by '(8 127)
|
||||
(defcustom avy-del-last-char-by '(?\b ?\d)
|
||||
"List of event types, i.e. key presses, that delete the last
|
||||
character read. The default represents `C-h' and `DEL'. See
|
||||
`event-convert-list'."
|
||||
:type 'list)
|
||||
|
||||
(defcustom avy-escape-chars '(?\e ?\C-g)
|
||||
"List of characters that quit avy during `read-char'."
|
||||
:type 'list)
|
||||
|
||||
(defvar avy-ring (make-ring 20)
|
||||
"Hold the window and point history.")
|
||||
|
||||
@ -383,11 +388,14 @@ SEQ-LEN is how many elements of KEYS it takes to identify a match."
|
||||
(nreverse path-alist)))
|
||||
|
||||
(defun avy-order-closest (x)
|
||||
(abs (- (caar x) (point))))
|
||||
(abs (- (if (numberp (car x))
|
||||
(car x)
|
||||
(caar x))
|
||||
(point))))
|
||||
|
||||
(defvar avy-command nil
|
||||
"Store the current command symbol.
|
||||
E.g. 'avy-goto-line or 'avy-goto-char.")
|
||||
E.g. `avy-goto-line' or `avy-goto-char'.")
|
||||
|
||||
(defun avy-tree (lst keys)
|
||||
"Coerce LST into a balanced tree.
|
||||
@ -447,15 +455,19 @@ KEYS is the path from the root of `avy-tree' to LEAF."
|
||||
(defvar avy-action nil
|
||||
"Function to call at the end of select.")
|
||||
|
||||
(defvar avy-action-oneshot nil
|
||||
"Function to call once at the end of select.")
|
||||
|
||||
(defun avy-handler-default (char)
|
||||
"The default handler for a bad CHAR."
|
||||
(let (dispatch)
|
||||
(cond ((setq dispatch (assoc char avy-dispatch-alist))
|
||||
(setq avy-action (cdr dispatch))
|
||||
(unless (eq avy-style 'words)
|
||||
(setq avy-action (cdr dispatch)))
|
||||
(throw 'done 'restart))
|
||||
((memq char '(27 ?\C-g))
|
||||
((memq char avy-escape-chars)
|
||||
;; exit silently
|
||||
(throw 'done 'exit))
|
||||
(throw 'done 'abort))
|
||||
((eq char ??)
|
||||
(avy-show-dispatch-help)
|
||||
(throw 'done 'restart))
|
||||
@ -485,8 +497,8 @@ KEYS is the path from the root of `avy-tree' to LEAF."
|
||||
"Store the current incomplete path during `avy-read'.")
|
||||
|
||||
(defun avy-mouse-event-window (char)
|
||||
"If CHAR is a mouse event, return the window of the event if any or the selected window.
|
||||
Return nil if not a mouse event."
|
||||
"Return the window of mouse event CHAR if any or the selected window.
|
||||
Return nil if CHAR is not a mouse event."
|
||||
(when (mouse-event-p char)
|
||||
(cond ((windowp (posn-window (event-start char)))
|
||||
(posn-window (event-start char)))
|
||||
@ -518,13 +530,14 @@ multiple DISPLAY-FN invocations."
|
||||
(funcall cleanup-fn)
|
||||
(if (setq window (avy-mouse-event-window char))
|
||||
(throw 'done (cons char window))
|
||||
;; Ensure avy-current-path stores the full path prior to
|
||||
;; exit so other packages can utilize its value.
|
||||
(setq avy-current-path
|
||||
(concat avy-current-path (string (avy--key-to-char char))))
|
||||
(if (setq branch (assoc char tree))
|
||||
(if (eq (car (setq tree (cdr branch))) 'leaf)
|
||||
(throw 'done (cdr tree)))
|
||||
(progn
|
||||
;; Ensure avy-current-path stores the full path prior to
|
||||
;; exit so other packages can utilize its value.
|
||||
(setq avy-current-path
|
||||
(concat avy-current-path (string (avy--key-to-char char))))
|
||||
(if (eq (car (setq tree (cdr branch))) 'leaf)
|
||||
(throw 'done (cdr tree))))
|
||||
(funcall avy-handler-function char)))))))
|
||||
|
||||
(defun avy-read-de-bruijn (lst keys)
|
||||
@ -653,7 +666,7 @@ Commands using `avy-with' macro can be resumed."
|
||||
|
||||
(defmacro avy-with (command &rest body)
|
||||
"Set `avy-keys' according to COMMAND and execute BODY.
|
||||
Set `avy-style' according to COMMMAND as well."
|
||||
Set `avy-style' according to COMMAND as well."
|
||||
(declare (indent 1)
|
||||
(debug (form body)))
|
||||
`(let ((avy-keys (or (cdr (assq ',command avy-keys-alist))
|
||||
@ -665,7 +678,9 @@ Set `avy-style' according to COMMMAND as well."
|
||||
(setf (symbol-function 'avy-resume)
|
||||
(lambda ()
|
||||
(interactive)
|
||||
,@body))
|
||||
,@(if (eq command 'avy-goto-char-timer)
|
||||
(cdr body)
|
||||
body)))
|
||||
,@body))
|
||||
|
||||
(defun avy-action-goto (pt)
|
||||
@ -709,6 +724,11 @@ Set `avy-style' according to COMMMAND as well."
|
||||
(yank)
|
||||
t)
|
||||
|
||||
(defun avy-action-yank-line (pt)
|
||||
"Yank sexp starting at PT at the current point."
|
||||
(let ((avy-command 'avy-goto-line))
|
||||
(avy-action-yank pt)))
|
||||
|
||||
(defun avy-action-kill-move (pt)
|
||||
"Kill sexp at PT and move there."
|
||||
(goto-char pt)
|
||||
@ -748,6 +768,11 @@ Set `avy-style' according to COMMMAND as well."
|
||||
|
||||
(declare-function flyspell-correct-word-before-point "flyspell")
|
||||
|
||||
(defcustom avy-flyspell-correct-function #'flyspell-correct-word-before-point
|
||||
"Function called to correct word by `avy-action-ispell' when
|
||||
`flyspell-mode' is enabled."
|
||||
:type 'function)
|
||||
|
||||
(defun avy-action-ispell (pt)
|
||||
"Auto correct word at PT."
|
||||
(save-excursion
|
||||
@ -758,7 +783,7 @@ Set `avy-style' according to COMMMAND as well."
|
||||
(line-beginning-position)
|
||||
(line-end-position)))
|
||||
((bound-and-true-p flyspell-mode)
|
||||
(flyspell-correct-word-before-point))
|
||||
(funcall avy-flyspell-correct-function))
|
||||
((looking-at-p "\\b")
|
||||
(ispell-word))
|
||||
(t
|
||||
@ -813,11 +838,11 @@ Set `avy-style' according to COMMMAND as well."
|
||||
avy-last-candidates))
|
||||
(min-dist
|
||||
(apply #'min
|
||||
(mapcar (lambda (x) (abs (- (caar x) (point)))) avy-last-candidates)))
|
||||
(mapcar (lambda (x) (abs (- (if (listp (car x)) (caar x) (car x)) (point)))) avy-last-candidates)))
|
||||
(pos
|
||||
(cl-position-if
|
||||
(lambda (x)
|
||||
(= (- (caar x) (point)) min-dist))
|
||||
(= (- (if (listp (car x)) (caar x) (car x)) (point)) min-dist))
|
||||
avy-last-candidates)))
|
||||
(funcall advancer pos avy-last-candidates)))
|
||||
|
||||
@ -827,7 +852,8 @@ Set `avy-style' according to COMMMAND as well."
|
||||
(avy--last-candidates-cycle
|
||||
(lambda (pos lst)
|
||||
(when (> pos 0)
|
||||
(goto-char (caar (nth (1- pos) lst)))))))
|
||||
(let ((candidate (nth (1- pos) lst)))
|
||||
(goto-char (if (listp (car candidate)) (caar candidate) (car candidate))))))))
|
||||
|
||||
(defun avy-next ()
|
||||
"Go to the next candidate of the last `avy-read'."
|
||||
@ -835,8 +861,10 @@ Set `avy-style' according to COMMMAND as well."
|
||||
(avy--last-candidates-cycle
|
||||
(lambda (pos lst)
|
||||
(when (< pos (1- (length lst)))
|
||||
(goto-char (caar (nth (1+ pos) lst)))))))
|
||||
(let ((candidate (nth (1+ pos) lst)))
|
||||
(goto-char (if (listp (car candidate)) (caar candidate) (car candidate))))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun avy-process (candidates &optional overlay-fn cleanup-fn)
|
||||
"Select one of CANDIDATES using `avy-read'.
|
||||
Use OVERLAY-FN to visualize the decision overlay.
|
||||
@ -854,19 +882,24 @@ multiple OVERLAY-FN invocations."
|
||||
(res (avy--process-1 candidates overlay-fn cleanup-fn)))
|
||||
(cond
|
||||
((null res)
|
||||
(message "zero candidates")
|
||||
t)
|
||||
(if (and (eq avy-style 'words) candidates)
|
||||
(avy-process original-cands overlay-fn cleanup-fn)
|
||||
(message "zero candidates")
|
||||
t))
|
||||
((eq res 'restart)
|
||||
(avy-process original-cands overlay-fn cleanup-fn))
|
||||
;; ignore exit from `avy-handler-function'
|
||||
((eq res 'exit))
|
||||
((eq res 'abort)
|
||||
nil)
|
||||
(t
|
||||
(funcall avy-pre-action res)
|
||||
(setq res (car res))
|
||||
(funcall (or avy-action 'avy-action-goto)
|
||||
(if (consp res)
|
||||
(car res)
|
||||
res))
|
||||
(let ((action (or avy-action avy-action-oneshot 'avy-action-goto)))
|
||||
(funcall action
|
||||
(if (consp res)
|
||||
(car res)
|
||||
res)))
|
||||
res))))
|
||||
|
||||
(define-obsolete-function-alias 'avy--process 'avy-process
|
||||
@ -902,14 +935,14 @@ multiple OVERLAY-FN invocations."
|
||||
(null (assoc invisible buffer-invisibility-spec)))))
|
||||
|
||||
(defun avy--next-visible-point ()
|
||||
"Return the next closest point without 'invisible property."
|
||||
"Return the next closest point without `invisible' property."
|
||||
(let ((s (point)))
|
||||
(while (and (not (= (point-max) (setq s (next-char-property-change s))))
|
||||
(not (avy--visible-p s))))
|
||||
s))
|
||||
|
||||
(defun avy--next-invisible-point ()
|
||||
"Return the next closest point with 'invisible property."
|
||||
"Return the next closest point with `invisible' property."
|
||||
(let ((s (point)))
|
||||
(while (and (not (= (point-max) (setq s (next-char-property-change s))))
|
||||
(avy--visible-p s)))
|
||||
@ -950,9 +983,12 @@ When GROUP is non-nil, (BEG . END) should delimit that regex group."
|
||||
(when (avy--visible-p (1- (point)))
|
||||
(when (or (null pred)
|
||||
(funcall pred))
|
||||
(push (cons (cons (match-beginning group)
|
||||
(match-end group))
|
||||
wnd) candidates)))))))
|
||||
(push (cons
|
||||
(if (numberp group)
|
||||
(cons (match-beginning group)
|
||||
(match-end group))
|
||||
(funcall group))
|
||||
wnd) candidates)))))))
|
||||
(nreverse candidates)))
|
||||
|
||||
(defvar avy--overlay-offset 0
|
||||
@ -985,10 +1021,11 @@ COMPOSE-FN is a lambda that concatenates the old string at BEG with STR."
|
||||
(os-line-prefix (get-text-property 0 'line-prefix old-str))
|
||||
(os-wrap-prefix (get-text-property 0 'wrap-prefix old-str))
|
||||
other-ol)
|
||||
(when os-line-prefix
|
||||
(add-text-properties 0 1 `(line-prefix ,os-line-prefix) str))
|
||||
(when os-wrap-prefix
|
||||
(add-text-properties 0 1 `(wrap-prefix ,os-wrap-prefix) str))
|
||||
(unless (= (length str) 0)
|
||||
(when os-line-prefix
|
||||
(add-text-properties 0 1 `(line-prefix ,os-line-prefix) str))
|
||||
(when os-wrap-prefix
|
||||
(add-text-properties 0 1 `(wrap-prefix ,os-wrap-prefix) str)))
|
||||
(when (setq other-ol (cl-find-if
|
||||
(lambda (o) (overlay-get o 'goto-address))
|
||||
(overlays-at beg)))
|
||||
@ -1046,19 +1083,22 @@ Do this even when the char is terminating."
|
||||
"Create an overlay with PATH at LEAF.
|
||||
PATH is a list of keys from tree root to LEAF.
|
||||
LEAF is normally ((BEG . END) . WND)."
|
||||
(let* ((path (mapcar #'avy--key-to-char path))
|
||||
(str (propertize (apply #'string (reverse path))
|
||||
'face 'avy-lead-face)))
|
||||
(when (or avy-highlight-first (> (length str) 1))
|
||||
(set-text-properties 0 1 '(face avy-lead-face-0) str))
|
||||
(setq str (concat
|
||||
(propertize avy-current-path
|
||||
'face 'avy-lead-face-1)
|
||||
str))
|
||||
(avy--overlay
|
||||
str
|
||||
(avy-candidate-beg leaf) nil
|
||||
(avy-candidate-wnd leaf))))
|
||||
(if (with-selected-window (cdr leaf)
|
||||
(bound-and-true-p visual-line-mode))
|
||||
(avy--overlay-at-full path leaf)
|
||||
(let* ((path (mapcar #'avy--key-to-char path))
|
||||
(str (propertize (apply #'string (reverse path))
|
||||
'face 'avy-lead-face)))
|
||||
(when (or avy-highlight-first (> (length str) 1))
|
||||
(set-text-properties 0 1 '(face avy-lead-face-0) str))
|
||||
(setq str (concat
|
||||
(propertize avy-current-path
|
||||
'face 'avy-lead-face-1)
|
||||
str))
|
||||
(avy--overlay
|
||||
str
|
||||
(avy-candidate-beg leaf) nil
|
||||
(avy-candidate-wnd leaf)))))
|
||||
|
||||
(defun avy--overlay-at (path leaf)
|
||||
"Create an overlay with PATH at LEAF.
|
||||
@ -1223,20 +1263,22 @@ exist."
|
||||
(ignore #'ignore)
|
||||
(t (error "Unexpected style %S" style))))
|
||||
|
||||
(cl-defun avy-jump (regex &key window-flip beg end action pred)
|
||||
(cl-defun avy-jump (regex &key window-flip beg end action pred group)
|
||||
"Jump to REGEX.
|
||||
The window scope is determined by `avy-all-windows'.
|
||||
When WINDOW-FLIP is non-nil, do the opposite of `avy-all-windows'.
|
||||
BEG and END narrow the scope where candidates are searched.
|
||||
ACTION is a function that takes point position as an argument.
|
||||
When PRED is non-nil, it's a filter for matching point positions."
|
||||
When PRED is non-nil, it's a filter for matching point positions.
|
||||
When GROUP is non-nil, it's either a match group in REGEX, or a function
|
||||
that returns a cons of match beginning and end."
|
||||
(setq avy-action (or action avy-action))
|
||||
(let ((avy-all-windows
|
||||
(if window-flip
|
||||
(not avy-all-windows)
|
||||
avy-all-windows)))
|
||||
(avy-process
|
||||
(avy--regex-candidates regex beg end pred))))
|
||||
(avy--regex-candidates regex beg end pred group))))
|
||||
|
||||
(defun avy--generic-jump (regex window-flip &optional beg end)
|
||||
"Jump to REGEX.
|
||||
@ -1281,8 +1323,18 @@ The window scope is determined by `avy-all-windows' (ARG negates it)."
|
||||
The window scope is determined by `avy-all-windows'.
|
||||
When ARG is non-nil, do the opposite of `avy-all-windows'.
|
||||
BEG and END narrow the scope where candidates are searched."
|
||||
(interactive (list (read-char "char 1: " t)
|
||||
(read-char "char 2: " t)
|
||||
(interactive (list (let ((c1 (read-char "char 1: " t)))
|
||||
(if (memq c1 '(? ?\b))
|
||||
(keyboard-quit)
|
||||
c1))
|
||||
(let ((c2 (read-char "char 2: " t)))
|
||||
(cond ((eq c2 ?)
|
||||
(keyboard-quit))
|
||||
((memq c2 avy-del-last-char-by)
|
||||
(keyboard-escape-quit)
|
||||
(call-interactively 'avy-goto-char-2))
|
||||
(t
|
||||
c2)))
|
||||
current-prefix-arg
|
||||
nil nil))
|
||||
(when (eq char1 ?
)
|
||||
@ -1331,12 +1383,14 @@ When ARG is non-nil, do the opposite of `avy-all-windows'."
|
||||
"Jump to one of the current isearch candidates."
|
||||
(interactive)
|
||||
(avy-with avy-isearch
|
||||
(let ((avy-background nil))
|
||||
(avy-process
|
||||
(avy--regex-candidates (if isearch-regexp
|
||||
isearch-string
|
||||
(regexp-quote isearch-string))))
|
||||
(isearch-done))))
|
||||
(let ((avy-background nil)
|
||||
(avy-case-fold-search case-fold-search))
|
||||
(prog1
|
||||
(avy-process
|
||||
(avy--regex-candidates (if isearch-regexp
|
||||
isearch-string
|
||||
(regexp-quote isearch-string))))
|
||||
(isearch-done)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun avy-goto-word-0 (arg &optional beg end)
|
||||
@ -1351,6 +1405,20 @@ BEG and END narrow the scope where candidates are searched."
|
||||
:beg beg
|
||||
:end end)))
|
||||
|
||||
;;;###autoload
|
||||
(defun avy-goto-whitespace-end (arg &optional beg end)
|
||||
"Jump to the end of a whitespace sequence.
|
||||
The window scope is determined by `avy-all-windows'.
|
||||
When ARG is non-nil, do the opposite of `avy-all-windows'.
|
||||
BEG and END narrow the scope where candidates are searched."
|
||||
(interactive "P")
|
||||
(avy-with avy-goto-whitespace-end
|
||||
(avy-jump "[ \t]+\\|\n[ \t]*"
|
||||
:window-flip arg
|
||||
:beg beg
|
||||
:end end
|
||||
:group (lambda () (cons (point) (1+ (point)))))))
|
||||
|
||||
(defun avy-goto-word-0-above (arg)
|
||||
"Jump to a word start between window start and point.
|
||||
The window scope is determined by `avy-all-windows'.
|
||||
@ -1367,6 +1435,22 @@ When ARG is non-nil, do the opposite of `avy-all-windows'."
|
||||
(avy-with avy-goto-word-0
|
||||
(avy-goto-word-0 arg (point) (window-end (selected-window) t))))
|
||||
|
||||
(defun avy-goto-whitespace-end-above (arg)
|
||||
"Jump to the end of a whitespace sequence between point and window end.
|
||||
The window scope is determined by `avy-all-windows'.
|
||||
When ARG is non-nil, do the opposite of `avy-all-windows'."
|
||||
(interactive "P")
|
||||
(avy-with avy-goto-whitespace-end
|
||||
(avy-goto-whitespace-end arg (window-start) (point))))
|
||||
|
||||
(defun avy-goto-whitespace-end-below (arg)
|
||||
"Jump to the end of a whitespace sequence between window start and point.
|
||||
The window scope is determined by `avy-all-windows'.
|
||||
When ARG is non-nil, do the opposite of `avy-all-windows'."
|
||||
(interactive "P")
|
||||
(avy-with avy-goto-whitespace-end
|
||||
(avy-goto-whitespace-end arg (point) (window-end (selected-window) t))))
|
||||
|
||||
;;;###autoload
|
||||
(defun avy-goto-word-1 (char &optional arg beg end symbol)
|
||||
"Jump to the currently visible CHAR at a word start.
|
||||
@ -1490,13 +1574,15 @@ BEG and END narrow the scope where candidates are searched."
|
||||
(when (or (null predicate)
|
||||
(and predicate (funcall predicate)))
|
||||
(unless (not (avy--visible-p (point)))
|
||||
(push (cons (point) (selected-window)) window-cands)))
|
||||
(push (cons (cons (point) (1+ (point)))
|
||||
(selected-window)) window-cands)))
|
||||
(subword-backward))
|
||||
(and (= (point) ws)
|
||||
(or (null predicate)
|
||||
(and predicate (funcall predicate)))
|
||||
(not (get-char-property (point) 'invisible))
|
||||
(push (cons (point) (selected-window)) window-cands)))
|
||||
(push (cons (cons (point) (1+ (point)))
|
||||
(selected-window)) window-cands)))
|
||||
(setq candidates (nconc candidates window-cands))))))
|
||||
(avy-process candidates))))
|
||||
|
||||
@ -1526,7 +1612,8 @@ Which one depends on variable `subword-mode'."
|
||||
(defvar visual-line-mode)
|
||||
|
||||
(defcustom avy-indent-line-overlay nil
|
||||
"When non-nil, `avy-goto-line' will display the line overlay next to the first non-whitespace character of each line."
|
||||
"When non-nil, display line overlay next to the first non-whitespace character.
|
||||
This affects `avy-goto-line'."
|
||||
:type 'boolean)
|
||||
|
||||
(defun avy--line-cands (&optional arg beg end bottom-up)
|
||||
@ -1554,9 +1641,7 @@ When BOTTOM-UP is non-nil, display avy candidates from top to bottom"
|
||||
(point)))
|
||||
(selected-window)) candidates))
|
||||
(if visual-line-mode
|
||||
(progn
|
||||
(setq temporary-goal-column 0)
|
||||
(line-move-visual 1 t))
|
||||
(line-move-visual 1 t)
|
||||
(forward-line 1)))))))
|
||||
(if bottom-up
|
||||
candidates
|
||||
@ -1581,6 +1666,7 @@ When BOTTOM-UP is non-nil, display avy candidates from top to bottom"
|
||||
(defvar linum-overlays)
|
||||
(defvar linum-format)
|
||||
(declare-function linum--face-width "linum")
|
||||
(declare-function linum-mode "linum")
|
||||
|
||||
(define-minor-mode avy-linum-mode
|
||||
"Minor mode that uses avy hints for `linum-mode'."
|
||||
@ -1651,8 +1737,8 @@ The window scope is determined by `avy-all-windows'.
|
||||
When ARG is non-nil, do the opposite of `avy-all-windows'.
|
||||
BEG and END narrow the scope where candidates are searched.
|
||||
When BOTTOM-UP is non-nil, display avy candidates from top to bottom"
|
||||
(let ((avy-action #'identity)
|
||||
(avy-style (if avy-linum-mode
|
||||
(setq avy-action (or avy-action #'identity))
|
||||
(let ((avy-style (if avy-linum-mode
|
||||
(progn
|
||||
(message "Goto line:")
|
||||
'ignore)
|
||||
@ -1694,7 +1780,7 @@ Otherwise, forward to `goto-line' with ARG."
|
||||
(forward-line (1- (string-to-number line))))
|
||||
(throw 'done 'exit))))))
|
||||
(r (avy--line (eq arg 4))))
|
||||
(unless (eq r t)
|
||||
(when (and (not (memq r '(t nil))) (eq avy-action #'identity))
|
||||
(avy-action-goto r))))))
|
||||
|
||||
;;;###autoload
|
||||
@ -1972,22 +2058,24 @@ newline."
|
||||
"Whether enter exits avy-goto-char-timer early. If nil it matches newline"
|
||||
:type 'boolean)
|
||||
|
||||
(defvar avy-text ""
|
||||
"Store the input read by `avy--read-candidates'.")
|
||||
|
||||
(defun avy--read-candidates (&optional re-builder)
|
||||
"Read as many chars as possible and return their occurrences.
|
||||
At least one char must be read, and then repeatedly one next char
|
||||
may be read if it is entered before `avy-timeout-seconds'. Any
|
||||
key defined in `avy-del-last-char-by' (by default `C-h' and `DEL')
|
||||
deletes the last char entered, and `RET' exits with the
|
||||
currently read string immediately instead of waiting for another
|
||||
char for `avy-timeout-seconds'.
|
||||
may be read if it is entered before `avy-timeout-seconds'. DEL
|
||||
deletes the last char entered, and RET exits with the currently
|
||||
read string immediately instead of waiting for another char for
|
||||
`avy-timeout-seconds'.
|
||||
The format of the result is the same as that of `avy--regex-candidates'.
|
||||
This function obeys `avy-all-windows' setting.
|
||||
RE-BUILDER is a function that takes a string and returns a regex.
|
||||
When nil, `regexp-quote' is used.
|
||||
If a group is captured, the first group is highlighted.
|
||||
Otherwise, the whole regex is highlighted."
|
||||
(let ((str "")
|
||||
(re-builder (or re-builder #'regexp-quote))
|
||||
(setq avy-text "")
|
||||
(let ((re-builder (or re-builder #'regexp-quote))
|
||||
char break overlays regex)
|
||||
(unwind-protect
|
||||
(progn
|
||||
@ -1997,11 +2085,11 @@ Otherwise, the whole regex is highlighted."
|
||||
(setq char
|
||||
(read-char (format "%d char%s: "
|
||||
(length overlays)
|
||||
(if (string= str "")
|
||||
str
|
||||
(format " (%s)" str)))
|
||||
(if (string= avy-text "")
|
||||
avy-text
|
||||
(format " (%s)" avy-text)))
|
||||
t
|
||||
(and (not (string= str ""))
|
||||
(and (not (string= avy-text ""))
|
||||
avy-timeout-seconds))))
|
||||
;; Unhighlight
|
||||
(dolist (ov overlays)
|
||||
@ -2012,21 +2100,21 @@ Otherwise, the whole regex is highlighted."
|
||||
((= char 13)
|
||||
(if avy-enter-times-out
|
||||
(setq break t)
|
||||
(setq str (concat str (list ?\n)))))
|
||||
(setq avy-text (concat avy-text (list ?\n)))))
|
||||
;; Handle C-h, DEL
|
||||
((memq char avy-del-last-char-by)
|
||||
(let ((l (length str)))
|
||||
(let ((l (length avy-text)))
|
||||
(when (>= l 1)
|
||||
(setq str (substring str 0 (1- l))))))
|
||||
(setq avy-text (substring avy-text 0 (1- l))))))
|
||||
;; Handle ESC
|
||||
((= char 27)
|
||||
(keyboard-quit))
|
||||
(t
|
||||
(setq str (concat str (list char)))))
|
||||
(setq avy-text (concat avy-text (list char)))))
|
||||
;; Highlight
|
||||
(when (>= (length str) 1)
|
||||
(when (>= (length avy-text) 1)
|
||||
(let ((case-fold-search
|
||||
(or avy-case-fold-search (string= str (downcase str))))
|
||||
(or avy-case-fold-search (string= avy-text (downcase avy-text))))
|
||||
found)
|
||||
(avy-dowindows current-prefix-arg
|
||||
(dolist (pair (avy--find-visible-regions
|
||||
@ -2034,7 +2122,7 @@ Otherwise, the whole regex is highlighted."
|
||||
(window-end (selected-window) t)))
|
||||
(save-excursion
|
||||
(goto-char (car pair))
|
||||
(setq regex (funcall re-builder str))
|
||||
(setq regex (funcall re-builder avy-text))
|
||||
(while (re-search-forward regex (cdr pair) t)
|
||||
(unless (not (avy--visible-p (1- (point))))
|
||||
(let* ((idx (if (= (length (match-data)) 4) 1 0))
|
||||
@ -2057,6 +2145,8 @@ Otherwise, the whole regex is highlighted."
|
||||
(delete-overlay ov))
|
||||
(avy--done))))
|
||||
|
||||
(defvar avy--old-cands nil)
|
||||
|
||||
;;;###autoload
|
||||
(defun avy-goto-char-timer (&optional arg)
|
||||
"Read one or many consecutive chars and jump to the first one.
|
||||
@ -2066,8 +2156,8 @@ The window scope is determined by `avy-all-windows' (ARG negates it)."
|
||||
(not avy-all-windows)
|
||||
avy-all-windows)))
|
||||
(avy-with avy-goto-char-timer
|
||||
(avy-process
|
||||
(avy--read-candidates)))))
|
||||
(setq avy--old-cands (avy--read-candidates))
|
||||
(avy-process avy--old-cands))))
|
||||
|
||||
(defun avy-push-mark ()
|
||||
"Store the current point and window."
|
||||
@ -2095,6 +2185,22 @@ The window scope is determined by `avy-all-windows' (ARG negates it)."
|
||||
(error
|
||||
(set-mark-command 4)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun avy-transpose-lines-in-region ()
|
||||
"Transpose lines in the active region."
|
||||
(interactive)
|
||||
(when (and (use-region-p) (> (count-lines (region-beginning) (region-end)) 1))
|
||||
(let ((avy-all-windows nil)
|
||||
(fst-line-point (avy--line nil (region-beginning) (region-end))))
|
||||
(when fst-line-point
|
||||
(let ((snd-line-point (avy--line nil (region-beginning) (region-end))))
|
||||
(when snd-line-point
|
||||
(save-mark-and-excursion
|
||||
(push-mark fst-line-point)
|
||||
(goto-char snd-line-point)
|
||||
(transpose-lines 0))
|
||||
(avy-transpose-lines-in-region)))))))
|
||||
|
||||
;; ** Org-mode
|
||||
(defvar org-reverse-note-order)
|
||||
(declare-function org-refile "org")
|
||||
|
@ -326,50 +326,50 @@ See [[https://github.com/abo-abo/avy/issues/116][#116]].
|
||||
* 0.5.0
|
||||
** Fixes
|
||||
*** el:avy-action-copy
|
||||
Save selected window and frame. See #133.
|
||||
Save selected window and frame. See [[https://github.com/abo-abo/avy/issues/133][#133]].
|
||||
|
||||
Copy line for el:avy-goto-line. See #191.
|
||||
Copy line for el:avy-goto-line. See [[https://github.com/abo-abo/avy/issues/191][#191]].
|
||||
*** el:avy-read
|
||||
Make ~C-g~ and ~ESC~ fail silently when reading char. See #137.
|
||||
Make ~C-g~ and ~ESC~ fail silently when reading char. See [[https://github.com/abo-abo/avy/issues/137][#137]].
|
||||
|
||||
Display error message on mouse clicks. See #226.
|
||||
Display error message on mouse clicks. See [[https://github.com/abo-abo/avy/issues/226][#226]].
|
||||
|
||||
Update el:avy-current-path before returning. See #226.
|
||||
Update el:avy-current-path before returning. See [[https://github.com/abo-abo/avy/issues/226][#226]].
|
||||
|
||||
Quit on ~ESC~. See #249.
|
||||
Quit on ~ESC~. See [[https://github.com/abo-abo/avy/issues/249][#249]].
|
||||
|
||||
Fix for el:org-toggle-link-display. See #261.
|
||||
Fix for el:org-toggle-link-display. See [[https://github.com/abo-abo/avy/issues/261][#261]].
|
||||
|
||||
Fix for el:buffer-invisibility-spec being t. See #264.
|
||||
Fix for el:buffer-invisibility-spec being t. See [[https://github.com/abo-abo/avy/issues/264][#264]].
|
||||
|
||||
Allow "invisible" 'org-link. See #269.
|
||||
Allow "invisible" 'org-link. See [[https://github.com/abo-abo/avy/issues/269][#269]].
|
||||
*** el:avy-goto-word-1
|
||||
Works for "^A"-"^Z", see #167.
|
||||
Works for "^A"-"^Z", see [[https://github.com/abo-abo/avy/issues/167][#167]].
|
||||
*** el:avy-goto-subword-0
|
||||
Add char at window start if empty, See #145.
|
||||
Add char at window start if empty, See [[https://github.com/abo-abo/avy/issues/145][#145]].
|
||||
|
||||
Add option to limit scope. See #235.
|
||||
Add option to limit scope. See [[https://github.com/abo-abo/avy/issues/235][#235]].
|
||||
*** el:avy-goto-subword-1
|
||||
Check el:char-after. See #163.
|
||||
Check el:char-after. See [[https://github.com/abo-abo/avy/issues/163][#163]].
|
||||
*** el:avy-isearch
|
||||
Escape regex. See #147.
|
||||
Escape regex. See [[https://github.com/abo-abo/avy/issues/147][#147]].
|
||||
*** el:avy-goto-char-2
|
||||
Translate ~RET~ to ~C-j~. See #153.
|
||||
Translate ~RET~ to ~C-j~. See [[https://github.com/abo-abo/avy/issues/153][#153]].
|
||||
*** el:avy-action-goto
|
||||
Add el:raise-frame.
|
||||
*** el:avy-goto-char-timer
|
||||
Allow ~C-h~ to delete. See #193.
|
||||
Allow ~C-h~ to delete. See [[https://github.com/abo-abo/avy/issues/193][#193]].
|
||||
|
||||
Obey el:avy-background for the initial search. See #259.
|
||||
Obey el:avy-background for the initial search. See [[https://github.com/abo-abo/avy/issues/259][#259]].
|
||||
*** el:avy-goto-line
|
||||
Fix for empty buffer. See #238.
|
||||
Fix for empty buffer. See [[https://github.com/abo-abo/avy/issues/238][#238]].
|
||||
|
||||
Add ability to display candidates from bottom to top. See #236.
|
||||
Add ability to display candidates from bottom to top. See [[https://github.com/abo-abo/avy/issues/236][#236]].
|
||||
*** el:avy--overlay-at-full
|
||||
More consistent face order.
|
||||
See #270.
|
||||
See [[https://github.com/abo-abo/avy/issues/270][#270]].
|
||||
*** documentation
|
||||
See #223, #226, #218, #245, #262.
|
||||
See [[https://github.com/abo-abo/avy/issues/223][#223]], [[https://github.com/abo-abo/avy/issues/226][#226]], [[https://github.com/abo-abo/avy/issues/218][#218]], [[https://github.com/abo-abo/avy/issues/245][#245]], [[https://github.com/abo-abo/avy/issues/262][#262]].
|
||||
|
||||
** New Features
|
||||
*** API
|
||||
@ -378,25 +378,25 @@ functions that were used in other packages and configs. Please replace the refer
|
||||
the obsolete functions.
|
||||
|
||||
**** el:avy-jump
|
||||
New API function to replace el:avy--generic-jump. See #265, #267.
|
||||
New API function to replace el:avy--generic-jump. See [[https://github.com/abo-abo/avy/issues/265][#265]], [[https://github.com/abo-abo/avy/issues/267][#267]].
|
||||
**** el:avy-process
|
||||
New API function to replace el:avy--process. See #266.
|
||||
New API function to replace el:avy--process. See [[https://github.com/abo-abo/avy/issues/266][#266]].
|
||||
|
||||
*** New actions
|
||||
**** el:avy-action-kill-stay
|
||||
Kill a word with el:avy-goto-char without moving there.
|
||||
Bound to ~X~.
|
||||
**** el:avy-action-ispell
|
||||
Auto-correct word at point. See #142, #160, #161.
|
||||
Auto-correct word at point. See [[https://github.com/abo-abo/avy/issues/142][#142]], [[https://github.com/abo-abo/avy/issues/160][#160]], [[https://github.com/abo-abo/avy/issues/161][#161]].
|
||||
Bound to ~i~.
|
||||
**** el:avy-action-yank
|
||||
Yank sexp starting at selected point at the current point. See #183.
|
||||
Yank sexp starting at selected point at the current point. See [[https://github.com/abo-abo/avy/issues/183][#183]].
|
||||
Bound to ~y~.
|
||||
**** el:avy-action-teleport
|
||||
Kill sexp starting on selected point and yank into the current location. See #207.
|
||||
Kill sexp starting on selected point and yank into the current location. See [[https://github.com/abo-abo/avy/issues/207][#207]].
|
||||
Bound to ~t~.
|
||||
**** el:avy-action-zap-to-char
|
||||
Kill from point up to selected point. See #234.
|
||||
Kill from point up to selected point. See [[https://github.com/abo-abo/avy/issues/234][#234]].
|
||||
Bound to ~z~.
|
||||
|
||||
*** New defcustoms
|
||||
@ -410,40 +410,40 @@ And you'll see overlays like "by", "if", "is", "it", "my" for 2-letter sequences
|
||||
"lls" and "jhl". But you will have to adjust your el:avy-dispatch-alist, e.g. to use only
|
||||
upper case characters.
|
||||
|
||||
See #210, #219.
|
||||
See [[https://github.com/abo-abo/avy/issues/210][#210]], [[https://github.com/abo-abo/avy/issues/219][#219]].
|
||||
**** el:avy-orders-alist
|
||||
Use it to customize the order of candidates with relation to point. The default is for
|
||||
el:avy-goto-char to have the shortest overlay for candidates closest to point.
|
||||
See #242.
|
||||
See [[https://github.com/abo-abo/avy/issues/242][#242]].
|
||||
**** el:avy-indent-line-overlay
|
||||
When non-nil el:avy-goto-line will display the line overlay next to the first
|
||||
non-whitespace character of each line. See #244.
|
||||
non-whitespace character of each line. See [[https://github.com/abo-abo/avy/issues/244][#244]].
|
||||
**** el:avy-single-candidate-jump
|
||||
When non-nil, and there is only one candidate, jump there. See #250.
|
||||
When non-nil, and there is only one candidate, jump there. See [[https://github.com/abo-abo/avy/issues/250][#250]].
|
||||
**** el:avy-del-last-char-by
|
||||
Customize keys which delete the last read char. The defaults are ~C-h~ and ~DEL~. See #251.
|
||||
Customize keys which delete the last read char. The defaults are ~C-h~ and ~DEL~. See [[https://github.com/abo-abo/avy/issues/251][#251]].
|
||||
**** el:avy-goto-word-0-regexp
|
||||
Customize el:avy-goto-word-0. See #136, #156.
|
||||
Customize el:avy-goto-word-0. See [[https://github.com/abo-abo/avy/issues/136][#136]], [[https://github.com/abo-abo/avy/issues/156][#156]].
|
||||
**** el:avy-pre-action
|
||||
Function to all before el:avy-action. See #260.
|
||||
Function to all before el:avy-action. See [[https://github.com/abo-abo/avy/issues/260][#260]].
|
||||
**** el:avy-enter-times-out
|
||||
When non-nil (the default), ~RET~ exists el:avy-goto-char-timer early.
|
||||
When nil, it matches a newline.
|
||||
See #220, #225.
|
||||
See [[https://github.com/abo-abo/avy/issues/220][#220]], [[https://github.com/abo-abo/avy/issues/225][#225]].
|
||||
|
||||
*** New commands
|
||||
**** el:avy-move-region
|
||||
Select two lines and move the text between them above the current line.
|
||||
See #75, #187, #188.
|
||||
See [[https://github.com/abo-abo/avy/issues/75][#75]], [[https://github.com/abo-abo/avy/issues/187][#187]], [[https://github.com/abo-abo/avy/issues/188][#188]].
|
||||
**** el:avy-goto-end-of-line
|
||||
Call el:avy-goto-line and move to the end of the line. See #240.
|
||||
Call el:avy-goto-line and move to the end of the line. See [[https://github.com/abo-abo/avy/issues/240][#240]].
|
||||
|
||||
**** el:avy-linum-mode
|
||||
Minor mode that uses avy hints for el:linum-mode.
|
||||
|
||||
**** el:avy-resume
|
||||
Holds last command avy command after user input. This is a quick way to bring back the
|
||||
same markers after a jump. See #157, #165.
|
||||
same markers after a jump. See [[https://github.com/abo-abo/avy/issues/157][#157]], [[https://github.com/abo-abo/avy/issues/165][#165]].
|
||||
**** el:avy-next
|
||||
Go to the next candidate after el:avy-read.
|
||||
Example config:
|
||||
@ -458,23 +458,23 @@ Example config:
|
||||
#+end_src
|
||||
|
||||
After e.g. el:avy-goto-char or el:avy-goto-char-timer, use the above hydra to cycle
|
||||
between the last candidates. See #254.
|
||||
between the last candidates. See [[https://github.com/abo-abo/avy/issues/254][#254]].
|
||||
**** *-above and *-below variants
|
||||
Command versions restricted to matches before or after the point.
|
||||
|
||||
See #148:
|
||||
See [[https://github.com/abo-abo/avy/issues/148][#148]]:
|
||||
- el:avy-goto-char-2-above
|
||||
- el:avy-goto-char-2-below
|
||||
|
||||
See #151:
|
||||
See [[https://github.com/abo-abo/avy/issues/151][#151]]:
|
||||
- el:avy-goto-word-1-above
|
||||
- el:avy-goto-word-1-below
|
||||
|
||||
See #156:
|
||||
See [[https://github.com/abo-abo/avy/issues/156][#156]]:
|
||||
- el:avy-goto-symbol-1-above
|
||||
- el:avy-goto-symbol-1-below
|
||||
|
||||
See #186:
|
||||
See [[https://github.com/abo-abo/avy/issues/186][#186]]:
|
||||
- el:avy-goto-word-0-below
|
||||
- el:avy-goto-word-0-above
|
||||
**** kill and save region functionality
|
||||
@ -484,15 +484,15 @@ New avy-enabled commands:
|
||||
- el:avy-kill-ring-save-whole-line
|
||||
- el:avy-kill-ring-save-region
|
||||
|
||||
See #158.
|
||||
See [[https://github.com/abo-abo/avy/issues/158][#158]].
|
||||
**** org-mode functionality
|
||||
New avy-enabled commands:
|
||||
- el:avy-org-refile-as-child
|
||||
- el:avy-org-goto-heading-timer
|
||||
See #214, #258.
|
||||
See [[https://github.com/abo-abo/avy/issues/214][#214]], [[https://github.com/abo-abo/avy/issues/258][#258]].
|
||||
*** el:avy-goto-char-timer
|
||||
Show the number of matches so far in the prompt. See #253.
|
||||
Show the number of matches so far in the prompt. See [[https://github.com/abo-abo/avy/issues/253][#253]].
|
||||
*** el:avy-read
|
||||
Ignore mistyping when no candidates are available. See #256.
|
||||
Ignore mistyping when no candidates are available. See [[https://github.com/abo-abo/avy/issues/256][#256]].
|
||||
|
||||
When the overlays are shown, press ~?~ to get dispatch help.
|
||||
|
Loading…
x
Reference in New Issue
Block a user