> > ... > > + (add-function :around (symbol-function 'current-time) #'org-at-current-time) > > While the function like you propose is long desired, reusing > implementation from tests is not the greatest idea. > We should not use advices in the main Org codebase. > > I suggest building upon existing patch that uses global variable > instead. See https://list.orgmode.org/orgmode/[email protected]/
I reverted my changes and followed your advice. Unfortunately, I was not able to create ert-tests for this approach. But it does work when I test it manually. Le sam. 4 juil. 2026 à 06:28, Ihor Radchenko <[email protected]> a écrit : > Earl Chase <[email protected]> writes: > > > I reused `org-test-at-time'. Specifically, `org-test-at-time' is now an > > alias of `org-at-time'. This "new" macro is what `org-todo-at' uses in > > order to set the current time to the time that you provide it. > > ... > > + (add-function :around (symbol-function 'current-time) > #'org-at-current-time) > > While the function like you propose is long desired, reusing > implementation from tests is not the greatest idea. > We should not use advices in the main Org codebase. > > I suggest building upon existing patch that uses global variable > instead. See https://list.orgmode.org/orgmode/[email protected]/ > > -- > Ihor Radchenko // yantar92, > Org mode maintainer, > Learn more about Org mode at <https://orgmode.org/>. > Support Org development at <https://liberapay.com/org-mode>, > or support my work at <https://liberapay.com/yantar92> >
From 3aa8e9bd1b9d9a0aeed4b80f0b070d4af35c8fa3 Mon Sep 17 00:00:00 2001 From: ApollonDeParnasse <[email protected]> Date: Thu, 2 Jul 2026 16:43:08 -0500 Subject: [PATCH] lisp/org.el: New function for calling `org-todo' at a given time. * lisp/org.el (org-overriding-effective-time): Place for `org-todo-at' to store user-entered time. (org-current-effective-time): Return the value of `org-overriding-effective-time' when it is non-nil. (org-todo-at): Call `org-todo' at a given time. * lisp/org-keys.el (org-mode-map): New keybinding for `org-todo-at'. --- doc/org-manual.org | 22 ++++++++++++++++++++++ etc/ORG-NEWS | 5 +++++ lisp/org-keys.el | 2 ++ lisp/org.el | 40 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/doc/org-manual.org b/doc/org-manual.org index 9201a341a..70e274611 100644 --- a/doc/org-manual.org +++ b/doc/org-manual.org @@ -3977,6 +3977,14 @@ The most important commands to work with TODO entries are: buffer with the {{{kbd(t)}}} command key (see [[*Commands in the Agenda Buffer]]). +- {{{kbd(C-c M-t)}}} (~org-todo-at~) :: + + #+kindex: C-c M-t + #+cindex: cycling, of TODO states + Rotate the TODO state of the current item, + just like ~org-todo~. Will prompt you for + a time for each state change. + - {{{kbd(S-RIGHT)}}} {{{kbd(S-LEFT)}}} :: #+kindex: S-RIGHT @@ -4369,6 +4377,13 @@ command ~org-todo~ with a prefix argument. The note is inserted as a list item below the headline, but can also be placed into a drawer, see [[*Tracking TODO state changes]]. +- {{{kbd(C-u C-c M-t)}}} (~org-todo-at~) :: + + #+kindex: C-u C-M C-t + Prompt for a time for the TODO state change and a note. + The note is inserted as a list item below the headline, + but can also be placed into a drawer, just like ~org-todo~. + If you want to be more systematic, Org mode can automatically record a timestamp and optionally a note when you mark a TODO item as DONE, or even each time you change the state of a TODO item. This system is @@ -7002,6 +7017,13 @@ about what to do with it. Changing the TODO state of an item to DONE automatically stops the clock if it is running in this same item. +- {{{kbd(C-c M-t)}}} (~org-todo-at~) :: + + #+kindex: C-c M-t + #+findex: org-todo-at + Changing the TODO state of an item to DONE automatically stops the + clock at the time that you provide if it is running in this same item. + - {{{kbd(C-c C-x C-q)}}} (~org-clock-cancel~) :: #+kindex: C-c C-x C-q diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 261d5d3be..edc336988 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -227,6 +227,11 @@ needs. The recommended alternative value is ~itemize~. Given the completed and total number of tasks, format the percent cookie =[N%]=. +*** New function ~org-todo-at~ + +Like `org-todo', but you will be first be prompted for a time. +This time will be used as the time of the TODO state change of +the item that you are editing. ** Removed or renamed functions and variables diff --git a/lisp/org-keys.el b/lisp/org-keys.el index 84eb3bf13..6853e9f3d 100644 --- a/lisp/org-keys.el +++ b/lisp/org-keys.el @@ -215,6 +215,7 @@ (declare-function org-timer-start "org-timer" (&optional offset)) (declare-function org-timer-stop "org-timer" ()) (declare-function org-todo "org" (&optional arg1)) +(declare-function org-todo-at "org" (time &optional arg)) (declare-function org-toggle-archive-tag "org-archive" (&optional find-done)) (declare-function org-toggle-checkbox "org-list" (&optional toggle-presence)) (declare-function org-toggle-radio-button "org-list" (&optional arg)) @@ -576,6 +577,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names." (org-defkey org-mode-map (kbd "C-c C-x q") #'org-toggle-tags-groups) (org-defkey org-mode-map (kbd "C-c C-j") #'org-goto) (org-defkey org-mode-map (kbd "C-c C-t") #'org-todo) +(org-defkey org-mode-map (kbd "C-c M-t") #'org-todo-at) (org-defkey org-mode-map (kbd "C-c C-q") #'org-set-tags-command) (org-defkey org-mode-map (kbd "C-c C-s") #'org-schedule) (org-defkey org-mode-map (kbd "C-c C-d") #'org-deadline) diff --git a/lisp/org.el b/lisp/org.el index 294a5eb52..3fb998ce1 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -9611,12 +9611,19 @@ nil or a string to be used for the todo mark." ) (defvar org-agenda-headline-snapshot-before-repeat) +(defvar org-overriding-effective-time nil + "Place for `org-todo-at' to store user-entered time. +Used to override the value return by `org-current-effective-time'.") + (defun org-current-effective-time () - "Return current time adjusted for `org-extend-today-until' variable." + "Return current time adjusted for `org-extend-today-until' variable. +If `org-overriding-effective-time' is non-nil, then its value will +be returned instead." (let* ((ct (org-current-time)) (dct (decode-time ct)) (ct1 (cond + (org-overriding-effective-time org-overriding-effective-time) (org-use-last-clock-out-time-as-effective-time (or (org-clock-get-last-clock-out-time) ct)) ((and org-use-effective-time (< (decoded-time-hour dct) org-extend-today-until)) @@ -9918,6 +9925,37 @@ When called through Elisp, arg is also interpreted in the following way: (run-hook-with-args 'org-trigger-hook change-plist))) (when commentp (org-toggle-comment)))))))) +(defun org-todo-at (&optional arg) + "Like `org-todo', but you will be prompted for a time. +The value you provided will be used as the time value of any +state change that is triggered by `org-todo'. + +With `\\[universal-argument]' prefix ARG, force logging the state change \ +and take a +logging note. +With a `\\[universal-argument] \\[universal-argument]' prefix, switch to the \ +next set of TODO \ +keywords (nextset). +Another way to achieve this is `S-C-<right>'. +With a `\\[universal-argument] \\[universal-argument] \\[universal-argument]' \ +prefix, circumvent any state blocking. +With numeric prefix arg, switch to the Nth state. + +With a numeric prefix arg of 0, inhibit note taking for the change. +With a numeric prefix arg of -1, cancel repeater to allow marking as DONE. + +When called through Elisp, arg is also interpreted in the following way: +`none' -> empty state +\"\" -> switch to empty state +`done' -> switch to DONE +`nextset' -> switch to the next set of keywords +`previousset' -> switch to the previous set of keywords +\"WAITING\" -> switch to the specified keyword, but only if it + really is a member of `org-todo-keywords'." + (interactive) + (let ((org-overriding-effective-time (org-read-date t t))) + (org-todo arg))) + (defun org-block-todo-from-children-or-siblings-or-parent (change-plist) "Block turning an entry into a TODO, using the hierarchy. This checks whether the current task should be blocked from state -- 2.54.0
