diff options
author | bptato <nincsnevem662@gmail.com> | 2022-07-31 15:44:54 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2022-08-01 18:21:54 +0200 |
commit | 8f7eb1f7d0ec0cac610c5dcc73188fdbe1577def (patch) | |
tree | 937f23221209b443e8827af610a4d91e943f6b0f | |
parent | b1c8e5edc277c84962955f1edbd8237adb2f5bc8 (diff) | |
download | chawan-8f7eb1f7d0ec0cac610c5dcc73188fdbe1577def.tar.gz |
Make marks a property of buffer
So that re-rendering the buffer doesn't destroy all marks.
-rw-r--r-- | src/client.nim | 16 | ||||
-rw-r--r-- | src/io/buffer.nim | 26 | ||||
-rw-r--r-- | src/io/cell.nim | 2 |
3 files changed, 28 insertions, 16 deletions
diff --git a/src/client.nim b/src/client.nim index 8cda16ec..4d7fc2f4 100644 --- a/src/client.nim +++ b/src/client.nim @@ -340,10 +340,9 @@ proc isearch(client: Client) = var iput: string let cpos = client.buffer.cpos var mark: Mark - var my: int template del_mark() = if mark != nil: - client.buffer.removeMark(my, mark) + client.buffer.removeMark(mark) let status = readLine("/", iput, client.buffer.width, {}, false, (proc(state: var LineState): bool = del_mark @@ -353,13 +352,16 @@ proc isearch(client: Client) = let match = client.buffer.cursorNextMatch(regex.get) if match.success: mark = client.buffer.addMark(match.x, match.y, match.str.width()) - my = match.y client.buffer.redraw = true client.buffer.refreshBuffer(true) print(HVP(client.buffer.height + 1, 2)) print(SGR()) else: del_mark + client.buffer.redraw = true + client.buffer.refreshBuffer(true) + print(HVP(client.buffer.height + 1, 2)) + print(SGR()) return true false )) @@ -377,10 +379,9 @@ proc isearchBack(client: Client) = var iput: string let cpos = client.buffer.cpos var mark: Mark - var my: int template del_mark() = if mark != nil: - client.buffer.removeMark(my, mark) + client.buffer.removeMark(mark) let status = readLine("?", iput, client.buffer.width, {}, false, (proc(state: var LineState): bool = del_mark let regex = compileSearchRegex($state.news) @@ -389,13 +390,16 @@ proc isearchBack(client: Client) = let match = client.buffer.cursorPrevMatch(regex.get) if match.success: mark = client.buffer.addMark(match.x, match.y, match.str.width()) - my = match.y client.buffer.redraw = true client.buffer.refreshBuffer(true) print(HVP(client.buffer.height + 1, 2)) print(SGR()) else: del_mark + client.buffer.redraw = true + client.buffer.refreshBuffer(true) + print(HVP(client.buffer.height + 1, 2)) + print(SGR()) return true false )) diff --git a/src/io/buffer.nim b/src/io/buffer.nim index f627ba42..4f434e5d 100644 --- a/src/io/buffer.nim +++ b/src/io/buffer.nim @@ -1,3 +1,4 @@ +import algorithm import httpclient import options import os @@ -67,6 +68,7 @@ type userstyle*: CSSStylesheet loader*: FileLoader markcolor*: CellColor + marks*: seq[Mark] proc newBuffer*(): Buffer = new(result) @@ -314,11 +316,11 @@ proc clearDisplay(buffer: Buffer) = proc refreshDisplay(buffer: Buffer) = var r: Rune - var y = 0 + var y = 0 # y position on screen buffer.clearDisplay() - for line in buffer.lines[buffer.fromy.. - buffer.lastVisibleLine - 1]: + for by in buffer.fromy..buffer.lastVisibleLine - 1: + let line = buffer.lines[by] # by: y position in lines var w = 0 # width of the row so far var i = 0 # byte in line.str @@ -362,8 +364,13 @@ proc refreshDisplay(buffer: Buffer) = # Then, for each cell that has a mark, override its formatting with that # specified by the mark. + var l = 0 + while l < buffer.marks.len and buffer.marks[l].y < by: + inc l # linear search to find the first applicable mark let aw = buffer.width - (startw - buffer.fromx) # actual width - for mark in line.marks: + while l < buffer.marks.len and buffer.marks[l].y == by: + let mark = buffer.marks[l] + inc l if mark.x >= startw + aw or mark.x + mark.width < startw: continue for i in max(mark.x, startw)..<min(mark.x + mark.width, startw + aw): buffer.display[dls + i].format = mark.format @@ -706,13 +713,14 @@ proc addMark*(buffer: Buffer, x, y, width: int): Mark = assert y < buffer.lines.len var format = newFormat() format.bgcolor = buffer.markcolor - result = Mark(x: x, width: width, format: format) - buffer.lines[y].marks.add(result) + result = Mark(x: x, y: y, width: width, format: format) + let previ = upperBound(buffer.marks, y, (proc(a: Mark, b: int): int = cmp(a.y, b))) + buffer.marks.insert(result, previ) -proc removeMark*(buffer: Buffer, y: int, mark: Mark) = - let i = buffer.lines[y].marks.find(mark) +proc removeMark*(buffer: Buffer, mark: Mark) = + let i = buffer.marks.find(mark) if i != -1: - buffer.lines[y].marks.delete(i) + buffer.marks.delete(i) proc cursorNextMatch(buffer: Buffer, regex: Regex, sy, ey: int, wrap = false): BufferMatch = for y in sy..ey: diff --git a/src/io/cell.nim b/src/io/cell.nim index 80ada720..d8f3d23b 100644 --- a/src/io/cell.nim +++ b/src/io/cell.nim @@ -35,10 +35,10 @@ type FlexibleLine* = object str*: string formats*: seq[FormatCell] - marks*: seq[Mark] Mark* = ref object x*: int + y*: int width*: int format*: Format |