aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarsten Dominik2008-12-07 18:49:09 +0000
committerCarsten Dominik2008-12-07 18:49:09 +0000
commitbc23baaabba9eaf24f784211dfe25f9ba2b92a14 (patch)
tree1050b5a0e9793c0a5b723b29949d78d7eb300d7f
parente5f29d662de4a262f839332107bd683a2fc99932 (diff)
downloademacs-bc23baaabba9eaf24f784211dfe25f9ba2b92a14.tar.gz
emacs-bc23baaabba9eaf24f784211dfe25f9ba2b92a14.zip
Checking in the correct versions of the files, sorry, I hade used the files
from an experimental branch.....
-rw-r--r--doc/misc/ChangeLog10
-rw-r--r--lisp/org/ChangeLog20
-rw-r--r--lisp/org/org-clock.el3
-rw-r--r--lisp/org/org-exp.el39
-rw-r--r--lisp/org/org-id.el252
-rw-r--r--lisp/org/org-timer.el181
-rw-r--r--lisp/org/org.el84
7 files changed, 280 insertions, 309 deletions
diff --git a/doc/misc/ChangeLog b/doc/misc/ChangeLog
index 82e0cfc47cf..14fa1bc91c2 100644
--- a/doc/misc/ChangeLog
+++ b/doc/misc/ChangeLog
@@ -1,3 +1,13 @@
12008-12-02 Carsten Dominik <carsten.dominik@gmail.com>
2
3 * org.texi (Using the mapping API): Fix bug in mapping example.
4 (Publishing options): Make the list of properties complete again, in
5 correspondence to the variable `org-export-plist-vars'.
6 (Property searches): Document new special values for time comparisons.
7 (Tag inheritance): Refine the description of tag inheritance.
8 (Project alist): Add info about the publishing sequence of components.
9 (Effort estimates): Document the new relativer timer.
10
12008-12-04 David Engster <dengste@eml.cc> 112008-12-04 David Engster <dengste@eml.cc>
2 12
3 * gnus.texi (nnmairix): Mention mairix.el. Point out the importance 13 * gnus.texi (nnmairix): Mention mairix.el. Point out the importance
diff --git a/lisp/org/ChangeLog b/lisp/org/ChangeLog
index cf1414a803b..ea7cfe16ebc 100644
--- a/lisp/org/ChangeLog
+++ b/lisp/org/ChangeLog
@@ -1,20 +1,3 @@
12008-12-07 Carsten Dominik <carsten.dominik@gmail.com>
2
3 * org-id.el (org-id-locations-file): Wrap file name with
4 `convert-standard-filename'.
5 (org-id-files): New variable.
6 (org-id-use-hash): New option.
7 (org-id-update-id-locations): Also search in all files current
8 listed in `org-id-files'. Convert the resulting alist to a hash
9 if the user customation says so.
10 (org-id-locations-save): Handle he case if `org-id-locations' is a
11 hash.
12 (org-id-locations-load): Convert the alist to a hash.
13 (org-id-add-location): Handle the hast case.
14 (kill-emacs-hook): Make sure id locations are saved when Emacs is
15 exited.
16 (org-id-hash-to-alist, org-id-alist-to-hash)
17 (org-id-paste-tracker): New functions.
18 1
192008-12-07 Carsten Dominik <carsten.dominik@gmail.com> 22008-12-07 Carsten Dominik <carsten.dominik@gmail.com>
20 3
@@ -244,9 +227,6 @@
244 (org-remember-mode): New minor mode. 227 (org-remember-mode): New minor mode.
245 (org-remember-apply-template): Turn on `org-remember-mode'. 228 (org-remember-apply-template): Turn on `org-remember-mode'.
246 229
247 * org-id.el (org-id-add-location): Avoid error when no file is
248 given.
249
250 * org-remember.el (org-remember-apply-template): Fix the way how 230 * org-remember.el (org-remember-apply-template): Fix the way how
251 the list of allowed properties is retrieved from the target file. 231 the list of allowed properties is retrieved from the target file.
252 232
diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el
index b6fc637509a..17fb7c2d10e 100644
--- a/lisp/org/org-clock.el
+++ b/lisp/org/org-clock.el
@@ -118,8 +118,7 @@ be visited."
118 (const :tag "Clock and history" t) 118 (const :tag "Clock and history" t)
119 (const :tag "No persistence" nil))) 119 (const :tag "No persistence" nil)))
120 120
121(defcustom org-clock-persist-file (convert-standard-filename 121(defcustom org-clock-persist-file "~/.emacs.d/org-clock-save.el"
122 "~/.emacs.d/org-clock-save.el")
123 "File to save clock data to" 122 "File to save clock data to"
124 :group 'org-clock 123 :group 'org-clock
125 :type 'string) 124 :type 'string)
diff --git a/lisp/org/org-exp.el b/lisp/org/org-exp.el
index 8e64a31a47c..bf1dd2a276b 100644
--- a/lisp/org/org-exp.el
+++ b/lisp/org/org-exp.el
@@ -1465,9 +1465,6 @@ on this string to produce the exported version."
1465 1465
1466 ;; Handle source code snippets 1466 ;; Handle source code snippets
1467 (org-export-replace-src-segments) 1467 (org-export-replace-src-segments)
1468
1469 ;; Find all headings and compute the targets for them
1470 (setq target-alist (org-export-define-heading-targets target-alist))
1471 1468
1472 ;; Get rid of drawers 1469 ;; Get rid of drawers
1473 (org-export-remove-or-extract-drawers drawers 1470 (org-export-remove-or-extract-drawers drawers
@@ -1490,6 +1487,9 @@ on this string to produce the exported version."
1490 ;; Remove todo-keywords before exporting, if the user has requested so 1487 ;; Remove todo-keywords before exporting, if the user has requested so
1491 (org-export-remove-headline-metadata parameters) 1488 (org-export-remove-headline-metadata parameters)
1492 1489
1490 ;; Find all headings and compute the targets for them
1491 (setq target-alist (org-export-define-heading-targets target-alist))
1492
1493 ;; Find targets in comments and move them out of comments, 1493 ;; Find targets in comments and move them out of comments,
1494 ;; but mark them as targets that should be invisible 1494 ;; but mark them as targets that should be invisible
1495 (setq target-alist (org-export-handle-invisible-targets target-alist)) 1495 (setq target-alist (org-export-handle-invisible-targets target-alist))
@@ -1513,6 +1513,7 @@ on this string to produce the exported version."
1513 ;; Remove comment environment and comment subtrees 1513 ;; Remove comment environment and comment subtrees
1514 (org-export-remove-comment-blocks-and-subtrees) 1514 (org-export-remove-comment-blocks-and-subtrees)
1515 1515
1516
1516 ;; Find matches for radio targets and turn them into internal links 1517 ;; Find matches for radio targets and turn them into internal links
1517 (org-export-mark-radio-links) 1518 (org-export-mark-radio-links)
1518 1519
@@ -1570,22 +1571,18 @@ on this string to produce the exported version."
1570The new targets are added to TARGET-ALIST, which is also returned." 1571The new targets are added to TARGET-ALIST, which is also returned."
1571 (goto-char (point-min)) 1572 (goto-char (point-min))
1572 (org-init-section-numbers) 1573 (org-init-section-numbers)
1573 (let ((re (concat "^" org-outline-regexp 1574 (let ((re (concat "^" org-outline-regexp))
1574 "\\| [ \t]*:ID:[ \t]*\\([^ \t\r\n]+\\)"))
1575 level target) 1575 level target)
1576 (while (re-search-forward re nil t) 1576 (while (re-search-forward re nil t)
1577 (if (match-end 1) 1577 (setq level (org-reduced-level
1578 (push (cons (org-match-string-no-properties 1) 1578 (save-excursion (goto-char (point-at-bol))
1579 target) target-alist) 1579 (org-outline-level))))
1580 (setq level (org-reduced-level 1580 (setq target (org-solidify-link-text
1581 (save-excursion (goto-char (point-at-bol)) 1581 (format "sec-%s" (org-section-number level))))
1582 (org-outline-level)))) 1582 (push (cons target target) target-alist)
1583 (setq target (org-solidify-link-text 1583 (add-text-properties
1584 (format "sec-%s" (org-section-number level)))) 1584 (point-at-bol) (point-at-eol)
1585 (push (cons target target) target-alist) 1585 (list 'target target))))
1586 (add-text-properties
1587 (point-at-bol) (point-at-eol)
1588 (list 'target target)))))
1589 target-alist) 1586 target-alist)
1590 1587
1591(defun org-export-handle-invisible-targets (target-alist) 1588(defun org-export-handle-invisible-targets (target-alist)
@@ -1614,11 +1611,9 @@ Mark them as invisible targets."
1614 target-alist) 1611 target-alist)
1615 1612
1616(defun org-export-target-internal-links (target-alist) 1613(defun org-export-target-internal-links (target-alist)
1617 "Find all internal links and assign targets to them. 1614 "Find all internal links and assign target to them.
1618If a link has a fuzzy match (i.e. not a *dedicated* target match), 1615If a link has a fuzzy match (i.e. not a *dedicated* target match),
1619let the link point to the corresponding section. 1616let the link point to the corresponding section."
1620This function also handles the id links, if they have a match in
1621the current file."
1622 (goto-char (point-min)) 1617 (goto-char (point-min))
1623 (while (re-search-forward org-bracket-link-regexp nil t) 1618 (while (re-search-forward org-bracket-link-regexp nil t)
1624 (org-if-unprotected 1619 (org-if-unprotected
@@ -1630,8 +1625,6 @@ the current file."
1630 (target 1625 (target
1631 (cond 1626 (cond
1632 ((cdr (assoc slink target-alist))) 1627 ((cdr (assoc slink target-alist)))
1633 ((and (string-match "^id:" link)
1634 (cdr (assoc (substring link 3) target-alist))))
1635 ((string-match org-link-types-re link) nil) 1628 ((string-match org-link-types-re link) nil)
1636 ((or (file-name-absolute-p link) 1629 ((or (file-name-absolute-p link)
1637 (string-match "^\\." link)) 1630 (string-match "^\\." link))
diff --git a/lisp/org/org-id.el b/lisp/org/org-id.el
index 143e0ee0c1e..07f78824fd6 100644
--- a/lisp/org/org-id.el
+++ b/lisp/org/org-id.el
@@ -1,4 +1,4 @@
1;;; org-id.el --- Global identifiers for Org-mode entries 1;;; org-id.el --- Global identifier for Org-mode entries
2;; Copyright (C) 2008 Free Software Foundation, Inc. 2;; Copyright (C) 2008 Free Software Foundation, Inc.
3;; 3;;
4;; Author: Carsten Dominik <carsten at orgmode dot org> 4;; Author: Carsten Dominik <carsten at orgmode dot org>
@@ -116,42 +116,17 @@ be added."
116 :group 'org-id 116 :group 'org-id
117 :type 'boolean) 117 :type 'boolean)
118 118
119(defcustom org-id-track-globally t
120 "Non-nil means, track ID's trhough files, so that links work globally.
121This work by maintaining a hash table for ID's and writing this table
122to disk when exiting Emacs. Because of this, it works best if you use
123a single Emacs process, not many.
124
125When nil, ID's are not tracked. Links to ID's will still work within
126a buffer, but not if the entry is located in another file.
127ID's can still be used if the entry with the id is in the same file as
128the link."
129 :group 'org-id
130 :type 'boolean)
131
132(defcustom org-id-locations-file (convert-standard-filename 119(defcustom org-id-locations-file (convert-standard-filename
133 "~/.emacs.d/.org-id-locations") 120 "~/.org-id-locations")
134 "The file for remembering in which file an ID was defined. 121 "The file for remembering the last ID number generated."
135This variable is only relevant when `org-id-track-globally' is set."
136 :group 'org-id 122 :group 'org-id
137 :type 'file) 123 :type 'file)
138 124
139(defvar org-id-locations nil 125(defvar org-id-locations nil
140 "List of files with ID's in those files. 126 "List of files with ID's in those files.")
141Depending on `org-id-use-hash' this can also be a hash table mapping ID's
142to files.")
143
144(defvar org-id-files nil
145 "List of files that contain ID's.")
146 127
147(defcustom org-id-extra-files 'org-agenda-text-search-extra-files 128(defcustom org-id-extra-files 'org-agenda-text-search-extra-files
148 "Files to be searched for ID's, besides the agenda files. 129 "Files to be searched for ID's, besides the agenda files."
149When Org reparses files to remake the list of files and ID's it is tracking,
150it will normally scan the agenda files, the archives related to agenda files,
151any files that are listed as ID containing in the current register, and
152any Org-mode files currently visited by Emacs.
153You can list additional files here.
154This variable is only relevant when `org-id-track-globally' is set."
155 :group 'org-id 130 :group 'org-id
156 :type 131 :type
157 '(choice 132 '(choice
@@ -159,14 +134,6 @@ This variable is only relevant when `org-id-track-globally' is set."
159 (repeat :tag "List of files" 134 (repeat :tag "List of files"
160 (file)))) 135 (file))))
161 136
162(defcustom org-id-search-archives t
163 "Non-nil means, search also the archive files of agenda files for entries.
164This is a possibility to reduce overhead, but it measn that entries moved
165to the archives can no longer be found by ID.
166This variable is only relevant when `org-id-track-globally' is set."
167 :group 'org-id
168 :type 'boolean)
169
170;;; The API functions 137;;; The API functions
171 138
172;;;###autoload 139;;;###autoload
@@ -235,7 +202,7 @@ It returns the ID of the entry. If necessary, the ID is created."
235(defun org-id-goto (id) 202(defun org-id-goto (id)
236 "Switch to the buffer containing the entry with id ID. 203 "Switch to the buffer containing the entry with id ID.
237Move the cursor to that entry in that buffer." 204Move the cursor to that entry in that buffer."
238 (interactive "sID: ") 205 (interactive)
239 (let ((m (org-id-find id 'marker))) 206 (let ((m (org-id-find id 'marker)))
240 (unless m 207 (unless m
241 (error "Cannot find entry with ID \"%s\"" id)) 208 (error "Cannot find entry with ID \"%s\"" id))
@@ -359,153 +326,77 @@ and time is the usual three-integer representation of time."
359 326
360;; Storing ID locations (files) 327;; Storing ID locations (files)
361 328
362(defun org-id-update-id-locations (&optional files check) 329(defun org-id-update-id-locations ()
363 "Scan relevant files for ID's. 330 "Scan relevant files for ID's.
364Store the relation between files and corresponding ID's. 331Store the relation between files and corresponding ID's."
365This will scan all agenda files, all associated archives, and all
366files currently mentioned in `org-id-locations'.
367When FILES is given, scan these files instead."
368 (interactive) 332 (interactive)
369 (if (not org-id-track-globally) 333 (let ((files (append (org-agenda-files)
370 (error "Please turn on `org-id-track-globally' if you want to track id's.") 334 (if (symbolp org-id-extra-files)
371 (let ((files 335 (symbol-value org-id-extra-files)
372 (or files 336 org-id-extra-files)))
373 (append 337 org-agenda-new-buffers
374 ;; Agenda files and all associated archives 338 file ids reg found id)
375 (org-agenda-files t org-id-search-archives) 339 (while (setq file (pop files))
376 ;; Explicit extra files 340 (setq ids nil)
377 (if (symbolp org-id-extra-files) 341 (with-current-buffer (org-get-agenda-file-buffer file)
378 (symbol-value org-id-extra-files) 342 (save-excursion
379 org-id-extra-files) 343 (save-restriction
380 ;; Files associated with live org-mode buffers 344 (widen)
381 (delq nil 345 (goto-char (point-min))
382 (mapcar (lambda (b) 346 (while (re-search-forward "^[ \t]*:ID:[ \t]+\\(\\S-+\\)[ \t]*$"
383 (with-current-buffer b 347 nil t)
384 (and (org-mode-p) (buffer-file-name)))) 348 (setq id (org-match-string-no-properties 1))
385 (buffer-list))) 349 (if (member id found)
386 ;; All files known to have id's 350 (error "Duplicate ID \"%s\"" id))
387 org-id-files))) 351 (push id found)
388 org-agenda-new-buffers 352 (push id ids))
389 file nfiles tfile ids reg found id seen (ndup 0)) 353 (push (cons file ids) reg)))))
390 (setq nfiles (length files)) 354 (org-release-buffers org-agenda-new-buffers)
391 (while (setq file (pop files)) 355 (setq org-agenda-new-buffers nil)
392 (message "Finding ID locations (%d/%d files): %s" 356 (setq org-id-locations reg)
393 (- nfiles (length files)) nfiles file) 357 (org-id-locations-save)))
394 (setq tfile (file-truename file))
395 (when (and (file-exists-p file) (not (member tfile seen)))
396 (push tfile seen)
397 (setq ids nil)
398 (with-current-buffer (org-get-agenda-file-buffer file)
399 (save-excursion
400 (save-restriction
401 (widen)
402 (goto-char (point-min))
403 (while (re-search-forward "^[ \t]*:ID:[ \t]+\\(\\S-+\\)[ \t]*$"
404 nil t)
405 (setq id (org-match-string-no-properties 1))
406 (if (member id found)
407 (progn
408 (message "Duplicate ID \"%s\"" id)
409 (setq ndup (1+ ndup)))
410 (push id found)
411 (push id ids)))
412 (push (cons (abbreviate-file-name file) ids) reg))))))
413 (org-release-buffers org-agenda-new-buffers)
414 (setq org-agenda-new-buffers nil)
415 (setq org-id-locations reg)
416 (setq org-id-files (mapcar 'car org-id-locations))
417 (org-id-locations-save) ;; this function can also handle the alist form
418 ;; now convert to a hash
419 (setq org-id-locations (org-id-alist-to-hash org-id-locations))
420 (if (> ndup 0)
421 (message "WARNING: %d duplicate ID's found, check *Messages* buffer" ndup)
422 (message "%d unique files scanned for ID's" (length org-id-files)))
423 org-id-locations)))
424 358
425(defun org-id-locations-save () 359(defun org-id-locations-save ()
426 "Save `org-id-locations' in `org-id-locations-file'." 360 "Save `org-id-locations' in `org-id-locations-file'."
427 (when org-id-track-globally 361 (with-temp-file org-id-locations-file
428 (let ((out (if (hash-table-p org-id-locations) 362 (print org-id-locations (current-buffer))))
429 (org-id-hash-to-alist org-id-locations)
430 org-id-locations)))
431 (with-temp-file org-id-locations-file
432 (print out (current-buffer))))))
433 363
434(defun org-id-locations-load () 364(defun org-id-locations-load ()
435 "Read the data from `org-id-locations-file'." 365 "Read the data from `org-id-locations-file'."
436 (setq org-id-locations nil) 366 (setq org-id-locations nil)
437 (when org-id-track-globally 367 (with-temp-buffer
438 (with-temp-buffer 368 (condition-case nil
439 (condition-case nil 369 (progn
440 (progn 370 (insert-file-contents-literally org-id-locations-file)
441 (insert-file-contents-literally org-id-locations-file) 371 (goto-char (point-min))
442 (goto-char (point-min)) 372 (setq org-id-locations (read (current-buffer))))
443 (setq org-id-locations (read (current-buffer)))) 373 (error
444 (error 374 (message "Could not read org-id-values from %s. Setting it to nil."
445 (message "Could not read org-id-values from %s. Setting it to nil." 375 org-id-locations-file)))))
446 org-id-locations-file))))
447 (setq org-id-files (mapcar 'car org-id-locations))
448 (setq org-id-locations (org-id-alist-to-hash org-id-locations))))
449 376
450(defun org-id-add-location (id file) 377(defun org-id-add-location (id file)
451 "Add the ID with location FILE to the database of ID loations." 378 "Add the ID with location FILE to the database of ID loations."
452 ;; Only if global tracking is on, and when the buffer has a file 379 (when (and id file) ; don't error when called from a buffer with no file
453 (when (and org-id-track-globally id file)
454 (unless org-id-locations (org-id-locations-load)) 380 (unless org-id-locations (org-id-locations-load))
455 (puthash id (abbreviate-file-name file) org-id-locations) 381 (catch 'exit
456 (add-to-list 'org-id-files (abbreviate-file-name file)))) 382 (let ((locs org-id-locations) list)
457 383 (while (setq list (pop locs))
458(add-hook 'kill-emacs-hook 'org-id-locations-save) 384 (when (equal (file-truename file) (file-truename (car list)))
459 385 (setcdr list (cons id (cdr list)))
460(defun org-id-hash-to-alist (hash) 386 (throw 'exit t))))
461 "Turn an org-id hash into an alist, so that it can be written to a file." 387 (push (list file id) org-id-locations))
462 (let (res x) 388 (org-id-locations-save)))
463 (maphash
464 (lambda (k v)
465 (if (setq x (member v res))
466 (push k (cdr x))
467 (push (list v k) res)))
468 hash)
469 res))
470
471(defun org-id-alist-to-hash (list)
472 "Turn an org-id location list into a hash table."
473 (let ((res (make-hash-table
474 :test 'equal
475 :size (apply '+ (mapcar 'length list))))
476 f i)
477 (mapc
478 (lambda (x)
479 (setq f (car x))
480 (mapc (lambda (i) (puthash i f res)) (cdr x)))
481 list)
482 res))
483
484(defun org-id-paste-tracker (txt &optional buffer-or-file)
485 "Update any ID's in TXT and assign BUFFER-OR-FILE to them."
486 (when org-id-track-globally
487 (save-match-data
488 (setq buffer-or-file (or buffer-or-file (current-buffer)))
489 (when (bufferp buffer-or-file)
490 (setq buffer-or-file (or (buffer-base-buffer buffer-or-file)
491 buffer-or-file))
492 (setq buffer-or-file (buffer-file-name buffer-or-file)))
493 (when buffer-or-file
494 (let ((fname (abbreviate-file-name buffer-or-file))
495 (s 0))
496 (while (string-match "^[ \t]*:ID:[ \t]+\\([^ \t\n\r]+\\)" txt s)
497 (setq s (match-end 0))
498 (org-id-add-location (match-string 1 txt) fname)))))))
499 389
500;; Finding entries with specified id 390;; Finding entries with specified id
501 391
502(defun org-id-find-id-file (id) 392(defun org-id-find-id-file (id)
503 "Query the id database for the file in which this ID is located." 393 "Query the id database for the file in which this ID is located."
504 (unless org-id-locations (org-id-locations-load)) 394 (unless org-id-locations (org-id-locations-load))
505 (or (gethash id org-id-locations) 395 (catch 'found
506 ;; ball back on current buffer 396 (mapc (lambda (x) (if (member id (cdr x))
507 (buffer-file-name (or (buffer-base-buffer (current-buffer)) 397 (throw 'found (car x))))
508 (current-buffer))))) 398 org-id-locations)
399 nil))
509 400
510(defun org-id-find-id-in-file (id file &optional markerp) 401(defun org-id-find-id-in-file (id file &optional markerp)
511 "Return the position of the entry ID in FILE. 402 "Return the position of the entry ID in FILE.
@@ -524,35 +415,8 @@ optional argument MARKERP, return the position as a new marker."
524 (move-marker (make-marker) pos buf) 415 (move-marker (make-marker) pos buf)
525 (cons file pos)))))))) 416 (cons file pos))))))))
526 417
527;; id link type
528
529;; Calling the following function is hard-coded into `org-store-link',
530;; so we do have to add it to `org-store-link-functions'.
531
532(defun org-id-store-link ()
533 "Store a link to the current entry, using it's ID."
534 (interactive)
535 (let* ((link (org-make-link "id:" (org-id-get-create)))
536 (desc (save-excursion
537 (org-back-to-heading t)
538 (or (and (looking-at org-complex-heading-regexp)
539 (if (match-end 4) (match-string 4) (match-string 0)))
540 link))))
541 (org-store-link-props :link link :description desc :type "id")
542 link))
543
544(defun org-id-open (id)
545 "Go to the entry with id ID."
546 (org-mark-ring-push)
547 (switch-to-buffer-other-window (current-buffer))
548 (org-id-goto id))
549
550(org-add-link-type "id" 'org-id-open)
551
552(provide 'org-id) 418(provide 'org-id)
553 419
554;;; org-id.el ends here 420;;; org-id.el ends here
555 421
556;; arch-tag: e5abaca4-e16f-4b25-832a-540cfb63a712 422;; arch-tag: e5abaca4-e16f-4b25-832a-540cfb63a712
557
558
diff --git a/lisp/org/org-timer.el b/lisp/org/org-timer.el
new file mode 100644
index 00000000000..ff2fc2bff2b
--- /dev/null
+++ b/lisp/org/org-timer.el
@@ -0,0 +1,181 @@
1;;; org-clock.el --- The time clocking code for Org-mode
2
3;; Copyright (C) 2008 Free Software Foundation, Inc.
4
5;; Author: Carsten Dominik <carsten at orgmode dot org>
6;; Keywords: outlines, hypermedia, calendar, wp
7;; Homepage: http://orgmode.org
8;; Version: 6.14
9;;
10;; This file is part of GNU Emacs.
11;;
12;; GNU Emacs is free software: you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25;;
26;;; Commentary:
27
28;; This file contains the relative timer code for Org-mode
29
30(require 'org)
31
32(defvar org-timer-start-time nil
33 "t=0 for the running timer.")
34
35(defconst org-timer-re "\\([-+]?[0-9]+\\):\\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)"
36 "Regular expression used to match timer stamps.")
37
38(defcustom org-timer-format "%s "
39 "The format to insert the time of the timer.
40This format must contain one instance of \"%s\" which will be replaced by
41the value of the relative timer."
42 :group 'org-time
43 :type 'string)
44
45;;;###autoload
46(defun org-timer-start (&optional offset)
47 "Set the starting time for the relative timer to now.
48When called with prefix argument OFFSET, prompt the user for an offset time,
49with the default taken from a timer stamp at point, if any.
50If OFFSET is a string or an integer, it is directly taken to be the offset
51without user interaction.
52When called with a double prefix arg, all timer strings in the active
53region will be shifted by a specific amount. You will be prompted for
54the amount, with the default to make the first timer string in
55the region 0:00:00."
56 (interactive "P")
57 (if (equal offset '(16))
58 (call-interactively 'org-timer-change-times-in-region)
59 (let (delta def s)
60 (if (not offset)
61 (setq org-timer-start-time (current-time))
62 (cond
63 ((integerp offset) (setq delta offset))
64 ((stringp offset) (setq delta (org-timer-hms-to-secs offset)))
65 (t
66 (setq def (if (org-in-regexp org-timer-re)
67 (match-string 0)
68 "0:00:00")
69 s (read-string
70 (format "Restart timer with offset [%s]: " def)))
71 (unless (string-match "\\S-" s) (setq s def))
72 (setq delta (org-timer-hms-to-secs (org-timer-fix-incomplete s)))))
73 (setq org-timer-start-time
74 (seconds-to-time
75 (-
76 (time-to-seconds (current-time))
77 (org-timer-hms-to-secs s)))))
78 (message "Timer start time set to %s, current value is %s"
79 (format-time-string "%T" org-timer-start-time)
80 (org-timer-secs-to-hms (or delta 0))))))
81
82;;;###autoload
83(defun org-timer (&optional restart)
84 "Insert a H:MM:SS string from the timer into the buffer.
85The first time this command is used, the timer is started. When used with
86a `C-u' prefix, force restarting the timer.
87When used with a double prefix arg `C-u C-u', change all the timer string
88in the region by a fixed amount. This can be used to recalibrate a timer
89that was not started at the correct moment."
90 (interactive "P")
91 (if (equal restart '(4)) (org-timer-start))
92 (or org-timer-start-time (org-timer-start))
93 (insert (format
94 org-timer-format
95 (org-timer-secs-to-hms
96 (floor
97 (- (time-to-seconds (current-time))
98 (time-to-seconds org-timer-start-time)))))))
99
100;;;###autoload
101(defun org-timer-change-times-in-region (beg end delta)
102 "Change all h:mm:ss time in region by a DELTA."
103 (interactive
104 "r\nsEnter time difference like \"-1:08:26\". Default is first time to zero: ")
105 (let ((re "[-+]?[0-9]+:[0-9]\\{2\\}:[0-9]\\{2\\}") p)
106 (unless (string-match "\\S-" delta)
107 (save-excursion
108 (goto-char beg)
109 (when (re-search-forward re end t)
110 (setq delta (match-string 0))
111 (if (equal (string-to-char delta) ?-)
112 (setq delta (substring delta 1))
113 (setq delta (concat "-" delta))))))
114 (setq delta (org-timer-hms-to-secs (org-timer-fix-incomplete delta)))
115 (when (= delta 0) (error "No change"))
116 (save-excursion
117 (goto-char end)
118 (while (re-search-backward re beg t)
119 (setq p (point))
120 (replace-match
121 (save-match-data
122 (org-timer-secs-to-hms (+ (org-timer-hms-to-secs (match-string 0)) delta)))
123 t t)
124 (goto-char p)))))
125
126;;;###autoload
127(defun org-timer-item (&optional arg)
128 "Insert a description-type item with the curren timer value."
129 (interactive "P")
130 (let ((ind 0))
131 (save-excursion
132 (skip-chars-backward " \n\t")
133 (condition-case nil
134 (progn
135 (org-beginning-of-item)
136 (setq ind (org-get-indentation)))
137 (error nil)))
138 (or (bolp) (newline))
139 (org-indent-line-to ind)
140 (insert "- ")
141 (org-timer (if arg '(4)))
142 (insert ":: ")))
143
144(defun org-timer-fix-incomplete (hms)
145 "If hms is a H:MM:SS string with missing hour or hour and minute, fix it."
146 (if (string-match "\\(?:\\([0-9]+:\\)?\\([0-9]+:\\)\\)?\\([0-9]+\\)" hms)
147 (replace-match
148 (format "%d:%02d:%02d"
149 (if (match-end 1) (string-to-number (match-string 1 hms)) 0)
150 (if (match-end 2) (string-to-number (match-string 2 hms)) 0)
151 (string-to-number (match-string 3 hms)))
152 t t hms)
153 (error "Canot parse HMS string \"%s\"" hms)))
154
155(defun org-timer-hms-to-secs (hms)
156 "Convert h:mm:ss string to an integer time.
157If the string starts with a minus sign, the integer will be negative."
158 (if (not (string-match
159 "\\([-+]?[0-9]+\\):\\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)"
160 hms))
161 0
162 (let* ((h (string-to-number (match-string 1 hms)))
163 (m (string-to-number (match-string 2 hms)))
164 (s (string-to-number (match-string 3 hms)))
165 (sign (equal (substring (match-string 1 hms) 0 1) "-")))
166 (setq h (abs h))
167 (* (if sign -1 1) (+ s (* 60 (+ m (* 60 h))))))))
168
169(defun org-timer-secs-to-hms (s)
170 "Convert integer S into h:mm:ss.
171If the integer is negative, the strig will start with \"-\"."
172 (let (sign m h)
173 (setq sign (if (< s 0) "-" "")
174 s (abs s)
175 m (/ s 60) s (- s (* 60 m))
176 h (/ m 60) m (- m (* 60 h)))
177 (format "%s%d:%02d:%02d" sign h m s)))
178
179;; arch-tag: 97538f8c-3871-4509-8f23-1e7b3ff3d107
180
181;;; org-timer.el ends here
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 8171a0271f6..cb105c24457 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -956,40 +956,6 @@ It should match if the message is from the user him/herself."
956 :group 'org-link-store 956 :group 'org-link-store
957 :type 'regexp) 957 :type 'regexp)
958 958
959(defcustom org-link-to-org-use-id 'create-if-interactive
960 "Non-nil means, storing a link to an Org file will use entry ID's.
961
962Note that before this variable is even considered, org-id must be loaded,
963to please customize `org-modules' and turn it on.
964
965The variable can have the following values:
966
967t Create an ID if needed to make a link to the current entry.
968
969create-if-interactive
970 If `org-store-link' is called directly (interactively, as a user
971 command), do create an ID to support the link. But when doing the
972 job for remember, only use the ID if it already exists. The
973 purpose of this setting is to avoid proliferation of unwanted
974 ID's, just because you happen to be in an Org file when you
975 call `org-remember' that automatically and preemptively
976 creates a link. If you do want to get an ID link in a remember
977 template to an entry not having an ID, create it first by
978 explicitly creating a link to it, using `C-c C-l' first.
979
980use-existing
981 Use existing ID, do not create one.
982
983nil Never use an ID to make a link, instead link using a text search for
984 the headline text."
985 :group 'org-link-store
986 :type '(choice
987 (const :tag "Create ID to make link" t)
988 (const :tag "Create if string link interactively"
989 'create-if-interactive)
990 (const :tag "Only use existing" 'use-existing)
991 (const :tag "Do not use ID to create link" nil)))
992
993(defcustom org-context-in-file-links t 959(defcustom org-context-in-file-links t
994 "Non-nil means, file links from `org-store-link' contain context. 960 "Non-nil means, file links from `org-store-link' contain context.
995A search string will be added to the file name with :: as separator and 961A search string will be added to the file name with :: as separator and
@@ -2840,12 +2806,11 @@ collapsed state."
2840 2806
2841;; Autoload ID code 2807;; Autoload ID code
2842 2808
2843(declare-function org-id-store-link "org-id")
2844(org-autoload "org-id" 2809(org-autoload "org-id"
2845 '(org-id-get-create org-id-new org-id-copy org-id-get 2810 '(org-id-get-create org-id-new org-id-copy org-id-get
2846 org-id-get-with-outline-path-completion 2811 org-id-get-with-outline-path-completion
2847 org-id-get-with-outline-drilling 2812 org-id-get-with-outline-drilling
2848 org-id-goto org-id-find org-id-store-link)) 2813 org-id-goto org-id-find))
2849 2814
2850;;; Variables for pre-computed regular expressions, all buffer local 2815;;; Variables for pre-computed regular expressions, all buffer local
2851 2816
@@ -5303,7 +5268,6 @@ the inserted text when done."
5303 (beginning-of-line 1) 5268 (beginning-of-line 1)
5304 (unless for-yank (org-back-over-empty-lines)) 5269 (unless for-yank (org-back-over-empty-lines))
5305 (setq beg (point)) 5270 (setq beg (point))
5306 (and (fboundp 'org-id-paste-tracker) (org-id-paste-tracker txt))
5307 (insert-before-markers txt) 5271 (insert-before-markers txt)
5308 (unless (string-match "\n\\'" txt) (insert "\n")) 5272 (unless (string-match "\n\\'" txt) (insert "\n"))
5309 (setq newend (point)) 5273 (setq newend (point))
@@ -6177,6 +6141,7 @@ type. For a simple example of an export function, see `org-bbdb.el'."
6177 (setcdr (assoc type org-link-protocols) (list follow export)) 6141 (setcdr (assoc type org-link-protocols) (list follow export))
6178 (push (list type follow export) org-link-protocols))) 6142 (push (list type follow export) org-link-protocols)))
6179 6143
6144
6180;;;###autoload 6145;;;###autoload
6181(defun org-store-link (arg) 6146(defun org-store-link (arg)
6182 "\\<org-mode-map>Store an org-link to the current location. 6147 "\\<org-mode-map>Store an org-link to the current location.
@@ -6237,34 +6202,14 @@ For file links, arg negates `org-context-in-file-links'."
6237 link (org-make-link cpltxt))) 6202 link (org-make-link cpltxt)))
6238 6203
6239 ((and buffer-file-name (org-mode-p)) 6204 ((and buffer-file-name (org-mode-p))
6240 (cond 6205 ;; Just link to current headline
6241 ((org-in-regexp "<<\\(.*?\\)>>") 6206 (setq cpltxt (concat "file:"
6242 (setq cpltxt 6207 (abbreviate-file-name buffer-file-name)))
6243 (concat "file:" 6208 ;; Add a context search string
6244 (abbreviate-file-name buffer-file-name) 6209 (when (org-xor org-context-in-file-links arg)
6245 "::" (match-string 1)) 6210 ;; Check if we are on a target
6246 link (org-make-link cpltxt))) 6211 (if (org-in-regexp "<<\\(.*?\\)>>")
6247 ((and (featurep 'org-id) 6212 (setq cpltxt (concat cpltxt "::" (match-string 1)))
6248 (or (eq org-link-to-org-use-id t)
6249 (and (eq org-link-to-org-use-id 'create-if-interactive)
6250 (interactive-p))
6251 (and org-link-to-org-use-id
6252 (condition-case nil
6253 (org-entry-get nil "ID")
6254 (error nil)))))
6255 ;; We can make a link using the ID.
6256 (setq link (condition-case nil
6257 (org-id-store-link)
6258 (error
6259 ;; probably before first headling, link to file only
6260 (concat "file:"
6261 (abbreviate-file-name buffer-file-name))))))
6262 (t
6263 ;; Just link to current headline
6264 (setq cpltxt (concat "file:"
6265 (abbreviate-file-name buffer-file-name)))
6266 ;; Add a context search string
6267 (when (org-xor org-context-in-file-links arg)
6268 (setq txt (cond 6213 (setq txt (cond
6269 ((org-on-heading-p) nil) 6214 ((org-on-heading-p) nil)
6270 ((org-region-active-p) 6215 ((org-region-active-p)
@@ -6276,10 +6221,10 @@ For file links, arg negates `org-context-in-file-links'."
6276 (condition-case nil 6221 (condition-case nil
6277 (org-make-org-heading-search-string txt) 6222 (org-make-org-heading-search-string txt)
6278 (error ""))) 6223 (error "")))
6279 desc "NONE"))) 6224 desc "NONE"))))
6280 (if (string-match "::\\'" cpltxt) 6225 (if (string-match "::\\'" cpltxt)
6281 (setq cpltxt (substring cpltxt 0 -2))) 6226 (setq cpltxt (substring cpltxt 0 -2)))
6282 (setq link (org-make-link cpltxt))))) 6227 (setq link (org-make-link cpltxt)))
6283 6228
6284 ((buffer-file-name (buffer-base-buffer)) 6229 ((buffer-file-name (buffer-base-buffer))
6285 ;; Just link to this file here. 6230 ;; Just link to this file here.
@@ -10614,7 +10559,6 @@ completion."
10614IDENT can be a string, a symbol or a number, this function will search for 10559IDENT can be a string, a symbol or a number, this function will search for
10615the string representation of it. 10560the string representation of it.
10616Return the position where this entry starts, or nil if there is no such entry." 10561Return the position where this entry starts, or nil if there is no such entry."
10617 (interactive "sID: ")
10618 (let ((id (cond 10562 (let ((id (cond
10619 ((stringp ident) ident) 10563 ((stringp ident) ident)
10620 ((symbol-name ident) (symbol-name ident)) 10564 ((symbol-name ident) (symbol-name ident))