org: Как отсортировать заголовки по TODO, а затем по приоритету?

24

У меня часто есть такой список:

* 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

Я хотел бы сначала отсортировать его в соответствии с заданием «TODO». Затем элементы внутри отсортированного TODO я хотел бы отсортировать по приоритету. (тогда было бы неплохо продолжить сортировку по "Усилию").

И я имею в виду, что в настоящее время я могу щелкнуть по главному заголовку и отсортировать детей уже по приоритету или по ключевому слову todo, но не обоим.

Возможна ли сортировка по обоим направлениям как стратегия сортировки?


В настоящее время у меня есть два заголовка

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

Но проблема с этим подходом состоит в том, что я должен постоянно перемешивать задачи, когда выполняю их.

[EDIT]
Это похоже на это, за исключением того, что я не мог понять его ответ, чтобы передать его для моих нужд?

Лев Уфимцев
источник
1
Функция org-sort-entriesбудет действовать как на главный заголовок для всех подзаголовков, так и может сортировать то, что находится в выбранной области. Есть интерактивные варианты для вас на выбор. Вы также можете программно использовать его, и возможны несколько сортировок - я часто использую a, o, p, t (один за другим, чтобы выполнить 4 уровня критериев сортировки). Например, вы можете отсортировать все сначала по алфавиту, затем по ключевым словам todo, затем по приоритету, а затем по времени.
законник
Здравствуйте, мне известна опция org-sort-records для сортировки дочерних задач. Я обновил вопрос, чтобы лучше отразить это. Спасибо за ваш комментарий.
Лев Уфимцев
Вот ссылка на подробный подход к программной сортировке буфера в режиме org: stackoverflow.com/a/22232709/2112489
lawlist
У меня есть эта ссылка в моем вопросе уже. Вышеуказанное приспособлено к чьим-то конкретным потребностям. Есть более общий подход / более простой подход?
Лев Уфимцев
1
@LeoUfimtsev Попробуйте установить org-refile-targetsчто-то вроде (setq org-refile-targets '((nil . (:maxlevel . 6)))). Это сделает org-modeпоказ заголовков до 6 глубины при повторной заправке. Вы можете проверить документацию для org-refile-targetsполучения дополнительной информации.
itjeyd

Ответы:

19

Было бы здорово, если бы что-то подобное org-agenda-sorting-stratagyработало org-sort-entries, но, похоже, нет. Мы можем подделать его, поскольку org-sort-entriesможем принимать аргумент, определяющий функцию, присваивающую ключ (строку или число) каждому заголовку, который будет использоваться для сортировки записей, когда ?fзадан тип сортировки. Все, что нам нужно сделать, это получить строку для свойств TODO и PRIORITY. Хитрость в том, что мы хотим отсортировать свойство TODO по его положению org-todo-keywords, а не по алфавиту.

(require 'cl)
(require 'dash)

(defun todo-to-int (todo)
    (first (-non-nil
            (mapcar (lambda (keywords)
                      (let ((todo-seq
                             (-map (lambda (x) (first (split-string  x "(")))
                                   (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сортирует по ключевому слову TODO и разрывает связи с PRIORITY (используется, org-default-priorityкогда приоритет не задан). Это сломается, если у вас будет более 1000 ключевых слов TODO, что является хорошей причиной, чтобы этого не делать.

erikstokes
источник
Омг, спасибо за сценарий. Проблема: я установил черту. Затем попробовал скрипт, но я получаю ошибку: определение символа недействительно: todo-to-int. Я предполагаю, что у вас есть эта функция где-то в вашем файле .emacs, но вы забыли включить в вышеупомянутый? или может быть какая-то опечатка?
Лев Уфимцев
Я изменил функцию, которая преобразует ключевое слово в int todo-to-intпосле того, как вставил в свой ответ. Это сейчас исправлено.
erikstokes
1
Сейчас все работает. Чувак, спасибо за все твои усилия, очень высоко ценю :-D.
Лев Уфимцев
1
NB: больше не рекомендуется использовать cl в соответствии с документами .
Cammil
1

Добавьте следующее в ваш файл:

#+ARCHIVE: :: * Completed.

И тасование становится архивированием

Вместо того, чтобы сортировать записи, как насчет отсортированного представления?

(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))))))

Ограничьте его текущим файлом с помощью <. Вы можете пометить ГОТОВО и архивировать в отсортированном виде.

Сын гну
источник
1

Вы также можете определить org-agenda-cmp-user-definedфункцию и добавить ее в org-agenda-sorting-strategy. Это тот, который я создал в качестве примера.

(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)
Prgrm.celeritas
источник
1

Вы можете использовать эту библиотеку, сделанную мной: https://github.com/felipelalli/org-sort-tasks

Он использует алгоритм сортировки слиянием, спрашивая пользователя, является ли задача A более важной, чем B, а затем создает отсортированный список.

Фелипе
источник
Можете ли вы добавить описание того, что это делает, и, в частности, чем оно отличается от других ответов.
Эндрю Суонн
Он использует Merge Sort algo, спрашивая пользователя, является ли задача A более важной, чем B, а затем создает отсортированный список.
Фелипе