Given:
1. A tendency of massively marking all items as schedule [1]
2. Some of that items should be done on daily basis (I generate them
with a daily template and the power of org-capture)
3. Life happens and some of them are accumulated, for my last case, that
was 29 entries pending to be processed
Action:
I procedure with a batch action for that 29 entries (imagine here a
batch script), and now that it is done, then I need to clear it up from
my org-agenda
org-agenda-bulk-action [2] does not serve me because it marks the TODO
thing without a note, and it's not possible to add a note with the
prefix. Going to offtopic, I also discovered that does not respect the
enforce-todo-dependencies [3], ignores if that entries have child todo
items.
I tried to create a org-agenda-bulk-custom-functions but I failed
because I wanted a chosen state and a shared note for all the bulk items
and the way that functions work cannot be done.
But the bulk items are in a variable (nice),
org-agenda-bulk-marked-entries, and you can traverse it with a generic
function, so I did it. It took me, unexpectetly, 1h30m to get it working
(and I could not find other stuff around), so I am sharing what I have
done so other people can benefit, and by the way, I would like to know
what do you think of that approach and if you have ideas to improve it.
See it attached in file org-agenda-bulk-todo-with-note.el
With that script I added a note of resolution of that items saying that
it was resolved through my task with CUSTOM_ID/ID X (like when you close
multiple issues in a ticketing software) [4]
A healthy 2025 for you guys,
pinmacs
[1] offtopic, but I am sharing it anyway
#+begin_src emacs-lisp
(defun my/org-heading-insert-scheduled ()
(if (or
(and (string-match-p my/diary-file (buffer-name))
(= (org-current-level) 4))
(and (string-match-p my/board-file (buffer-name))
(= (org-current-level) 4))
(and (string-match-p "projects.org" (buffer-name))
;; projects are 4-level (tasks start at 6-level, we don't
care on its children)
(> (org-current-level) 5))
(and (string-match-p "projects-candidates.org" (buffer-name))
;; projects are 4-level (tasks start at 3-level, we don't
care on its children)
(> (org-current-level) 3))
)
(save-excursion
;; src
https://emacs.stackexchange.com/questions/72147/org-mode-adding-creation-date-property-upon-heading-creation
;;(org-back-to-heading)
(org-schedule nil (format-time-string "[%Y-%m-%d %a]" nil)))))
(add-hook 'org-insert-heading-hook 'my/org-heading-insert-scheduled 'append)
#+end_src
[2] https://orgmode.org/manual/Agenda-Commands.html
[3] (setq org-enforce-todo-dependencies t)
https://orgmode.org/manual/TODO-dependencies.html
[4] all that state changes are stored, in my case, in (setq
org-log-state-notes-into-drawer "TRACE");; this should be run with M-x
;; all selected bulk entries should have same todo keywords
(defun my/bulk-todo-with-note ()
"For each marked entry in the Org agenda, set the TODO state with a shared note,
and insert the same user-provided note for all items."
(interactive)
(unless org-agenda-bulk-marked-entries
(user-error "No entries are marked in the agenda"))
(let* ((buffer-todo-keywords (with-current-buffer (marker-buffer (car org-agenda-bulk-marked-entries)) org-todo-keywords-1))
(chosen-state
;; not good when specific on a buffer
(org-icompleting-read "Choose new TODO state: " buffer-todo-keywords nil t))
(shared-note (read-string "Enter note for all marked items: ")))
(dolist (marker org-agenda-bulk-marked-entries)
(with-current-buffer (marker-buffer marker)
(goto-char marker)
(org-todo chosen-state)
(org-add-log-setup 'state chosen-state nil nil)
;; Insert the shared note and finalize it.
(org-add-log-note)
(insert shared-note)
(org-store-log-note)))))