@@ -135,4 +135,72 @@ describe("Testing utils module", function()
135135 eq (utils .strsplit (" ,foo,bar," , " ," ), { " " , " foo" , " bar" , " " })
136136 eq (utils .strsplit (" foobar" , " ," ), { " foobar" })
137137 end )
138+
139+ it (" regex_strip_anchors" , function ()
140+ -- nil input
141+ eq ({ utils .regex_strip_anchors (nil ) }, { [2 ] = 0 , [3 ] = 0 })
142+ -- empty string
143+ eq ({ utils .regex_strip_anchors (" " ) }, { " " , 0 , 0 })
144+ -- no anchors
145+ eq ({ utils .regex_strip_anchors (" foobar" ) }, { " foobar" , 0 , 0 })
146+ -- only start anchor
147+ eq ({ utils .regex_strip_anchors (" ^foobar" ) }, { " foobar" , 1 , 0 })
148+ -- only end anchor
149+ eq ({ utils .regex_strip_anchors (" foobar$" ) }, { " foobar" , 0 , 1 })
150+ -- both anchors
151+ eq ({ utils .regex_strip_anchors (" ^foobar$" ) }, { " foobar" , 1 , 1 })
152+ -- anchors in middle (should not be stripped)
153+ eq ({ utils .regex_strip_anchors (" foo^bar$baz" ) }, { " foo^bar$baz" , 0 , 0 })
154+ -- only anchors
155+ eq ({ utils .regex_strip_anchors (" ^" ) }, { " " , 1 , 0 })
156+ eq ({ utils .regex_strip_anchors (" $" ) }, { " " , 0 , 1 })
157+ eq ({ utils .regex_strip_anchors (" ^$" ) }, { " " , 1 , 1 })
158+ -- single character with anchors
159+ eq ({ utils .regex_strip_anchors (" ^x$" ) }, { " x" , 1 , 1 })
160+ end )
161+
162+ it (" ctag_match" , function ()
163+ -- no slashes
164+ eq (utils .ctag_match (" foobar" ), nil )
165+ -- single slash (needs at least 2 slashes)
166+ eq (utils .ctag_match (" foo/bar" ), nil )
167+ -- two slashes (finds the two rightmost unescaped slashes)
168+ eq ({ utils .ctag_match (" /foo/bar/baz" ) }, { 5 , 9 })
169+ -- escaped slash only (should ignore escaped ones)
170+ eq (utils .ctag_match (" foo\\ /bar" ), nil )
171+ -- mixed escaped and unescaped
172+ eq ({ utils .ctag_match (" foo/bar\\ /baz/qux" ) }, { 4 , 13 })
173+ -- reverse search from end
174+ eq ({ utils .ctag_match (" /a/b/c/d" ) }, { 5 , 7 })
175+ end )
176+
177+ it (" ctag_escape" , function ()
178+ -- empty string
179+ eq (utils .ctag_escape (" " ), " " )
180+ -- no special characters
181+ eq (utils .ctag_escape (" foobar" ), " foobar" )
182+ -- escaped backslash (\\ becomes \, then rg_escape doubles it back)
183+ eq (utils .ctag_escape (" foo\\ bar" ), " foo\\\\ bar" )
184+ -- unescape escaped slash (\/ becomes /)
185+ eq (utils .ctag_escape (" foo\\ /bar" ), " foo/bar" )
186+ -- regex escape (rg_escape behavior)
187+ eq (utils .ctag_escape (" foo.bar" ), " foo\\ .bar" )
188+ eq (utils .ctag_escape (" foo*bar" ), " foo\\ *bar" )
189+ -- ^ at start gets unescaped (was escaped by rg_escape)
190+ eq (utils .ctag_escape (" ^foobar" ), " ^foobar" )
191+ -- $ at end gets unescaped (was escaped by rg_escape)
192+ eq (utils .ctag_escape (" foobar$" ), " foobar$" )
193+ -- already escaped ^ at start stays escaped (rg_escape adds another backslash)
194+ eq (utils .ctag_escape (" \\ ^foobar" ), " \\\\\\ ^foobar" )
195+ -- already escaped $ at end stays escaped
196+ eq (utils .ctag_escape (" foobar\\ $" ), " foobar\\\\ $" )
197+ -- ^ in middle stays escaped
198+ eq (utils .ctag_escape (" foo^bar" ), " foo\\ ^bar" )
199+ -- $ in middle stays escaped
200+ eq (utils .ctag_escape (" foo$bar" ), " foo\\ $bar" )
201+ -- combination of patterns
202+ eq (utils .ctag_escape (" ^foo.bar$" ), " ^foo\\ .bar$" )
203+ -- escaped backslash before dot (\. becomes ., then rg_escape escapes both)
204+ eq (utils .ctag_escape (" foo\\ .bar" ), " foo\\\\\\ .bar" )
205+ end )
138206end )
0 commit comments