Commit | Line | Data |
---|---|---|
3ab2c837 BG |
1 | ;;; org-pcomplete.el --- In-buffer completion code |
2 | ||
09ade3a3 | 3 | ;; Copyright (C) 2004-2011 Free Software Foundation, Inc. |
3ab2c837 BG |
4 | ;; |
5 | ;; Author: Carsten Dominik <carsten at orgmode dot org> | |
6 | ;; John Wiegley <johnw at gnu dot org> | |
7 | ;; Keywords: outlines, hypermedia, calendar, wp | |
8 | ;; Homepage: http://orgmode.org | |
9 | ;; Version: 7.7 | |
10 | ;; | |
11 | ;; This file is part of GNU Emacs. | |
12 | ;; | |
13 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
14 | ;; it under the terms of the GNU General Public License as published by | |
15 | ;; the Free Software Foundation, either version 3 of the License, or | |
16 | ;; (at your option) any later version. | |
17 | ||
18 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
19 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 | ;; GNU General Public License for more details. | |
22 | ||
23 | ;; You should have received a copy of the GNU General Public License | |
24 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
25 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
26 | ;; | |
27 | ;;; Code: | |
28 | ||
29 | ;;;; Require other packages | |
30 | ||
31 | (eval-when-compile | |
32 | (require 'cl)) | |
33 | ||
34 | (require 'org-macs) | |
35 | (require 'pcomplete) | |
36 | ||
37 | (declare-function org-split-string "org" (string &optional separators)) | |
38 | (declare-function org-get-current-options "org-exp" ()) | |
39 | (declare-function org-make-org-heading-search-string "org" | |
40 | (&optional string heading)) | |
41 | (declare-function org-get-buffer-tags "org" ()) | |
42 | (declare-function org-get-tags "org" ()) | |
43 | (declare-function org-buffer-property-keys "org" | |
44 | (&optional include-specials include-defaults include-columns)) | |
45 | (declare-function org-entry-properties "org" (&optional pom which specific)) | |
46 | ||
47 | ;;;; Customization variables | |
48 | ||
49 | (defgroup org-complete nil | |
50 | "Outline-based notes management and organizer." | |
51 | :tag "Org" | |
52 | :group 'org) | |
53 | ||
54 | (defun org-thing-at-point () | |
55 | "Examine the thing at point and let the caller know what it is. | |
56 | The return value is a string naming the thing at point." | |
57 | (let ((beg1 (save-excursion | |
58 | (skip-chars-backward (org-re "[:alnum:]_@")) | |
59 | (point))) | |
60 | (beg (save-excursion | |
61 | (skip-chars-backward "a-zA-Z0-9_:$") | |
62 | (point))) | |
63 | (line-to-here (buffer-substring (point-at-bol) (point)))) | |
64 | (cond | |
65 | ((string-match "\\`[ \t]*#\\+begin: clocktable[ \t]+" line-to-here) | |
66 | (cons "block-option" "clocktable")) | |
67 | ((string-match "\\`[ \t]*#\\+begin_src[ \t]+" line-to-here) | |
68 | (cons "block-option" "src")) | |
69 | ((save-excursion | |
70 | (re-search-backward "^[ \t]*#\\+\\([A-Z_]+\\):.*" | |
71 | (line-beginning-position) t)) | |
72 | (cons "file-option" (match-string-no-properties 1))) | |
73 | ((string-match "\\`[ \t]*#\\+[a-zA-Z]*\\'" line-to-here) | |
74 | (cons "file-option" nil)) | |
75 | ((equal (char-before beg) ?\[) | |
76 | (cons "link" nil)) | |
77 | ((equal (char-before beg) ?\\) | |
78 | (cons "tex" nil)) | |
79 | ((string-match "\\`\\*+[ \t]+\\'" | |
80 | (buffer-substring (point-at-bol) beg)) | |
81 | (cons "todo" nil)) | |
82 | ((equal (char-before beg) ?*) | |
83 | (cons "searchhead" nil)) | |
84 | ((and (equal (char-before beg1) ?:) | |
85 | (equal (char-after (point-at-bol)) ?*)) | |
86 | (cons "tag" nil)) | |
87 | ((and (equal (char-before beg1) ?:) | |
88 | (not (equal (char-after (point-at-bol)) ?*))) | |
89 | (cons "prop" nil)) | |
90 | (t nil)))) | |
91 | ||
92 | (defun org-command-at-point () | |
93 | "Return the qualified name of the Org completion entity at point. | |
94 | When completing for #+STARTUP, for example, this function returns | |
95 | \"file-option/startup\"." | |
96 | (let ((thing (org-thing-at-point))) | |
97 | (cond | |
98 | ((string= "file-option" (car thing)) | |
99 | (concat (car thing) "/" (downcase (cdr thing)))) | |
100 | ((string= "block-option" (car thing)) | |
101 | (concat (car thing) "/" (downcase (cdr thing)))) | |
102 | (t | |
103 | (car thing))))) | |
104 | ||
105 | (defun org-parse-arguments () | |
106 | "Parse whitespace separated arguments in the current region." | |
107 | (let ((begin (line-beginning-position)) | |
108 | (end (line-end-position)) | |
109 | begins args) | |
110 | (save-restriction | |
111 | (narrow-to-region begin end) | |
112 | (save-excursion | |
113 | (goto-char (point-min)) | |
114 | (while (not (eobp)) | |
115 | (skip-chars-forward " \t\n[") | |
116 | (setq begins (cons (point) begins)) | |
117 | (skip-chars-forward "^ \t\n[") | |
118 | (setq args (cons (buffer-substring-no-properties | |
119 | (car begins) (point)) | |
120 | args))) | |
121 | (cons (reverse args) (reverse begins)))))) | |
122 | ||
123 | ||
124 | (defun org-pcomplete-initial () | |
125 | "Calls the right completion function for first argument completions." | |
126 | (ignore | |
127 | (funcall (or (pcomplete-find-completion-function | |
128 | (car (org-thing-at-point))) | |
129 | pcomplete-default-completion-function)))) | |
130 | ||
131 | (defvar org-additional-option-like-keywords) | |
132 | (defun pcomplete/org-mode/file-option () | |
133 | "Complete against all valid file options." | |
134 | (require 'org-exp) | |
135 | (pcomplete-here | |
136 | (org-pcomplete-case-double | |
137 | (mapcar (lambda (x) | |
138 | (if (= ?: (aref x (1- (length x)))) | |
139 | (concat x " ") | |
140 | x)) | |
141 | (delq nil | |
142 | (pcomplete-uniqify-list | |
143 | (append | |
144 | (mapcar (lambda (x) | |
145 | (if (string-match "^#\\+\\([A-Z_]+:?\\)" x) | |
146 | (match-string 1 x))) | |
147 | (org-split-string (org-get-current-options) "\n")) | |
148 | org-additional-option-like-keywords))))) | |
149 | (substring pcomplete-stub 2))) | |
150 | ||
151 | (defvar org-startup-options) | |
152 | (defun pcomplete/org-mode/file-option/startup () | |
153 | "Complete arguments for the #+STARTUP file option." | |
154 | (while (pcomplete-here | |
155 | (let ((opts (pcomplete-uniqify-list | |
156 | (mapcar 'car org-startup-options)))) | |
157 | ;; Some options are mutually exclusive, and shouldn't be completed | |
158 | ;; against if certain other options have already been seen. | |
159 | (dolist (arg pcomplete-args) | |
160 | (cond | |
161 | ((string= arg "hidestars") | |
162 | (setq opts (delete "showstars" opts))))) | |
163 | opts)))) | |
164 | ||
165 | (defun pcomplete/org-mode/file-option/bind () | |
166 | "Complete arguments for the #+BIND file option, which are variable names" | |
167 | (let (vars) | |
168 | (mapatoms | |
169 | (lambda (a) (if (boundp a) (setq vars (cons (symbol-name a) vars))))) | |
170 | (pcomplete-here vars))) | |
171 | ||
172 | (defvar org-link-abbrev-alist-local) | |
173 | (defvar org-link-abbrev-alist) | |
174 | (defun pcomplete/org-mode/link () | |
175 | "Complete against defined #+LINK patterns." | |
176 | (pcomplete-here | |
177 | (pcomplete-uniqify-list | |
178 | (copy-sequence | |
179 | (append (mapcar 'car org-link-abbrev-alist-local) | |
180 | (mapcar 'car org-link-abbrev-alist)))))) | |
181 | ||
182 | (defvar org-entities) | |
183 | (defun pcomplete/org-mode/tex () | |
184 | "Complete against TeX-style HTML entity names." | |
185 | (require 'org-entities) | |
186 | (while (pcomplete-here | |
187 | (pcomplete-uniqify-list (remove nil (mapcar 'car-safe org-entities))) | |
188 | (substring pcomplete-stub 1)))) | |
189 | ||
190 | (defvar org-todo-keywords-1) | |
191 | (defun pcomplete/org-mode/todo () | |
192 | "Complete against known TODO keywords." | |
193 | (pcomplete-here (pcomplete-uniqify-list (copy-sequence org-todo-keywords-1)))) | |
194 | ||
195 | (defvar org-todo-line-regexp) | |
196 | (defun pcomplete/org-mode/searchhead () | |
197 | "Complete against all headings. | |
198 | This needs more work, to handle headings with lots of spaces in them." | |
199 | (while | |
200 | (pcomplete-here | |
201 | (save-excursion | |
202 | (goto-char (point-min)) | |
203 | (let (tbl) | |
204 | (while (re-search-forward org-todo-line-regexp nil t) | |
205 | (push (org-make-org-heading-search-string | |
206 | (match-string-no-properties 3) t) | |
207 | tbl)) | |
208 | (pcomplete-uniqify-list tbl))) | |
209 | (substring pcomplete-stub 1)))) | |
210 | ||
211 | (defvar org-tag-alist) | |
212 | (defun pcomplete/org-mode/tag () | |
213 | "Complete a tag name. Omit tags already set." | |
214 | (while (pcomplete-here | |
215 | (mapcar (lambda (x) | |
216 | (concat x ":")) | |
217 | (let ((lst (pcomplete-uniqify-list | |
218 | (or (remove | |
219 | nil | |
220 | (mapcar (lambda (x) | |
221 | (and (stringp (car x)) (car x))) | |
222 | org-tag-alist)) | |
223 | (mapcar 'car (org-get-buffer-tags)))))) | |
224 | (dolist (tag (org-get-tags)) | |
225 | (setq lst (delete tag lst))) | |
226 | lst)) | |
227 | (and (string-match ".*:" pcomplete-stub) | |
228 | (substring pcomplete-stub (match-end 0)))))) | |
229 | ||
230 | (defun pcomplete/org-mode/prop () | |
231 | "Complete a property name. Omit properties already set." | |
232 | (pcomplete-here | |
233 | (mapcar (lambda (x) | |
234 | (concat x ": ")) | |
235 | (let ((lst (pcomplete-uniqify-list | |
236 | (copy-sequence | |
237 | (org-buffer-property-keys nil t t))))) | |
238 | (dolist (prop (org-entry-properties)) | |
239 | (setq lst (delete (car prop) lst))) | |
240 | lst)) | |
241 | (substring pcomplete-stub 1))) | |
242 | ||
243 | (defun pcomplete/org-mode/block-option/src () | |
244 | "Complete the arguments of a begin_src block. | |
245 | Complete a language in the first field, the header arguments and switches." | |
246 | (pcomplete-here | |
247 | (mapcar | |
248 | (lambda(x) (symbol-name (nth 3 x))) | |
249 | (cdr (car (cdr (memq :key-type (plist-get | |
250 | (symbol-plist | |
251 | 'org-babel-load-languages) | |
252 | 'custom-type))))))) | |
253 | (while (pcomplete-here | |
254 | '("-n" "-r" "-l" | |
255 | ":cache" ":colnames" ":comments" ":dir" ":eval" ":exports" | |
256 | ":file" ":hlines" ":no-expand" ":noweb" ":results" ":rownames" | |
257 | ":session" ":shebang" ":tangle" ":var")))) | |
258 | ||
259 | (defun pcomplete/org-mode/block-option/clocktable () | |
260 | "Complete keywords in a clocktable line" | |
261 | (while (pcomplete-here '(":maxlevel" ":scope" | |
262 | ":tstart" ":tend" ":block" ":step" | |
263 | ":stepskip0" ":fileskip0" | |
264 | ":emphasize" ":link" ":narrow" ":indent" | |
265 | ":tcolumns" ":level" ":compact" ":timestamp" | |
266 | ":formula" ":formatter")))) | |
267 | ||
268 | (defun org-pcomplete-case-double (list) | |
269 | "Return list with both upcase and downcase version of all strings in LIST." | |
270 | (let (e res) | |
271 | (while (setq e (pop list)) | |
272 | (setq res (cons (downcase e) (cons (upcase e) res)))) | |
273 | (nreverse res))) | |
274 | ||
275 | ;;;; Finish up | |
276 | ||
277 | (provide 'org-pcomplete) | |
278 | ||
5b409b39 | 279 | |
3ab2c837 BG |
280 | |
281 | ;;; org-pcomplete.el ends here |