@@ -15,6 +15,7 @@ local ts_org = require('orgmode.treesitter')
15
15
local ts_table = require (' orgmode.treesitter.table' )
16
16
local EventManager = require (' orgmode.events' )
17
17
local Promise = require (' orgmode.utils.promise' )
18
+ local TodoConfig = require (' orgmode.parser.todo-config' )
18
19
local events = EventManager .event
19
20
local Link = require (' orgmode.objects.link' )
20
21
386
387
function OrgMappings :_todo_change_state (direction )
387
388
local headline = ts_org .closest_headline ()
388
389
local _ , old_state , was_done = headline :todo ()
390
+ --- @cast old_state - nil
391
+ --- @cast was_done - nil
389
392
local changed = self :_change_todo_state (direction , true )
390
393
if not changed then
391
394
return
@@ -403,9 +406,37 @@ function OrgMappings:_todo_change_state(direction)
403
406
return dispatchEvent ()
404
407
end
405
408
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
+
409
440
local indent = config :get_indent (headline :level () + 1 )
410
441
411
442
local get_note = function (note )
@@ -423,11 +454,12 @@ function OrgMappings:_todo_change_state(direction)
423
454
424
455
local repeater_dates = item :get_repeater_dates ()
425
456
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
427
459
headline :set_closed_date ()
428
460
item = Files .get_closest_headline ()
429
461
430
- if log_note then
462
+ if log_config == ' note ' then
431
463
dispatchEvent ()
432
464
return self .capture .closing_note :open ():next (function (note )
433
465
local valid_note = get_note (note )
@@ -438,7 +470,9 @@ function OrgMappings:_todo_change_state(direction)
438
470
end )
439
471
end
440
472
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
442
476
headline :remove_closed_date ()
443
477
end
444
478
return dispatchEvent ()
@@ -450,19 +484,19 @@ function OrgMappings:_todo_change_state(direction)
450
484
451
485
self :_change_todo_state (' reset' )
452
486
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 ()),
454
488
}
455
489
456
490
dispatchEvent ()
457
491
return Promise .resolve ()
458
492
:next (function ()
459
- if not log_note then
493
+ if log_config == ' time ' then
460
494
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 )
461
499
end
462
-
463
- return self .capture .closing_note :open ():next (function (closing_note )
464
- return get_note (closing_note )
465
- end )
466
500
end )
467
501
:next (function (note )
468
502
headline :set_property (' LAST_REPEAT' , Date .now ():to_wrapped_string (false ))
0 commit comments