Mercurial > emacs
annotate lisp/org/org-id.el @ 99501:e3acb52d33e1
2008-11-12 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-yank): Make any prefix force normal yanking.
Suppress folding if text would be swallowed into a folded
subtree.
(org-yank-folded-subtrees, org-yank): Docstring updates.
* org-agenda.el (org-agenda-compare-effort): Treat no effort
defined as 0.
* org-exp.el (org-export-language-setup): Add Catalan and
Esperanto language entries.
2008-11-12 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-refile): Allow refiling of entire regions.
* org-clock.el (org-clock-time%): New function.
* org.el (org-entry-get, org-entry-delete): Use safer regexps to
retrieve property values.
2008-11-12 Carsten Dominik <carsten.dominik@gmail.com>
* org-agenda.el (org-agenda-list): Handle the value `only' of
org-agenda-show-log'.
(org-agenda-log-mode): Interpret a double prefix arg.
2008-11-12 Carsten Dominik <carsten.dominik@gmail.com>
* org-exp.el (org-export-html-footnotes-section): New variable.
(org-export-as-html): Use `org-export-html-footnotes-section' to
insert the footnotes.
(org-export-language-setup): Add "Footnotes" to language words.
2008-11-12 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-yank): Fix bug when not inserting a subtree.
2008-11-12 Carsten Dominik <carsten.dominik@gmail.com>
* org-vm.el (org-vm-follow-link): Call `vm-preview-current-message'
instead of `vm-beginning-of-message'.
* org.el (org-make-link-regexps): Make sure that links to gnus can
contain brackets.
2008-11-12 Carsten Dominik <carsten.dominik@gmail.com>
* org-attach.el (org-attach-dir): Remove duplicate ID creation
code.
* org-id.el (org-id-new): Use `org-trim' to extract the uuid from
shell output.
* org.el (org-link-abbrev-alist): Improve customization type.
* org-attach.el (org-attach-expand-link, org-attach-expand): New
functions.
* org-agenda.el (org-agenda-get-progress): Renamed from
`org-get-closed'. Implement searching for state changes as well.
(org-agenda-log-mode-items): New option.
(org-agenda-log-mode): New option prefix argument, interpreted as
request to show all possible progress info.
(org-agenda-get-day-entries): Call `org-get-progress' instead of
`org-get-closed'.
(org-agenda-set-mode-name): Handle the more complex log mode
settings.
(org-get-closed): New alias, pointing to `org-get-progress'.
2008-11-12 Carsten Dominik <dominik@science.uva.nl>
* org.el (org-file-apps-defaults-gnu)
(org-file-apps-defaults-macosx)
(org-file-apps-defaults-windowsnt): Add an entry defining the
system command.
(org-file-apps): Allow `system' as key and value.
(org-open-at-point): Explain the effect of a double prefix arg.
(org-open-file): If the argument `in-emacs' is (16),
i.e. corresponding to a double prefix argument, try to open the
file externally.
2008-11-12 Carsten Dominik <dominik@science.uva.nl>
* org.el (org-insert-link): Abbreviate absolute files names in
links. Also, fix a bug in which the double C-u prefix would not
be honored.
2008-11-12 Carsten Dominik <dominik@science.uva.nl>
* org.el (org-insert-heading): If buffer does not end with a
newline, add one if necessary to insert headline correctly.
* org-exp.el (org-export-as-html): Make sure that <hr/> is between
paragraphs, not inside.
* org.el (org-todo): Quote
`org-agenda-headline-snapshot-before-repeat'.
* org-exp.el (org-export-as-html): Fully process link descriptions.
(org-export-html-format-desc): New function.
(org-export-as-html): Collect footnotes into the correct basket.
(org-html-protect): No longer protect quotations marks here, this
goes wrong.
* org-agenda.el (org-agenda-remove-marked-text): Bind variable
BEG.
* org-compat.el (org-fit-window-to-buffer): New function (not
really, a preliminary and incomplete version was present earlier,
but not used).
* org.el (org-fast-todo-selection, org-fast-tag-selection): Use
`org-fit-window-to-buffer'.
* org-exp.el (org-export): Use `org-fit-window-to-buffer'.
* org-agenda.el (org-agenda-get-restriction-and-command)
(org-fit-agenda-window, org-agenda-convert-date): Use
`org-fit-window-to-buffer'.
* org-exp.el (org-export-as-html): Process href links through
`org-export-html-format-href'.
(org-export-html-format-href): New function.
* org-agenda.el (org-agenda-todo): Update only the current
headline if this is a repeated TODO, marked done for today.
(org-agenda-change-all-lines): New argument JUST-THIS, to change
only the current line.
* org.el (org-todo): Take a snapshot of the headline if the
repeater might change it.
2008-11-12 Carsten Dominik <dominik@science.uva.nl>
* org-publish.el (org-publish-find-title): Remove buffers visited
only for extracting the title.
* org-exp.el (org-export-html-style)
(org-export-html-style-default): Mark style definitions as
unparsed CDATA.
* org-publish.el (org-publish-validate-link): Function
re-introduced.
2008-11-12 Charles Sebold <csebold@gmail.com>
* org-plot.el (org-plot/add-options-to-plist): Supports timefmt
property.
(org-plot-quote-timestamp-field): New function.
(org-plot-quote-tsv-field): Call timestamp field function when
necessary rather than just quoting as a string.
(org-plot/gnuplot-to-data): Pass in timefmt property.
(org-plot/gnuplot-script): Supports timefmt property.
(org-plot/gnuplot): Checks for timestamp column before checking
for text index column.
2008-11-12 Carsten Dominik <dominik@science.uva.nl>
* org.el (org-insert-heading): Improve behavior with hidden subtrees.
* org-publish.el (org-publish-org-index): Create a section in the
index file.
(org-publish-org-index): Stop linking to directories.
* org.el (org-emphasis-alist): Use span instead of <u> to
underline text.
* org-exp.el (org-export-as-html): Make sure <p> is closed before
<pre> sections.
2008-11-12 Sebastian Rose <sebastian_rose@gmx.de>
* org-jsinfo.el (org-infojs-template): Remove language attribute
from script tag.
2008-11-12 Carsten Dominik <dominik@science.uva.nl>
* org-agenda.el (org-agenda-remove-marked-text): New function.
(org-agenda-mark-filtered-text)
(org-agenda-unmark-filtered-text): New functions.
(org-write-agenda): Remove fltered text.
* org.el (org-make-tags-matcher): Give access to TODO "property"
without speed penalty.
2008-11-12 Carsten Dominik <dominik@science.uva.nl>
* org.el (org-link-frame-setup): Add `org-gnus-no-new-news' as an
option.
(org-store-link-props): Make sure adding to the plist works
correctly.
* org-gnus.el (org-gnus-no-new-news): New function.
(org-gnus-follow-link): Allow the article ID to be a message-id,
in addition to allowing article numbers. Message IDs make much
more roubust links.
(org-gnus-store-link): Use message-id to create link.
2008-11-12 Carsten Dominik <dominik@science.uva.nl>
* org.el (org-emphasize): Reverse the selection array.
(org-emphasis-alist): Set <code> tags for the verbatim
environment.
* org-remember.el (org-remember-handler): Fix bug with
prefix-related changing of the note storage target.
* org-exp.el (org-print-icalendar-entries): Make the exported
priorities compatible with RFC 2445.
* org-clock.el (org-clock-save): Insert time stamp without
dependence on time-stamp.el.
2008-11-12 Carsten Dominik <dominik@science.uva.nl>
* org.el ("saveplace"): If saveplace puts point into an invisible
location, make it visible.
(org-make-tags-matcher): Allow inactive time stamps in time
comparisons.
(org-yank-adjusted-subtrees): New option.
(org-yank): Incorporate adjusting trees.
(org-paste-subtree): New argument FOR-YANK which will cause
insertion at point without backing up over white lines, and leave
point at the end of the inserted text. Also if the cursor is
at the beginning of a headline, use the same level or the inserted
tree.
* org-publish.el (org-publish-get-base-files-1): Deal correctly
with broken symlinks
2008-11-12 Carsten Dominik <dominik@science.uva.nl>
* org-exp.el (org-export-select-tags, org-get-current-options):
Fix typo.
author | Carsten Dominik <dominik@science.uva.nl> |
---|---|
date | Wed, 12 Nov 2008 08:01:06 +0000 |
parents | 8fa7ef477c04 |
children | 621e15919df0 |
rev | line source |
---|---|
96045 | 1 ;;; org-id.el --- Global identifier for Org-mode entries |
2 ;; Copyright (C) 2008 Free Software Foundation, Inc. | |
3 ;; | |
4 ;; Author: Carsten Dominik <carsten at orgmode dot org> | |
5 ;; Keywords: outlines, hypermedia, calendar, wp | |
6 ;; Homepage: http://orgmode.org | |
99501
e3acb52d33e1
2008-11-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
99139
diff
changeset
|
7 ;; Version: 6.12a |
96045 | 8 ;; |
9 ;; This file is part of GNU Emacs. | |
10 ;; | |
11 ;; GNU Emacs is free software: you can redistribute it and/or modify | |
12 ;; it under the terms of the GNU General Public License as published by | |
13 ;; the Free Software Foundation, either version 3 of the License, or | |
14 ;; (at your option) any later version. | |
15 | |
16 ;; GNU Emacs is distributed in the hope that it will be useful, | |
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 ;; GNU General Public License for more details. | |
20 | |
21 ;; You should have received a copy of the GNU General Public License | |
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
23 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
24 ;; | |
25 ;;; Commentary: | |
26 | |
27 ;; This file implements globally unique identifiers for Org-mode entries. | |
28 ;; Identifiers are stored in the entry as an :ID: property. Functions | |
29 ;; are provided that create and retrieve such identifiers, and that find | |
30 ;; entries based on the identifier. | |
31 | |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
32 ;; Identifiers consist of a prefix (default "Org" given by the variable |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
33 ;; `org-id-prefix') and a unique part that can be created by a number |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
34 ;; of different methods, see the variable `org-id-method'. |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
35 ;; Org has a builtin method that uses a compact encoding of the creation |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
36 ;; time of the ID, with microsecond accuracy. This virtually |
96045 | 37 ;; guarantees globally unique identifiers, even if several people are |
38 ;; creating ID's at the same time in files that will eventually be used | |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
39 ;; together. As an exernal method `uuidgen' is supported, if installed |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
40 ;; on the system. |
96045 | 41 ;; |
42 ;; This file defines the following API: | |
43 ;; | |
44 ;; org-id-get-create | |
45 ;; Create an ID for the entry at point if it does not yet have one. | |
46 ;; Returns the ID (old or new). This function can be used | |
47 ;; interactively, with prefix argument the creation of a new ID is | |
48 ;; forced, even if there was an old one. | |
49 ;; | |
50 ;; org-id-get | |
51 ;; Get the ID property of an entry. Using appropriate arguments | |
52 ;; to the function, it can also create the ID for this entry. | |
53 ;; | |
54 ;; org-id-goto | |
55 ;; Command to go to a specific ID, this command can be used | |
56 ;; interactively. | |
57 ;; | |
58 ;; org-id-get-with-outline-path-completion | |
59 ;; Retrieve the ID of an entry, using outline path completion. | |
60 ;; This function can work for multiple files. | |
61 ;; | |
62 ;; org-id-get-with-outline-drilling | |
63 ;; Retrieve the ID of an entry, using outline path completion. | |
64 ;; This function only works for the current file. | |
65 ;; | |
66 ;; org-id-find | |
67 ;; Find the location of an entry with specific id. | |
68 ;; | |
69 | |
70 (require 'org) | |
71 | |
72 (declare-function message-make-fqdn "message" ()) | |
73 | |
74 ;;; Customization | |
75 | |
76 (defgroup org-id nil | |
77 "Options concerning global entry identifiers in Org-mode." | |
78 :tag "Org ID" | |
79 :group 'org) | |
80 | |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
81 (defcustom org-id-method 'org |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
82 "The method that should be used to create new ID's. |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
83 |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
84 An ID will consist of the prefix specified in `org-id-prefix', and a unique |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
85 part created by the method this variable specifies. |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
86 |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
87 Allowed values are: |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
88 |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
89 org Org's own internal method, using an encoding of the current time, |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
90 and the current domain of the computer. This method will |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
91 honor the variable `org-id-include-domain'. |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
92 |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
93 uuidgen Call the external command uuidgen." |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
94 :group 'org-id |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
95 :type '(choice |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
96 (const :tag "Org's internal method" org) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
97 (const :tag "external: uuidgen" uuidgen))) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
98 |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
99 (defcustom org-id-prefix nil |
96045 | 100 "The prefix for IDs. |
101 | |
102 This may be a string, or it can be nil to indicate that no prefix is required. | |
103 When a string, the string should have no space characters as IDs are expected | |
104 to have no space characters in them." | |
105 :group 'org-id | |
106 :type '(choice | |
107 (const :tag "No prefix") | |
108 (string :tag "Prefix"))) | |
109 | |
110 (defcustom org-id-include-domain t | |
111 "Non-nil means, add the domain name to new IDs. | |
112 This ensures global uniqueness of ID's, and is also suggested by | |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
113 RFC 2445 in combination with RFC 822. This is only relevant if |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
114 `org-id-method' is `org'. When uuidgen is used, the domain will never |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
115 be added." |
96045 | 116 :group 'org-id |
117 :type 'boolean) | |
118 | |
99139
8fa7ef477c04
2008-10-26 Carsten Dominik <dominik@science.uva.nl>
Carsten Dominik <dominik@science.uva.nl>
parents:
98871
diff
changeset
|
119 (defcustom org-id-locations-file (convert-standard-filename |
8fa7ef477c04
2008-10-26 Carsten Dominik <dominik@science.uva.nl>
Carsten Dominik <dominik@science.uva.nl>
parents:
98871
diff
changeset
|
120 "~/.org-id-locations") |
96045 | 121 "The file for remembering the last ID number generated." |
122 :group 'org-id | |
123 :type 'file) | |
124 | |
125 (defvar org-id-locations nil | |
126 "List of files with ID's in those files.") | |
127 | |
128 (defcustom org-id-extra-files 'org-agenda-text-search-extra-files | |
129 "Files to be searched for ID's, besides the agenda files." | |
130 :group 'org-id | |
131 :type | |
132 '(choice | |
133 (symbol :tag "Variable") | |
134 (repeat :tag "List of files" | |
135 (file)))) | |
136 | |
137 ;;; The API functions | |
138 | |
139 ;;;###autoload | |
140 (defun org-id-get-create (&optional force) | |
141 "Create an ID for the current entry and return it. | |
142 If the entry already has an ID, just return it. | |
143 With optional argument FORCE, force the creation of a new ID." | |
144 (interactive "P") | |
145 (when force | |
146 (org-entry-put (point) "ID" nil)) | |
147 (org-id-get (point) 'create)) | |
148 | |
149 ;;;###autoload | |
150 (defun org-id-copy () | |
151 "Copy the ID of the entry at point to the kill ring. | |
152 Create an ID if necessary." | |
153 (interactive) | |
154 (kill-new (org-id-get nil 'create))) | |
155 | |
156 ;;;###autoload | |
157 (defun org-id-get (&optional pom create prefix) | |
158 "Get the ID property of the entry at point-or-marker POM. | |
159 If POM is nil, refer to the entry at point. | |
160 If the entry does not have an ID, the function returns nil. | |
161 However, when CREATE is non nil, create an ID if none is present already. | |
162 PREFIX will be passed through to `org-id-new'. | |
163 In any case, the ID of the entry is returned." | |
164 (let ((id (org-entry-get pom "ID"))) | |
165 (cond | |
166 ((and id (stringp id) (string-match "\\S-" id)) | |
167 id) | |
168 (create | |
169 (setq id (org-id-new prefix)) | |
170 (org-entry-put pom "ID" id) | |
171 (org-id-add-location id (buffer-file-name (buffer-base-buffer))) | |
172 id) | |
173 (t nil)))) | |
174 | |
175 ;;;###autoload | |
176 (defun org-id-get-with-outline-path-completion (&optional targets) | |
177 "Use outline-path-completion to retrieve the ID of an entry. | |
178 TARGETS may be a setting for `org-refile-targets' to define the eligible | |
179 headlines. When omitted, all headlines in all agenda files are | |
180 eligible. | |
181 It returns the ID of the entry. If necessary, the ID is created." | |
182 (let* ((org-refile-targets (or targets '((nil . (:maxlevel . 10))))) | |
183 (org-refile-use-outline-path | |
184 (if (caar org-refile-targets) 'file t)) | |
185 (spos (org-refile-get-location "Entry: ")) | |
186 (pom (and spos (move-marker (make-marker) (nth 3 spos) | |
187 (get-file-buffer (nth 1 spos)))))) | |
188 (prog1 (org-id-get pom 'create) | |
189 (move-marker pom nil)))) | |
190 | |
191 ;;;###autoload | |
192 (defun org-id-get-with-outline-drilling (&optional targets) | |
193 "Use an outline-cycling interface to retrieve the ID of an entry. | |
194 This only finds entries in the current buffer, using `org-get-location'. | |
195 It returns the ID of the entry. If necessary, the ID is created." | |
196 (let* ((spos (org-get-location (current-buffer) org-goto-help)) | |
197 (pom (and spos (move-marker (make-marker) (car spos))))) | |
198 (prog1 (org-id-get pom 'create) | |
199 (move-marker pom nil)))) | |
200 | |
201 ;;;###autoload | |
202 (defun org-id-goto (id) | |
203 "Switch to the buffer containing the entry with id ID. | |
204 Move the cursor to that entry in that buffer." | |
205 (interactive) | |
206 (let ((m (org-id-find id 'marker))) | |
207 (unless m | |
208 (error "Cannot find entry with ID \"%s\"" id)) | |
209 (switch-to-buffer (marker-buffer m)) | |
210 (goto-char m) | |
211 (move-marker m nil) | |
212 (org-show-context))) | |
213 | |
214 ;;;###autoload | |
215 (defun org-id-find (id &optional markerp) | |
216 "Return the location of the entry with the id ID. | |
217 The return value is a cons cell (file-name . position), or nil | |
218 if there is no entry with that ID. | |
219 With optional argument MARKERP, return the position as a new marker." | |
220 (let ((file (org-id-find-id-file id)) | |
221 org-agenda-new-buffers where) | |
222 (when file | |
223 (setq where (org-id-find-id-in-file id file markerp))) | |
224 (unless where | |
225 (org-id-update-id-locations) | |
226 (setq file (org-id-find-id-file id)) | |
227 (when file | |
228 (setq where (org-id-find-id-in-file id file markerp)))) | |
229 where)) | |
230 | |
231 ;;; Internal functions | |
232 | |
233 ;; Creating new IDs | |
234 | |
235 (defun org-id-new (&optional prefix) | |
236 "Create a new globally unique ID. | |
237 | |
238 An ID consists of two parts separated by a colon: | |
239 - a prefix | |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
240 - a unique part that will be created according to `org-id-method'. |
96045 | 241 |
242 PREFIX can specify the prefix, the default is given by the variable | |
243 `org-id-prefix'. However, if PREFIX is the symbol `none', don't use any | |
244 prefix even if `org-id-prefix' specifies one. | |
245 | |
246 So a typical ID could look like \"Org:4nd91V40HI\"." | |
247 (let* ((prefix (if (eq prefix 'none) | |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
248 "" |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
249 (concat (or prefix org-id-prefix) ":"))) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
250 unique) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
251 (if (equal prefix ":") (setq prefix "")) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
252 (cond |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
253 ((eq org-id-method 'uuidgen) |
99501
e3acb52d33e1
2008-11-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
99139
diff
changeset
|
254 (setq unique (org-trim (shell-command-to-string "uuidgen")))) |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
255 ((eq org-id-method 'org) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
256 (let* ((etime (org-id-reverse-string (org-id-time-to-b36))) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
257 (postfix (if org-id-include-domain |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
258 (progn |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
259 (require 'message) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
260 (concat "@" (message-make-fqdn)))))) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
261 (setq unique (concat etime postfix)))) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
262 (t (error "Invalid `org-id-method'"))) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
263 (concat prefix unique))) |
96045 | 264 |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
265 (defun org-id-reverse-string (s) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
266 (mapconcat 'char-to-string (nreverse (string-to-list s)) "")) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
267 |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
268 (defun org-id-int-to-b36-one-digit (i) |
96045 | 269 "Turn an integer between 0 and 61 into a single character 0..9, A..Z, a..z." |
270 (cond | |
271 ((< i 10) (+ ?0 i)) | |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
272 ((< i 36) (+ ?a i -10)) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
273 (t (error "Larger that 35")))) |
96045 | 274 |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
275 (defun org-id-b36-to-int-one-digit (i) |
96045 | 276 "Turn a character 0..9, A..Z, a..z into a number 0..61. |
277 The input I may be a character, or a single-letter string." | |
278 (and (stringp i) (setq i (string-to-char i))) | |
279 (cond | |
280 ((and (>= i ?0) (<= i ?9)) (- i ?0)) | |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
281 ((and (>= i ?a) (<= i ?z)) (+ (- i ?a) 10)) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
282 (t (error "Invalid b36 letter")))) |
96045 | 283 |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
284 (defun org-id-int-to-b36 (i &optional length) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
285 "Convert an integer to a base-36 number represented as a string." |
96045 | 286 (let ((s "")) |
287 (while (> i 0) | |
288 (setq s (concat (char-to-string | |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
289 (org-id-int-to-b36-one-digit (mod i 36))) s) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
290 i (/ i 36))) |
96045 | 291 (setq length (max 1 (or length 1))) |
292 (if (< (length s) length) | |
293 (setq s (concat (make-string (- length (length s)) ?0) s))) | |
294 s)) | |
295 | |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
296 (defun org-id-b36-to-int (s) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
297 "Convert a base-36 string into the corresponding integer." |
96045 | 298 (let ((r 0)) |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
299 (mapc (lambda (i) (setq r (+ (* r 36) (org-id-b36-to-int-one-digit i)))) |
96045 | 300 s) |
301 r)) | |
302 | |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
303 (defun org-id-time-to-b36 (&optional time) |
96045 | 304 "Encode TIME as a 10-digit string. |
305 This string holds the time to micro-second accuracy, and can be decoded | |
306 using `org-id-decode'." | |
307 (setq time (or time (current-time))) | |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
308 (concat (org-id-int-to-b36 (nth 0 time) 4) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
309 (org-id-int-to-b36 (nth 1 time) 4) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
310 (org-id-int-to-b36 (or (nth 2 time) 0) 4))) |
96045 | 311 |
312 (defun org-id-decode (id) | |
313 "Split ID into the prefix and the time value that was used to create it. | |
314 The return value is (prefix . time) where PREFIX is nil or a string, | |
315 and time is the usual three-integer representation of time." | |
316 (let (prefix time parts) | |
317 (setq parts (org-split-string id ":")) | |
318 (if (= 2 (length parts)) | |
319 (setq prefix (car parts) time (nth 1 parts)) | |
320 (setq prefix nil time (nth 0 parts))) | |
98644
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
321 (setq time (org-id-reverse-string time)) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
322 (setq time (list (org-id-b36-to-int (substring time 0 4)) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
323 (org-id-b36-to-int (substring time 4 8)) |
e1cc41b9282d
2008-10-12 Carsten Dominik <carsten.dominik@gmail.com>
Carsten Dominik <dominik@science.uva.nl>
parents:
97027
diff
changeset
|
324 (org-id-b36-to-int (substring time 8 12)))) |
96045 | 325 (cons prefix time))) |
326 | |
327 ;; Storing ID locations (files) | |
328 | |
329 (defun org-id-update-id-locations () | |
330 "Scan relevant files for ID's. | |
331 Store the relation between files and corresponding ID's." | |
332 (interactive) | |
333 (let ((files (append (org-agenda-files) | |
334 (if (symbolp org-id-extra-files) | |
335 (symbol-value org-id-extra-files) | |
336 org-id-extra-files))) | |
337 org-agenda-new-buffers | |
338 file ids reg found id) | |
339 (while (setq file (pop files)) | |
340 (setq ids nil) | |
341 (with-current-buffer (org-get-agenda-file-buffer file) | |
342 (save-excursion | |
343 (save-restriction | |
344 (widen) | |
345 (goto-char (point-min)) | |
346 (while (re-search-forward "^[ \t]*:ID:[ \t]+\\(\\S-+\\)[ \t]*$" | |
347 nil t) | |
348 (setq id (org-match-string-no-properties 1)) | |
349 (if (member id found) | |
350 (error "Duplicate ID \"%s\"" id)) | |
351 (push id found) | |
352 (push id ids)) | |
353 (push (cons file ids) reg))))) | |
354 (org-release-buffers org-agenda-new-buffers) | |
355 (setq org-agenda-new-buffers nil) | |
356 (setq org-id-locations reg) | |
357 (org-id-locations-save))) | |
358 | |
359 (defun org-id-locations-save () | |
360 "Save `org-id-locations' in `org-id-locations-file'." | |
361 (with-temp-file org-id-locations-file | |
362 (print org-id-locations (current-buffer)))) | |
363 | |
364 (defun org-id-locations-load () | |
365 "Read the data from `org-id-locations-file'." | |
366 (setq org-id-locations nil) | |
367 (with-temp-buffer | |
368 (condition-case nil | |
369 (progn | |
370 (insert-file-contents-literally org-id-locations-file) | |
371 (goto-char (point-min)) | |
372 (setq org-id-locations (read (current-buffer)))) | |
373 (error | |
374 (message "Could not read org-id-values from %s. Setting it to nil." | |
375 org-id-locations-file))))) | |
376 | |
377 (defun org-id-add-location (id file) | |
378 "Add the ID with location FILE to the database of ID loations." | |
379 (unless org-id-locations (org-id-locations-load)) | |
380 (catch 'exit | |
381 (let ((locs org-id-locations) list) | |
382 (while (setq list (pop locs)) | |
383 (when (equal (file-truename file) (file-truename (car list))) | |
384 (setcdr list (cons id (cdr list))) | |
385 (throw 'exit t)))) | |
386 (push (list file id) org-id-locations)) | |
387 (org-id-locations-save)) | |
388 | |
389 ;; Finding entries with specified id | |
390 | |
391 (defun org-id-find-id-file (id) | |
392 "Query the id database for the file in which this ID is located." | |
393 (unless org-id-locations (org-id-locations-load)) | |
394 (catch 'found | |
395 (mapc (lambda (x) (if (member id (cdr x)) | |
396 (throw 'found (car x)))) | |
397 org-id-locations) | |
398 nil)) | |
399 | |
400 (defun org-id-find-id-in-file (id file &optional markerp) | |
401 "Return the position of the entry ID in FILE. | |
402 If that files does not exist, or if it does not contain this ID, | |
403 return nil. | |
404 The position is returned as a cons cell (file-name . position). With | |
405 optional argument MARKERP, return the position as a new marker." | |
406 (let (org-agenda-new-buffers m buf pos) | |
407 (cond | |
408 ((not file) nil) | |
409 ((not (file-exists-p file)) nil) | |
410 (t (with-current-buffer (setq buf (org-get-agenda-file-buffer file)) | |
411 (setq pos (org-find-entry-with-id id)) | |
412 (when pos | |
413 (if markerp | |
414 (move-marker (make-marker) pos buf) | |
415 (cons file pos)))))))) | |
416 | |
417 (provide 'org-id) | |
418 | |
419 ;;; org-id.el ends here | |
420 | |
96052 | 421 ;; arch-tag: e5abaca4-e16f-4b25-832a-540cfb63a712 |