diff options
author | bptato <nincsnevem662@gmail.com> | 2023-01-01 16:14:01 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2023-01-01 18:31:17 +0100 |
commit | 1a24350ee44859f6b3370ac15e8875a79fa7ae9b (patch) | |
tree | 0c168d725baa44bf1813c1456c9c835c4e1bf776 /src/buffer | |
parent | 9a22a844c956d80f0d5c80330e898d52acadfd2f (diff) | |
download | chawan-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.nim | 54 | ||||
-rw-r--r-- | src/buffer/container.nim | 40 |
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 |