Skip to content

Instantly share code, notes, and snippets.

@agenbite
Last active April 16, 2023 19:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agenbite/4706a9e74040f0164eeb170ce5e0bced to your computer and use it in GitHub Desktop.
Save agenbite/4706a9e74040f0164eeb170ce5e0bced to your computer and use it in GitHub Desktop.
My configuration for avy after reading "avy can do anything"
;; Inspired by https://karthinks.com/software/avy-can-do-anything/ and
;; https://gist.github.com/Zetagon/1068474ef68ae0640f14dda240966ad1
;; The dispatcher:
(defun avy-show-dispatch-help ()
(let* ((len (length "avy-action-"))
(fw (frame-width))
(raw-strings (mapcar
(lambda (x)
(format "%2s: %-19s"
(propertize
(char-to-string (car x))
'face 'aw-key-face)
(substring (symbol-name (cdr x)) len)))
avy-dispatch-alist))
(max-len (1+ (apply #'max (mapcar #'length raw-strings))))
(strings-len (length raw-strings))
(per-row (floor fw max-len))
display-strings)
(cl-loop for string in raw-strings
for N from 1 to strings-len do
(push (concat string " ") display-strings)
(when (= (mod N per-row) 0) (push "\n" display-strings)))
(message "%s" (apply #'concat (nreverse display-strings)))))
;; Copy text (in the sense of replicating)
(defun inwit/avy--copy (pt)
"Copy (duplicate) sexp starting on PT."
(avy-action-yank pt))
(defun avy-action-copy-whole-line (pt)
(avy-action-yank-whole-line pt)
(save-excursion (yank))
t)
;; Yank text (in the sense of copying to clipboard)
(defun inwit/avy--yank (pt)
(avy-action-copy pt))
(defun avy-action-yank-whole-line (pt)
(save-excursion
(goto-char pt)
(cl-destructuring-bind (start . end)
(bounds-of-thing-at-point 'line)
(copy-region-as-kill start end)))
(select-window
(cdr
(ring-ref avy-ring 0)))
t)
;; Teleport (replicate and delete original)
(defun avy-action-teleport-whole-line (pt)
(avy-action-kill-whole-line pt)
(save-excursion (yank)) t)
;; Deleting text
(defun inwit/avy--delete (pt)
(avy-action-kill-stay pt))
(defun avy-action-delete-whole-line (pt)
(save-excursion
(goto-char pt)
(kill-whole-line))
(select-window
(cdr
(ring-ref avy-ring 0)))
t)
;; Avy+Embark
(defun avy-action-embark (pt)
(unwind-protect
(save-excursion
(goto-char pt)
(embark-act))
(select-window
(cdr (ring-ref avy-ring 0))))
t)
(defun avy-action-mark-to-char (pt)
(activate-mark)
(goto-char pt))
;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;;
;; Avy + Evil
(defvar inwit/evil-extract-count-keys nil)
(defun inwit/evil-extract-count (orig-fn keys)
"When an evil operation is called from avy, `evil-extract-count'
will get the last key given to avy as input. In order to behave
normally we wrap the function so that we can give the input
manually using a let-binding."
(funcall orig-fn
(or inwit/evil-extract-count-keys keys)))
(advice-add #'evil-extract-count
:around #'inwit/evil-extract-count)
(defun inwit/avy--evil-delete (pt)
(interactive)
(save-excursion
(goto-char pt)
(let ((inwit/evil-extract-count-keys "d"))
(call-interactively #'evil-delete)))
(select-window
(cdr
(ring-ref avy-ring 0)))
t)
(defun inwit/avy--evil-yank (pt)
(interactive)
(save-excursion
(goto-char pt)
(let ((inwit/evil-extract-count-keys "y"))
(call-interactively #'evil-yank)))
(select-window
(cdr
(ring-ref avy-ring 0)))
t)
(defvar inwit/avy-evil-change-marker nil
"The place where the user called avy from.")
(defun inwit/avy--evil-change (pt)
(interactive)
(setq inwit/avy-evil-change-marker (point-marker))
(goto-char pt)
(add-hook 'evil-insert-state-exit-hook #'inwit/avy-evil-change-h)
(call-interactively #'evil-change)
t)
(defun inwit/avy-evil-change-h ()
(remove-hook 'evil-insert-state-exit-hook #'inwit/avy-evil-change-h)
(select-window
(cdr
(ring-ref avy-ring 0)))
(goto-char (marker-position inwit/avy-evil-change-marker)))
;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;;
;; Keybindings
(setq avy-keys '(?a ?s ;?d
?f ?g ?h ?j ?k ?l))
(setf
(alist-get ? avy-dispatch-alist) #'avy-action-mark-to-char
(alist-get ?. avy-dispatch-alist) #'avy-action-embark
(alist-get ?T avy-dispatch-alist) #'avy-action-teleport-whole-line
(alist-get ?t avy-dispatch-alist) #'avy-action-teleport
(alist-get ?c avy-dispatch-alist) #'inwit/avy--evil-change
(alist-get ?X avy-dispatch-alist) #'avy-action-copy-whole-line
(alist-get ?x avy-dispatch-alist) #'inwit/avy--copy
; (alist-get ?x avy-dispatch-alist) #'inwit/avy--evil-copy
(alist-get ?D avy-dispatch-alist) #'avy-action-delete-whole-line
(alist-get ?i avy-dispatch-alist) #'inwit/avy--delete
(alist-get ?d avy-dispatch-alist) #'inwit/avy--evil-delete
(alist-get ?Y avy-dispatch-alist) #'avy-action-yank-whole-line
(alist-get ?u avy-dispatch-alist) #'inwit/avy--yank
(alist-get ?y avy-dispatch-alist) #'inwit/avy--evil-yank
)
;; Make avy work only on current window by default (C-u for all windows)
(setq avy-all-windows nil)
(setq avy-all-windows-alt t)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment