Commit bc23baaa authored by Carsten Dominik's avatar Carsten Dominik
Browse files

Checking in the correct versions of the files, sorry, I hade used the files

from an experimental branch.....
parent e5f29d66
2008-12-02 Carsten Dominik <>
* org.texi (Using the mapping API): Fix bug in mapping example.
(Publishing options): Make the list of properties complete again, in
correspondence to the variable `org-export-plist-vars'.
(Property searches): Document new special values for time comparisons.
(Tag inheritance): Refine the description of tag inheritance.
(Project alist): Add info about the publishing sequence of components.
(Effort estimates): Document the new relativer timer.
2008-12-04 David Engster <>
* gnus.texi (nnmairix): Mention mairix.el. Point out the importance
2008-12-07 Carsten Dominik <>
* org-id.el (org-id-locations-file): Wrap file name with
(org-id-files): New variable.
(org-id-use-hash): New option.
(org-id-update-id-locations): Also search in all files current
listed in `org-id-files'. Convert the resulting alist to a hash
if the user customation says so.
(org-id-locations-save): Handle he case if `org-id-locations' is a
(org-id-locations-load): Convert the alist to a hash.
(org-id-add-location): Handle the hast case.
(kill-emacs-hook): Make sure id locations are saved when Emacs is
(org-id-hash-to-alist, org-id-alist-to-hash)
(org-id-paste-tracker): New functions.
2008-12-07 Carsten Dominik <>
......@@ -244,9 +227,6 @@
(org-remember-mode): New minor mode.
(org-remember-apply-template): Turn on `org-remember-mode'.
* org-id.el (org-id-add-location): Avoid error when no file is
* org-remember.el (org-remember-apply-template): Fix the way how
the list of allowed properties is retrieved from the target file.
......@@ -118,8 +118,7 @@ be visited."
(const :tag "Clock and history" t)
(const :tag "No persistence" nil)))
(defcustom org-clock-persist-file (convert-standard-filename
(defcustom org-clock-persist-file "~/.emacs.d/org-clock-save.el"
"File to save clock data to"
:group 'org-clock
:type 'string)
......@@ -1465,9 +1465,6 @@ on this string to produce the exported version."
;; Handle source code snippets
;; Find all headings and compute the targets for them
(setq target-alist (org-export-define-heading-targets target-alist))
;; Get rid of drawers
(org-export-remove-or-extract-drawers drawers
......@@ -1490,6 +1487,9 @@ on this string to produce the exported version."
;; Remove todo-keywords before exporting, if the user has requested so
(org-export-remove-headline-metadata parameters)
;; Find all headings and compute the targets for them
(setq target-alist (org-export-define-heading-targets target-alist))
;; Find targets in comments and move them out of comments,
;; but mark them as targets that should be invisible
(setq target-alist (org-export-handle-invisible-targets target-alist))
......@@ -1513,6 +1513,7 @@ on this string to produce the exported version."
;; Remove comment environment and comment subtrees
;; Find matches for radio targets and turn them into internal links
......@@ -1570,22 +1571,18 @@ on this string to produce the exported version."
The new targets are added to TARGET-ALIST, which is also returned."
(goto-char (point-min))
(let ((re (concat "^" org-outline-regexp
"\\| [ \t]*:ID:[ \t]*\\([^ \t\r\n]+\\)"))
(let ((re (concat "^" org-outline-regexp))
level target)
(while (re-search-forward re nil t)
(if (match-end 1)
(push (cons (org-match-string-no-properties 1)
target) target-alist)
(setq level (org-reduced-level
(save-excursion (goto-char (point-at-bol))
(setq target (org-solidify-link-text
(format "sec-%s" (org-section-number level))))
(push (cons target target) target-alist)
(point-at-bol) (point-at-eol)
(list 'target target)))))
(setq level (org-reduced-level
(save-excursion (goto-char (point-at-bol))
(setq target (org-solidify-link-text
(format "sec-%s" (org-section-number level))))
(push (cons target target) target-alist)
(point-at-bol) (point-at-eol)
(list 'target target))))
(defun org-export-handle-invisible-targets (target-alist)
......@@ -1614,11 +1611,9 @@ Mark them as invisible targets."
(defun org-export-target-internal-links (target-alist)
"Find all internal links and assign targets to them.
"Find all internal links and assign target to them.
If a link has a fuzzy match (i.e. not a *dedicated* target match),
let the link point to the corresponding section.
This function also handles the id links, if they have a match in
the current file."
let the link point to the corresponding section."
(goto-char (point-min))
(while (re-search-forward org-bracket-link-regexp nil t)
......@@ -1630,8 +1625,6 @@ the current file."
((cdr (assoc slink target-alist)))
((and (string-match "^id:" link)
(cdr (assoc (substring link 3) target-alist))))
((string-match org-link-types-re link) nil)
((or (file-name-absolute-p link)
(string-match "^\\." link))
;;; 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 @@ be added."
: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
"The file for remembering in which file an ID was defined.
This variable is only relevant when `org-id-track-globally' is set."
"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
......@@ -159,14 +134,6 @@ This variable is only relevant when `org-id-track-globally' is set."
(repeat :tag "List of files"
(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
......@@ -235,7 +202,7 @@ It returns the ID of the entry. If necessary, the ID is created."
(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: ")
(let ((m (org-id-find id 'marker)))
(unless m
(error "Cannot find entry with ID \"%s\"" id))
......@@ -359,153 +326,77 @@ and time is the usual three-integer representation of time."
;; 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."
(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
;; 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)
;; Files associated with live org-mode buffers
(delq nil
(mapcar (lambda (b)
(with-current-buffer b
(and (org-mode-p) (buffer-file-name))))
;; All files known to have id's
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)
(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)
(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)))
(let ((files (append (org-agenda-files)
(if (symbolp org-id-extra-files)
(symbol-value org-id-extra-files)
file ids reg found id)
(while (setq file (pop files))
(setq ids nil)
(with-current-buffer (org-get-agenda-file-buffer file)
(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)
(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)
(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
(condition-case nil
(insert-file-contents-literally org-id-locations-file)
(goto-char (point-min))
(setq org-id-locations (read (current-buffer))))
(message "Could not read org-id-values from %s. Setting it to nil."
(setq org-id-files (mapcar 'car org-id-locations))
(setq org-id-locations (org-id-alist-to-hash org-id-locations))))
(condition-case nil
(insert-file-contents-literally org-id-locations-file)
(goto-char (point-min))
(setq org-id-locations (read (current-buffer))))
(message "Could not read org-id-values from %s. Setting it to nil."
(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)
(lambda (k v)
(if (setq x (member v res))
(push k (cdr x))
(push (list v k) 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)
(lambda (x)
(setq f (car x))
(mapc (lambda (i) (puthash i f res)) (cdr x)))
(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
(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)
(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))
;; 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))
(catch 'found
(mapc (lambda (x) (if (member id (cdr x))
(throw 'found (car x))))
(defun org-id-find-id-in-file (id file &optional markerp)
"Return the position of the entry ID in FILE.
......@@ -524,35 +415,8 @@ optional argument MARKERP, return the position as a new marker."
(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."
(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)))
(org-store-link-props :link link :description desc :type "id")
(defun org-id-open (id)
"Go to the entry with id ID."
(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
;;; org-clock.el --- The time clocking code for Org-mode
;; Copyright (C) 2008 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp
;; Homepage:
;; Version: 6.14
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <>.
;;; Commentary:
;; This file contains the relative timer code for Org-mode
(require 'org)
(defvar org-timer-start-time nil
"t=0 for the running timer.")
(defconst org-timer-re "\\([-+]?[0-9]+\\):\\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)"
"Regular expression used to match timer stamps.")
(defcustom org-timer-format "%s "
"The format to insert the time of the timer.
This format must contain one instance of \"%s\" which will be replaced by
the value of the relative timer."
:group 'org-time
:type 'string)
(defun org-timer-start (&optional offset)
"Set the starting time for the relative timer to now.
When called with prefix argument OFFSET, prompt the user for an offset time,
with the default taken from a timer stamp at point, if any.
If OFFSET is a string or an integer, it is directly taken to be the offset
without user interaction.
When called with a double prefix arg, all timer strings in the active
region will be shifted by a specific amount. You will be prompted for
the amount, with the default to make the first timer string in
the region 0:00:00."
(interactive "P")
(if (equal offset '(16))
(call-interactively 'org-timer-change-times-in-region)
(let (delta def s)
(if (not offset)
(setq org-timer-start-time (current-time))
((integerp offset) (setq delta offset))
((stringp offset) (setq delta (org-timer-hms-to-secs offset)))
(setq def (if (org-in-regexp org-timer-re)
(match-string 0)
s (read-string
(format "Restart timer with offset [%s]: " def)))
(unless (string-match "\\S-" s) (setq s def))
(setq delta (org-timer-hms-to-secs (org-timer-fix-incomplete s)))))
(setq org-timer-start-time
(time-to-seconds (current-time))
(org-timer-hms-to-secs s)))))
(message "Timer start time set to %s, current value is %s"
(format-time-string "%T" org-timer-start-time)
(org-timer-secs-to-hms (or delta 0))))))
(defun org-timer (&optional restart)
"Insert a H:MM:SS string from the timer into the buffer.
The first time this command is used, the timer is started. When used with
a `C-u' prefix, force restarting the timer.
When used with a double prefix arg `C-u C-u', change all the timer string
in the region by a fixed amount. This can be used to recalibrate a timer
that was not started at the correct moment."
(interactive "P")
(if (equal restart '(4)) (org-timer-start))
(or org-timer-start-time (org-timer-start))
(insert (format
(- (time-to-seconds (current-time))
(time-to-seconds org-timer-start-time)))))))
(defun org-timer-change-times-in-region (beg end delta)
"Change all h:mm:ss time in region by a DELTA."
"r\nsEnter time difference like \"-1:08:26\". Default is first time to zero: ")
(let ((re "[-+]?[0-9]+:[0-9]\\{2\\}:[0-9]\\{2\\}") p)
(unless (string-match "\\S-" delta)
(goto-char beg)
(when (re-search-forward re end t)
(setq delta (match-string 0))
(if (equal (string-to-char delta) ?-)
(setq delta (substring delta 1))
(setq delta (concat "-" delta))))))
(setq delta (org-timer-hms-to-secs (org-timer-fix-incomplete delta)))
(when (= delta 0) (error "No change"))
(goto-char end)
(while (re-search-backward re beg t)
(setq p (point))
(org-timer-secs-to-hms (+ (org-timer-hms-to-secs (match-string 0)) delta)))
t t)
(goto-char p)))))
(defun org-timer-item (&optional arg)
"Insert a description-type item with the curren timer value."
(interactive "P")
(let ((ind 0))
(skip-chars-backward " \n\t")
(condition-case nil
(setq ind (org-get-indentation)))
(error nil)))
(or (bolp) (newline))
(org-indent-line-to ind)
(insert "- ")
(org-timer (if arg '(4)))
(insert ":: ")))
(defun org-timer-fix-incomplete (hms)
"If hms is a H:MM:SS string with missing hour or hour and minute, fix it."
(if (string-match "\\(?:\\([0-9]+:\\)?\\([0-9]+:\\)\\)?\\([0-9]+\\)" hms)
(format "%d:%02d:%02d"
(if (match-end 1) (string-to-number (match-string 1 hms)) 0)
(if (match-end 2) (string-to-number (match-string 2 hms)) 0)
(string-to-number (match-string 3 hms)))
t t hms)
(error "Canot parse HMS string \"%s\"" hms)))
(defun org-timer-hms-to-secs (hms)
"Convert h:mm:ss string to an integer time.
If the string starts with a minus sign, the integer will be negative."
(if (not (string-match
(let* ((h (string-to-number (match-string 1 hms)))
(m (string-to-number (match-string 2 hms)))
(s (string-to-number (match-string 3 hms)))
(sign (equal (substring (match-string 1 hms) 0 1) "-")))
(setq h (abs h))
(* (if sign -1 1) (+ s (* 60 (+ m (* 60 h))))))))
(defun org-timer-secs-to-hms (s)
"Convert integer S into h:mm:ss.
If the integer is negative, the strig will start with \"-\"."
(let (sign m h)
(setq sign (if (< s 0) "-" "")
s (abs s)
m (/ s 60) s (- s (