Часто возникает необходимость запланировать какую-то сложную штуку к определенной дате. Например, это экспедиции, ММБ, тренировочный план и т.д. То есть, некое мероприятие, к которому надо начинать готовиться заранее и которое содержит к себе кучу отдельных задач, каждое со своим смещением от основной даты. Раньше для решения этой задачи я написал систему темплейтов в org-mode, но оказалось слишком сложно.
Это вторая попытка: мероприятие описываем в стандартном виде, а потом специальная функция копирует всё поддерево с соразмерным сдвигом всех дат. Функция:
(defun my-org-clone-to-date ()
"Clone current subtree into specified file with all dates shifted to the same period."
(interactive)
(let* ((title (message (nth 4 (org-heading-components))))
(orig-date (org-time-string-to-absolute (org-entry-get nil "SCHEDULED")))
(dest-date (org-time-string-to-absolute
(org-read-date nil nil nil (format "Дата для '%s'" title))))
(offset (format "+%id" (- dest-date orig-date))))
(org-copy-subtree)
(with-temp-buffer
(org-mode)
(org-paste-subtree)
(org-clone-subtree-with-time-shift 1 offset)
(org-forward-element)
(org-refile))))
Скажем, у нас есть шаблон вечеринки:
* Грандиозная вечеринка
SCHEDULED: <2019-05-01 Ср>
** TODO Позвать друзей
SCHEDULED: <2019-04-29 Пн>
** TODO Купить всё необходимое
SCHEDULED: <2019-04-30 Вт>
Если мы в корневом заголовке позовем нашу функцию и укажем дату [2020-03-06 Пт], то получим дерево с совсем другими датами:
* Грандиозная вечеринка
SCHEDULED: <2020-03-06 Пт>
** TODO Позвать друзей
SCHEDULED: <2020-03-04 Ср>
** TODO Купить всё необходимое
SCHEDULED: <2020-03-05 Чт>
По-моему, получилось удобно.