The following Elisp code defines a new command org-todo-keep-repeater
.
Used interactively it prompts the user for a new TODO state with completion and applies it without modifying the repeater.
The OP Matthew Piziak mentioned that org-cancel-repeater
should save information for restoring the repeater.
That idea is implemented in org-todo-keep-repeater
.
It works by temporarily augmenting replace-match
used in org-cancel-repeater
such that it saves the match string, the beginning position, and end position of the match before replacing it.
With this information the repeater is restored after calling org-todo
.
(defun org-todo-keep-repeater (todo)
"Call `org-todo' with TODO keyword but keep repeater."
(interactive (list (completing-read "Set todo state of current headline to:" org-todo-keywords-1)))
(let ((my-marker-b (make-marker))
(my-marker-e (make-marker))
my-original-repeater)
(cl-letf* ((old-replace-match (symbol-function 'replace-match))
((symbol-function 'replace-match)
(lambda (&rest args)
(setq my-original-repeater (match-string 0))
(set-marker my-marker-b (match-beginning 0))
(set-marker my-marker-e (match-end 0))
(apply old-replace-match args))))
(org-cancel-repeater))
(if my-original-repeater
(progn
(org-todo todo)
(save-excursion
(goto-char my-marker-b)
(delete-region my-marker-b my-marker-e)
(insert my-original-repeater))
(set-marker my-marker-b nil)
(set-marker my-marker-e nil))
(org-todo todo))))
Alternatively one could write a new function that works like org-cancel-repeater
saving the original repeater before canceling it.
Both approaches
- temporarily modifying the old
org-cancel-repeater
- writing an new function working like
org-cancel-repeater
have advantages and disadvantages.
The first approach works as long as org-cancel-repeater
uses replace-match
for the repeater. It follows all other potential future modifications on org-cancel-repeater
. The second approach would make org-todo-keep-repeater
more robust against modifications of org-cancel-repeater
but it would also not follow potential development on org-cancel-repeater
.