-
Notifications
You must be signed in to change notification settings - Fork 4
/
org-linker.el
119 lines (92 loc) · 4.01 KB
/
org-linker.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
;;; org-linker.el --- Link things in orgmode -*- lexical-binding: t; -*-
;; Copyright (C) 2020 tosh
;; Author: tosh <tosh.lyons@gmail.com>
;; Version: 0.1
;; Package-Requires: ((emacs "24.1") org helm-org-ql)
;; URL: https://github.com/toshism/org-linker
;; Keywords: convenience, hypermedia
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Link things in org
;;
;; I should describe how it actually works here.
;;; Code:
(defgroup org-linker nil
"Link things in Org mode"
:group 'outlines
:group 'convenience
:group 'org)
;; Silence byte compiler
(declare-function helm "ext:helm")
(declare-function helm-org-ql-source "ext:helm-org-ql")
(declare-function org-agenda-files "ext:org")
(declare-function org-back-to-heading "ext:org")
(defvar helm-input-idle-delay)
(defvar helm-org-ql-input-idle-delay)
(defvar org-linker-to-heading nil)
(defcustom org-linker-buffer-function #'org-agenda-files
"Function used to get a list of Org files or buffers.
Each item can be either a file name or a buffer, since `org-ql'
accepts any of both."
:type 'function)
(defun org-linker-buffer-mode (&optional buffer-or-name)
"Return the major mode associated with a buffer.
If BUFFER-OR-NAME is nil return current buffer's mode."
(buffer-local-value 'major-mode
(if buffer-or-name (get-buffer buffer-or-name) (current-buffer))))
(defun org-linker-get-search-buffers ()
"Return a list of buffers to provide to `helm-org-ql`.
This is defined by `org-linker-buffer-function', and it defaults
to `org-agenda-files'.
If the current buffer is in `org-mode', it is also prepended to
the list."
;; this needs to add the buffer you were on before opening a capture
;; template too (if it's an org mode file)
(append (when (and (derived-mode-p 'org-mode)
(buffer-file-name))
(list (current-buffer)))
(funcall org-linker-buffer-function)))
(defun org-linker-search-interface (callback)
"Setup the helm-org-ql search interface.
Call CALLBACK with a marker to target heading."
(require 'helm-org-ql)
(let* ((boolean 'and)
(helm-input-idle-delay helm-org-ql-input-idle-delay)
(source (helm-org-ql-source (org-linker-get-search-buffers)
:name "org-linker target")))
(setcdr (assoc 'action source) callback)
(helm :prompt (format "Query (boolean %s): " (upcase (symbol-name boolean)))
:sources source)))
(defun org-linker-callback-wrapper (callback m)
"Call user provided CALLBACK with source marker and target marker M.
Recieve the user provided callback and the target marker (M).
Call the user callback with target marker (M) and source marker."
(save-excursion
(when org-linker-to-heading
(org-back-to-heading))
(let ((source (point-marker))
(target m))
(funcall callback source target))))
;;;###autoload
(defun org-linker (callback)
"Call CALLBACK function with two markers.
CALLBACK should be a function that accepts two arguments SOURCE and
TARGET markers.
SOURCE: 'marker-position' is in the heading where org-linker was
called. If 'org-linker-to-heading' is non-nil, source
'marker-position' will be the first char in the heading. Otherwise it
will be the point were it was called.
TARGET: 'marker-postion' will be the first char in the target
heading."
(org-linker-search-interface (apply-partially 'org-linker-callback-wrapper callback)))
(provide 'org-linker)
;;; org-linker.el ends here