30

I often have a list like this:

* Main heading ** TODO [#A] Make world better ** TODO [#B] Make Emacs better ** TODO [#B] Customize emacs ** DONE [#C] some task ** TODO [#A] Launch rocket to mars 

I would like to sort it according to the 'TODO' taskword first. Then the items inside the sorted TODO I would like to sort by priority. (it would then be nice to further sort by "Effort").

And I mean currently I can click on the main heading and sort the children already by either priority or by todo keyword, but not both.

Is sorting by both possible like sort-strategy?


Currently I have two headings

* Tasks ** TODO [#A] meh ** TODO [#B] meh2 * Completed. ** DONE [#B] meh3. 

But the problem with this approach is that I have to constantly shuffle tasks around when I complete them.

[EDIT]
This is kinda similar to this except that I couldn't make sense of his answer to transfer it to my needs?

10
  • 1
    The function org-sort-entries will either act on a main heading for all subheadings, or it can sort what is in a selected region. There are interactive options for you to choose from. You can programmatically use it also, and several sorts are possible -- I often use a, o, p, t (one after the next to accomplish 4 levels of sorting criteria). For example, you can sort everything first by alphabetic, then by todo keywords, then by priority, and then by time. Commented Feb 25, 2015 at 22:14
  • Hello, I'm aware of the org-sort-entries option to sort child tasks. I have updated the question so as to better reflect that. Thank you for your comment. Commented Feb 25, 2015 at 22:16
  • Here is a link to a detailed approach for sorting an org-mode buffer programmatically: stackoverflow.com/a/22232709/2112489 Commented Feb 25, 2015 at 22:27
  • I have this link in my question already. The above is kinda tailored to someone's specific needs. Is there a more general purpose/easier approach? Commented Feb 25, 2015 at 22:29
  • 1
    @LeoUfimtsev Try setting org-refile-targets to something like (setq org-refile-targets '((nil . (:maxlevel . 6)))). That will make org-mode show headings up to a depth of 6 when refiling. You can check the documentation for org-refile-targets for more information. Commented Feb 25, 2015 at 23:16

4 Answers 4

24

It would be great if there was something like org-agenda-sorting-stratagy that worked with org-sort-entries, but there doesn't seem to be. We can fake it since org-sort-entries can take an argument specifying a function assigning a (string or number) key to each heading, which will be used to sort the entries when the ?f sorting type is given. All we have to do is get a string for the TODO and PRIORITY properties. The trick is that we want to sort the TODO property by its position in org-todo-keywords, not alphabetically.

(require 'dash) (defun todo-to-int (todo) (cl-first (-non-nil (mapcar (lambda (keywords) (let ((todo-seq (-map (lambda (x) (cl-first (split-string x "("))) (cl-rest keywords)))) (cl-position-if (lambda (x) (string= x todo)) todo-seq))) org-todo-keywords)))) (defun my/org-sort-key () (let* ((todo-max (apply #'max (mapcar #'length org-todo-keywords))) (todo (org-entry-get (point) "TODO")) (todo-int (if todo (todo-to-int todo) todo-max)) (priority (org-entry-get (point) "PRIORITY")) (priority-int (if priority (string-to-char priority) org-default-priority))) (format "%03d %03d" todo-int priority-int) )) (defun my/org-sort-entries () (interactive) (org-sort-entries nil ?f #'my/org-sort-key)) 

M-x my/org-sort-entries will sort by the TODO keyword and break ties with PRIORITY (using org-default-priority when no priority is given). This will break if you have more than 1000 TODO keywords, which is a good reason not to do that.

4
  • Omg, thank you for script. An issue: I installed dash. Then tried the script, but I'm getting an error: Symbol definition is void: todo-to-int. I'm gonna guess you have that function somewhere in your .emacs file but forgot include in the above? or maybe some typo? Commented Feb 26, 2015 at 2:02
  • I changed the function that converts a keyword to an int to todo-to-int after I had pasted into my answer. It's fixed now. Commented Feb 26, 2015 at 2:06
  • 1
    Now all works. Dude, thank you for all your effort, very highly appreciated :-D. Commented Feb 26, 2015 at 2:08
  • 1
    NB: It is no longer recommended to use cl according to docs. Commented Jan 2, 2017 at 11:09
4

Add the following to your file:

#+ARCHIVE: :: * Completed. 

And shuffling becomes archiving

Rather than sort the entries, how about a sorted view?

(setq org-agenda-custom-commands '(("cx" "TODOs sorted by state, priority, effort" todo "*" ((org-agenda-overriding-header "\nTODOs sorted by state, priority, effort") (org-agenda-sorting-strategy '(todo-state-down priority-down effort-up)))))) 

Restrict it to the current file with <. You can mark DONE and archive from the sorted view.

3

You can also define a org-agenda-cmp-user-defined function and add it to org-agenda-sorting-strategy. This is the one I created as an example.

(setq org-todo-sort-order '("WAIT" "TODO" "DOING" "CANCELED" "DONE")) (defun my:user-todo-sort (a b) "Sort todo based on which I want to see first" (when-let ((state-a (get-text-property 14 'todo-state a)) (state-b (get-text-property 14 'todo-state b)) (cmp (--map (cl-position-if (lambda (x) (equal x it)) org-todo-sort-order) (list state-a state-b)))) (cond ((apply '> cmp) 1) ((apply '< cmp) -1) (t nil)))) (setq org-agenda-cmp-user-defined 'my:user-todo-sort) 
1

You can use this library made by me: https://github.com/felipelalli/org-sort-tasks

It uses Merge Sort algo by asking the user if a task A is more important than B, and then builds a sorted list.

2
  • Can you add some description of what this does, and in particular how it differs from the other answers. Commented May 10, 2019 at 6:01
  • It uses Merge Sort algo by asking the user if a task A is more important than B, and then build a sorted list. Commented May 10, 2019 at 23:27

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.