diff options
author | bptato <nincsnevem662@gmail.com> | 2023-09-14 01:08:10 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2023-09-14 01:08:10 +0200 |
commit | db0798acccbedcef4b16737f6be0cf7388cc0528 (patch) | |
tree | 208616de68fe9729e09e4084557f27f5b7204387 /src/buffer/select.nim | |
parent | c2004e4aba182473e79100759a2d58e1bd7d184c (diff) | |
download | chawan-db0798acccbedcef4b16737f6be0cf7388cc0528.tar.gz |
move some modules to local/
makes a bit more sense than the previous arrangement
Diffstat (limited to 'src/buffer/select.nim')
-rw-r--r-- | src/buffer/select.nim | 306 |
1 files changed, 0 insertions, 306 deletions
diff --git a/src/buffer/select.nim b/src/buffer/select.nim deleted file mode 100644 index f7afa4d9..00000000 --- a/src/buffer/select.nim +++ /dev/null @@ -1,306 +0,0 @@ -import unicode - -import buffer/buffer -import buffer/cell -import js/regex -import utils/twtstr - -type - SubmitSelect* = proc(selected: seq[int]) - CloseSelect* = proc() - - Select* = object - open*: bool - options: seq[string] - multiple: bool - # old selection - oselected*: seq[int] - # new selection - selected*: seq[int] - # cursor distance from y - cursor: int - # widest option - maxw: int - # maximum height on screen (yes the naming is dumb) - maxh: int - # first index to display - si: int - # location on screen - x: int - y: int - redraw*: bool - submitFun: SubmitSelect - bpos: seq[int] - -proc windowChange*(select: var Select, height: int) = - select.maxh = height - 2 - if select.y + select.options.len >= select.maxh: - select.y = height - select.options.len - if select.y < 0: - select.si = -select.y - select.y = 0 - if select.selected.len > 0: - let i = select.selected[0] - if select.si > i: - select.si = i - elif select.si + select.maxh < i: - select.si = max(i - select.maxh, 0) - select.redraw = true - -proc initSelect*(select: var Select, selectResult: SelectResult, - x, y, height: int, submitFun: SubmitSelect) = - select.open = true - select.multiple = selectResult.multiple - select.options = selectResult.options - select.oselected = selectResult.selected - select.selected = selectResult.selected - select.submitFun = submitFun - for opt in select.options.mitems: - opt.mnormalize() - select.maxw = max(select.maxw, opt.width()) - select.x = x - select.y = y - select.windowChange(height) - -# index of option currently under cursor -func hover(select: Select): int = - return select.cursor + select.si - -func dispheight(select: Select): int = - return select.maxh - select.y - -proc `hover=`(select: var Select, i: int) = - let i = clamp(i, 0, select.options.high) - if i >= select.si + select.dispheight: - select.si = i - select.dispheight + 1 - select.cursor = select.dispheight - 1 - elif i < select.si: - select.si = i - select.cursor = 0 - else: - select.cursor = i - select.si - -proc cursorDown*(select: var Select) = - if select.hover < select.options.high and - select.cursor + select.y < select.maxh - 1: - inc select.cursor - select.redraw = true - elif select.si < select.options.len - select.maxh: - inc select.si - select.redraw = true - -proc cursorUp*(select: var Select) = - if select.cursor > 0: - dec select.cursor - select.redraw = true - elif select.si > 0: - dec select.si - select.redraw = true - elif select.multiple and select.cursor > -1: - select.cursor = -1 - -proc close(select: var Select) = - select = Select() - -proc cancel*(select: var Select) = - select.submitFun(select.oselected) - select.close() - -proc submit(select: var Select) = - select.submitFun(select.selected) - select.close() - -proc click*(select: var Select) = - if not select.multiple: - select.selected = @[select.hover] - select.submit() - elif select.cursor == -1: - select.submit() - else: - var k = select.selected.len - let i = select.hover - for j in 0 ..< select.selected.len: - if select.selected[j] >= i: - k = j - break - if k < select.selected.len and select.selected[k] == i: - select.selected.delete(k) - else: - select.selected.insert(i, k) - select.redraw = true - -proc cursorLeft*(select: var Select) = - select.submit() - -proc cursorRight*(select: var Select) = - select.click() - -proc getCursorX*(select: var Select): int = - if select.cursor == -1: - return select.x - return select.x + 1 - -proc getCursorY*(select: var Select): int = - return select.y + 1 + select.cursor - -proc cursorFirstLine*(select: var Select) = - if select.cursor != 0 or select.si != 0: - select.cursor = 0 - select.si = 0 - select.redraw = true - -proc cursorLastLine*(select: var Select) = - if select.hover < select.options.len: - select.cursor = select.dispheight - 1 - select.si = max(select.options.len - select.maxh, 0) - select.redraw = true - -proc cursorNextMatch*(select: var Select, regex: Regex, wrap: bool) = - var j = -1 - for i in select.hover + 1 ..< select.options.len: - if regex.exec(select.options[i]).success: - j = i - break - if j != -1: - select.hover = j - select.redraw = true - elif wrap: - for i in 0 ..< select.hover: - if regex.exec(select.options[i]).success: - j = i - break - if j != -1: - select.hover = j - select.redraw = true - -proc cursorPrevMatch*(select: var Select, regex: Regex, wrap: bool) = - var j = -1 - for i in countdown(select.hover - 1, 0): - if regex.exec(select.options[i]).success: - j = i - break - if j != -1: - select.hover = j - select.redraw = true - elif wrap: - for i in countdown(select.options.high, select.hover): - if regex.exec(select.options[i]).success: - j = i - break - if j != -1: - select.hover = j - select.redraw = true - -proc pushCursorPos*(select: var Select) = - select.bpos.add(select.hover) - -proc popCursorPos*(select: var Select, nojump = false) = - select.hover = select.bpos.pop() - if not nojump: - select.redraw = true - -const HorizontalBar = $Rune(0x2500) -const VerticalBar = $Rune(0x2502) -const CornerTopLeft = $Rune(0x250C) -const CornerTopRight = $Rune(0x2510) -const CornerBottomLeft = $Rune(0x2514) -const CornerBottomRight = $Rune(0x2518) - -proc drawBorders(display: var FixedGrid, sx, ex, sy, ey: int, - upmore, downmore: bool) = - for y in sy .. ey: - var x = 0 - while x < sx: - if display[y * display.width + x].str == "": - display[y * display.width + x].str = " " - inc x - else: - #x = display[y * display.width + x].str.twidth(x) - inc x - # Draw corners. - let tl = if upmore: VerticalBar else: CornerTopLeft - let tr = if upmore: VerticalBar else: CornerTopRight - let bl = if downmore: VerticalBar else: CornerBottomLeft - let br = if downmore: VerticalBar else: CornerBottomRight - const fmt = newFormat() - display[sy * display.width + sx].str = tl - display[sy * display.width + ex].str = tr - display[ey * display.width + sx].str = bl - display[ey * display.width + ex].str = br - display[sy * display.width + sx].format = fmt - display[sy * display.width + ex].format = fmt - display[ey * display.width + sx].format = fmt - display[ey * display.width + ex].format = fmt - # Draw top, bottom borders. - let ups = if upmore: " " else: HorizontalBar - let downs = if downmore: " " else: HorizontalBar - for x in sx + 1 .. ex - 1: - display[sy * display.width + x].str = ups - display[ey * display.width + x].str = downs - display[sy * display.width + x].format = fmt - display[ey * display.width + x].format = fmt - if upmore: - display[sy * display.width + sx + (ex - sx) div 2].str = ":" - if downmore: - display[ey * display.width + sx + (ex - sx) div 2].str = ":" - # Draw left, right borders. - for y in sy + 1 .. ey - 1: - display[y * display.width + sx].str = VerticalBar - display[y * display.width + ex].str = VerticalBar - display[y * display.width + sx].format = fmt - display[y * display.width + ex].format = fmt - -proc drawSelect*(select: Select, display: var FixedGrid) = - if display.width < 2 or display.height < 2: - return # border does not fit... - # Max width, height with one row/column on the sides. - let mw = display.width - 2 - let mh = display.height - 2 - var sy = select.y - let si = select.si - var ey = min(sy + select.options.len, mh) + 1 - var sx = select.x - if sx + select.maxw >= mw: - sx = display.width - select.maxw - if sx < 0: - # This means the widest option is wider than the available screen. - # w3m simply cuts off the part that doesn't fit, and we do that too, - # but I feel like this may not be the best solution. - sx = 0 - var ex = min(sx + select.maxw, mw) + 1 - let upmore = select.si > 0 - let downmore = select.si + mh < select.options.len - drawBorders(display, sx, ex, sy, ey, upmore, downmore) - if select.multiple and not upmore: - display[sy * display.width + sx].str = "X" - # move inside border - inc sy - inc sx - var r: Rune - var k = 0 - var format = newFormat() - while k < select.selected.len and select.selected[k] < si: - inc k - for y in sy ..< ey: - let i = y - sy + si - var j = 0 - var x = sx - let dls = y * display.width - if k < select.selected.len and select.selected[k] == i: - format.reverse = true - inc k - else: - format.reverse = false - while j < select.options[i].len: - fastRuneAt(select.options[i], j, r) - let rw = r.twidth(x) - let ox = x - x += rw - if x > ex: - break - display[dls + ox].str = $r - display[dls + ox].format = format - while x < ex: - display[dls + x].str = " " - display[dls + x].format = format - inc x |