Skip to content

Commit f874118

Browse files
refactor(closing note)!: Use different title per closing note type
1 parent 95fb795 commit f874118

File tree

7 files changed

+119
-49
lines changed

7 files changed

+119
-49
lines changed

DOCS.md

-7
Original file line numberDiff line numberDiff line change
@@ -1168,13 +1168,6 @@ Save note window content as closing note for a headline. Ignores first comment (
11681168
_mapped to_: `<Leader>ok`<br />
11691169
Close note window without saving anything
11701170

1171-
#### **org_note_show_help**
1172-
1173-
_mapped to_: `g?`<br />
1174-
Show help popup with mappings
1175-
1176-
These mappings live under `mappings.note`, and can be changed like this:
1177-
11781171
```lua
11791172
require('orgmode').setup({
11801173
org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'},

lua/orgmode/agenda/init.lua

+7
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,13 @@ function Agenda:clock_in()
255255
})
256256
end
257257

258+
function Agenda:add_note()
259+
return self:_remote_edit({
260+
action = 'org_mappings.add_note',
261+
redo = true,
262+
})
263+
end
264+
258265
function Agenda:refile()
259266
return self:_remote_edit({
260267
action = 'capture.refile_headline_to_destination',

lua/orgmode/capture/init.lua

+62-17
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,66 @@ function Capture:autocomplete_refile(arg_lead)
428428
end, result)
429429
end
430430

431+
function Capture:build_note_capture(title)
432+
return CaptureWindow:new({
433+
template = Template:new({
434+
template = '# ' .. title .. '\n\n%?',
435+
}),
436+
on_finish = function(content)
437+
local result = {}
438+
439+
-- Remove lines from the beginning that are empty or comments
440+
-- until we find a non-empty line
441+
local trim_obsolete = true
442+
443+
for _, line in ipairs(content) do
444+
local is_non_empty_line = not line:match('^%s*#%s') and vim.trim(line) ~= ''
445+
446+
if trim_obsolete and is_non_empty_line then
447+
trim_obsolete = false
448+
end
449+
450+
if not trim_obsolete then
451+
table.insert(result, line)
452+
end
453+
end
454+
455+
if #result == 0 then
456+
return nil
457+
end
458+
459+
local has_non_empty_line = vim.tbl_filter(function(line)
460+
return vim.trim(line) ~= ''
461+
end, result)
462+
463+
if has_non_empty_line then
464+
return result
465+
end
466+
467+
return nil
468+
end,
469+
on_open = function(capture_window)
470+
local maps = config:get_mappings('note', vim.api.nvim_get_current_buf())
471+
if not maps then
472+
return
473+
end
474+
local finalize_map = maps.org_note_finalize
475+
finalize_map.map_entry
476+
:with_handler(function()
477+
return capture_window:finish()
478+
end)
479+
:attach(finalize_map.default_map, finalize_map.user_map, finalize_map.opts)
480+
481+
local kill_map = maps.org_note_kill
482+
kill_map.map_entry
483+
:with_handler(function()
484+
return capture_window:kill()
485+
end)
486+
:attach(kill_map.default_map, kill_map.user_map, kill_map.opts)
487+
end,
488+
})
489+
end
490+
431491
---@param from_mapping? boolean
432492
function Capture:kill(from_mapping)
433493
if self._window then
@@ -483,25 +543,10 @@ function Capture:_get_refile_vars()
483543
return opts
484544
end
485545

546+
---@deprecated
486547
---@private
487548
function Capture:_setup_closing_note()
488-
return CaptureWindow:new({
489-
template = Template:new({
490-
template = '# Insert note for closed todo item\n\n%?',
491-
}),
492-
on_finish = function(content)
493-
if content[1] and content[1]:match('#%s+') then
494-
content = { unpack(content, 2) }
495-
end
496-
if content[1] and vim.trim(content[1]) == '' then
497-
content = { unpack(content, 2) }
498-
end
499-
return content
500-
end,
501-
on_open = function()
502-
config:setup_mappings('note', vim.api.nvim_get_current_buf())
503-
end,
504-
})
549+
return self:build_note_capture('Insert note for closed todo item')
505550
end
506551

507552
---@private

lua/orgmode/capture/window.lua

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ local Promise = require('orgmode.utils.promise')
44

55
---@class OrgCaptureWindowOpts
66
---@field template OrgCaptureTemplate
7-
---@field on_open? fun()
8-
---@field on_finish? fun(lines: string[]): string[]
7+
---@field on_open? fun(self: OrgCaptureWindow)
8+
---@field on_finish? fun(lines: string[]): string[] | nil
99
---@field on_close? fun()
1010

1111
---@class OrgCaptureWindow :OrgCaptureWindowOpts
@@ -41,7 +41,7 @@ function CaptureWindow:open()
4141
self._bufnr = vim.api.nvim_get_current_buf()
4242

4343
if self.on_open then
44-
self.on_open()
44+
self.on_open(self)
4545
end
4646

4747
return Promise.new(function(resolve)

lua/orgmode/config/defaults.lua

+2-1
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ local DefaultConfig = {
113113
org_agenda_schedule = '<prefix>is',
114114
org_agenda_filter = '/',
115115
org_agenda_refile = '<prefix>r',
116+
org_agenda_add_note = '<prefix>na',
116117
org_agenda_show_help = 'g?',
117118
},
118119
capture = {
@@ -124,7 +125,6 @@ local DefaultConfig = {
124125
note = {
125126
org_note_finalize = '<C-c>',
126127
org_note_kill = '<prefix>k',
127-
org_note_show_help = 'g?',
128128
},
129129
org = {
130130
org_refile = '<prefix>r',
@@ -142,6 +142,7 @@ local DefaultConfig = {
142142
org_toggle_heading = '<prefix>*',
143143
org_open_at_point = '<prefix>o',
144144
org_edit_special = [[<prefix>']],
145+
org_add_note = '<prefix>na',
145146
org_cycle = '<TAB>',
146147
org_global_cycle = '<S-TAB>',
147148
org_archive_subtree = '<prefix>$',

lua/orgmode/config/mappings/init.lua

+8-4
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ return {
123123
help_desc = 'Refile headline to specific destination',
124124
},
125125
}),
126+
org_agenda_add_note = m.action(
127+
'agenda.add_note',
128+
{ opts = { desc = 'org add note', help_desc = 'Add a note to the current headline' } }
129+
),
126130
org_agenda_show_help = m.action(
127131
'org_mappings.show_help',
128132
{ args = { 'agenda' }, opts = { desc = 'org show help', help_desc = 'Show this help' } }
@@ -152,10 +156,6 @@ return {
152156
'capture.closing_note.kill',
153157
{ opts = { desc = 'org kill note', help_desc = 'Close without saving' } }
154158
),
155-
org_note_show_help = m.action('org_mappings.show_help', {
156-
args = { 'note' },
157-
opts = { desc = 'org show help' },
158-
}),
159159
},
160160
org = {
161161
org_refile = m.action(
@@ -222,6 +222,10 @@ return {
222222
'org_mappings.edit_special',
223223
{ opts = { desc = 'org edit special', help_desc = 'Edit the source block under the cursor in another buffer' } }
224224
),
225+
org_add_note = m.action(
226+
'org_mappings.add_note',
227+
{ opts = { desc = 'org add note', help_desc = 'Add a note to the current headline' } }
228+
),
225229
org_cycle = m.action('org_mappings.cycle', { opts = { desc = 'org toggle fold', help_desc = 'Toggle folding' } }),
226230
org_global_cycle = m.action(
227231
'org_mappings.global_cycle',

lua/orgmode/org/mappings.lua

+37-17
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,26 @@ function OrgMappings:toggle_heading()
376376
vim.fn.setline('.', line)
377377
end
378378

379+
---Prompt for a note
380+
---@private
381+
---@param template string
382+
---@param indent string
383+
---@param title string
384+
---@return OrgPromise<string[]>
385+
function OrgMappings:_get_note(template, indent, title)
386+
return self.capture:build_note_capture(title):open():next(function(closing_note)
387+
if closing_note == nil then
388+
return
389+
end
390+
391+
for i, line in ipairs(closing_note) do
392+
closing_note[i] = indent .. ' ' .. line
393+
end
394+
395+
return vim.list_extend({ template }, closing_note)
396+
end)
397+
end
398+
379399
function OrgMappings:_todo_change_state(direction)
380400
local headline = self.files:get_closest_headline()
381401
local old_state = headline:get_todo()
@@ -403,20 +423,7 @@ function OrgMappings:_todo_change_state(direction)
403423
local indent = headline:get_indent()
404424

405425
local closing_note_text = ('%s- CLOSING NOTE %s \\\\'):format(indent, Date.now():to_wrapped_string(false))
406-
407-
local get_note = function(template)
408-
return self.capture.closing_note:open():next(function(closing_note)
409-
if closing_note == nil then
410-
return
411-
end
412-
413-
for i, line in ipairs(closing_note) do
414-
closing_note[i] = indent .. ' ' .. line
415-
end
416-
417-
return vim.list_extend({ template }, closing_note)
418-
end)
419-
end
426+
local closed_title = 'Insert note for closed todo item'
420427

421428
local repeater_dates = item:get_repeater_dates()
422429

@@ -436,7 +443,7 @@ function OrgMappings:_todo_change_state(direction)
436443
return item
437444
end
438445

439-
return get_note(closing_note_text):next(function(closing_note)
446+
return self:_get_note(closing_note_text, indent, closed_title):next(function(closing_note)
440447
return item:add_note(closing_note)
441448
end)
442449
end
@@ -455,6 +462,7 @@ function OrgMappings:_todo_change_state(direction)
455462
old_state,
456463
Date.now():to_string()
457464
)
465+
local repeat_note_title = ('Insert note for state change from "%s" to "%s"'):format(old_state, new_todo)
458466

459467
if log_repeat_enabled then
460468
item:set_property('LAST_REPEAT', Date.now():to_wrapped_string(false))
@@ -470,12 +478,12 @@ function OrgMappings:_todo_change_state(direction)
470478

471479
-- Done note has precedence over repeat note
472480
if prompt_done_note then
473-
return get_note(closing_note_text):next(function(closing_note)
481+
return self:_get_note(closing_note_text, indent, closed_title):next(function(closing_note)
474482
return item:add_note(closing_note)
475483
end)
476484
end
477485

478-
return get_note(repeat_note_template .. ' \\\\'):next(function(closing_note)
486+
return self:_get_note(repeat_note_template .. ' \\\\', indent, repeat_note_title):next(function(closing_note)
479487
return item:add_note(closing_note)
480488
end)
481489
end
@@ -803,6 +811,18 @@ function OrgMappings:_edit_special_callback()
803811
EditSpecial:new():done()
804812
end
805813

814+
function OrgMappings:add_note()
815+
local headline = self.files:get_closest_headline()
816+
local indent = headline:get_indent()
817+
local text = ('%s- Note taken on %s \\\\'):format(indent, Date.now():to_wrapped_string(false))
818+
return self:_get_note(text, indent, 'Insert note for entry.'):next(function(note)
819+
if not note then
820+
return false
821+
end
822+
return headline:add_note(note)
823+
end)
824+
end
825+
806826
function OrgMappings:open_at_point()
807827
local link = Hyperlinks.get_link_under_cursor()
808828
if not link then

0 commit comments

Comments
 (0)