Alguém está ciente de uma função / modificação org-sort
que pode refilar / organizar um grupo de TODO para classificá-los por três (3) critérios: primeiro classificar por data de vencimento, segundo por prioridade e terceiro por por título da tarefa?
EDIT: Acredito que org-sort
por prazo final ( ?d
) tem um bug que não pode tratar adequadamente tarefas não datadas. Eu estou trabalhando em uma solução alternativa (ou seja, movendo o todo não datado para um cabeçalho diferente antes do prazo final ( ?d
) classificar ocorre), mas talvez a melhor coisa a fazer seja tentar corrigir a função de classificação original. O desenvolvimento da solução alternativa pode ser encontrado no seguinte tópico (ou seja, mover as tarefas não datadas para um cabeçalho diferente de uma só vez): Como automatizar org-refile para múltiplos todo
EDIT: O código a seguir parece promissor, mas precisa de algum TLC e uma solução alternativa para o bug todo undater:
;; multiple sort
(defun org-sort-multi (&rest sort-types)
"Multiple sorts on a certain level of an outline tree, or plain list items.
SORT-TYPES is a list where each entry is either a character or a
cons pair (BOOL . CHAR), where BOOL is whether or not to sort
case-sensitively, and CHAR is one of the characters defined in
'org-sort-entries-or-items'. Entries are applied in back to
front order.
Example: To sort first by TODO status, then by priority, then by
date, then alphabetically (case-sensitive) use the following
call:
(org-sort-multi '(?d ?p ?t (t . ?a)))"
(interactive)
(dolist (x (nreverse sort-types))
(when (char-valid-p x)
(setq x (cons nil x)))
(condition-case nil
(org-sort-entries (car x) (cdr x))
(error nil))))
;; sort current level
(defun lawlist-sort (&rest sort-types)
"Sort the current org level.
SORT-TYPES is a list where each entry is either a character or a
cons pair (BOOL . CHAR), where BOOL is whether or not to sort
case-sensitively, and CHAR is one of the characters defined in
'org-sort-entries-or-items'. Entries are applied in back to
front order.
Defaults to \"?o ?p\" which is sorted by TODO status, then by
priority"
(interactive)
(when (equal mode-name "Org")
(let ((sort-types (or sort-types
(if (or (org-entry-get nil "TODO")
(org-entry-get nil "PRIORITY"))
'(?d ?t ?p) ;; date, time, priority
'((nil . ?a))))))
(save-excursion
(outline-up-heading 1)
(let ((start (point))
end)
(while (and (not (bobp)) (not (eobp)) (<= (point) start))
(condition-case nil
(outline-forward-same-level 1)
(error (outline-up-heading 1))))
(unless (> (point) start)
(goto-char (point-max)))
(setq end (point))
(goto-char start)
(apply 'org-sort-multi sort-types)
(goto-char end)
(when (eobp)
(forward-line -1))
(when (looking-at "^\s-*$")
(kill-whole-line)
)
(goto-char start)
;; (dotimes (x ) (org-cycle))
)))))
EDIT: Esta função também está mostrando promessa e eu vou informar quando eu tiver feito mais testes.
(defun org-sort-all ()
(interactive)
(save-excursion
(goto-char (point-min))
(while (re-search-forward "^\* " nil t)
(goto-char (match-beginning 0))
(condition-case err
(progn
(org-sort-entries t ?a)
(org-sort-entries t ?p)
(org-sort-entries t ?o)
(forward-line))
(error nil)))
(goto-char (point-min))
(while (re-search-forward "\* PROJECT " nil t)
(goto-char (line-beginning-position))
(ignore-errors
(org-sort-entries t ?a)
(org-sort-entries t ?p)
(org-sort-entries t ?o))
(forward-line))))
EDIT: Para as almas aventureiras interessadas em consertar a ordenação de prazos ( ?d
) para que o todo sem data seja movido para a parte inferior do esboço, em vez de misturado com o todo datado, aqui está um excerto do atual org.el
incluído no Tronco Emacs (a partir de 1 de julho de 2013):
(defun org-sort (with-case)
"Call 'org-sort-entries', 'org-table-sort-lines' or 'org-sort-list'.
Optional argument WITH-CASE means sort case-sensitively."
(interactive "P")
(cond
((org-at-table-p) (org-call-with-arg 'org-table-sort-lines with-case))
((org-at-item-p) (org-call-with-arg 'org-sort-list with-case))
(t
(org-call-with-arg 'org-sort-entries with-case))))
(defun org-sort-remove-invisible (s)
(remove-text-properties 0 (length s) org-rm-props s)
(while (string-match org-bracket-link-regexp s)
(setq s (replace-match (if (match-end 2)
(match-string 3 s)
(match-string 1 s)) t t s)))
s)
(defvar org-priority-regexp) ; defined later in the file
(defvar org-after-sorting-entries-or-items-hook nil
"Hook that is run after a bunch of entries or items have been sorted.
When children are sorted, the cursor is in the parent line when this
hook gets called. When a region or a plain list is sorted, the cursor
will be in the first entry of the sorted region/list.")
(defun org-sort-entries
(&optional with-case sorting-type getkey-func compare-func property)
"Sort entries on a certain level of an outline tree.
If there is an active region, the entries in the region are sorted.
Else, if the cursor is before the first entry, sort the top-level items.
Else, the children of the entry at point are sorted.
Sorting can be alphabetically, numerically, by date/time as given by
a time stamp, by a property or by priority.
The command prompts for the sorting type unless it has been given to the
function through the SORTING-TYPE argument, which needs to be a character,
\(?n ?N ?a ?A ?t ?T ?s ?S ?d ?D ?p ?P ?o ?O ?r ?R ?f ?F). Here is the
precise meaning of each character:
n Numerically, by converting the beginning of the entry/item to a number.
a Alphabetically, ignoring the TODO keyword and the priority, if any.
o By order of TODO keywords.
t By date/time, either the first active time stamp in the entry, or, if
none exist, by the first inactive one.
s By the scheduled date/time.
d By deadline date/time.
c By creation time, which is assumed to be the first inactive time stamp
at the beginning of a line.
p By priority according to the cookie.
r By the value of a property.
Capital letters will reverse the sort order.
If the SORTING-TYPE is ?f or ?F, then GETKEY-FUNC specifies a function to be
called with point at the beginning of the record. It must return either
a string or a number that should serve as the sorting key for that record.
Comparing entries ignores case by default. However, with an optional argument
WITH-CASE, the sorting considers case as well."
(interactive "P")
(let ((case-func (if with-case 'identity 'downcase))
(cmstr
;; The clock marker is lost when using 'sort-subr', let's
;; store the clocking string.
(when (equal (marker-buffer org-clock-marker) (current-buffer))
(save-excursion
(goto-char org-clock-marker)
(looking-back "^.*") (match-string-no-properties 0))))
start beg end stars re re2
txt what tmp)
;; Find beginning and end of region to sort
(cond
((org-region-active-p)
;; we will sort the region
(setq end (region-end)
what "region")
(goto-char (region-beginning))
(if (not (org-at-heading-p)) (outline-next-heading))
(setq start (point)))
((or (org-at-heading-p)
(condition-case nil (progn (org-back-to-heading) t) (error nil)))
;; we will sort the children of the current headline
(org-back-to-heading)
(setq start (point)
end (progn (org-end-of-subtree t t)
(or (bolp) (insert "\n"))
(org-back-over-empty-lines)
(point))
what "children")
(goto-char start)
(show-subtree)
(outline-next-heading))
(t
;; we will sort the top-level entries in this file
(goto-char (point-min))
(or (org-at-heading-p) (outline-next-heading))
(setq start (point))
(goto-char (point-max))
(beginning-of-line 1)
(when (looking-at ".*?\S-")
;; File ends in a non-white line
(end-of-line 1)
(insert "\n"))
(setq end (point-max))
(setq what "top-level")
(goto-char start)
(show-all)))
(setq beg (point))
(if (>= beg end) (error "Nothing to sort"))
(looking-at "\(\*+\)")
(setq stars (match-string 1)
re (concat "^" (regexp-quote stars) " +")
re2 (concat "^" (regexp-quote (substring stars 0 -1)) "[ \t\n]")
txt (buffer-substring beg end))
(if (not (equal (substring txt -1) "\n")) (setq txt (concat txt "\n")))
(if (and (not (equal stars "*")) (string-match re2 txt))
(error "Region to sort contains a level above the first entry"))
(unless sorting-type
(message
"Sort %s: [a]lpha [n]umeric [p]riority p[r]operty todo[o]rder [f]unc
[t]ime [s]cheduled [d]eadline [c]reated
A/N/P/R/O/F/T/S/D/C means reversed:"
what)
(setq sorting-type (read-char-exclusive))
(and (= (downcase sorting-type) ?f)
(setq getkey-func
(org-icompleting-read "Sort using function: "
obarray 'fboundp t nil nil))
(setq getkey-func (intern getkey-func)))
(and (= (downcase sorting-type) ?r)
(setq property
(org-icompleting-read "Property: "
(mapcar 'list (org-buffer-property-keys t))
nil t))))
(message "Sorting entries...")
(save-restriction
(narrow-to-region start end)
(let ((dcst (downcase sorting-type))
(case-fold-search nil)
(now (current-time)))
(sort-subr
(/= dcst sorting-type)
;; This function moves to the beginning character of the "record" to
;; be sorted.
(lambda nil
(if (re-search-forward re nil t)
(goto-char (match-beginning 0))
(goto-char (point-max))))
;; This function moves to the last character of the "record" being
;; sorted.
(lambda nil
(save-match-data
(condition-case nil
(outline-forward-same-level 1)
(error
(goto-char (point-max))))))
;; This function returns the value that gets sorted against.
(lambda nil
(cond
((= dcst ?n)
(if (looking-at org-complex-heading-regexp)
(string-to-number (match-string 4))
nil))
((= dcst ?a)
(if (looking-at org-complex-heading-regexp)
(funcall case-func (match-string 4))
nil))
((= dcst ?t)
(let ((end (save-excursion (outline-next-heading) (point))))
(if (or (re-search-forward org-ts-regexp end t)
(re-search-forward org-ts-regexp-both end t))
(org-time-string-to-seconds (match-string 0))
(org-float-time now))))
((= dcst ?c)
(let ((end (save-excursion (outline-next-heading) (point))))
(if (re-search-forward
(concat "^[ \t]*\[" org-ts-regexp1 "\]")
end t)
(org-time-string-to-seconds (match-string 0))
(org-float-time now))))
((= dcst ?s)
(let ((end (save-excursion (outline-next-heading) (point))))
(if (re-search-forward org-scheduled-time-regexp end t)
(org-time-string-to-seconds (match-string 1))
(org-float-time now))))
((= dcst ?d)
(let ((end (save-excursion (outline-next-heading) (point))))
(if (re-search-forward org-deadline-time-regexp end t)
(org-time-string-to-seconds (match-string 1))
(org-float-time now))))
((= dcst ?p)
(if (re-search-forward org-priority-regexp (point-at-eol) t)
(string-to-char (match-string 2))
org-default-priority))
((= dcst ?r)
(or (org-entry-get nil property) ""))
((= dcst ?o)
(if (looking-at org-complex-heading-regexp)
(- 9999 (length (member (match-string 2)
org-todo-keywords-1)))))
((= dcst ?f)
(if getkey-func
(progn
(setq tmp (funcall getkey-func))
(if (stringp tmp) (setq tmp (funcall case-func tmp)))
tmp)
(error "Invalid key function '%s'" getkey-func)))
(t (error "Invalid sorting type '%c'" sorting-type))))
nil
(cond
((= dcst ?a) 'string<)
((= dcst ?f) compare-func)
((member dcst '(?p ?t ?s ?d ?c)) '<)))))
(run-hooks 'org-after-sorting-entries-or-items-hook)
;; Reset the clock marker if needed
(when cmstr
(save-excursion
(goto-char start)
(search-forward cmstr nil t)
(move-marker org-clock-marker (point))))
(message "Sorting entries...done")))
(defun org-do-sort (table what &optional with-case sorting-type)
"Sort TABLE of WHAT according to SORTING-TYPE.
The user will be prompted for the SORTING-TYPE if the call to this
function does not specify it. WHAT is only for the prompt, to indicate
what is being sorted. The sorting key will be extracted from
the car of the elements of the table.
If WITH-CASE is non-nil, the sorting will be case-sensitive."
(unless sorting-type
(message
"Sort %s: [a]lphabetic, [n]umeric, [t]ime. A/N/T means reversed:"
what)
(setq sorting-type (read-char-exclusive)))
(let ((dcst (downcase sorting-type))
extractfun comparefun)
;; Define the appropriate functions
(cond
((= dcst ?n)
(setq extractfun 'string-to-number
comparefun (if (= dcst sorting-type) '< '>)))
((= dcst ?a)
(setq extractfun (if with-case (lambda(x) (org-sort-remove-invisible x))
(lambda(x) (downcase (org-sort-remove-invisible x))))
comparefun (if (= dcst sorting-type)
'string<
(lambda (a b) (and (not (string< a b))
(not (string= a b)))))))
((= dcst ?t)
(setq extractfun
(lambda (x)
(if (or (string-match org-ts-regexp x)
(string-match org-ts-regexp-both x))
(org-float-time
(org-time-string-to-time (match-string 0 x)))
0))
comparefun (if (= dcst sorting-type) '< '>)))
(t (error "Invalid sorting type '%c'" sorting-type)))
(sort (mapcar (lambda (x) (cons (funcall extractfun (car x)) (cdr x)))
table)
(lambda (a b) (funcall comparefun (car a) (car b))))))