diff options
author | bptato <nincsnevem662@gmail.com> | 2024-06-03 20:29:10 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-06-03 20:29:10 +0200 |
commit | 3e12a95ab34e120fb958ba0eeebaada5def7cd11 (patch) | |
tree | ff46a2d73d32c2a2a72df82801483dc7fd0134a2 | |
parent | 5acbab703ba074e20dbc0ce729d9f57f467901e0 (diff) | |
download | chawan-3e12a95ab34e120fb958ba0eeebaada5def7cd11.tar.gz |
js: improve jsregex interface
It's easier to just use nested seqs here. (This also fixes reverse-search highlighting the last capture group instead of the whole match.)
-rw-r--r-- | adapter/protocol/man.nim | 134 | ||||
-rw-r--r-- | src/js/jsregex.nim | 29 | ||||
-rw-r--r-- | src/server/buffer.nim | 26 |
3 files changed, 88 insertions, 101 deletions
diff --git a/adapter/protocol/man.nim b/adapter/protocol/man.nim index a5b7dab9..4d6de03f 100644 --- a/adapter/protocol/man.nim +++ b/adapter/protocol/man.nim @@ -94,13 +94,11 @@ proc isCommand(paths: seq[string]; name, s: string): bool = return true false -iterator myCaptures(captures: var seq[RegexCapture]; target: int; - offset: var int): RegexCapture = - for cap in captures.mitems: - if cap.i == target: - cap.s += offset - cap.e += offset - yield cap +iterator myCaptures(res: var RegexResult; i, offset: int): RegexCapture = + for cap in res.captures.mitems: + cap[i].s += offset + cap[i].e += offset + yield cap[i] proc readErrorMsg(efile: File; line: var string): string = var msg = "" @@ -176,70 +174,64 @@ proc processManpage(ofile, efile: File; header, keyword: string) = var fileRes = fileRe.exec(line) var includeRes = includeRe.exec(line) var manRes = manRe.exec(line) - if linkRes.success: - for cap in linkRes.captures.myCaptures(0, offset): - let s = line[cap.s..<cap.e] - let link = "<a href='" & s & "'>" & s & "</a>" - line[cap.s..<cap.e] = link - offset += link.len - (cap.e - cap.s) - if mailRes.success: - for cap in mailRes.captures.myCaptures(2, offset): - let s = line[cap.s..<cap.e] - let link = "<a href='mailto:" & s & "'>" & s & "</a>" - line[cap.s..<cap.e] = link - offset += link.len - (cap.e - cap.s) - if fileRes.success: - for cap in fileRes.captures.myCaptures(0, offset): - let s = line[cap.s..<cap.e] - let target = s.expandTilde() - if not fileExists(target) and not symlinkExists(target) and - not dirExists(target): - continue - let name = target.afterLast('/') - let link = if paths.isCommand(name, target): - "<a href='man:" & name & "'>" & s & "</a>" - else: - "<a href='file:" & target & "'>" & s & "</a>" - line[cap.s..<cap.e] = link - offset += link.len - (cap.e - cap.s) - if includeRes.success: - for cap in includeRes.captures.myCaptures(2, offset): - let s = line[cap.s..<cap.e] - const includePaths = [ - "/usr/include/", - "/usr/local/include/", - "/usr/X11R6/include/", - "/usr/X11/include/", - "/usr/X/include/", - "/usr/include/X11/" - ] - for path in includePaths: - let file = path & s - if fileExists(file): - let link = "<a href='file:" & file & "'>" & s & "</a>" - line[cap.s..<cap.e] = link - offset += link.len - (cap.e - cap.s) - break - if manRes.success: - for j, cap in manRes.captures.mpairs: - if cap.i == 0: - cap.s += offset - cap.e += offset - var manCap = manRes.captures[j + 2] - manCap.s += offset - manCap.e += offset - var secCap = manRes.captures[j + 4] - secCap.s += offset - secCap.e += offset - let man = line[manCap.s..<manCap.e] - # ignore footers like MYPAGE(1) - # (just to be safe, we also check if it's in paths too) - if man == ignoreMan and not paths.isCommand(man.afterLast('/'), man): - continue - let cat = man & line[secCap.s..<secCap.e] - let link = "<a href='man:" & cat & "'>" & man & "</a>" - line[manCap.s..<manCap.e] = link - offset += link.len - (manCap.e - manCap.s) + for cap in linkRes.myCaptures(0, offset): + let s = line[cap.s..<cap.e] + let link = "<a href='" & s & "'>" & s & "</a>" + line[cap.s..<cap.e] = link + offset += link.len - (cap.e - cap.s) + for cap in mailRes.myCaptures(2, offset): + let s = line[cap.s..<cap.e] + let link = "<a href='mailto:" & s & "'>" & s & "</a>" + line[cap.s..<cap.e] = link + offset += link.len - (cap.e - cap.s) + for cap in fileRes.myCaptures(0, offset): + let s = line[cap.s..<cap.e] + let target = s.expandTilde() + if not fileExists(target) and not symlinkExists(target) and + not dirExists(target): + continue + let name = target.afterLast('/') + let link = if paths.isCommand(name, target): + "<a href='man:" & name & "'>" & s & "</a>" + else: + "<a href='file:" & target & "'>" & s & "</a>" + line[cap.s..<cap.e] = link + offset += link.len - (cap.e - cap.s) + for cap in includeRes.myCaptures(2, offset): + let s = line[cap.s..<cap.e] + const includePaths = [ + "/usr/include/", + "/usr/local/include/", + "/usr/X11R6/include/", + "/usr/X11/include/", + "/usr/X/include/", + "/usr/include/X11/" + ] + for path in includePaths: + let file = path & s + if fileExists(file): + let link = "<a href='file:" & file & "'>" & s & "</a>" + line[cap.s..<cap.e] = link + offset += link.len - (cap.e - cap.s) + break + for cap in manRes.captures.mitems: + cap[0].s += offset + cap[0].e += offset + var manCap = cap[2] + manCap.s += offset + manCap.e += offset + var secCap = cap[4] + secCap.s += offset + secCap.e += offset + let man = line[manCap.s..<manCap.e] + # ignore footers like MYPAGE(1) + # (just to be safe, we also check if it's in paths too) + if man == ignoreMan and not paths.isCommand(man.afterLast('/'), man): + continue + let cat = man & line[secCap.s..<secCap.e] + let link = "<a href='man:" & cat & "'>" & man & "</a>" + line[manCap.s..<manCap.e] = link + offset += link.len - (manCap.e - manCap.s) stdout.write(line & '\n') ofile.close() efile.close() diff --git a/src/js/jsregex.nim b/src/js/jsregex.nim index f24633d1..9fb09872 100644 --- a/src/js/jsregex.nim +++ b/src/js/jsregex.nim @@ -10,23 +10,19 @@ export LREFlags type Regex* = object bytecode: seq[uint8] - buf: string + when defined(debug): + buf: string - RegexCapture* = tuple # start, end, index + RegexCapture* = tuple # start, end s, e: int - i: int32 RegexResult* = object success*: bool - captures*: seq[RegexCapture] + captures*: seq[seq[RegexCapture]] - RegexReplace* = object - regex: Regex - rule: string - global: bool - -func `$`*(regex: Regex): string = - regex.buf +when defined(debug): + func `$`*(regex: Regex): string = + regex.buf # this is hardcoded into quickjs, so we must override it here. proc lre_realloc(opaque, p: pointer; size: csize_t): pointer {.exportc.} = @@ -43,10 +39,9 @@ proc compileRegex*(buf: string; flags: LREFlags = {}): Result[Regex, string] = var bcseq = newSeqUninitialized[uint8](plen) copyMem(addr bcseq[0], bytecode, plen) dealloc(bytecode) - let regex = Regex( - buf: buf, - bytecode: bcseq - ) + var regex = Regex(bytecode: bcseq) + when defined(debug): + regex.buf = buf return ok(regex) func countBackslashes(buf: string; i: int): int = @@ -133,13 +128,15 @@ proc exec*(regex: Regex; str: string; start = 0; length = -1; nocaps = false): result.success = true if captureCount == 0 or nocaps: break + var caps: seq[RegexCapture] = @[] let cstrAddress = cast[int](cstr) let ps = start start = capture[1] - cstrAddress for i in 0 ..< captureCount: let s = capture[i * 2] - cstrAddress let e = capture[i * 2 + 1] - cstrAddress - result.captures.add((s, e, i)) + caps.add((s, e)) + result.captures.add(caps) if LRE_FLAG_GLOBAL notin flags: break if start >= str.len: diff --git a/src/server/buffer.nim b/src/server/buffer.nim index 6b214b4e..9a141135 100644 --- a/src/server/buffer.nim +++ b/src/server/buffer.nim @@ -594,8 +594,8 @@ proc findPrevMatch*(buffer: Buffer; regex: Regex; cursorx, cursory: int; let b = buffer.cursorBytes(y, cursorx) let res = regex.exec(buffer.lines[y].str, 0, b) var numfound = 0 - if res.success and res.captures.len > 0: - let cap = res.captures[^1] + if res.captures.len > 0: + let cap = res.captures[^1][0] let x = buffer.lines[y].str.width(0, cap.s) let str = buffer.lines[y].str.substr(cap.s, cap.e - 1) inc numfound @@ -609,8 +609,8 @@ proc findPrevMatch*(buffer: Buffer; regex: Regex; cursorx, cursory: int; else: break let res = regex.exec(buffer.lines[y].str) - if res.success and res.captures.len > 0: - let cap = res.captures[^1] + if res.captures.len > 0: + let cap = res.captures[^1][0] let x = buffer.lines[y].str.width(0, cap.s) let str = buffer.lines[y].str.substr(cap.s, cap.e - 1) inc numfound @@ -628,7 +628,7 @@ proc findNextMatch*(buffer: Buffer; regex: Regex; cursorx, cursory: int; let res = regex.exec(buffer.lines[y].str, b, buffer.lines[y].str.len) var numfound = 0 if res.success and res.captures.len > 0: - let cap = res.captures[0] + let cap = res.captures[0][0] let x = buffer.lines[y].str.width(0, cap.s) let str = buffer.lines[y].str.substr(cap.s, cap.e - 1) inc numfound @@ -643,7 +643,7 @@ proc findNextMatch*(buffer: Buffer; regex: Regex; cursorx, cursory: int; break let res = regex.exec(buffer.lines[y].str) if res.success and res.captures.len > 0: - let cap = res.captures[0] + let cap = res.captures[0][0] let x = buffer.lines[y].str.width(0, cap.s) let str = buffer.lines[y].str.substr(cap.s, cap.e - 1) inc numfound @@ -1779,10 +1779,8 @@ proc markURL*(buffer: Buffer; schemes: seq[string]) {.proxy.} = var data = "" var j = 0 for cap in res.captures.mitems: - if cap.i != 0: - continue - let capLen = cap.e - cap.s - while j < cap.s: + let capLen = cap[0].e - cap[0].s + while j < cap[0].s: case (let c = text.data[j]; c) of '<': data &= "<" @@ -1802,13 +1800,13 @@ proc markURL*(buffer: Buffer; schemes: seq[string]) {.proxy.} = else: data &= c inc j - cap.s += offset - cap.e += offset + cap[0].s += offset + cap[0].e += offset let s = text.data[j ..< j + capLen] let news = "<a href=\"" & s & "\">" & s.htmlEscape() & "</a>" data &= news - j += cap.e - cap.s - offset += news.len - (cap.e - cap.s) + j += cap[0].e - cap[0].s + offset += news.len - (cap[0].e - cap[0].s) while j < text.data.len: case (let c = text.data[j]; c) of '<': data &= "<" |