about summary refs log tree commit diff stats
path: root/src/buffer
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2023-01-01 16:14:01 +0100
committerbptato <nincsnevem662@gmail.com>2023-01-01 18:31:17 +0100
commit1a24350ee44859f6b3370ac15e8875a79fa7ae9b (patch)
tree0c168d725baa44bf1813c1456c9c835c4e1bf776 /src/buffer
parent9a22a844c956d80f0d5c80330e898d52acadfd2f (diff)
downloadchawan-1a24350ee44859f6b3370ac15e8875a79fa7ae9b.tar.gz
buffer: fix some search bugs & refactor regex stuff
cursorBytes uses twidth now.
cursorNextMatch matches the byte *after* the cursor (somewhat more
consistently than before).
match() no longer counts capture groups. LRE_FLAG_GLOBAL now goes
through the entire string.
Diffstat (limited to 'src/buffer')
-rw-r--r--src/buffer/buffer.nim54
-rw-r--r--src/buffer/container.nim40
2 files changed, 44 insertions, 50 deletions
diff --git a/src/buffer/buffer.nim b/src/buffer/buffer.nim
index b4a1c202..7b38b255 100644
--- a/src/buffer/buffer.nim
+++ b/src/buffer/buffer.nim
@@ -288,7 +288,7 @@ func cursorBytes(buffer: Buffer, y: int, cc: int): int =
   while i < line.len and w < cc:
     var r: Rune
     fastRuneAt(line, i, r)
-    w += r.width()
+    w += r.twidth(w)
   return i
 
 proc findPrevLink*(buffer: Buffer, cursorx, cursory: int): tuple[x, y: int] {.proxy.} =
