Mercurial > emacs
diff lisp/org/org-id.el @ 100269:032aa24b2125
Checking in the correct versions of the files, sorry, I hade used the files
from an experimental branch.....
author | Carsten Dominik <dominik@science.uva.nl> |
---|---|
date | Sun, 07 Dec 2008 18:45:03 +0000 |
parents | c851df8e004e |
children | cea079b68b76 |
line wrap: on
line diff
--- a/lisp/org/org-id.el Sun Dec 07 18:37:17 2008 +0000 +++ b/lisp/org/org-id.el Sun Dec 07 18:45:03 2008 +0000 @@ -1,4 +1,4 @@ -;;; org-id.el --- Global identifiers for Org-mode entries +;;; org-id.el --- Global identifier for Org-mode entries ;; Copyright (C) 2008 Free Software Foundation, Inc. ;; ;; Author: Carsten Dominik <carsten at orgmode dot org> @@ -116,42 +116,17 @@ :group 'org-id :type 'boolean) -(defcustom org-id-track-globally t - "Non-nil means, track ID's trhough files, so that links work globally. -This work by maintaining a hash table for ID's and writing this table -to disk when exiting Emacs. Because of this, it works best if you use -a single Emacs process, not many. - -When nil, ID's are not tracked. Links to ID's will still work within -a buffer, but not if the entry is located in another file. -ID's can still be used if the entry with the id is in the same file as -the link." - :group 'org-id - :type 'boolean) - (defcustom org-id-locations-file (convert-standard-filename - "~/.emacs.d/.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." + "~/.org-id-locations") + "The file for remembering the last ID number generated." :group 'org-id :type 'file) (defvar org-id-locations nil - "List of files with ID's in those files. -Depending on `org-id-use-hash' this can also be a hash table mapping ID's -to files.") - -(defvar org-id-files nil - "List of files that contain ID's.") + "List of files with ID's in those files.") (defcustom org-id-extra-files 'org-agenda-text-search-extra-files - "Files to be searched for ID's, besides the agenda files. -When Org reparses files to remake the list of files and ID's it is tracking, -it will normally scan the agenda files, the archives related to agenda files, -any files that are listed as ID containing in the current register, and -any Org-mode files currently visited by Emacs. -You can list additional files here. -This variable is only relevant when `org-id-track-globally' is set." + "Files to be searched for ID's, besides the agenda files." :group 'org-id :type '(choice @@ -159,14 +134,6 @@ (repeat :tag "List of files" (file)))) -(defcustom org-id-search-archives t - "Non-nil means, search also the archive files of agenda files for entries. -This is a possibility to reduce overhead, but it measn that entries moved -to the archives can no longer be found by ID. -This variable is only relevant when `org-id-track-globally' is set." - :group 'org-id - :type 'boolean) - ;;; The API functions ;;;###autoload @@ -235,7 +202,7 @@ (defun org-id-goto (id) "Switch to the buffer containing the entry with id ID. Move the cursor to that entry in that buffer." - (interactive "sID: ") + (interactive) (let ((m (org-id-find id 'marker))) (unless m (error "Cannot find entry with ID \"%s\"" id)) @@ -359,153 +326,77 @@ ;; Storing ID locations (files) -(defun org-id-update-id-locations (&optional files check) +(defun org-id-update-id-locations () "Scan relevant files for ID's. -Store the relation between files and corresponding ID's. -This will scan all agenda files, all associated archives, and all -files currently mentioned in `org-id-locations'. -When FILES is given, scan these files instead." +Store the relation between files and corresponding ID's." (interactive) - (if (not org-id-track-globally) - (error "Please turn on `org-id-track-globally' if you want to track id's.") - (let ((files - (or files - (append - ;; Agenda files and all associated archives - (org-agenda-files t org-id-search-archives) - ;; Explicit extra files - (if (symbolp org-id-extra-files) - (symbol-value org-id-extra-files) - org-id-extra-files) - ;; Files associated with live org-mode buffers - (delq nil - (mapcar (lambda (b) - (with-current-buffer b - (and (org-mode-p) (buffer-file-name)))) - (buffer-list))) - ;; All files known to have id's - org-id-files))) - org-agenda-new-buffers - file nfiles tfile ids reg found id seen (ndup 0)) - (setq nfiles (length files)) - (while (setq file (pop files)) - (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) - (setq ids nil) - (with-current-buffer (org-get-agenda-file-buffer file) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (while (re-search-forward "^[ \t]*:ID:[ \t]+\\(\\S-+\\)[ \t]*$" - nil t) - (setq id (org-match-string-no-properties 1)) - (if (member id found) - (progn - (message "Duplicate ID \"%s\"" id) - (setq ndup (1+ ndup))) - (push id found) - (push id ids))) - (push (cons (abbreviate-file-name file) ids) reg)))))) - (org-release-buffers org-agenda-new-buffers) - (setq org-agenda-new-buffers nil) - (setq org-id-locations reg) - (setq org-id-files (mapcar 'car org-id-locations)) - (org-id-locations-save) ;; this function can also handle the alist form - ;; now convert to a hash - (setq org-id-locations (org-id-alist-to-hash org-id-locations)) - (if (> ndup 0) - (message "WARNING: %d duplicate ID's found, check *Messages* buffer" ndup) - (message "%d unique files scanned for ID's" (length org-id-files))) - org-id-locations))) + (let ((files (append (org-agenda-files) + (if (symbolp org-id-extra-files) + (symbol-value org-id-extra-files) + org-id-extra-files))) + org-agenda-new-buffers + file ids reg found id) + (while (setq file (pop files)) + (setq ids nil) + (with-current-buffer (org-get-agenda-file-buffer file) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (while (re-search-forward "^[ \t]*:ID:[ \t]+\\(\\S-+\\)[ \t]*$" + nil t) + (setq id (org-match-string-no-properties 1)) + (if (member id found) + (error "Duplicate ID \"%s\"" id)) + (push id found) + (push id ids)) + (push (cons file ids) reg))))) + (org-release-buffers org-agenda-new-buffers) + (setq org-agenda-new-buffers nil) + (setq org-id-locations reg) + (org-id-locations-save))) (defun org-id-locations-save () "Save `org-id-locations' in `org-id-locations-file'." - (when org-id-track-globally - (let ((out (if (hash-table-p org-id-locations) - (org-id-hash-to-alist org-id-locations) - org-id-locations))) - (with-temp-file org-id-locations-file - (print out (current-buffer)))))) + (with-temp-file org-id-locations-file + (print org-id-locations (current-buffer)))) (defun org-id-locations-load () "Read the data from `org-id-locations-file'." (setq org-id-locations nil) - (when org-id-track-globally - (with-temp-buffer - (condition-case nil - (progn - (insert-file-contents-literally 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." - 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)))) + (with-temp-buffer + (condition-case nil + (progn + (insert-file-contents-literally 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." + org-id-locations-file))))) (defun org-id-add-location (id file) "Add the ID with location FILE to the database of ID loations." - ;; Only if global tracking is on, and when the buffer has a file - (when (and org-id-track-globally id file) + (when (and id file) ; don't error when called from a buffer with no file (unless org-id-locations (org-id-locations-load)) - (puthash id (abbreviate-file-name file) org-id-locations) - (add-to-list 'org-id-files (abbreviate-file-name file)))) - -(add-hook 'kill-emacs-hook 'org-id-locations-save) - -(defun org-id-hash-to-alist (hash) - "Turn an org-id hash into an alist, so that it can be written to a file." - (let (res x) - (maphash - (lambda (k v) - (if (setq x (member v res)) - (push k (cdr x)) - (push (list v k) res))) - hash) - res)) - -(defun org-id-alist-to-hash (list) - "Turn an org-id location list into a hash table." - (let ((res (make-hash-table - :test 'equal - :size (apply '+ (mapcar 'length list)))) - f i) - (mapc - (lambda (x) - (setq f (car x)) - (mapc (lambda (i) (puthash i f res)) (cdr x))) - list) - res)) - -(defun org-id-paste-tracker (txt &optional buffer-or-file) - "Update any ID's in TXT and assign BUFFER-OR-FILE to them." - (when org-id-track-globally - (save-match-data - (setq buffer-or-file (or buffer-or-file (current-buffer))) - (when (bufferp buffer-or-file) - (setq buffer-or-file (or (buffer-base-buffer buffer-or-file) - buffer-or-file)) - (setq buffer-or-file (buffer-file-name buffer-or-file))) - (when buffer-or-file - (let ((fname (abbreviate-file-name buffer-or-file)) - (s 0)) - (while (string-match "^[ \t]*:ID:[ \t]+\\([^ \t\n\r]+\\)" txt s) - (setq s (match-end 0)) - (org-id-add-location (match-string 1 txt) fname))))))) + (catch 'exit + (let ((locs org-id-locations) list) + (while (setq list (pop locs)) + (when (equal (file-truename file) (file-truename (car list))) + (setcdr list (cons id (cdr list))) + (throw 'exit t)))) + (push (list file id) org-id-locations)) + (org-id-locations-save))) ;; Finding entries with specified id (defun org-id-find-id-file (id) "Query the id database for the file in which this ID is located." (unless org-id-locations (org-id-locations-load)) - (or (gethash id org-id-locations) - ;; ball back on current buffer - (buffer-file-name (or (buffer-base-buffer (current-buffer)) - (current-buffer))))) + (catch 'found + (mapc (lambda (x) (if (member id (cdr x)) + (throw 'found (car x)))) + org-id-locations) + nil)) (defun org-id-find-id-in-file (id file &optional markerp) "Return the position of the entry ID in FILE. @@ -524,35 +415,8 @@ (move-marker (make-marker) pos buf) (cons file pos)))))))) -;; id link type - -;; Calling the following function is hard-coded into `org-store-link', -;; so we do have to add it to `org-store-link-functions'. - -(defun org-id-store-link () - "Store a link to the current entry, using it's ID." - (interactive) - (let* ((link (org-make-link "id:" (org-id-get-create))) - (desc (save-excursion - (org-back-to-heading t) - (or (and (looking-at org-complex-heading-regexp) - (if (match-end 4) (match-string 4) (match-string 0))) - link)))) - (org-store-link-props :link link :description desc :type "id") - link)) - -(defun org-id-open (id) - "Go to the entry with id ID." - (org-mark-ring-push) - (switch-to-buffer-other-window (current-buffer)) - (org-id-goto id)) - -(org-add-link-type "id" 'org-id-open) - (provide 'org-id) ;;; org-id.el ends here ;; arch-tag: e5abaca4-e16f-4b25-832a-540cfb63a712 - -