diff options
author | Adam Porter <adam@alphapapa.net> | 2017-08-12 15:41:17 -0500 |
---|---|---|
committer | Adam Porter <adam@alphapapa.net> | 2017-08-12 15:47:07 -0500 |
commit | f4c45d329a31870fb3c927e50dd2561c33ac78a6 (patch) | |
tree | 00eb6f7c3e55c7128ffb38732499463426100fca | |
parent | 0ed6408f18bf13840f6f57638f86c3b9dfe4a07a (diff) |
avy.el: Add org-mode commands for jumping to and refiling headings
* (avy-org-refile-as-child): Refile current heading to a heading
selected with Avy.
* (avy-org-goto-heading-timer): Jump to a heading selected with Avy.
Like avy-goto-char-timer, but for Org headings.
* (avy--read-string-with-timeout): Read a string from the minibuffer
with a timeout. Basically factored out of avy-goto-char-timer.
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | avy.el | 50 |
2 files changed, 54 insertions, 0 deletions
@@ -80,6 +80,10 @@ After <kbd>M-g e</kbd>: ![avy-goto-word-0](http://oremacs.com/download/avi-goto-word-0.png) +### Org-mode commands + + * `avy-org-goto-heading-timer`: Type part of an Org heading. When you stop typing, if only one heading on the screen matches, it will be jumped to; if more than one matches, you can jump to a heading with Avy. This is like `avy-goto-char-timer` but for Org headings. + * `avy-org-refile-as-child`: With point in an entry you want to refile, run this command, select a heading with Avy, and the entry will be refiled as its first child heading. This makes it quick and easy to refile to headings that are visible on-screen, even to other windows or buffers. ### Other commands @@ -538,6 +538,56 @@ multiple DISPLAY-FN invokations." (funcall avy-handler-function char)))) (cdar alist)))) +;; ** Org-mode + +(defun avy-org-refile-as-child () + "Refile current heading as first child of heading selected with `avy.'" + ;; Inspired by `org-teleport': http://kitchingroup.cheme.cmu.edu/blog/2016/03/18/Org-teleport-headlines/ + (interactive) + (let ((rfloc (save-excursion + (let* ((org-reverse-note-order t) + (pos (avy-with avy-goto-line + (avy--generic-jump (rx bol (1+ "*") (1+ space)) + nil avy-style) + (point))) + (filename (buffer-file-name (or (buffer-base-buffer (current-buffer)) + (current-buffer))))) + (list nil filename nil pos))))) + ;; org-refile must be called outside of the excursion + (org-refile nil nil rfloc))) + +(defun avy-org-goto-heading-timer (&optional arg) + "Read one or many characters and jump to matching Org headings. +The window scope is determined by `avy-all-windows' (ARG negates it)." + (interactive "P") + (let* ((avy-all-windows (if arg + (not avy-all-windows) + avy-all-windows)) + (input (avy--read-string-with-timeout)) + (regexp (rx-to-string `(seq bol (1+ "*") (1+ space) (0+ not-newline) + ,input (0+ not-newline) eol)))) + (avy-with avy-goto-char-timer + (avy--process (avy--regex-candidates regexp) + (avy--style-fn avy-style))))) + +(defun avy--read-string-with-timeout () + "Read string from minibuffer with a timeout." + ;; It's a shame that only `read-char' has the timeout option, so we + ;; have to do this funky loop ourselves, instead of + ;; e.g. `read-string' with a timeout. + (cl-loop with charnum + with string = "" + while (not (equal 13 charnum)) + for charnum = (read-char (format "Prompt: %s" string ) + t + (unless (string-empty-p string) + avy-timeout-seconds)) + if (and charnum + (not (equal 13 charnum))) + concat (make-string 1 charnum) into string + else do (setq charnum 13) + finally return string)) + ;;** Rest (defun avy-window-list () "Return a list of windows depending on `avy-all-windows'." |