diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el index b1fa5f5..417566d 100644 --- a/lisp/org-agenda.el +++ b/lisp/org-agenda.el @@ -587,12 +587,19 @@ When nil, these trees are also scanned by agenda commands." :type 'boolean) (defcustom org-agenda-todo-list-sublevels t - "Non-nil means check also the sublevels of a TODO entry for TODO entries. -When nil, the sublevels of a TODO entry are not checked, resulting in -potentially much shorter TODO lists." + "How to display TODO entries that are sublevels of a TODO entry. +When nil, the sublevels of a TODO entry are not returned, +resulting in potentially much shorter TODO lists. When t, the +default, show all TODO entries as a flat list. 'indent and 'fade +change the way TODO entries that follow a parent TODO are +displayed." :group 'org-agenda-skip :group 'org-agenda-todo-list - :type 'boolean) + :type '(choice + (const :tag "Create a flat list of sublevels" t) + (const :tag "Do not list sublevel todos" nil) + (const :tag "Indent sublevel todos" indent) + (const :tag "Fade out sublevel todos" fade))) (defcustom org-agenda-todo-ignore-with-date nil "Non-nil means don't show entries with a date in the global todo list. @@ -4563,6 +4570,7 @@ the documentation of `org-diary'." (setq results (append results rtn)))))))) results)))) + (defun org-agenda-get-todos () "Return the TODO information for agenda display." (let* ((props (list 'face nil @@ -4582,40 +4590,57 @@ the documentation of `org-diary'." (mapconcat 'identity (org-split-string org-select-this-todo-keyword "|") "\\|") - "\\)\\>")) + "\\)\\>")) org-not-done-regexp) "[^\n\r]*\\)")) - marker priority category category-pos tags todo-state ee txt beg end) - (goto-char (point-min)) - (while (re-search-forward regexp nil t) - (catch :skip - (save-match-data - (beginning-of-line) - (org-agenda-skip) - (setq beg (point) end (save-excursion (outline-next-heading) (point))) - (when (org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item end) - (goto-char (1+ beg)) - (or org-agenda-todo-list-sublevels (org-end-of-subtree 'invisible)) - (throw :skip nil))) - (goto-char (match-beginning 1)) - (setq marker (org-agenda-new-marker (match-beginning 0)) - category (org-get-category) - category-pos (get-text-property (point) 'org-category-position) - txt (match-string 1) - tags (org-get-tags-at (point)) - txt (org-format-agenda-item "" txt category tags) - priority (1+ (org-get-priority txt)) - todo-state (org-get-todo-state)) - (org-add-props txt props - 'org-marker marker 'org-hd-marker marker - 'priority priority 'org-category category - 'org-category-position category-pos - 'type "todo" 'todo-state todo-state) - (push txt ee) - (if org-agenda-todo-list-sublevels - (goto-char (match-end 1)) - (org-end-of-subtree 'invisible)))) - (nreverse ee))) + (depth 0)) + + (flet ((mk-td (start finish) + (goto-char start) + (let (marker priority category category-pos tags todo-state ee txt beg end) + (while (re-search-forward regexp finish t) + (catch :skip + (save-match-data + (beginning-of-line) + (org-agenda-skip) + (setq beg (point) end (save-excursion (outline-next-heading) (point))) + (when (org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item end) + (goto-char (1+ beg)) + (or org-agenda-todo-list-sublevels (org-end-of-subtree 'invisible)) + (throw :skip nil))) + (goto-char (match-beginning 1)) + (setq marker (org-agenda-new-marker (match-beginning 0)) + category (org-get-category) + category-pos (get-text-property (point) 'org-category-position) + txt (concat (if + (> depth 0) + (make-string (* 2 depth) ?.) + "") (match-string 1)) + tags (org-get-tags-at (point)) + txt (org-format-agenda-item "" txt category tags depth) + priority (1+ (org-get-priority txt)) + todo-state (org-get-todo-state)) + (org-add-props txt props + 'org-marker marker 'org-hd-marker marker + 'priority priority 'org-category category + 'org-category-position category-pos + 'type "todo" 'todo-state todo-state) + (if (not org-agenda-todo-list-sublevels) + (progn + (push txt ee) + (org-end-of-subtree 'invisible)) + (goto-char (match-end 0)) + (let* ((depth (1+ depth)) + (subtree-todos + (mk-td (point) + (save-excursion (org-end-of-subtree 'invisible) (point))))) + (when subtree-todos + (setq txt (cons txt (nreverse subtree-todos)))) + (push txt ee))))) + ee))) + (goto-char (point-min)) + (nreverse (mk-td (point) (point-max)))))) + (defun org-agenda-todo-custom-ignore-p (time n) "Check whether timestamp is farther away then n number of days. @@ -5785,12 +5810,18 @@ could bind the variable in the options section of a custom command.") (defun org-finalize-agenda-entries (list &optional nosort) "Sort and concatenate the agenda items." - (setq list (mapcar 'org-agenda-highlight-todo list)) - (if nosort - list - (when org-agenda-before-sorting-filter-function - (setq list (delq nil (mapcar org-agenda-before-sorting-filter-function list)))) - (mapconcat 'identity (sort list 'org-entries-lessp) "\n"))) + (flet ((flatten (l) + (cond + ((null l) nil) + ((atom l) (if (and org-agenda-before-sorting-filter-function + (not (org-agenda-before-sorting-filter-function l))) + nil + (list (org-agenda-highlight-todo l)))) + (t (append (flatten (car l)) + (flatten (if nosort + (cdr l) + (sort (cdr l) 'org-entries-lessp)))))))) + (mapconcat 'identity (flatten list) "\n"))) (defun org-agenda-highlight-todo (x) (let ((org-done-keywords org-done-keywords-for-agenda) @@ -5926,6 +5957,10 @@ could bind the variable in the options section of a custom command.") (defun org-entries-lessp (a b) "Predicate for sorting agenda entries." + (when (consp a) + (setq a (car a))) + (when (consp b) + (setq b (car b))) ;; The following variables will be used when the form is evaluated. ;; So even though the compiler complains, keep them. (let* ((ss org-agenda-sorting-strategy-selected)