Skip to content

Commit 71f38a7

Browse files
committed
Handle nested lists with cookies
1 parent e09227a commit 71f38a7

File tree

4 files changed

+47
-15
lines changed

4 files changed

+47
-15
lines changed

lua/orgmode/org/mappings.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ function OrgMappings:toggle_checkbox()
165165
vim.fn.setline('.', new_line)
166166
local headline = Headline:new(tree_utils.closest_headline())
167167
local list = List:new(tree_utils.closest_list())
168-
headline:update_cookie(list)
168+
list:update_parent_cookie()
169169
end
170170

171171
function OrgMappings:timestamp_up_day()

lua/orgmode/treesitter/headline.lua

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -124,20 +124,6 @@ function Headline:cookie()
124124
return self:parse('%[%d?/%d?%]')
125125
end
126126

127-
function Headline:update_cookie(list)
128-
local checkbox_status = self:cookie()
129-
if not checkbox_status then
130-
return
131-
end
132-
133-
local checkboxes = list:checkboxes()
134-
local checked_boxes = vim.tbl_filter(function(box)
135-
return box:match('%[%w%]')
136-
end, checkboxes)
137-
local new_status = ('[%d/%d]'):format(#checked_boxes, #checkboxes)
138-
tree_utils.set_node_text(checkbox_status, new_status)
139-
end
140-
141127
-- @return tsnode, string
142128
function Headline:parse(pattern)
143129
local match = ''

lua/orgmode/treesitter/list.lua

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
local ts_utils = require('nvim-treesitter.ts_utils')
22
local tree_utils = require('orgmode.utils.treesitter')
33
local query = vim.treesitter.query
4+
local Headline = require('orgmode.treesitter.headline')
45

56
local List = {}
67

@@ -11,6 +12,40 @@ function List:new(list_node)
1112
return data
1213
end
1314

15+
-- Updates the cookie of the immediate parent
16+
-- This always checks for a parent list first
17+
-- then for a headline.
18+
function List:parent_cookie()
19+
local parent_list = tree_utils.find_list(self.list:parent())
20+
if parent_list then
21+
-- We only care about the cookie if it's at the top
22+
local top_item = parent_list:named_child(0)
23+
local content = top_item:field('contents')[1]
24+
-- The cookie should be the last thing on the line
25+
local cookie_node = content:named_child(content:named_child_count() - 1)
26+
if query.get_node_text(cookie_node, 0):match('%[%d?/%d?%]') then
27+
return cookie_node
28+
end
29+
end
30+
31+
local parent_header = Headline:new(tree_utils.closest_headline())
32+
return parent_header:cookie()
33+
end
34+
35+
function List:update_parent_cookie()
36+
local parent_cookie = self:parent_cookie()
37+
if not parent_cookie then
38+
return
39+
end
40+
41+
local checkboxes = self:checkboxes()
42+
local checked_boxes = vim.tbl_filter(function(box)
43+
return box:match('%[%w%]')
44+
end, checkboxes)
45+
local new_status = ('[%d/%d]'):format(#checked_boxes, #checkboxes)
46+
tree_utils.set_node_text(parent_cookie, new_status)
47+
end
48+
1449
function List:checkboxes()
1550
return vim.tbl_map(function(node)
1651
local text = query.get_node_text(node, 0)

tests/plenary/ui/mappings_spec.lua

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,4 +1607,15 @@ describe('Mappings', function()
16071607
vim.cmd([[exe "norm \<C-space>"]])
16081608
assert.are.same('* Test orgmode [1/2]', vim.fn.getline(1))
16091609
end)
1610+
1611+
it('should update the checklist cookies on a parent list', function()
1612+
helpers.load_file_content({
1613+
'- Test orgmode [/]',
1614+
' - [ ] checkbox item',
1615+
' - [ ] checkbox item',
1616+
})
1617+
vim.fn.cursor(2, 1)
1618+
vim.cmd([[exe "norm \<C-space>"]])
1619+
assert.are.same('- Test orgmode [1/2]', vim.fn.getline(1))
1620+
end)
16101621
end)

0 commit comments

Comments
 (0)