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

(org-agenda-toggle-time-grid): New command.

	(org-agenda-use-time-grid, org-agenda-time-grid): New options.
	(org-agenda-add-time-grid-maybe): New function.
	(org-agenda): Call `org-agenda-add-time-grid-maybe'.
	(org-table-create): `dotimes' instead of `mapcar'.
	(org-xor): Simplified implementation.
	(org-agenda): `inhibit-redisplay' turned on.
	(org-agenda-change-all-lines): Use `org-format-agenda-item' to get
	a consistent line after a state change.
	(org-agenda-remove-times-when-in-prefix): New option.
	(org-prefix-has-time): New variable.
	(org-parse-time-string): Optional argument NODEFAULT.
	(org-format-agenda-item): Parse items for time-of-day
	specifications and move these into the prefix if possible.
	(org-agenda-priority): Get current heading, not previous heading
	during agenda remote editing.
parent f3fbdb1f
......@@ -5,7 +5,7 @@
;; Author: Carsten Dominik <dominik at science dot uva dot nl>
;; Keywords: outlines, hypermedia, calendar
;; Homepage: http://www.astro.uva.nl/~dominik/Tools/org/
;; Version: 3.08
;; Version: 3.09
;;
;; This file is part of GNU Emacs.
;;
......@@ -31,27 +31,30 @@
;; project planning with a fast and effective plain-text system.
;;
;; Org-mode develops organizational tasks around a NOTES file that contains
;; information about projects as plain text. Org-mode is implemented on
;; top of outline-mode - ideal to keep the content of large files well
;; structured. It supports ToDo items, deadlines and time stamps, which
;; magically appear in the diary listing of the Emacs calendar. Tables are
;; easily created with a built-in table editor. Plain text URL-like links
;; connect to websites, emails (VM,RMAIL,WANDERLUST), Usenet messages (Gnus),
;; BBDB entries, and any files related to the projects. For printing and
;; sharing of notes, an Org-mode file (or a part of it) can be exported as
;; a structured ASCII file, or as HTML.
;; information about projects as plain text. Org-mode is implemented on top
;; of outline-mode - ideal to keep the content of large files well structured.
;; It supports ToDo items, deadlines and time stamps, which can be extracted
;; to create a daily/weekly agenda that also integrates the diary of the Emacs
;; calendar. Tables are easily created with a built-in table editor. Plain
;; text URL-like links connect to websites, emails (VM, RMAIL, WANDERLUST),
;; Usenet messages (Gnus), BBDB entries, and any files related to the
;; projects. For printing and sharing of notes, an Org-mode file (or a part
;; of it) can be exported as a structured ASCII file, or as HTML.
;;
;; Installation
;; ------------
;; The instruction below assume that you have downloaded Org-mode from the
;; web. If Org-mode is part of the Emacs distribution or an XEmacs package,
;; you only need to add to .emacs the last three lines of Lisp code listed
;; below, i.e. the `auto-mode-alist' modification and the global key bindings.
;; If Org-mode is part of the Emacs distribution or an XEmacs package, you
;; only need to copy the following lines to your .emacs file. The last two
;; lines define *global* keys for the commands `org-store-link' and
;; `org-agenda' - please choose suitable keys yourself.
;;
;; Byte-compile org.el and put it on your load path. Then copy the
;; following lines into .emacs. The last two lines define *global*
;; keys for the commands `org-store-link' and `org-agenda' - please
;; choose suitable keys yourself.
;; (add-to-list 'auto-mode-alist '("\\.org$" . org-mode))
;; (define-key global-map "\C-cl" 'org-store-link)
;; (define-key global-map "\C-ca" 'org-agenda)
;;
;; If you have downloaded Org-mode from the Web, you must byte-compile
;; org.el and put it on your load path. In addition to the Emacs Lisp
;; lines above, you also need to add the following lines to .emacs:
;;
;; (autoload 'org-mode "org" "Org mode" t)
;; (autoload 'org-diary "org" "Diary entries from Org mode")
......@@ -59,12 +62,9 @@
;; (autoload 'org-store-link "org" "Store a link to the current location" t)
;; (autoload 'orgtbl-mode "org" "Org tables as a minor mode" t)
;; (autoload 'turn-on-orgtbl "org" "Org tables as a minor mode")
;; (add-to-list 'auto-mode-alist '("\\.org$" . org-mode))
;; (define-key global-map "\C-cl" 'org-store-link)
;; (define-key global-map "\C-ca" 'org-agenda)
;;
;; This will put all files with extension ".org" into Org-mode. As an
;; alternative, make the first line of a file look like this:
;; This setup will put all files with extension ".org" into Org-mode. As
;; an alternative, make the first line of a file look like this:
;;
;; MY PROJECTS -*- mode: org; -*-
;;
......@@ -73,12 +73,18 @@
;;
;; Documentation
;; -------------
;; The documentation of Org-mode can be found in the TeXInfo file.
;; The distribution also contains a PDF version of it. At the homepage
;; of Org-mode, you can read the same text online as HTML.
;; The documentation of Org-mode can be found in the TeXInfo file. The
;; distribution also contains a PDF version of it. At the homepage of
;; Org-mode, you can read the same text online as HTML. There is also an
;; excellent reference card made by Philip Rooke.
;;
;; Changes:
;; -------
;; Version 3.09
;; - Time-of-day specifications in agenda are extracted and placed
;; into the prefix. Timed entries can be placed into a time grid for
;; day.
;;
;; Version 3.08
;; - "|" no longer allowed as part of a link, to allow links in tables.
;; - The prefix of items in the agenda buffer can be configured.
......@@ -136,7 +142,7 @@
;; warnings about upcoming deadlines/overdue scheduled items.
;; That functionality is now limited to the (multifile) agenda.
;; - When reading a date, the calendar can be manipulated with keys.
;; - Link support for RMAIL and Wanderlust (from planner.el, untested)
;; - Link support for RMAIL and Wanderlust (from planner.el, untested).
;; - Minor bug fixes and documentation improvements.
;;; Code:
......@@ -148,16 +154,15 @@
;;; Customization variables
(defvar org-version "3.08"
(defvar org-version "3.09"
"The version number of the file org.el.")
(defun org-version ()
(interactive)
(message "Org-mode version %s" org-version))
;; The following two constants are for compatibility with different
;; Emacs versions (Emacs versus XEmacs) and with different versions of
;; outline.el. All the compatibility code in org.el is based on these two
;; constants.
;; The following two constants are for compatibility with different Emacs
;; versions (Emacs versus XEmacs) and with different versions of outline.el.
;; The compatibility code in org.el is based on these two constants.
(defconst org-xemacs-p (featurep 'xemacs)
"Are we running xemacs?")
(defconst org-noutline-p (featurep 'noutline)
......@@ -570,7 +575,7 @@ the grouped in categories, don't sort the categories, but keep them in
the sequence given in `org-agenda-files'. Within each category sort by
priority.
Leaving out the `category-keep' would mean that items will be sorted across
Leaving out `category-keep' would mean that items will be sorted across
categories by priority."
:group 'org-agenda
:type '(repeat
......@@ -583,7 +588,7 @@ categories by priority."
(const priority-up)
(const priority-down))))
(defcustom org-agenda-prefix-format " %-12:c% s"
(defcustom org-agenda-prefix-format " %-12:c%?-12t% s"
"Format specification for the prefix of items in the agenda buffer.
This format works similar to a printf format, with the following meaning:
......@@ -593,22 +598,39 @@ This format works similar to a printf format, with the following meaning:
format HH:MM
%s Scheduling/Deadline information, a short string
In addition to the normal printf field modifiers like field width and
padding instructions, in this format you can also add an additional
punctuation or whitespace character just before the final format letter.
This character will be appended to the field value if the value is not
empty. For example, the format \"%-12:c\" leads to \"Diary: \" if
the category is \"Diary\". If the category were be empty, no additional
colon would be interted.
Including `%t' in the format string leads to a double time specification
because the headline/diary item will contain the time specification as
well. However, using `%t' in the format will result in a canonical 24
hour time specification at a consistent position in the prefix, while the
time specification in the headline/diary item may be at any position and in
various formats.
Example:
(setq org-agenda-prefix-format \" %-12:c% t% s\")"
All specifiers work basically like the standard `%s' of printf, but may
contain two additional characters: A question mark just after the `%' and
a whitespace/punctuation character just before the final letter.
If the first character after `%' is a question mark, the entire field
will only be included if the corresponding value applies to the
current entry. This is useful for fields which should have fixed
width when present, but zero width when absent. For example,
\"%?-12t\" will result in a 12 character time field if a time of the
day is specified, but will completely disappear in entries which do
not contain a time.
If there is punctuation or whitespace character just before the final
format letter, this character will be appended to the field value if
the value is not empty. For example, the format \"%-12:c\" leads to
\"Diary: \" if the category is \"Diary\". If the category were be
empty, no additional colon would be interted.
The default value of this option is \" %-12:c%?-12t% s\", meaning:
- Indent the line with two space characters
- Give the category in a 12 chars wide field, padded with whitespace on
the right (because of `-'). Append a colon if there is a category
(because of `:').
- If there is a time-of-day, put it into a 12 chars wide field. If no
time, don't put in an empty field, just skip it (because of '?').
- Finally, put the scheduling information and append a whitespace.
As another example, if you don't want the time-of-day of entries in
the prefix, you could use:
(setq org-agenda-prefix-format \" %-11:c% s\")
See also the variable `org-agenda-remove-times-when-in-prefix'."
:type 'string
:group 'org-agenda)
......@@ -618,13 +640,64 @@ Example:
:group 'org-agenda)
(defvar org-prefix-format-compiled nil
"The compiled version of `org-???-prefix-format'.")
"The compiled version of the most recently used prefix format.
Depending on which command was used last, this may be the compiled version
of `org-agenda-prefix-format' or `org-timeline-prefix-format'.")
(defcustom org-agenda-use-time-grid t
"Non-nil means, show a time grid in the agenda schedule.
A time grid is a set of lines for specific times (like every two hours between
8:00 and 20:00. The items scheduled for a day at specific times are
sorted in between these lines.
For deails about when the grid will be shown, and what it will look like, see
the variable `org-agenda-time-grid'."
:group 'org-agenda
:type 'boolean)
(defcustom org-agenda-time-grid
'((daily today require-timed)
"----------------"
(800 1000 1200 1400 1600 1800 2000))
"FIXME: document"
:group 'org-agenda
:type
'(list
(set :greedy t :tag "Grid Display Options"
(const :tag "Show grid in single day agenda display" daily)
(const :tag "Show grid in weekly agenda display" weekly)
(const :tag "Always show grid for today" today)
(const :tag "Show grid only if any timed entries are present"
require-timed)
(const :tag "Skip grid times already present in an entry"
remove-match))
(string :tag "Grid String")
(repeat :tag "Grid Times" (integer :tag "Time"))))
(defcustom org-agenda-remove-times-when-in-prefix t
"Non-nil means, remove duplicate time specifications in agenda items.
When the format `org-agenda-prefix-format' contains a `%t' specifier, a
time-of-day specification in a headline or diary entry is extracted and
placed into the prefix. If this option is non-nil, the original specification
\(a timestamp or -range, or just a plain time(range) specification like
11:30-4pm) will be removed for agenda display. This makes the agenda less
cluttered.
The option can be t or nil. It may also be the symbol `beg', indicating
that the time should only be removed what it is located at the beginning of
the headline/diary entry."
:group 'org-agenda
:type '(choice
(const :tag "Always" t)
(const :tag "Never" nil)
(const :tag "When at beginning of entry" beg)))
(defcustom org-sort-agenda-notime-is-late t
"Non-nil means, items without time are considered late.
This is only relevant for sorting. When t, items which have no explicit
time like 15:30 will be considered as 24:01, i.e. later than any items which
do have a time. When nil, the default time is before 0:00."
do have a time. When nil, the default time is before 0:00. You can use this
option to decide if the schedule for today should come before or after timeless
agenda entries."
:group 'org-agenda
:type 'boolean)
......@@ -1370,6 +1443,14 @@ When this is non-nil, the headline after the keyword is set to the
"Face used for tables."
:group 'org-faces)
(defface org-time-grid-face ;; font-lock-variable-name-face
'((((type tty) (class color)) (:foreground "yellow" :weight light))
(((class color) (background light)) (:foreground "DarkGoldenrod"))
(((class color) (background dark)) (:foreground "LightGoldenrod"))
(t (:bold t :italic t)))
"Face used for level 2 headlines."
:group 'org-faces)
(defvar org-level-faces
'(
org-level-1-face
......@@ -1496,7 +1577,7 @@ The following commands are available:
(save-excursion
(goto-char (point-min))
(insert " -*- mode: org -*-\n\n")))
(run-hooks 'org-mode-hook) ;FIXME: Should be run-mode-hooks.
(run-hooks 'org-mode-hook)
(unless org-inhibit-startup
(if org-startup-with-deadline-check
(call-interactively 'org-check-deadlines)
......@@ -1565,7 +1646,7 @@ The following commands are available:
(save-excursion
(org-back-to-heading t)
(- (match-end 0) (match-beginning 0))))
(defvar org-font-lock-keywords nil)
(defun org-set-font-lock-defaults ()
......@@ -2844,13 +2925,17 @@ days in order to avoid rounding problems."
(defun org-time-string-to-time (s)
(apply 'encode-time (org-parse-time-string s)))
(defun org-parse-time-string (s)
(defun org-parse-time-string (s &optional nodefault)
"Parse the standard Org-mode time string.
This should be a lot faster than the normal `parse-time-string'."
This should be a lot faster than the normal `parse-time-string'.
If time is not given, defaults to 0:00. However, with optional NODEFAULT,
hour and minute fields will be nil if not given."
(if (string-match org-ts-regexp1 s)
(list 0
(string-to-number (or (match-string 8 s) "0"))
(string-to-number (or (match-string 7 s) "0"))
(if (or (match-beginning 8) (not nodefault))
(string-to-number (or (match-string 8 s) "0")))
(if (or (match-beginning 7) (not nodefault))
(string-to-number (or (match-string 7 s) "0")))
(string-to-number (match-string 4 s))
(string-to-number (match-string 3 s))
(string-to-number (match-string 2 s))
......@@ -3056,6 +3141,7 @@ The following commands are available:
(define-key org-agenda-mode-map "f" 'org-agenda-follow-mode)
(define-key org-agenda-mode-map "d" 'org-agenda-toggle-diary)
(define-key org-agenda-mode-map "g" 'org-agenda-toggle-time-grid)
(define-key org-agenda-mode-map "r" 'org-agenda-redo)
(define-key org-agenda-mode-map "q" 'org-agenda-quit)
(define-key org-agenda-mode-map "x" 'org-agenda-exit)
......@@ -3115,7 +3201,7 @@ The following commands are available:
["Decrease Priority" org-agenda-priority-down t]
["Show Priority" org-agenda-show-priority t])
"--"
["Rebuild" org-agenda-redo t]
["Rebuild buffer" org-agenda-redo t]
["Goto Today" org-agenda-goto-today t]
["Next Dates" org-agenda-later (local-variable-p 'starting-day)]
["Previous Dates" org-agenda-earlier (local-variable-p 'starting-day)]
......@@ -3124,6 +3210,8 @@ The following commands are available:
(local-variable-p 'starting-day)]
["Include Diary" org-agenda-toggle-diary
:style toggle :selected org-agenda-include-diary :active t]
["Use Time Grid" org-agenda-toggle-time-grid
:style toggle :selected org-agenda-use-time-grid :active t]
"--"
["New Diary Entry" org-agenda-diary-entry t]
("Calendar Commands"
......@@ -3294,11 +3382,13 @@ NDAYS defaults to `org-agenda-ndays'."
(d (- nt n1)))
(- sd (+ (if (< d 0) 7 0) d)))))
(day-numbers (list start))
s e rtn rtnall file date d start-pos end-pos)
(inhibit-redisplay t)
s e rtn rtnall file date d start-pos end-pos todayp nd)
(setq org-agenda-redo-command
(list 'org-agenda include-all start-day ndays))
;; Make the list of days
(setq ndays (or ndays org-agenda-ndays))
(setq ndays (or ndays org-agenda-ndays)
nd ndays)
(while (> ndays 1)
(push (1+ (car day-numbers)) day-numbers)
(setq ndays (1- ndays)))
......@@ -3324,11 +3414,15 @@ NDAYS defaults to `org-agenda-ndays'."
rtn (org-agenda-get-day-entries
file date :todo))
(setq rtnall (append rtnall rtn))))
(if rtnall (insert (org-finalize-agenda-entries rtnall) "\n")))
(when rtnall
(insert "ALL CURRENTLY OPEN TODO ITEMS:\n")
(add-text-properties (point-min) (1- (point))
(list 'face 'org-link-face))
(insert (org-finalize-agenda-entries rtnall) "\n")))
(while (setq d (pop day-numbers))
(setq date (calendar-gregorian-from-absolute d)
s (point))
(if (or (= d today)
(if (or (setq todayp (= d today))
(and (not start-pos) (= d sd)))
(setq start-pos (point))
(if (and start-pos (not end-pos))
......@@ -3347,14 +3441,18 @@ NDAYS defaults to `org-agenda-ndays'."
(setq rtnall (append rtnall rtn))))
(if (or rtnall org-agenda-show-all-dates)
(progn
(insert (format "%-9s %2d %-9s %4d\n"
(insert (format "%-9s %2d %s %4d\n"
(calendar-day-name date)
(extract-calendar-day date)
(calendar-month-name (extract-calendar-month date))
(extract-calendar-year date)))
(put-text-property s (1- (point)) 'face
'org-link-face)
(if rtnall (insert (org-finalize-agenda-entries rtnall) "\n"))
(if rtnall (insert
(org-finalize-agenda-entries ;; FIXME: condition needed
(org-agenda-add-time-grid-maybe
rtnall nd todayp))
"\n"))
(put-text-property s (1- (point)) 'day d))))
(goto-char (point-min))
(setq buffer-read-only t)
......@@ -3502,6 +3600,15 @@ With prefix ARG, go back that many times `org-agenda-ndays'."
(message "Diary inclusion turned %s"
(if org-agenda-include-diary "on" "off")))
(defun org-agenda-toggle-time-grid ()
"Toggle follow mode in an agenda buffer."
(interactive)
(setq org-agenda-use-time-grid (not org-agenda-use-time-grid))
(org-agenda-redo)
(org-agenda-set-mode-name)
(message "Time-grid turned %s"
(if org-agenda-use-time-grid "on" "off")))
(defun org-agenda-set-mode-name ()
"Set the mode name to indicate all the small mode settings."
(setq mode-name
......@@ -3509,7 +3616,8 @@ With prefix ARG, go back that many times `org-agenda-ndays'."
(if (equal org-agenda-ndays 1) " Day" "")
(if (equal org-agenda-ndays 7) " Week" "")
(if org-agenda-follow-mode " Follow" "")
(if org-agenda-include-diary " Diary" "")))
(if org-agenda-include-diary " Diary" "")
(if org-agenda-use-time-grid " Grid" "")))
(force-mode-line-update))
(defun org-agenda-post-command-hook ()
......@@ -3524,7 +3632,7 @@ With prefix ARG, go back that many times `org-agenda-ndays'."
"Get the (Emacs Calendar) diary entries for DATE."
(let* ((fancy-diary-buffer "*temporary-fancy-diary-buffer*")
(diary-display-hook '(fancy-diary-display))
(list-diary-entries-hook
(list-diary-entries-hook
(cons 'org-diary-default-entry list-diary-entries-hook))
entries
(org-disable-diary t))
......@@ -3551,7 +3659,7 @@ With prefix ARG, go back that many times `org-agenda-ndays'."
(setq entries
(mapcar
(lambda (x)
(setq x (org-format-agenda-item "" x "Diary"))
(setq x (org-format-agenda-item "" x "Diary" 'time))
;; Extend the text properties to the beginning of the line
(add-text-properties
0 (length x)
......@@ -3764,7 +3872,7 @@ the documentation of `org-diary'."
arg results rtn)
(if (not buffer)
;; If file does not exist, make sure an error message ends up in diary
(format "ORG-AGENDA-ERROR: No such org-file %s" file)
(list (format "ORG-AGENDA-ERROR: No such org-file %s" file))
(with-current-buffer buffer
(unless (eq major-mode 'org-mode)
(error "Agenda file %s is not in `org-mode'" file))
......@@ -3796,8 +3904,8 @@ the documentation of `org-diary'."
((and (eq arg :deadline)
(equal date (calendar-current-date)))
(setq rtn (org-agenda-get-deadlines))
(setq results (append results rtn))))))))))
results))
(setq results (append results rtn))))))))
results))))
(defun org-entry-is-done-p ()
"Is the current entry marked DONE?"
......@@ -3876,7 +3984,7 @@ the documentation of `org-diary'."
(list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
0 11)))
marker hdmarker deadlinep scheduledp donep tmp priority
ee txt)
ee txt timestr)
(goto-char (point-min))
(while (re-search-forward regexp nil t)
(if (not (save-match-data (org-at-date-range-p)))
......@@ -3886,9 +3994,13 @@ the documentation of `org-diary'."
(- (match-beginning 0)
org-ds-keyword-length))
(match-beginning 0))
timestr (buffer-substring (match-beginning 0) (point-at-eol))
deadlinep (string-match org-deadline-regexp tmp)
scheduledp (string-match org-scheduled-regexp tmp)
donep (org-entry-is-done-p))
(if (string-match ">" timestr)
;; substring should only run to end of time stamp
(setq timestr (substring timestr 0 (match-end 0))))
(save-excursion
(if (re-search-backward "\\(^\\|\r\\)\\*+" nil t)
(progn
......@@ -3899,7 +4011,7 @@ the documentation of `org-diary'."
(format "%s%s"
(if deadlinep "Deadline: " "")
(if scheduledp "Scheduled: " ""))
(match-string 1))))
(match-string 1) nil timestr)))
(setq txt org-agenda-no-heading-message))
(setq priority (org-get-priority txt))
(add-text-properties
......@@ -4044,10 +4156,11 @@ the documentation of `org-diary'."
(abbreviate-file-name (buffer-file-name)))))
(regexp org-tr-regexp)
(d0 (calendar-absolute-from-gregorian date))
marker hdmarker ee txt d1 d2 s1 s2)
marker hdmarker ee txt d1 d2 s1 s2 timestr)
(goto-char (point-min))
(while (re-search-forward regexp nil t)
(setq s1 (match-string 1)
(setq timestr (match-string 0)
s1 (match-string 1)
s2 (match-string 2)
d1 (time-to-days (org-time-string-to-time s1))
d2 (time-to-days (org-time-string-to-time s2)))
......@@ -4062,9 +4175,9 @@ the documentation of `org-diary'."
(goto-char (match-end 1))
(looking-at "\\*+[ \t]*\\([^\r\n]+\\)")
(setq txt (org-format-agenda-item
(format "(%d/%d): "
(format (if (= d1 d2) "" "(%d/%d): ")
(1+ (- d0 d1)) (1+ (- d2 d1)))
(match-string 1))))
(match-string 1) nil (if (= d0 d1) timestr))))
(setq txt org-agenda-no-heading-message))
(add-text-properties
0 (length txt) (append (list 'org-marker marker
......@@ -4077,66 +4190,187 @@ the documentation of `org-diary'."
;; Sort the entries by expiration date.
(nreverse ee)))
(defun org-format-agenda-item (prefix txt &optional category)
(defconst org-plain-time-of-day-regexp
(concat
"\\(\\<[012]?[0-9]"
"\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
"\\(--?"
"\\(\\<[012]?[0-9]"
"\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
"\\)?")
"Regular expression to match a plain time or time range.
Examples: 11:45 or 8am-13:15 or 2:45-2:45pm. After a match, the following
groups carry important information:
0 the full match
1 the first time, range or not
8 the second time, if it is a range.")
(defconst org-stamp-time-of-day-regexp
(concat
"<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} +[a-zA-Z]+ +\\)"
"\\([012][0-9]:[0-5][0-9]\\)>"
"\\(--?"
"<\\1\\([012][0-9]:[0-5][0-9]\\)>\\)?")
"Regular expression to match a timestamp time or time range.
After a match, the following groups carry important information:
0 the full match
1 date plus weekday, for backreferencing to make sure both times on same day
2 the first time, range or not
4 the second time, if it is a range.")
(defvar org-prefix-has-time nil
"A flag, set by `org-compile-prefix-format'.
The flag is set if the currently compiled format contains a `%t'.")
(defun org-format-agenda-item (extra txt &optional category dotime noprefix)
"Format TXT to be inserted into the agenda buffer.
In particular, this indents the line and adds a category."
(let* ((category (or category
org-category
(file-name-sans-extension
(file-name-nondirectory (buffer-file-name)))))
(extra prefix)
(time-of-day (org-get-time-of-day txt))
(t1 (if time-of-day (concat "0" (int-to-string time-of-day)) "0000"))
(time (if time-of-day
(concat (substring t1 -4 -2)
":" (substring t1 -2))
""))
rtn)
(if (symbolp category) (setq category (symbol-name category)))
(setq rtn (concat (eval org-prefix-format-compiled) txt))
(add-text-properties
0 (length rtn) (list 'category (downcase category)
'prefix-length (- (length rtn) (length txt))
'time-of-day time-of-day)
rtn)
rtn))
In particular, it adds the prefix and corresponding text properties. EXTRA
must be a string and replaces the `%s' specifier in the prefix format.
CATEGORY (string, symbol or nil) may be used to overule the default
category taken from local variable or file name. It will replace the `%c'
specifier in the format. DOTIME, when non-nil, indicates that a
time-of-day should be extracted from TXT for sorting of this entry, and for
the `%t' specifier in the format. When DOTIME is a string, this string is
searched for a time before TXT is. NOPREFIX is a flag and indicates that
only the correctly processes TXT should be returned - this is used by
`org-agenda-change-all-lines'."
(save-match-data
;; Diary entries sometimes have extra whitespace at the beginning
(if (string-match "^ +" txt) (setq txt (replace-match "" nil nil txt)))
(let* ((category (or category
org-category
(if (buffer-file-name)
(file-name-sans-extension
(file-name-nondirectory (buffer-file-name)))
"")))
time ;; needed for the eval of the prefix format
(ts (if dotime (concat (if (stringp dotime) dotime "") txt)))
(time-of-day (and dotime (org-get-time-of-day ts)))
stamp plain s0 s1 s2 rtn)
(when (and dotime time-of-day org-prefix-has-time)
;; Extract starting and ending time and move them to prefix
(when (or (setq stamp (string-match org-stamp-time-of-day-regexp ts))
(setq plain (string-match org-plain-time-of-day-regexp ts)))
(setq s0 (match-string 0 ts)
s1 (match-string (if plain 1 2) ts)
s2 (match-string (if plain 8 4) ts))
;; If the times are in TXT (not in DOTIMES), and the prefix will list
;; them, we might want to remove them there to avoid duplication.
;; The user can turn this off with a variable.
(if (and org-agenda-remove-times-when-in-prefix (or stamp plain)
(string-match (concat (regexp-quote s0) " *") txt)
(if (eq org-agenda-remove-times-when-in-prefix 'beg)
(= (match-beginning 0) 0)
t))
(setq txt (replace-match "" nil nil txt))))
;; Normalize the time(s) to 24 hour
(if s1 (setq s1 (org-get-time-of-day s1 'string)))
(if s2 (setq s2 (org-get-time-of-day s2 'string))))
;; Create the final string
(if noprefix
(setq rtn txt)
;; Prepare the variables needed in the eval of the compiled format
(setq time (cond (s2 (concat s1 "-" s2))
(s1 (concat s1 "......"))
(t ""))
extra (or extra "")
category (if (symbolp category) (symbol-name category) category))
;; Evaluate the compiled format
(setq rtn (concat (eval org-prefix-format-compiled) txt)))
;; And finally add the text properties
(add-text-properties
0 (length rtn) (list 'category (downcase category)
'prefix-length (- (length rtn) (length txt))
'time-of-day time-of-day
'dotime dotime)
rtn)
rtn)))
(defun org-agenda-add-time-grid-maybe (list ndays todayp)
(catch 'exit
(cond ((not org-agenda-use-time-grid) (throw 'exit list))
((and todayp (member 'today (car org-agenda-time-grid))))
((and (= ndays 1) (member 'daily (car org-agenda-time-grid))))
((member 'weekly (car org-agenda-time-grid)))
(t (throw 'exit list)))
(let* ((have (delq nil (mapcar
(lambda (x) (get-text-property 1 'time-of-day x))
list)))
(string (nth 1 org-agenda-time-grid))
(gridtimes (nth 2 org-agenda-time-grid))
(req (car org-agenda-time-grid))
(remove (member 'remove-match req))
new time)
(if (and (member 'require-timed req) (not have))
;; don't show empty grid
(throw 'exit list))
(while (setq time (pop gridtimes))
(unless (and remove (member time have))
(setq time (int-to-string time))
(push (org-format-agenda-item
nil string "" ;; FIXME: put a category?
(concat (substring time 0 -2) ":" (substring time -2)))
new)
(put-text-property
1 (length (car new)) 'face 'org-time-grid-face (car new))))
(if (member 'time-up org-agenda-sorting-strategy)
(append new list)
(append list new)))))