diff --git a/modules/config/default/+evil-bindings.el b/modules/config/default/+evil-bindings.el index 6c2a6f2de..e278284d3 100644 --- a/modules/config/default/+evil-bindings.el +++ b/modules/config/default/+evil-bindings.el @@ -85,6 +85,10 @@ :n "q" #'kill-current-buffer) :m "gs" #'+evil/easymotion ; lazy-load `evil-easymotion' + (:after org + :map org-mode-map + :m "gsh" #'+org/goto-visible) + (:when (featurep! :editor multiple-cursors) :prefix "gz" :nv "d" #'evil-mc-make-and-goto-next-match diff --git a/modules/lang/org/autoload/org-avy.el b/modules/lang/org/autoload/org-avy.el new file mode 100644 index 000000000..0e10663e7 --- /dev/null +++ b/modules/lang/org/autoload/org-avy.el @@ -0,0 +1,19 @@ +;;; lang/org/autoload/org-avy.el -*- lexical-binding: t; -*- + +;;;###autoload +(defun +org-headline-avy () + "TODO" + (save-excursion + (when-let* ((org-reverse-note-order t) + (pos (avy-with avy-goto-line (avy-jump (rx bol (1+ "*") (1+ blank)))))) + (when (integerp (car pos)) + ;; If avy is aborted with "C-g", it returns `t', so we know it was NOT + ;; aborted when it returns an int. If it doesn't return an int, we + ;; return nil. + (copy-marker (car pos)))))) + +;;;###autoload +(defun +org/goto-visible () + "TODO" + (interactive) + (goto-char (+org-headline-avy))) diff --git a/modules/lang/org/autoload/org-refile.el b/modules/lang/org/autoload/org-refile.el index 5f2a50457..ba4aa4101 100644 --- a/modules/lang/org/autoload/org-refile.el +++ b/modules/lang/org/autoload/org-refile.el @@ -62,3 +62,22 @@ (lambda (_p _coll _pred _rm _ii _h default &rest _) default))) (org-refile))) + +(defvar org-after-refile-insert-hook) +;; Inspired by org-teleport and alphapapa/alpha-org +;;;###autoload +(defun +org/refile-to-visible () + "Refile current heading as first child of visible heading selected with Avy." + (interactive) + (when-let (marker (+org-headline-avy)) + (let* ((buffer (marker-buffer marker)) + (filename + (buffer-file-name (or (buffer-base-buffer buffer) + buffer))) + (heading + (org-with-point-at marker + (org-get-heading 'no-tags 'no-todo))) + ;; Won't work with target buffers whose filename is nil + (rfloc (list heading filename nil marker)) + (org-after-refile-insert-hook (cons #'org-reveal org-after-refile-insert-hook))) + (org-refile nil nil rfloc)))) diff --git a/modules/lang/org/config.el b/modules/lang/org/config.el index 7a8f2c106..307c0a2b6 100644 --- a/modules/lang/org/config.el +++ b/modules/lang/org/config.el @@ -675,6 +675,7 @@ between the two." "C" (λ! (org-clock-goto 'select)) "i" #'org-id-goto "r" #'org-refile-goto-last-stored + "v" #'+org/goto-visible "x" #'org-capture-goto-last-stored) (:prefix ("l" . "links") "c" 'org-cliplink @@ -690,6 +691,7 @@ between the two." "l" #'+org/refile-to-last-location "o" #'+org/refile-to-other-window "O" #'+org/refile-to-other-buffers + "v" #'+org/refile-to-visible "r" #'org-refile)) ; to all `org-refile-targets' (map! :after org-agenda diff --git a/modules/lang/org/packages.el b/modules/lang/org/packages.el index fa055fb49..43899dba1 100644 --- a/modules/lang/org/packages.el +++ b/modules/lang/org/packages.el @@ -24,6 +24,7 @@ (package! org-plus-contrib) ; install cutting-edge version of org-mode +(package! avy) (package! htmlize) (package! org-bullets :recipe (:host github :repo "Kaligule/org-bullets")) (package! org-fancy-priorities)