diff options
author | bptato <nincsnevem662@gmail.com> | 2021-11-13 11:17:40 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2021-11-13 11:17:40 +0100 |
commit | a6099512e42cc95cf6276ab784afd70febdd43b7 (patch) | |
tree | def2061199d9f119a3176858e331ba376c89e2c5 /src/io/cell.nim | |
parent | c141a3cea17f32f526853cd4085ae4cc80c4fed6 (diff) | |
download | chawan-a6099512e42cc95cf6276ab784afd70febdd43b7.tar.gz |
Parse ansi escape codes when displaying plain text
Diffstat (limited to 'src/io/cell.nim')
-rw-r--r-- | src/io/cell.nim | 182 |
1 files changed, 128 insertions, 54 deletions
diff --git a/src/io/cell.nim b/src/io/cell.nim index 133b88d6..67b7361c 100644 --- a/src/io/cell.nim +++ b/src/io/cell.nim @@ -1,4 +1,7 @@ import unicode +import strutils +import sequtils +import sugar import types/color import utils/twtstr @@ -28,6 +31,16 @@ type FixedGrid* = seq[FixedCell] +func newFixedGrid*(w: int, h: int = 1): FixedGrid = + return newSeq[FixedCell](w * h) + +func width*(line: FlexibleLine): int = + for c in line: + result += c.rune.width() + +func newFormatting*(): Formatting = + return Formatting(fgcolor: defaultColor, bgcolor: defaultColor) + proc setText*(grid: var FlexibleGrid, x: int, y: int, text: seq[Rune]) = while grid.len <= y: grid.add(newSeq[FlexibleCell]()) @@ -40,15 +53,121 @@ proc setText*(grid: var FlexibleGrid, x: int, y: int, text: seq[Rune]) = grid[y][i].rune = text[i] inc i -func newFixedGrid*(w: int, h: int = 1): FixedGrid = - return newSeq[FixedCell](w * h) - -func width*(line: FlexibleLine): int = - for c in line: - result += c.rune.width() - -func newFormatting*(): Formatting = - return Formatting(fgcolor: defaultColor, bgcolor: defaultColor) +template inc_check(i: int) = + inc i + if i >= buf.len: + return i + +proc parseAnsiCode*(formatting: var Formatting, buf: string, fi: int): int = + var i = fi + if buf[i] != '\e': + return i + + inc_check i + if 0x40 <= int(buf[i]) and int(buf[i]) <= 0x5F: + if buf[i] != '[': + #C1, TODO? + return + inc_check i + + let sp = i + #parameter bytes + while 0x30 <= int(buf[i]) and int(buf[i]) <= 0x3F: + inc_check i + let params = buf.substr(sp, i - 1) + + let si = i + #intermediate bytes + while 0x20 <= int(buf[i]) and int(buf[i]) <= 0x2F: + inc_check i + let interm = buf.substr(si, i) + + let final = buf[i] + #final byte + if 0x40 <= int(buf[i]) and int(buf[i]) <= 0x7E: + inc_check i + + case final + of 'm': + if params.len == 0: + formatting = newFormatting() + else: + let sparams = params.split(';') + try: + let ip = sparams.map((x) => parseInt(x)) + var pi = 0 + while pi < ip.len: + case ip[pi] + of 0: + formatting = newFormatting() + of 1: + formatting.bold = true + of 3: + formatting.italic = true + of 4: + formatting.underline = true + of 9: + formatting.strike = true + of 22: + formatting.bold = false + of 23: + formatting.italic = false + of 29: + formatting.strike = false + of 30..37: + formatting.fgcolor = CellColor(rgb: false, color: uint8(ip[pi])) + of 38: + inc pi + if pi < ip.len: + if ip[pi] == 2: + inc pi + if pi + 2 < ip.len: + let r = uint8(ip[pi]) + inc pi + let g = uint8(ip[pi]) + inc pi + let b = uint8(ip[pi]) + formatting.fgcolor = CellColor(rgb: true, rgbcolor: (r: r, g: g, b: b)) + else: + #TODO + inc pi + continue + else: + break + of 39: + formatting.fgcolor = defaultColor + of 40..47: + formatting.bgcolor = CellColor(rgb: false, color: uint8(ip[0])) + of 48: + inc pi + if pi < ip.len: + if ip[pi] == 2: + inc pi + if pi + 2 < ip.len: + let r = uint8(ip[pi]) + inc pi + let g = uint8(ip[pi]) + inc pi + let b = uint8(ip[pi]) + formatting.bgcolor = CellColor(rgb: true, rgbcolor: (r: r, g: g, b: b)) + else: + #TODO + inc pi + continue + else: + break + of 49: + formatting.bgcolor = defaultColor + of 53: + formatting.overline = true + of 55: + formatting.overline = false + else: discard + inc pi + except ValueError: discard + else: discard + + return i proc processFormatting*(formatting: var Formatting, cellf: Formatting): string = if formatting.bold and not cellf.bold: @@ -96,48 +215,3 @@ proc processFormatting*(formatting: var Formatting, cellf: Formatting): string = result &= SGR(53) formatting = cellf - if formatting.bold and not cellf.bold: - result &= SGR(22) - if formatting.italic and not cellf.italic: - result &= SGR(23) - if formatting.underline and not cellf.underline: - result &= SGR(24) - if formatting.strike and not cellf.strike: - result &= SGR(29) - if formatting.overline and not cellf.overline: - result &= SGR(55) - - if cellf.fgcolor != formatting.fgcolor: - var color = cellf.fgcolor - if color.rgb: - let rgb = color.rgbcolor - result &= SGR(38, 2, rgb.r, rgb.g, rgb.b) - elif color == defaultColor: - result &= SGR() - formatting = newFormatting() - else: - result &= SGR(color.color) - - if cellf.bgcolor != formatting.bgcolor: - var color = cellf.bgcolor - if color.rgb: - let rgb = color.rgbcolor - result &= SGR(48, 2, rgb.r, rgb.g, rgb.b) - elif color == defaultColor: - result &= SGR() - formatting = newFormatting() - else: - result &= SGR(color.color) - - if not formatting.bold and cellf.bold: - result &= SGR(1) - if not formatting.italic and cellf.italic: - result &= SGR(3) - if not formatting.underline and cellf.underline: - result &= SGR(4) - if not formatting.strike and cellf.strike: - result &= SGR(9) - if not formatting.overline and cellf.overline: - result &= SGR(53) - - formatting = cellf |