11-- TODO: Support regex search
22
33local Date = require (' orgmode.objects.date' )
4+ local parsing = require (' orgmode.utils.parsing' )
45
56--- @class Search
67--- @field term string
@@ -88,66 +89,6 @@ local OPERATORS = {
8889 end ,
8990}
9091
91- --- Parses a pattern from the beginning of an input using Lua's pattern syntax
92- --- @param input string
93- --- @param pattern string
94- --- @return string ?, string
95- local function parse_pattern (input , pattern )
96- local value = input :match (' ^' .. pattern )
97- if value then
98- return value , input :sub (# value + 1 )
99- else
100- return nil , input
101- end
102- end
103-
104- --- Parses the first of a sequence of patterns
105- --- @param input string The input to parse
106- --- @param ... string The patterns to accept
107- --- @return string ?, string
108- local function parse_pattern_choice (input , ...)
109- for _ , pattern in ipairs ({ ... }) do
110- local value , remaining = parse_pattern (input , pattern )
111- if value then
112- return value , remaining
113- end
114- end
115-
116- return nil , input
117- end
118-
119- --- @generic T
120- --- @param input string
121- --- @param item_parser fun ( input : string ): ( T ?, string )
122- --- @param delimiter_pattern string
123- --- @return (T[] )?, string
124- local function parse_delimited_sequence (input , item_parser , delimiter_pattern )
125- local sequence , item , delimiter = {}, nil , nil
126- local original_input = input
127-
128- -- Parse the first item
129- item , input = item_parser (input )
130- if not item then
131- return sequence , input
132- end
133- table.insert (sequence , item )
134-
135- -- Continue parsing items while there's a trailing delimiter
136- delimiter , input = parse_pattern (input , delimiter_pattern )
137- while delimiter do
138- item , input = item_parser (input )
139- if not item then
140- return nil , original_input
141- end
142-
143- table.insert (sequence , item )
144-
145- delimiter , input = parse_pattern (input , delimiter_pattern )
146- end
147-
148- return sequence , input
149- end
150-
15192--- @param term string
15293--- @return Search
15394function Search :new (term )
190131function Search :_parse ()
191132 local input = self .term
192133 -- Parse the sequence of ORs
193- self .or_items , input = parse_delimited_sequence (input , function (i )
134+ self .or_items , input = parsing . parse_delimited_sequence (input , function (i )
194135 return OrItem :parse (i )
195136 end , ' %|' )
196137
@@ -220,7 +161,7 @@ function OrItem:parse(input)
220161 local and_items
221162 local original_input = input
222163
223- and_items , input = parse_delimited_sequence (input , function (i )
164+ and_items , input = parsing . parse_delimited_sequence (input , function (i )
224165 return AndItem :parse (i )
225166 end , ' %&' )
226167
@@ -269,7 +210,7 @@ function AndItem:parse(input)
269210 local operator
270211 local original_input = input
271212
272- operator , input = parse_pattern (input , ' [%+%-]?' )
213+ operator , input = parsing . parse_pattern (input , ' [%+%-]?' )
273214
274215 -- A '+' operator is implied if none is present
275216 if operator == ' ' then
@@ -300,7 +241,7 @@ function AndItem:parse(input)
300241 end
301242
302243 -- Attempt to parse the next operator
303- operator , input = parse_pattern (input , ' [%+%-]' )
244+ operator , input = parsing . parse_pattern (input , ' [%+%-]' )
304245 end
305246
306247 return and_item , input
339280--- @return TagMatch ?, string
340281function TagMatch :parse (input )
341282 local tag
342- tag , input = parse_pattern (input , ' [%w_@#%%]+' )
283+ tag , input = parsing . parse_pattern (input , ' [%w_@#%%]+' )
343284 if not tag then
344285 return nil , input
345286 end
@@ -371,7 +312,7 @@ function PropertyMatch:parse(input)
371312 local name , operator , string_str , number_str , date_str
372313 local original_input = input
373314
374- name , input = parse_pattern (input , ' [^=<>]+' )
315+ name , input = parsing . parse_pattern (input , ' [^=<>]+' )
375316 if not name then
376317 return nil , original_input
377318 end
@@ -383,14 +324,14 @@ function PropertyMatch:parse(input)
383324 end
384325
385326 -- Number property
386- number_str , input = parse_pattern (input , ' %d+' )
327+ number_str , input = parsing . parse_pattern (input , ' %d+' )
387328 if number_str then
388329 local number = tonumber (number_str ) --[[ @as number]]
389330 return PropertyNumberMatch :new (name , operator , number ), input
390331 end
391332
392333 -- Date property
393- date_str , input = parse_pattern (input , ' "(<[^>]+>)"' )
334+ date_str , input = parsing . parse_pattern (input , ' "(<[^>]+>)"' )
394335 if date_str then
395336 --- @type string ?, Date ?
396337 local date_content , date_value
@@ -422,7 +363,7 @@ function PropertyMatch:parse(input)
422363 end
423364
424365 -- String property
425- string_str , input = parse_pattern (input , ' "[^"]+"' )
366+ string_str , input = parsing . parse_pattern (input , ' "[^"]+"' )
426367 if string_str then
427368 --- @type string
428369 local unquote_string = string_str :match (' ^"([^"]+)"$' )
437378--- @param input string
438379--- @return PropertyMatchOperator , string
439380function PropertyMatch :_parse_operator (input )
440- return parse_pattern_choice (input , ' %=' , ' %<%>' , ' %<%=' , ' %<' , ' %>%=' , ' %>' ) --[[ @as PropertyMatchOperator]]
381+ return parsing . parse_pattern_choice (input , ' %=' , ' %<%>' , ' %<%=' , ' %<' , ' %>%=' , ' %>' ) --[[ @as PropertyMatchOperator]]
441382end
442383
443384--- Constructs a PropertyNumberMatch
@@ -559,16 +500,16 @@ function TodoMatch:parse(input)
559500 -- Parse the '/' or '/!' prefix that indicates a TodoMatch
560501 --- @type string ?
561502 local prefix
562- prefix , input = parse_pattern (input , ' %/[%!]?' )
503+ prefix , input = parsing . parse_pattern (input , ' %/[%!]?' )
563504 if not prefix then
564505 return nil , original_input
565506 end
566507
567508 -- Parse a whitelist of keywords
568509 --- @type string[] ?
569510 local anyOf
570- anyOf , input = parse_delimited_sequence (input , function (i )
571- return parse_pattern (i , ' %w+' )
511+ anyOf , input = parsing . parse_delimited_sequence (input , function (i )
512+ return parsing . parse_pattern (i , ' %w+' )
572513 end , ' %|' )
573514 if anyOf and # anyOf > 0 then
574515 -- Successfully parsed the whitelist, return it
@@ -580,11 +521,11 @@ function TodoMatch:parse(input)
580521 -- Parse a blacklist of keywords
581522 --- @type string ?
582523 local negation
583- negation , input = parse_pattern (input , ' -' )
524+ negation , input = parsing . parse_pattern (input , ' -' )
584525 if negation then
585526 local negative_items
586- negative_items , input = parse_delimited_sequence (input , function (i )
587- return parse_pattern (i , ' %w+' )
527+ negative_items , input = parsing . parse_delimited_sequence (input , function (i )
528+ return parsing . parse_pattern (i , ' %w+' )
588529 end , ' %-' )
589530
590531 if negative_items then
0 commit comments