@@ -15,6 +15,7 @@ local ts = require('orgmode.treesitter.compat')
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
20
21
--- @class OrgMappings
377
378
function OrgMappings :_todo_change_state (direction )
378
379
local headline = ts_org .closest_headline ()
379
380
local _ , old_state , was_done = headline :todo ()
381
+ --- @cast old_state - nil
382
+ --- @cast was_done - nil
380
383
local changed = self :_change_todo_state (direction , true )
381
384
if not changed then
382
385
return
@@ -394,9 +397,37 @@ function OrgMappings:_todo_change_state(direction)
394
397
return dispatchEvent ()
395
398
end
396
399
397
- local log_note = config .org_log_done == ' note'
398
- local log_time = config .org_log_done == ' time'
399
- local should_log_time = log_note or log_time
400
+ local new_state = item .todo_keyword .value
401
+
402
+ -- Determine which configuration to use
403
+ local global_config = config .org_log_done
404
+
405
+ --- @type nil | false | ' time' | ' note'
406
+ local section_config
407
+ local logging_prop = item .properties .items .logging
408
+ if logging_prop == ' nil' then
409
+ section_config = false
410
+ elseif logging_prop ~= nil then
411
+ local todoConfig = TodoConfig :parse (logging_prop )
412
+ if todoConfig ~= nil then
413
+ section_config = todoConfig :get_logging_behavior (old_state , new_state )
414
+ else
415
+ -- TODO: Report invalid config?
416
+ section_config = nil
417
+ end
418
+ else
419
+ section_config = nil
420
+ end
421
+
422
+ -- Use the most locally available log config
423
+ --- @type false | ' time' | ' note'
424
+ local log_config
425
+ if section_config ~= nil then
426
+ log_config = section_config
427
+ else
428
+ log_config = global_config
429
+ end
430
+
400
431
local indent = config :get_indent (headline :level () + 1 )
401
432
402
433
local get_note = function (note )
@@ -414,11 +445,12 @@ function OrgMappings:_todo_change_state(direction)
414
445
415
446
local repeater_dates = item :get_repeater_dates ()
416
447
if # repeater_dates == 0 then
417
- if should_log_time and item :is_done () and not was_done then
448
+ -- If going from "not done" to "done", set the closed date and add the note/time
449
+ if log_config ~= false and item :is_done () and not was_done then
418
450
headline :set_closed_date ()
419
451
item = Files .get_closest_headline ()
420
452
421
- if log_note then
453
+ if log_config == ' note ' then
422
454
dispatchEvent ()
423
455
return self .capture .closing_note :open ():next (function (note )
424
456
local valid_note = get_note (note )
@@ -429,7 +461,9 @@ function OrgMappings:_todo_change_state(direction)
429
461
end )
430
462
end
431
463
end
432
- if should_log_time and not item :is_done () and was_done then
464
+
465
+ -- If going from "done" to "not done", remove the close date
466
+ if log_config ~= false and not item :is_done () and was_done then
433
467
headline :remove_closed_date ()
434
468
end
435
469
return dispatchEvent ()
@@ -441,19 +475,19 @@ function OrgMappings:_todo_change_state(direction)
441
475
442
476
self :_change_todo_state (' reset' )
443
477
local state_change = {
444
- string.format (' %s- State "%s" from "%s" [%s]' , indent , item . todo_keyword . value , old_state , Date .now ():to_string ()),
478
+ string.format (' %s- State "%s" from "%s" [%s]' , indent , new_state , old_state , Date .now ():to_string ()),
445
479
}
446
480
447
481
dispatchEvent ()
448
482
return Promise .resolve ()
449
483
:next (function ()
450
- if not log_note then
484
+ if log_config == ' time ' then
451
485
return state_change
486
+ elseif log_config == ' note' then
487
+ return self .capture .closing_note :open ():next (function (closing_note )
488
+ return get_note (closing_note )
489
+ end )
452
490
end
453
-
454
- return self .capture .closing_note :open ():next (function (closing_note )
455
- return get_note (closing_note )
456
- end )
457
491
end )
458
492
:next (function (note )
459
493
headline :set_property (' LAST_REPEAT' , Date .now ():to_wrapped_string (false ))
0 commit comments