@@ -15,6 +15,7 @@ local ts_org = require('orgmode.treesitter')
1515local ts_table = require (' orgmode.treesitter.table' )
1616local EventManager = require (' orgmode.events' )
1717local Promise = require (' orgmode.utils.promise' )
18+ local TodoConfig = require (' orgmode.parser.todo-config' )
1819local events = EventManager .event
1920local Link = require (' orgmode.objects.link' )
2021
386387function OrgMappings :_todo_change_state (direction )
387388 local headline = ts_org .closest_headline ()
388389 local _ , old_state , was_done = headline :todo ()
390+ --- @cast old_state - nil
391+ --- @cast was_done - nil
389392 local changed = self :_change_todo_state (direction , true )
390393 if not changed then
391394 return
@@ -403,9 +406,37 @@ function OrgMappings:_todo_change_state(direction)
403406 return dispatchEvent ()
404407 end
405408
406- local log_note = config .org_log_done == ' note'
407- local log_time = config .org_log_done == ' time'
408- local should_log_time = log_note or log_time
409+ local new_state = item .todo_keyword .value
410+
411+ -- Determine which configuration to use
412+ local global_config = config .org_log_done
413+
414+ --- @type nil | false | ' time' | ' note'
415+ local section_config
416+ local logging_prop = item .properties .items .logging
417+ if logging_prop == ' nil' then
418+ section_config = false
419+ elseif logging_prop ~= nil then
420+ local todoConfig = TodoConfig :parse (logging_prop )
421+ if todoConfig ~= nil then
422+ section_config = todoConfig :get_logging_behavior (old_state , new_state )
423+ else
424+ -- TODO: Report invalid config?
425+ section_config = nil
426+ end
427+ else
428+ section_config = nil
429+ end
430+
431+ -- Use the most locally available log config
432+ --- @type false | ' time' | ' note'
433+ local log_config
434+ if section_config ~= nil then
435+ log_config = section_config
436+ else
437+ log_config = global_config
438+ end
439+
409440 local indent = config :get_indent (headline :level () + 1 )
410441
411442 local get_note = function (note )
@@ -423,11 +454,12 @@ function OrgMappings:_todo_change_state(direction)
423454
424455 local repeater_dates = item :get_repeater_dates ()
425456 if # repeater_dates == 0 then
426- if should_log_time and item :is_done () and not was_done then
457+ -- If going from "not done" to "done", set the closed date and add the note/time
458+ if log_config ~= false and item :is_done () and not was_done then
427459 headline :set_closed_date ()
428460 item = Files .get_closest_headline ()
429461
430- if log_note then
462+ if log_config == ' note ' then
431463 dispatchEvent ()
432464 return self .capture .closing_note :open ():next (function (note )
433465 local valid_note = get_note (note )
@@ -438,7 +470,9 @@ function OrgMappings:_todo_change_state(direction)
438470 end )
439471 end
440472 end
441- if should_log_time and not item :is_done () and was_done then
473+
474+ -- If going from "done" to "not done", remove the close date
475+ if log_config ~= false and not item :is_done () and was_done then
442476 headline :remove_closed_date ()
443477 end
444478 return dispatchEvent ()
@@ -450,19 +484,19 @@ function OrgMappings:_todo_change_state(direction)
450484
451485 self :_change_todo_state (' reset' )
452486 local state_change = {
453- string.format (' %s- State "%s" from "%s" [%s]' , indent , item . todo_keyword . value , old_state , Date .now ():to_string ()),
487+ string.format (' %s- State "%s" from "%s" [%s]' , indent , new_state , old_state , Date .now ():to_string ()),
454488 }
455489
456490 dispatchEvent ()
457491 return Promise .resolve ()
458492 :next (function ()
459- if not log_note then
493+ if log_config == ' time ' then
460494 return state_change
495+ elseif log_config == ' note' then
496+ return self .capture .closing_note :open ():next (function (closing_note )
497+ return get_note (closing_note )
498+ end )
461499 end
462-
463- return self .capture .closing_note :open ():next (function (closing_note )
464- return get_note (closing_note )
465- end )
466500 end )
467501 :next (function (note )
468502 headline :set_property (' LAST_REPEAT' , Date .now ():to_wrapped_string (false ))
0 commit comments