blob: ab7308f6e235fdd8238fdf4765c32d0b74e64121 (
plain) (
tree)
|
|
import types/opt
import monoucha/jsregex
import monoucha/libregexp
func countBackslashes(buf: string; i: int): int =
var j = 0
for i in countdown(i, 0):
if buf[i] != '\\':
break
inc j
return j
# ^abcd -> ^abcd
# efgh$ -> efgh$
# ^ijkl$ -> ^ijkl$
# mnop -> ^mnop$
proc compileMatchRegex*(buf: string): Result[Regex, string] =
if buf.len == 0:
return compileRegex(buf)
if buf[0] == '^':
return compileRegex(buf)
if buf[^1] == '$':
# Check whether the final dollar sign is escaped.
if buf.len == 1 or buf[^2] != '\\':
return compileRegex(buf)
let j = buf.countBackslashes(buf.high - 2)
if j mod 2 == 1: # odd, because we do not count the last backslash
return compileRegex(buf)
# escaped. proceed as if no dollar sign was at the end
if buf[^1] == '\\':
# Check if the regex contains an invalid trailing backslash.
let j = buf.countBackslashes(buf.high - 1)
if j mod 2 != 1: # odd, because we do not count the last backslash
return err("unexpected end")
var buf2 = "^"
buf2 &= buf
buf2 &= "$"
return compileRegex(buf2)
proc compileSearchRegex*(str: string; defaultFlags: LREFlags):
Result[Regex, string] =
# Emulate vim's \c/\C: override defaultFlags if one is found, then remove it
# from str.
# Also, replace \< and \> with \b as (a bit sloppy) vi emulation.
var flags = defaultFlags
var s = newStringOfCap(str.len)
var quot = false
for c in str:
if quot:
quot = false
case c
of 'c': flags.incl(LRE_FLAG_IGNORECASE)
of 'C': flags.excl(LRE_FLAG_IGNORECASE)
of '<', '>': s &= "\\b"
else: s &= '\\' & c
elif c == '\\':
quot = true
else:
s &= c
if quot:
s &= '\\'
flags.incl(LRE_FLAG_GLOBAL) # for easy backwards matching
return compileRegex(s, flags)
|