org-jump.el 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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.
  13. ;;
  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.
  18. ;;
  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/>.
  21. (defun org-jump-to-child ()
  22. "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."
  23. (interactive)
  24. (let* ((child-position
  25. (save-excursion
  26. ;; Go to the heading of the current node
  27. (org-back-to-heading)
  28. (let* ((ref-level (org-reduced-level (org-outline-level))))
  29. (outline-next-heading)
  30. ;; If the next visible heading is one level lower, then ...
  31. (if (= (- (org-reduced-level (org-outline-level)) ref-level) 1)
  32. (let* ((children nil)
  33. (continue t))
  34. (while continue
  35. (let* ((old-point (point)))
  36. ;; ... continue adding its headline text and the point to a list
  37. (add-to-list 'children
  38. (cons
  39. ;; remove any markup such as links (copied from org-clock-in)
  40. (replace-regexp-in-string
  41. "\\[\\[.*?\\]\\[\\(.*?\\)\\]\\]" "\\1"
  42. (substring-no-properties (nth 4 (org-heading-components))))
  43. old-point))
  44. ;; ... and go to the next sibling.
  45. (org-forward-heading-same-level 1 t)
  46. (setq continue (/= (point) old-point))))
  47. ;; Prompt for a child headline text, ...
  48. (let* ((child (org-icompleting-read "Headline text: " (mapcar 'car children))))
  49. ;; ... and return its location (point).
  50. (cdr (assoc child children))))
  51. ;; Otherwise return -1.
  52. -1)))))
  53. ;; Go to the desired heading and make it visible, or otherwise output an error message.
  54. (if (> child-position -1)
  55. (progn
  56. (goto-char child-position)
  57. (org-show-context))
  58. (message "No children."))))
  59. (define-key org-mode-map (kbd "\C-coc") 'org-jump-to-child)
  60. (defun org-jump-to-id ()
  61. "Interactively prompts for an identifier and searches for the first node in the current file that has this identifier as a CUSTOM_ID property."
  62. (interactive)
  63. (let* ((property "CUSTOM_ID")
  64. (custom-id (org-icompleting-read "CUSTOM_ID of entry: "
  65. (mapcar 'list (org-property-values property)))))
  66. ;; What will happen if there is more than one node with this CUSTOM_ID?
  67. ;; Alternative implementation:
  68. ;; (org-jump-to-first-node-with-property-value property custom-id)
  69. (org-link-search (concat "#" custom-id))))
  70. (define-key org-mode-map (kbd "\C-coj") 'org-jump-to-id)
  71. (defun org-jump-to-first-node-with-property-value (property value)
  72. (interactive)
  73. (goto-char
  74. (car
  75. (org-scan-tags 'point
  76. (cdr
  77. (org-make-tags-matcher (format "%s=\"%s\"" property value))))))
  78. (org-show-context))
  79. ;; further idea: org-find-text-property-in-string