Last active
April 16, 2023 19:43
-
-
Save agenbite/4706a9e74040f0164eeb170ce5e0bced to your computer and use it in GitHub Desktop.
My configuration for avy after reading "avy can do anything"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; 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