Skip to content

Commit 0b0a383

Browse files
committed
Initial todo config parser definition
1 parent 38b73f9 commit 0b0a383

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed

lua/orgmode/parser/todo-config.lua

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
local parsing = require('orgmode.utils.parsing')
2+
3+
--- @class TodoConfig
4+
--- @field words TodoConfigWord[]
5+
local TodoConfig = {}
6+
TodoConfig.__index = TodoConfig
7+
8+
--- @alias TodoConfigRecordBehavior 'time' | 'note' | false
9+
10+
--- @class TodoConfigWord
11+
--- @field name string
12+
--- @field is_active boolean
13+
--- @field hotkey string
14+
--- @field on_enter TodoConfigRecordBehavior
15+
--- @field on_leave TodoConfigRecordBehavior
16+
local TodoConfigWord = {}
17+
18+
--- @param words TodoConfigWord[]
19+
--- @return TodoConfig
20+
function TodoConfig:_new(words)
21+
--- @type TodoConfig
22+
local instance = {}
23+
setmetatable(instance, TodoConfig)
24+
25+
instance.words = words
26+
27+
return instance
28+
end
29+
30+
--- @param input string
31+
--- @return TodoConfig?, string
32+
function TodoConfig:parse(input)
33+
local original = input
34+
35+
--- @type TodoConfigWord[]
36+
local active
37+
active, input = parsing.parse_delimited_sequence(input, function(inner_input)
38+
return TodoConfigWord:parse(inner_input, true)
39+
end, '%s+')
40+
41+
if #active == 0 then
42+
return nil, original
43+
end
44+
45+
local pipe
46+
pipe, input = parsing.parse_pattern(input, '%s*%|%s*')
47+
if pipe == nil then
48+
return nil, original
49+
end
50+
51+
--- @type TodoConfigWord[]
52+
local inactive
53+
inactive, input = parsing.parse_delimited_sequence(input, function(inner_input)
54+
return TodoConfigWord:parse(inner_input, false)
55+
end, '%s+')
56+
57+
if #inactive == 0 then
58+
return nil, original
59+
end
60+
61+
--- @type TodoConfigWord[]
62+
local words = {}
63+
for _, x in ipairs(active) do
64+
table.insert(words, x)
65+
end
66+
for _, x in ipairs(inactive) do
67+
table.insert(words, x)
68+
end
69+
70+
return TodoConfig:_new(words), input
71+
end
72+
end
73+
74+
--- @param name string
75+
--- @param hotkey string
76+
--- @param is_active boolean
77+
--- @param on_enter TodoConfigRecordBehavior
78+
--- @param on_leave TodoConfigRecordBehavior
79+
--- @return TodoConfigWord
80+
function TodoConfigWord:_new(name, is_active, hotkey, on_enter, on_leave)
81+
--- @type TodoConfigWord
82+
local instance = {}
83+
setmetatable(instance, TodoConfigWord)
84+
85+
instance.name = name
86+
instance.is_active = is_active
87+
instance.hotkey = hotkey
88+
instance.on_enter = on_enter
89+
instance.on_leave = on_leave
90+
91+
return instance
92+
end
93+
94+
--- @param input string
95+
--- @param is_active boolean
96+
--- @return TodoConfigWord?, string
97+
function TodoConfigWord:parse(input, is_active)
98+
local original = input
99+
100+
--- @type string?, string?, string?, string?
101+
local name, open, hotkey, enter, slash, leave, close
102+
103+
name, input = parsing.parse_pattern(input, '%w+')
104+
if name == nil then
105+
return nil, original
106+
end
107+
108+
open, input = parsing.parse_pattern(input, '%(')
109+
if open == nil then
110+
return nil, original
111+
end
112+
113+
hotkey, input = parsing.parse_pattern(input, '%w')
114+
if hotkey == nil then
115+
return nil, original
116+
end
117+
118+
---@type TodoConfigRecordBehavior
119+
local on_enter = false
120+
enter, input = parsing.parse_pattern_choice(input, '%@', '%!')
121+
if enter ~= nil then
122+
if enter == '!' then
123+
on_enter = 'time'
124+
elseif enter == '@' then
125+
on_enter = 'note'
126+
else
127+
return nil, original
128+
end
129+
end
130+
131+
--- @type TodoConfigRecordBehavior
132+
local on_leave = false
133+
slash, input = parsing.parse_pattern(input, '%/')
134+
if slash ~= nil then
135+
leave, input = parsing.parse_pattern_choice(input, '%@', '%!')
136+
if leave == nil then
137+
return nil, original
138+
end
139+
140+
if leave == '!' then
141+
on_leave = 'time'
142+
elseif leave == '@' then
143+
on_leave = 'note'
144+
else
145+
return nil, original
146+
end
147+
end
148+
149+
close, input = parsing.parse_pattern(input, '%)')
150+
if close == nil then
151+
return nil, original
152+
end
153+
154+
local word = TodoConfigWord:_new(name, is_active, hotkey, on_enter, on_leave)
155+
return word, input
156+
end
157+
158+
return TodoConfig

0 commit comments

Comments
 (0)