org-faq.org: Fix typos and style in "setup for indenting"
[worg.git] / code / elisp / org-jump.el
blob627a87acd3101c3cc0b797666007a17c573644b7
1 ;;; org-jump.el --- navigate over the structure of an org file
2 ;;
3 ;; Author: Christoph Lange <math.semantic.web@gmail.com>
4 ;;
5 ;; Copyright (C) 2016 by Christoph Lange
6 ;;
7 ;; This file is NOT part of GNU Emacs.
8 ;;
9 ;; This program is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
14 ;; This program is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
22 (defun org-jump-to-child ()
23 "Interactively prompts for the title of a child node of the current heading and jumps to the last child node having that title. This function will not work if the first child node is not exactly one level below the current heading."
24 (interactive)
25 (let* ((child-position
26 (save-excursion
27 ;; Go to the heading of the current node
28 (org-back-to-heading)
29 (let* ((ref-level (org-reduced-level (org-outline-level))))
30 (outline-next-heading)
31 ;; If the next visible heading is one level lower, then ...
32 (if (= (- (org-reduced-level (org-outline-level)) ref-level) 1)
33 (let* ((children nil)
34 (continue t))
35 (while continue
36 (let* ((old-point (point)))
37 ;; ... continue adding its headline text and the point to a list
38 (add-to-list 'children
39 (cons
40 ;; remove any markup such as links (copied from org-clock-in)
41 (replace-regexp-in-string
42 "\\[\\[.*?\\]\\[\\(.*?\\)\\]\\]" "\\1"
43 (substring-no-properties (nth 4 (org-heading-components))))
44 old-point))
45 ;; ... and go to the next sibling.
46 (org-forward-heading-same-level 1 t)
47 (setq continue (/= (point) old-point))))
48 ;; Prompt for a child headline text, ...
49 (let* ((child (org-icompleting-read "Headline text: " (mapcar 'car children))))
50 ;; ... and return its location (point).
51 (cdr (assoc child children))))
52 ;; Otherwise return -1.
53 -1)))))
54 ;; Go to the desired heading and make it visible, or otherwise output an error message.
55 (if (> child-position -1)
56 (progn
57 (goto-char child-position)
58 (org-show-context))
59 (message "No children."))))
61 (define-key org-mode-map (kbd "\C-coc") 'org-jump-to-child)
63 (defun org-jump-to-id ()
64 "Interactively prompts for an identifier and searches for the first node in the current file that has this identifier as a CUSTOM_ID property."
65 (interactive)
66 (let* ((property "CUSTOM_ID")
67 (custom-id (org-icompleting-read "CUSTOM_ID of entry: "
68 (mapcar 'list (org-property-values property)))))
69 ;; What will happen if there is more than one node with this CUSTOM_ID?
70 ;; Alternative implementation:
71 ;; (org-jump-to-first-node-with-property-value property custom-id)
72 (org-link-search (concat "#" custom-id))))
74 (define-key org-mode-map (kbd "\C-coj") 'org-jump-to-id)
76 (defun org-jump-to-first-node-with-property-value (property value)
77 (interactive)
78 (goto-char
79 (car
80 (org-scan-tags 'point
81 (cdr
82 (org-make-tags-matcher (format "%s=\"%s\"" property value))))))
83 (org-show-context))
85 ;; further idea: org-find-text-property-in-string