;;; org-id.el --- Global identifiers for Org-mode entries
;;
-;; Copyright (C) 2008-2011 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2015 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp
;; Homepage: http://orgmode.org
-;; Version: 7.7
;;
;; This file is part of GNU Emacs.
;;
(require 'org)
(declare-function message-make-fqdn "message" ())
+(declare-function org-pop-to-buffer-same-window
+ "org-compat" (&optional buffer-or-name norecord label))
;;; Customization
:tag "Org ID"
:group 'org)
+(define-obsolete-variable-alias
+ 'org-link-to-org-use-id 'org-id-link-to-org-use-id "24.3")
+(defcustom org-id-link-to-org-use-id nil
+ "Non-nil means storing a link to an Org file will use entry IDs.
+
+The variable can have the following values:
+
+t Create an ID if needed to make a link to the current entry.
+
+create-if-interactive
+ If `org-store-link' is called directly (interactively, as a user
+ command), do create an ID to support the link. But when doing the
+ job for capture, only use the ID if it already exists. The
+ purpose of this setting is to avoid proliferation of unwanted
+ IDs, just because you happen to be in an Org file when you
+ call `org-capture' that automatically and preemptively creates a
+ link. If you do want to get an ID link in a capture template to
+ an entry not having an ID, create it first by explicitly creating
+ a link to it, using `C-c C-l' first.
+
+create-if-interactive-and-no-custom-id
+ Like create-if-interactive, but do not create an ID if there is
+ a CUSTOM_ID property defined in the entry.
+
+use-existing
+ Use existing ID, do not create one.
+
+nil Never use an ID to make a link, instead link using a text search for
+ the headline text."
+ :group 'org-link-store
+ :group 'org-id
+ :version "24.3"
+ :type '(choice
+ (const :tag "Create ID to make link" t)
+ (const :tag "Create if storing link interactively"
+ create-if-interactive)
+ (const :tag "Create if storing link interactively and no CUSTOM_ID is present"
+ create-if-interactive-and-no-custom-id)
+ (const :tag "Only use existing" use-existing)
+ (const :tag "Do not use ID to create link" nil)))
+
(defcustom org-id-uuid-program "uuidgen"
"The uuidgen program."
:group 'org-id
:type 'boolean)
(defcustom org-id-locations-file (convert-standard-filename
- "~/.emacs.d/.org-id-locations")
+ (concat user-emacs-directory ".org-id-locations"))
"The file for remembering in which file an ID was defined.
This variable is only relevant when `org-id-track-globally' is set."
:group 'org-id
(setq id (org-id-new prefix))
(org-entry-put pom "ID" id)
(org-id-add-location id (buffer-file-name (buffer-base-buffer)))
- id)
- (t nil)))))
+ id)))))
;;;###autoload
(defun org-id-get-with-outline-path-completion (&optional targets)
- "Use outline-path-completion to retrieve the ID of an entry.
-TARGETS may be a setting for `org-refile-targets' to define the eligible
-headlines. When omitted, all headlines in all agenda files are
-eligible.
-It returns the ID of the entry. If necessary, the ID is created."
+ "Use `outline-path-completion' to retrieve the ID of an entry.
+TARGETS may be a setting for `org-refile-targets' to define
+eligible headlines. When omitted, all headlines in the current
+file are eligible. This function returns the ID of the entry.
+If necessary, the ID is created."
(let* ((org-refile-targets (or targets '((nil . (:maxlevel . 10)))))
(org-refile-use-outline-path
(if (caar org-refile-targets) 'file t))
(let ((m (org-id-find id 'marker)))
(unless m
(error "Cannot find entry with ID \"%s\"" id))
- (switch-to-buffer (marker-buffer m))
+ (org-pop-to-buffer-same-window (marker-buffer m))
(goto-char m)
(move-marker m nil)
(org-show-context)))
(when file
(setq where (org-id-find-id-in-file id file markerp)))
(unless where
- (org-id-update-id-locations)
+ (org-id-update-id-locations nil t)
(setq file (org-id-find-id-file id))
(when file
(setq where (org-id-find-id-in-file id file markerp))))
;; Creating new IDs
+;;;###autoload
(defun org-id-new (&optional prefix)
"Create a new globally unique ID.
(unless (org-uuidgen-p unique)
(setq unique (org-id-uuid))))
((eq org-id-method 'org)
- (let* ((etime (org-id-reverse-string (org-id-time-to-b36)))
+ (let* ((etime (org-reverse-string (org-id-time-to-b36)))
(postfix (if org-id-include-domain
(progn
(require 'message)
(defun org-id-uuid ()
"Return string with random (version 4) UUID."
(let ((rnd (md5 (format "%s%s%s%s%s%s%s"
- (random t)
+ (random)
(current-time)
(user-uid)
(emacs-pid)
(substring rnd 18 20)
(substring rnd 20 32))))
-(defun org-id-reverse-string (s)
- (mapconcat 'char-to-string (nreverse (string-to-list s)) ""))
-
(defun org-id-int-to-b36-one-digit (i)
"Turn an integer between 0 and 61 into a single character 0..9, A..Z, a..z."
(cond
(if (= 2 (length parts))
(setq prefix (car parts) time (nth 1 parts))
(setq prefix nil time (nth 0 parts)))
- (setq time (org-id-reverse-string time))
+ (setq time (org-reverse-string time))
(setq time (list (org-id-b36-to-int (substring time 0 4))
(org-id-b36-to-int (substring time 4 8))
(org-id-b36-to-int (substring time 8 12))))
;; Storing ID locations (files)
-(defun org-id-update-id-locations (&optional files)
+;;;###autoload
+(defun org-id-update-id-locations (&optional files silent)
"Scan relevant files for IDs.
Store the relation between files and corresponding IDs.
This will scan all agenda files, all associated archives, and all
(if (symbolp org-id-extra-files)
(symbol-value org-id-extra-files)
org-id-extra-files)
- ;; Files associated with live org-mode buffers
+ ;; Files associated with live org-mode buffers
(delq nil
(mapcar (lambda (b)
(with-current-buffer b
- (and (org-mode-p) (buffer-file-name))))
+ (and (derived-mode-p 'org-mode) (buffer-file-name))))
(buffer-list)))
;; All files known to have IDs
org-id-files)))
(setq files (delq 'agenda-archives (copy-sequence files))))
(setq nfiles (length files))
(while (setq file (pop files))
- (message "Finding ID locations (%d/%d files): %s"
- (- nfiles (length files)) nfiles file)
+ (unless silent
+ (message "Finding ID locations (%d/%d files): %s"
+ (- nfiles (length files)) nfiles file))
(setq tfile (file-truename file))
(when (and (file-exists-p file) (not (member tfile seen)))
(push tfile seen)
(org-id-hash-to-alist org-id-locations)
org-id-locations)))
(with-temp-file org-id-locations-file
- (print out (current-buffer))))))
+ (let ((print-level nil)
+ (print-length nil))
+ (print out (current-buffer)))))))
(defun org-id-locations-load ()
"Read the data from `org-id-locations-file'."
(goto-char (point-min))
(setq org-id-locations (read (current-buffer))))
(error
- (message "Could not read org-id-values from %s. Setting it to nil."
+ (message "Could not read org-id-values from %s. Setting it to nil."
org-id-locations-file))))
(setq org-id-files (mapcar 'car org-id-locations))
(setq org-id-locations (org-id-alist-to-hash org-id-locations))))
(defun org-id-store-link ()
"Store a link to the current entry, using its ID."
(interactive)
- (when (and (buffer-file-name (buffer-base-buffer)) (org-mode-p))
- (let* ((link (org-make-link "id:" (org-id-get-create)))
+ (when (and (buffer-file-name (buffer-base-buffer)) (derived-mode-p 'org-mode))
+ (let* ((link (concat "id:" (org-id-get-create)))
(case-fold-search nil)
(desc (save-excursion
(org-back-to-heading t)
(provide 'org-id)
-;;; org-id.el ends here
-
-
-
+;; Local variables:
+;; generated-autoload-file: "org-loaddefs.el"
+;; End:
+;;; org-id.el ends here