@@ -378,17 +378,14 @@ proc findNextLink*(buffer: Buffer, cursorx, cursory: int): tuple[x, y: int] {.pr
 
 proc findPrevMatch*(buffer: Buffer, regex: Regex, cursorx, cursory: int, wrap: bool): BufferMatch {.proxy.} =
   if cursory >= buffer.lines.len: return
-  template return_if_match =
-    if res.success and res.captures.len > 0:
-      let cap = res.captures[^1]
-      let x = buffer.lines[y].str.width(cap.s)
-      let str = buffer.lines[y].str.substr(cap.s, cap.e - 1)
-      return BufferMatch(success: true, x: x, y: y, str: str)
   var y = cursory
   let b = buffer.cursorBytes(y, cursorx)
-  let b2 = if b > 0: b - buffer.lines[y].str.lastRune(b)[1] else: 0
-  let res = regex.exec(buffer.lines[y].str, 0, b2)
-  return_if_match
+  let res = regex.exec(buffer.lines[y].str, 0, b)
+  if res.success and res.captures.len > 0:
+    let cap = res.captures[^1]
+    let x = buffer.lines[y].str.width(0, cap.s)
+    let str = buffer.lines[y].str.substr(cap.s, cap.e - 1)
+    return BufferMatch(success: true, x: x, y: y, str: str)
   dec y
   while true:
     if y < 0:
@@ -396,27 +393,26 @@ proc findPrevMatch*(buffer: Buffer, regex: Regex, cursorx, cursory: int, wrap: b
         y = buffer.lines.high
       else:
         break
+    let res = regex.exec(buffer.lines[y].str)
+    if res.success and res.captures.len > 0:
+      let cap = res.captures[^1]
+      let x = buffer.lines[y].str.width(0, cap.s)
+      let str = buffer.lines[y].str.substr(cap.s, cap.e - 1)
+      return BufferMatch(success: true, x: x, y: y, str: str)
     if y == cursory:
-      let res = regex.exec(buffer.lines[y].str, b, buffer.lines[y].str.len)
-      return_if_match
       break
-    let res = regex.exec(buffer.lines[y].str)
-    return_if_match
     dec y
 
 proc findNextMatch*(buffer: Buffer, regex: Regex, cursorx, cursory: int, wrap: bool): BufferMatch {.proxy.} =
   if cursory >= buffer.lines.len: return
-  template return_if_match =
-    if res.success and res.captures.len > 0:
-      let cap = res.captures[0]
-      let x = buffer.lines[y].str.width(cap.s)
-      let str = buffer.lines[y].str.substr(cap.s, cap.e - 1)
-      return BufferMatch(success: true, x: x, y: y, str: str)
   var y = cursory
-  let b = buffer.cursorBytes(y, cursorx)
-  let b2 = if buffer.lines[y].str.len > b: b + buffer.lines[y].str.runeLenAt(b) else: b
-  let res = regex.exec(buffer.lines[y].str, b2, buffer.lines[y].str.len)
-  return_if_match
+  let b = buffer.cursorBytes(y, cursorx + 1)
+  let res = regex.exec(buffer.lines[y].str, b, buffer.lines[y].str.len)
+  if res.success and res.captures.len > 0:
+    let cap = res.captures[0]
+    let x = buffer.lines[y].str.width(0, cap.s)
+    let str = buffer.lines[y].str.substr(cap.s, cap.e - 1)
+    return BufferMatch(success: true, x: x, y: y, str: str)
   inc y
   while true:
     if y > buffer.lines.high:
@@ -424,12 +420,14 @@ proc findNextMatch*(buffer: Buffer, regex: Regex, cursorx, cursory: int, wrap: b
         y = 0
       else:
         break
+    let res = regex.exec(buffer.lines[y].str)
+    if res.success and res.captures.len > 0:
+      let cap = res.captures[0]
+      let x = buffer.lines[y].str.width(0, cap.s)
+      let str = buffer.lines[y].str.substr(cap.s, cap.e - 1)
+      return BufferMatch(success: true, x: x, y: y, str: str)
     if y == cursory:
-      let res = regex.exec(buffer.lines[y].str, 0, b)
-      return_if_match
       break
-    let res = regex.exec(buffer.lines[y].str)
-    return_if_match
     inc y
 
 proc gotoAnchor*(buffer: Buffer): tuple[x, y: int] {.proxy.} =
diff --git a/src/buffer/container.nim b/src/buffer/container.nim
index a3406463..2d2ff73e 100644
--- a/src/buffer/container.nim
+++ b/src/buffer/container.nim
@@ -601,37 +601,33 @@ proc clearSearchHighlights*(container: Container) =
     if container.highlights[i].clear:
       container.highlights.del(i)
 
+proc onMatch(container: Container, res: BufferMatch) =
+  if res.success:
+    container.setCursorXY(res.x, res.y)
+    if container.hlon:
+      container.clearSearchHighlights()
+      let ex = res.str.twidth(res.x) - 1
+      let hl = Highlight(x: res.x, y: res.y, endx: ex, endy: res.y, clear: true)
+      container.highlights.add(hl)
+      container.triggerEvent(UPDATE)
+      container.hlon = false
+  elif container.hlon:
+    container.clearSearchHighlights()
+    container.triggerEvent(UPDATE)
+    container.needslines = true
+    container.hlon = false
+
 proc cursorNextMatch*(container: Container, regex: Regex, wrap: bool) {.jsfunc.} =
   container.iface
     .findNextMatch(regex, container.cursorx, container.cursory, wrap)
     .then(proc(res: BufferMatch) =
-      if res.success:
-        container.setCursorXY(res.x, res.y)
-        if container.hlon:
-          container.clearSearchHighlights()
-          let ex = res.str.twidth(res.x) - 1
-          let hl = Highlight(x: res.x, y: res.y, endx: ex, endy: res.y, clear: true)
-          container.highlights.add(hl)
-          container.triggerEvent(UPDATE)
-          container.hlon = false
-      elif container.hlon:
-        container.clearSearchHighlights()
-        container.triggerEvent(UPDATE)
-        container.needslines = true
-        container.hlon = false)
+      container.onMatch(res))
 
 proc cursorPrevMatch*(container: Container, regex: Regex, wrap: bool) {.jsfunc.} =
   container.iface
     .findPrevMatch(regex, container.cursorx, container.cursory, wrap)
     .then(proc(res: BufferMatch) =
-      if res.success:
-        container.setCursorXY(res.x, res.y)
-        if container.hlon:
-          container.clearSearchHighlights()
-          let ex = res.str.twidth(res.x) - 1
-          let hl = Highlight(x: res.x, y: res.y, endx: ex, endy: res.y, clear: true)
-          container.highlights.add(hl)
-          container.hlon = false)
+      container.onMatch(res))
 
 proc setLoadInfo(container: Container, msg: string) =
   container.loadinfo = msg