about summary refs log tree commit diff stats
path: root/src/utils
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-06-03 20:42:16 +0200
committerbptato <nincsnevem662@gmail.com>2024-06-03 21:15:44 +0200
commit3aa8f1e0694d1606c3f3795f8b83e8a82caacd3e (patch)
tree9708d4599360116a96e4aa7f983eea387e8437c6 /src/utils
parent3e12a95ab34e120fb958ba0eeebaada5def7cd11 (diff)
downloadchawan-3aa8f1e0694d1606c3f3795f8b83e8a82caacd3e.tar.gz
Move JS wrapper into Monoucha
Operation "modularize Chawan somewhat" part 3
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/luwrap.nim5
-rw-r--r--src/utils/regexutils.nim64
2 files changed, 67 insertions, 2 deletions
diff --git a/src/utils/luwrap.nim b/src/utils/luwrap.nim
index 853d3015..7ccb2c51 100644
--- a/src/utils/luwrap.nim
+++ b/src/utils/luwrap.nim
@@ -2,7 +2,7 @@ import std/algorithm
 import std/strutils
 import std/unicode
 
-import bindings/libunicode
+import monoucha/libunicode
 import utils/charcategory
 
 proc passRealloc(opaque, p: pointer; size: csize_t): pointer {.cdecl.} =
@@ -50,7 +50,8 @@ proc capitalizeLU*(s: string): string =
   result = newStringOfCap(s.len)
   var wordStart = true
   for r in s.runes:
-    if lre_is_space(uint32(r)) == 1:
+    if uint32(r) < 256 and char(r) in AsciiWhitespace or
+        lre_is_space_non_ascii(uint32(r)) == 1:
       wordStart = true
       result &= $r
     elif wordStart:
diff --git a/src/utils/regexutils.nim b/src/utils/regexutils.nim
new file mode 100644
index 00000000..ab7308f6
--- /dev/null
+++ b/src/utils/regexutils.nim
@@ -0,0 +1,64 @@
+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)