Skip to content

Commit 914de06

Browse files
Migration to ts-org parser 0.2.0.
1 parent b28a976 commit 914de06

File tree

10 files changed

+158
-130
lines changed

10 files changed

+158
-130
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ local parser_config = require "nvim-treesitter.parsers".get_parser_configs()
7575
parser_config.org = {
7676
install_info = {
7777
url = 'https://github.com/milisims/tree-sitter-org',
78-
revision = 'f110024d539e676f25b72b7c80b0fd43c34264ef',
78+
revision = 'main',
7979
files = {'src/parser.c', 'src/scanner.cc'},
8080
},
8181
filetype = 'org',
@@ -105,7 +105,7 @@ local parser_config = require "nvim-treesitter.parsers".get_parser_configs()
105105
parser_config.org = {
106106
install_info = {
107107
url = 'https://github.com/milisims/tree-sitter-org',
108-
revision = 'f110024d539e676f25b72b7c80b0fd43c34264ef',
108+
revision = 'main',
109109
files = {'src/parser.c', 'src/scanner.cc'},
110110
},
111111
filetype = 'org',

lua/orgmode/colors/todo_highlighter.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ local function add_todo_keyword_highlights()
3131
end, todo_keywords.DONE),
3232
' '
3333
)
34-
table.insert(lines, string.format([[(item "keyword?" @OrgTODO (#any-of? @OrgTODO %s))]], todo_type))
35-
table.insert(lines, string.format([[(item "keyword?" @OrgDONE (#any-of? @OrgDONE %s))]], done_type))
34+
table.insert(lines, string.format([[(item . (expr) @OrgTODO (#any-of? @OrgTODO %s))]], todo_type))
35+
table.insert(lines, string.format([[(item . (expr) @OrgDONE (#any-of? @OrgDONE %s))]], done_type))
3636
for face_name, face_hl in pairs(faces) do
37-
table.insert(lines, string.format([[(item "keyword?" @%s (#eq? @%s %s))]], face_hl, face_hl, face_name))
37+
table.insert(lines, string.format([[(item . (expr) @%s (#eq? @%s %s))]], face_hl, face_hl, face_name))
3838
end
3939
vim.treesitter.set_query('org', 'highlights', table.concat(lines, '\n'))
4040
if vim.bo.filetype == 'org' then

lua/orgmode/objects/date.lua

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,35 @@ local function from_string(datestr, opts)
213213
return parse_date(date, dayname, adjustments, opts)
214214
end
215215

216+
--- @param datestr string
217+
--- @return table[]
218+
local function parse_parts(datestr)
219+
local result = {}
220+
local counter = 1
221+
local patterns = {
222+
{ type = 'date', rgx = '^%d%d%d%d%-%d%d%-%d%d$' },
223+
{ type = 'dayname', rgx = '^%a%a%a$' },
224+
{ type = 'time', rgx = '^%d?%d:%d%d$' },
225+
{ type = 'time_range', rgx = '^%d?%d:%d%d%-%d?%d:%d%d$' },
226+
{ type = 'adjustment', rgx = '^[%.%+%-]+%d+[hdwmy]?$' },
227+
}
228+
for space, item in string.gmatch(datestr, '(%s*)(%S+)') do
229+
local from = counter + space:len()
230+
for _, dt_pattern in ipairs(patterns) do
231+
if item:match(dt_pattern.rgx) then
232+
table.insert(result, {
233+
type = dt_pattern.type,
234+
value = item,
235+
from = from,
236+
to = from + item:len() - 1,
237+
})
238+
counter = counter + item:len() + space:len()
239+
end
240+
end
241+
end
242+
return result
243+
end
244+
216245
local function from_org_date(datestr, opts)
217246
local from_open, from, from_close, delimiter, to_open, to, to_close = datestr:match(pattern .. '(%-%-)' .. pattern)
218247
if not delimiter then
@@ -858,6 +887,7 @@ local function parse_all_from_line(line, lnum)
858887
end
859888

860889
return {
890+
parse_parts = parse_parts,
861891
from_org_date = from_org_date,
862892
from_string = from_string,
863893
now = now,

lua/orgmode/objects/edit_special/init.lua

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@ function EditSpecial:new()
2121
end
2222

2323
function EditSpecial:_parse_position()
24-
local nearest_block_node_info = utils.get_nearest_block_node(
25-
self.file,
26-
{ 'name', 'contents', 'parameters' },
27-
self.org_pos,
28-
true
29-
)
24+
local nearest_block_node_info = utils.get_nearest_block_node(self.file, self.org_pos, true)
3025

3126
if not nearest_block_node_info then
3227
utils.echo_warning('No block node found near cursor')

lua/orgmode/org/mappings.lua

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -183,38 +183,70 @@ function OrgMappings:_adjust_date_part(direction, amount, fallback)
183183
local do_replacement = function(date)
184184
local col = vim.fn.col('.')
185185
local char = vim.fn.getline('.'):sub(col, col)
186+
local raw_date_value = vim.fn.getline('.'):sub(date.range.start_col + 1, date.range.end_col - 1)
186187
if col == date.range.start_col or col == date.range.end_col then
187188
date.active = not date.active
188189
return self:_replace_date(date)
189190
end
190-
local node = Files.get_node_at_cursor()
191191
local col_from_start = col - date.range.start_col
192-
local modify_end_time = false
192+
local parts = Date.parse_parts(raw_date_value)
193193
local adj = nil
194-
if node:type() == 'date' then
195-
if col_from_start <= 5 then
194+
local modify_end_time = false
195+
local part = nil
196+
for _, p in ipairs(parts) do
197+
if col_from_start >= p.from and col_from_start <= p.to then
198+
part = p
199+
break
200+
end
201+
end
202+
203+
if not part then
204+
return
205+
end
206+
207+
local offset = col_from_start - part.from
208+
209+
if part.type == 'date' then
210+
if offset <= 4 then
196211
adj = get_adj('y')
197-
elseif col_from_start <= 8 then
212+
elseif offset <= 7 then
198213
adj = get_adj('m')
199-
elseif col_from_start <= 15 then
214+
else
200215
adj = get_adj('d')
201216
end
202-
elseif node:type() == 'time' then
203-
local has_end_time = node:parent() and node:parent():type() == 'timerange'
204-
if col_from_start <= 17 then
217+
end
218+
219+
if part.type == 'dayname' then
220+
adj = get_adj('d')
221+
end
222+
223+
if part.type == 'time' then
224+
if offset <= 2 then
225+
adj = get_adj('h')
226+
else
227+
adj = minute_adj
228+
end
229+
end
230+
231+
if part.type == 'time_range' then
232+
if offset <= 2 then
205233
adj = get_adj('h')
206-
elseif col_from_start <= 20 then
234+
elseif offset <= 5 then
207235
adj = minute_adj
208-
elseif has_end_time and col_from_start <= 23 then
236+
elseif offset <= 8 then
209237
adj = get_adj('h')
210238
modify_end_time = true
211-
elseif has_end_time and col_from_start <= 26 then
239+
else
212240
adj = minute_adj
213241
modify_end_time = true
214242
end
215-
elseif (node:type() == 'repeater' or node:type() == 'delay') and char:match('[hdwmy]') ~= nil then
243+
end
244+
245+
if part.type == 'adjustment' then
216246
local map = { h = 'd', d = 'w', w = 'm', m = 'y', y = 'h' }
217-
vim.cmd(string.format('norm!r%s', map[char]))
247+
if map[char] then
248+
vim.cmd(string.format('norm!r%s', map[char]))
249+
end
218250
return true
219251
end
220252

@@ -397,6 +429,9 @@ function OrgMappings:handle_return(suffix)
397429
suffix = suffix or ''
398430
local current_file = Files.get_current_file()
399431
local item = current_file:get_current_node()
432+
if item.type == 'expr' then
433+
item = current_file:convert_to_file_node(item.node:parent())
434+
end
400435

401436
if item.node:parent() and item.node:parent():type() == 'headline' then
402437
item = current_file:convert_to_file_node(item.node:parent())

lua/orgmode/parser/file.lua

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ end
4343

4444
function File:_parse()
4545
self:_parse_source_code_filetypes()
46-
self:_parse_sections_and_root_directives()
46+
self:_parse_directives()
47+
self:_parse_sections()
4748
end
4849

4950
function File:get_errors()
@@ -335,11 +336,8 @@ function File:get_section(index)
335336
end
336337

337338
---@private
338-
function File:_parse_sections_and_root_directives()
339+
function File:_parse_sections()
339340
for child in self.tree:root():iter_children() do
340-
if child:type() == 'directive' then
341-
self:_parse_directive(child)
342-
end
343341
if child:type() == 'section' then
344342
local section = Section.from_node(child, self)
345343
table.insert(self.sections, section)
@@ -366,11 +364,10 @@ end
366364

367365
---@private
368366
function File:_parse_source_code_filetypes()
369-
local blocks = self:get_ts_matches('(block (name) @name (parameters) @parameters (#eq? @name "SRC"))')
367+
local blocks = self:get_ts_matches('(block name: (expr) @name parameter: (expr) @parameters (#eq? @name "SRC"))')
370368
local source_code_filetypes = {}
371369
for _, item in ipairs(blocks) do
372-
local params = vim.split(item.parameters.text, '%s+')
373-
local ft = params[1]
370+
local ft = item.parameters and item.parameters.text
374371
if
375372
ft
376373
and ft ~= ''
@@ -383,18 +380,15 @@ function File:_parse_source_code_filetypes()
383380
self.source_code_filetypes = source_code_filetypes
384381
end
385382

386-
function File:_parse_directive(node)
387-
local name = node:named_child(0)
388-
local value = node:named_child(1)
389-
if not name or not value then
390-
return
391-
end
392-
393-
local name_text = self:get_node_text(name)
394-
if name_text:upper() == 'FILETAGS' then
395-
local value_text = self:get_node_text(value)
396-
self.tags = utils.parse_tags_string(value_text)
383+
function File:_parse_directives()
384+
local directives = self:get_ts_matches(
385+
[[(directive name: (expr) @name value: (value) @value (#match? @name "\\cfiletags"))]]
386+
)
387+
local tags = {}
388+
for _, directive in ipairs(directives) do
389+
utils.concat(tags, utils.parse_tags_string(directive.value.text), true)
397390
end
391+
self.tags = tags
398392
end
399393

400394
return File

lua/orgmode/parser/section.lua

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -88,49 +88,41 @@ function Section.from_node(section_node, file, parent)
8888

8989
for child in section_node:iter_children() do
9090
if child:type() == 'plan' then
91-
local plan_children = ts_utils.get_named_children(child)
92-
local len = #plan_children
93-
local i = 1
94-
while i <= len do
95-
local plan_item = plan_children[i]
96-
if not plan_item then
97-
break
98-
end
99-
local next_item = plan_children[i + 1]
100-
101-
local type = 'NONE'
102-
local node = plan_item
103-
local item_type = plan_item:type():upper()
104-
105-
if item_type == 'NAME' and next_item and next_item:type():upper() == 'TIMESTAMP' then
106-
local t = file:get_node_text(plan_item):upper()
107-
if t == 'DEADLINE:' or t == 'SCHEDULED:' or t == 'CLOSED:' then
108-
node = next_item
109-
type = t:sub(1, t:len() - 1)
110-
i = i + 1
91+
for entry in child:iter_children() do
92+
if entry:type() == 'entry' then
93+
local first_node = entry:named_child(0)
94+
local first_node_text = file:get_node_text(first_node)
95+
if entry:named_child_count() == 1 and first_node:type() == 'timestamp' then
96+
utils.concat(
97+
data.dates,
98+
Date.from_org_date(first_node_text, {
99+
range = Range.from_node(first_node),
100+
})
101+
)
102+
end
103+
if entry:named_child_count() == 2 and first_node:type() == 'entry_name' then
104+
local valid_plan_types = { 'SCHEDULED', 'DEADLINE', 'CLOSED' }
105+
local type = 'NONE'
106+
if vim.tbl_contains(valid_plan_types, first_node_text:upper()) then
107+
type = first_node_text
108+
end
109+
local timestamp = file:get_node_text(entry:named_child(1))
110+
utils.concat(
111+
data.dates,
112+
Date.from_org_date(timestamp, {
113+
range = Range.from_node(entry:named_child(1)),
114+
type = type,
115+
})
116+
)
111117
end
112118
end
113-
114-
local date = file:get_node_text(node)
115-
utils.concat(
116-
data.dates,
117-
Date.from_org_date(date, {
118-
type = type,
119-
range = Range.from_node(node),
120-
})
121-
)
122-
i = i + 1
123119
end
124120
end
125121
if child:type() == 'body' then
126-
local dates = file:get_ts_matches('(timestamp) @timestamp', child)
127-
for _, date in ipairs(dates) do
128-
utils.concat(
129-
data.dates,
130-
Date.from_org_date(date.timestamp.text, {
131-
range = Range.from_node(date.timestamp.node),
132-
})
133-
)
122+
local start_line = child:range()
123+
local lines = file:get_node_text_list(child)
124+
for i, line in ipairs(lines) do
125+
utils.concat(data.dates, Date.parse_all_from_line(line, start_line + i))
134126
end
135127
local drawers = file:get_ts_matches('(drawer) @drawer', child)
136128
for _, drawer_item in ipairs(drawers) do
@@ -166,13 +158,16 @@ function Section.from_node(section_node, file, parent)
166158
data.title = file:get_node_text(headline_node)
167159
data.todo_keyword_node = headline_node:child(0)
168160
end
169-
if headline_node:type() == 'tag' then
170-
local tag = file:get_node_text(headline_node)
171-
if not vim.tbl_contains(data.tags, tag) then
172-
table.insert(data.tags, tag)
173-
end
174-
if not vim.tbl_contains(data.own_tags, tag) then
175-
table.insert(data.own_tags, tag)
161+
if headline_node:type() == 'tag_list' then
162+
local tags = ts_utils.get_named_children(headline_node)
163+
for _, tag_node in ipairs(tags) do
164+
local tag = file:get_node_text(tag_node)
165+
if not vim.tbl_contains(data.tags, tag) then
166+
table.insert(data.tags, tag)
167+
end
168+
if not vim.tbl_contains(data.own_tags, tag) then
169+
table.insert(data.own_tags, tag)
170+
end
176171
end
177172
end
178173
end

0 commit comments

Comments
 (0)