@@ -59,9 +59,12 @@ PropertyStringMatch.__index = PropertyStringMatch
59
59
local PropertyNumberMatch = {}
60
60
PropertyNumberMatch .__index = PropertyNumberMatch
61
61
62
+ --- @class OrgTodoMatchAndItem
63
+ --- @field operator string
64
+ --- @field value string
65
+
62
66
--- @class OrgTodoMatch
63
- --- @field anyOf string[]
64
- --- @field noneOf string[]
67
+ --- @field orItems OrgTodoMatchAndItem[][]
65
68
local TodoMatch = {}
66
69
TodoMatch .__index = TodoMatch
67
70
541
544
--- @private
542
545
--- @return OrgTodoMatch
543
546
function TodoMatch :_new ()
544
- --- @type OrgTodoMatch
545
547
local todo_match = {
546
- anyOf = {},
547
- noneOf = {},
548
+ orItems = {},
548
549
}
549
550
550
551
setmetatable (todo_match , TodoMatch )
@@ -567,65 +568,68 @@ function TodoMatch:parse(input)
567
568
568
569
-- Parse a whitelist of keywords
569
570
--- @type string[] ?
570
- local anyOf
571
- anyOf , input = parse_delimited_sequence (input , function (i )
572
- return parse_pattern (i , ' %w+' )
573
- end , ' %|' )
574
- if anyOf and # anyOf > 0 then
575
- -- Successfully parsed the whitelist, return it
576
- local todo_match = TodoMatch :_new ()
577
- todo_match .anyOf = anyOf
578
- return todo_match , input
579
- end
571
+ local orItems
572
+ orItems , input = parse_delimited_sequence (input , function (i )
573
+ --- @type string ?
574
+ local operator
575
+ operator , i = parse_pattern (i , ' [%+%-]?' )
576
+
577
+ if operator == ' ' then
578
+ operator = ' +'
579
+ end
580
580
581
- -- Parse a blacklist of keywords
582
- --- @type string ?
583
- local negation
584
- negation , input = parse_pattern (input , ' -' )
585
- if negation then
586
- local negative_items
587
- negative_items , input = parse_delimited_sequence (input , function (i )
588
- return parse_pattern (i , ' %w+' )
589
- end , ' %-' )
590
-
591
- if negative_items then
592
- if # negation > 0 then
593
- local todo_match = TodoMatch :_new ()
594
- todo_match .noneOf = negative_items
595
- return todo_match , input
596
- else
597
- return nil , original_input
581
+ local andItems = {}
582
+
583
+ while operator do
584
+ --- @type string ?
585
+ local value
586
+ value , i = parse_pattern (i , ' %w+' )
587
+ if not value then
588
+ break
598
589
end
590
+ table.insert (andItems , {
591
+ operator = operator ,
592
+ value = value ,
593
+ })
594
+
595
+ operator , i = parse_pattern (i , ' [%+%-]' )
599
596
end
597
+
598
+ return andItems , i
599
+ end , ' %|' )
600
+
601
+ if not orItems or # orItems == 0 then
602
+ return nil , original_input
600
603
end
601
604
602
- return nil , original_input
605
+ local todo_match = TodoMatch :_new ()
606
+ todo_match .orItems = orItems
607
+ return todo_match , input
603
608
end
604
609
605
610
--- @param item OrgSearchable
606
611
--- @return boolean
607
612
function TodoMatch :match (item )
608
613
local item_todo = item .todo
609
614
610
- if # self .anyOf > 0 then
611
- for _ , todo_value in ipairs (self .anyOf ) do
612
- if item_todo == todo_value then
613
- return true
615
+ for _ , orItem in ipairs (self .orItems ) do
616
+ local validItems = true
617
+ for _ , andItem in ipairs (orItem ) do
618
+ if andItem .operator == ' -' and item_todo == andItem .value then
619
+ validItems = false
620
+ break
621
+ elseif andItem .operator == ' +' and item_todo ~= andItem .value then
622
+ validItems = false
623
+ break
614
624
end
615
625
end
616
626
617
- return false
618
- elseif # self .noneOf > 0 then
619
- for _ , todo_value in ipairs (self .noneOf ) do
620
- if item_todo == todo_value then
621
- return false
622
- end
627
+ if validItems then
628
+ return true
623
629
end
624
-
625
- return true
626
- else
627
- return true
628
630
end
631
+
632
+ return false
629
633
end
630
634
631
635
return Search
0 commit comments