THE SHORT ANSWER
STEP # 1:? Place the cursor on the parent.
STEP # 2:? M-x org-sort-entries RET a RET
STEP # 3:??M-x org-sort-entries RET o RET
STEP # 4:? Crack open your favorite beverage and have a drink.
THE LONG-WINDED ANSWER
To expand upon the answer of @pmr (i.e., sorting a selected region), one may also wish to consider acting upon main headings to organize subheadings. For example, I like to perform a multi-sort -- first by alphabetic, second by todo-order, third by priority, and fourth by time. For subheadings that do not contain deadlines and contain only one type of todo status, it is sufficient for my needs to only sort by alphabetic. Set forth below is a sample function that I use to sort the entire buffer containing various main headings and subheadings. Here is the cheat-sheet from org-sort-entries
:
Sort: [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.
NOTE: ?org-sort-entries
uses the current-time
when sorting entries based on time-stamp if the entry does not contain a time-stamp. The consequence of using the current-time
is that undated entries will be sorted prior to future tasks containing time-stamps when sorting with the options t
, c
, s
, or d
. To weight the undated entries so that they are sorted after the dated entries, it is possible to use a later date than the current-time
. The relevant let-bound variable is defined as (now (current-time))
, and its usage within the function is written as (org-float-time now)
. This can be dealt with many different ways -- e.g., modifying the code containing (org-float-time now)
with something containing an artificial date far off into the future -- e.g., (org-time-string-to-seconds "<2030-12-31 Tue>")
.
(defun lawlist-sort ()
(when
(save-excursion
(goto-char (point-max))
(re-search-backward "^\* CONTACTS" nil t)
(re-search-forward "^\*\* \(Planning\)" nil t))
(goto-char (point-max))
(re-search-backward "^\* CONTACTS" nil t)
(org-sort-entries t ?a) )
(when
(save-excursion
(goto-char (point-max))
(re-search-backward "^\* DONE" nil t)
(re-search-forward "^\*\* \(None\)" nil t))
(goto-char (point-max))
(re-search-backward "^\* DONE" nil t)
(org-sort-entries t ?a) )
(when
(save-excursion
(goto-char (point-max))
(re-search-backward "^\* UNDATED" nil t)
(re-search-forward "^\*\* \(Someday\)" nil t))
(goto-char (point-max))
(re-search-backward "^\* UNDATED" nil t)
(org-sort-entries t ?a) )
(when
(save-excursion
(goto-char (point-max))
(re-search-backward "^\* EVENTS" nil t)
(re-search-forward "^\*\* \(Reference\|Delegated\|Postponed\|Waiting\)" nil t))
(goto-char (point-max))
(re-search-backward "^\* EVENTS" nil t)
(org-sort-entries t ?a)
(org-sort-entries t ?o)
(org-sort-entries t ?p)
(org-sort-entries t ?t) )
(when
(save-excursion
(goto-char (point-max))
(re-search-backward "^\* TASKS" nil t)
(re-search-forward "^\*\* \(Active\|Next Action\|Hold\|Canceled\)" nil t))
(goto-char (point-max))
(re-search-backward "^\* TASKS" nil t)
(org-sort-entries t ?a)
(org-sort-entries t ?o)
(org-sort-entries t ?p)
(org-sort-entries t ?t) ) )
Here is an example of how to sort and reorganize an entire buffer containing main headings and subheadings. This is especially useful if the user desires synchronization with the Toodledo server using the org-toodledo
library: https://github.com/christopherjwhite/org-toodledo ?To speed up the process when reorganizing a buffer containing hundreds of subheadings, the user may wish to consider suppressing the messages by modifying the functions responsible -- however, that is beyond the scope of this answer.
(setq org-todo-keywords '(
(sequence
"Active(a)"
"Next Action(n)"
"Canceled(c)"
"Hold(h)"
"Reference(r)"
"Delegated(d)"
"Waiting(w)"
"Postponed(P)"
"Someday(s)"
"Planning(p)"
"|"
"None(N)") ))
(defun lawlist-reorganize ()
(interactive)
(with-current-buffer (get-buffer "test.org")
(setq buffer-read-only nil)
(lawlist-refile-tasks)
(lawlist-refile-events)
(lawlist-refile-undated)
(lawlist-refile-contacts)
(lawlist-refile-done)
(lawlist-sort)
(goto-char (point-min))
(save-buffer)
(setq buffer-read-only t)))
(defun lawlist-refile-tasks ()
(interactive)
(let* (
(org-archive-location "/Users/HOME/Desktop/test.org::* TASKS")
(org-archive-save-context-info nil))
(goto-char (point-min))
(unless (re-search-forward "^\* TASKS" nil t)
(goto-char (point-max))
(insert "* TASKS
"))
(goto-char (point-max))
(while
(re-search-backward
"^\*\* \(Active\|Next Action\|Hold\|Canceled\)" nil t)
(org-archive-subtree))))
(defun lawlist-refile-events ()
(let* (
(org-archive-location "/Users/HOME/Desktop/test.org::* EVENTS")
(org-archive-save-context-info nil))
(goto-char (point-min))
(unless (re-search-forward "^\* EVENTS" nil t)
(goto-char (point-max))
(insert "* EVENTS
"))
(goto-char (point-max))
(while
(re-search-backward
"^\*\* \(Reference\|Delegated\|Postponed\|Waiting\)" nil t)
(org-archive-subtree))))
(defun lawlist-refile-undated ()
(let* (
(org-archive-location "/Users/HOME/Desktop/test.org::* UNDATED")
(org-archive-save-context-info nil))
(goto-char (point-min))
(unless (re-search-forward "^\* UNDATED" nil t)
(goto-char (point-max))
(insert "* UNDATED
"))
(goto-char (point-max))
(while
(re-search-backward
"^\*\* \(Someday\)" nil t)
(org-archive-subtree))))
(defun lawlist-refile-done ()
(let* (
(org-archive-location "/Users/HOME/Desktop/test.org::* DONE")
(org-archive-save-context-info nil))
(goto-char (point-min))
(unless (re-search-forward "^\* DONE" nil t)
(goto-char (point-max))
(insert "* DONE
"))
(goto-char (point-max))
(while
(re-search-backward
"^\*\* \(None\)" nil t)
(org-archive-subtree))))
(defun lawlist-refile-contacts ()
(let* (
(org-archive-location "/Users/HOME/Desktop/test.org::* CONTACTS")
(org-archive-save-context-info nil))
(goto-char (point-min))
(unless (re-search-forward "^\* CONTACTS" nil t)
(goto-char (point-max))
(insert "* CONTACTS
"))
(goto-char (point-max))
(while
(re-search-backward
"^\*\* \(Planning\)" nil t)
(org-archive-subtree))))
Here is a sample clean-up function to put proper spacing between entries and delete any empty lines at the end of the buffer -- the regexp assumes headings and subheadings are all flush-left:
(defun lawlist-cleanup ()
(interactive)
(let ((query-replace-lazy-highlight nil))
(replace-regexp "
+\*\* " "
** " nil (point-min) (point-max))
(replace-regexp "
+\* " "
* " nil (point-min) (point-max))
(goto-char (point-max))
(delete-blank-lines)
(let ((trailnewlines (abs (skip-chars-backward "
"))))
(if (> trailnewlines 0)
(delete-char trailnewlines))) ))
This solution does not rely upon selecting regions, but instead acts upon each main heading and organizes everything under that main heading -- i.e., all subheadings are organized. The code in this answer will regroup entries by refiling them underneath the correct main heading. For example -- if a task has been completed, the completed subheading will be ** None
-- the code will look for all subheadings with ** None
and move them to the main heading of * DONE
, and then sort them alphabetically.
The main headings are: * TASKS
; * EVENTS
; * SOMEDAY
; * CONTACTS
; * DONE
.
The following subheadings were chosen because they are a method of Getting Things Done, and the Toodledo server uses this same methodology: ?** Active
; ** Next Action
; ** Hold
; ** Canceled
; ** Reference
; ** Delegated
; ** Postponed
; ** Waiting
; ** Someday
; ** Planning
; ** None
.
* TASKS
** Active
** Next Action
** Hold
** Canceled
* EVENTS
** Reference
** Delegated
** Postponed
** Waiting
* SOMEDAY
** Someday
* CONTACTS
** Planning
* DONE
** None