diff options
Diffstat (limited to 'src/types/cell.nim')
-rw-r--r-- | src/types/cell.nim | 208 |
1 files changed, 1 insertions, 207 deletions
diff --git a/src/types/cell.nim b/src/types/cell.nim index 2f2e5203..d66743c0 100644 --- a/src/types/cell.nim +++ b/src/types/cell.nim @@ -1,10 +1,5 @@ -import std/options -import std/tables - -import css/stylednode import types/color import utils/strwidth -import utils/twtstr type FormatFlags* = enum @@ -21,31 +16,14 @@ type bgcolor*: CellColor flags*: set[FormatFlags] - # A FormatCell *starts* a new terminal formatting context. - # If no FormatCell exists before a given cell, the default formatting is used. - FormatCell* = object - format*: Format - pos*: int - node*: StyledNode - SimpleFormatCell* = object format*: Format pos*: int - # Following properties should hold for `formats': - # * Position should be >= 0, <= str.width(). - # * The position of every FormatCell should be greater than the position - # of the previous FormatCell. - FlexibleLine* = object - str*: string - formats*: seq[FormatCell] - SimpleFlexibleLine* = object str*: string formats*: seq[SimpleFormatCell] - FlexibleGrid* = seq[FlexibleLine] - SimpleFlexibleGrid* = seq[SimpleFlexibleLine] FixedCell* = object @@ -77,13 +55,6 @@ const FormatCodes*: array[FormatFlags, tuple[s, e: uint8]] = [ FLAG_BLINK: (5u8, 25u8), ] -const FormatCodeMap = block: - var res: Table[uint8, tuple[flag: FormatFlags, reverse: bool]] - for x in FormatFlags: - res[FormatCodes[x][0]] = (x, false) - res[FormatCodes[x][1]] = (x, true) - res - template flag_template(format: Format, val: bool, flag: FormatFlags) = if val: format.flags.incl(flag) else: format.flags.excl(flag) @@ -99,14 +70,11 @@ template `blink=`*(f: var Format, b: bool) = flag_template f, b, FLAG_BLINK func newFixedGrid*(w: int, h: int = 1): FixedGrid = return FixedGrid(width: w, height: h, cells: newSeq[FixedCell](w * h)) -func width*(line: FlexibleLine): int = - return line.str.width() - func width*(cell: FixedCell): int = return cell.str.width() # Get the first format cell after pos, if any. -func findFormatN*(line: FlexibleLine|SimpleFlexibleLine, pos: int): int = +func findFormatN*(line: SimpleFlexibleLine, pos: int): int = var i = 0 while i < line.formats.len: if line.formats[i].pos > pos: @@ -114,13 +82,6 @@ func findFormatN*(line: FlexibleLine|SimpleFlexibleLine, pos: int): int = inc i return i -func findFormat*(line: FlexibleLine, pos: int): FormatCell = - let i = line.findFormatN(pos) - 1 - if i != -1: - result = line.formats[i] - else: - result.pos = -1 - func findFormat*(line: SimpleFlexibleLine, pos: int): SimpleFormatCell = let i = line.findFormatN(pos) - 1 if i != -1: @@ -128,176 +89,9 @@ func findFormat*(line: SimpleFlexibleLine, pos: int): SimpleFormatCell = else: result.pos = -1 -func findNextFormat*(line: FlexibleLine, pos: int): FormatCell = - let i = line.findFormatN(pos) - if i < line.formats.len: - result = line.formats[i] - else: - result.pos = -1 - func findNextFormat*(line: SimpleFlexibleLine, pos: int): SimpleFormatCell = let i = line.findFormatN(pos) if i < line.formats.len: result = line.formats[i] else: result.pos = -1 - -proc addLine*(grid: var FlexibleGrid) = - grid.add(FlexibleLine()) - -proc addLines*(grid: var FlexibleGrid, n: int) = - grid.setLen(grid.len + n) - -proc insertFormat*(line: var FlexibleLine, i: int, cell: FormatCell) = - line.formats.insert(cell, i) - -proc insertFormat*(line: var FlexibleLine, pos, i: int, format: Format, - node: StyledNode = nil) = - line.insertFormat(i, FormatCell(format: format, node: node, pos: pos)) - -proc addFormat*(line: var FlexibleLine, pos: int, format: Format, - node: StyledNode = nil) = - line.formats.add(FormatCell(format: format, node: node, pos: pos)) - -# https://www.ecma-international.org/wp-content/uploads/ECMA-48_5th_edition_june_1991.pdf -type - AnsiCodeParseState* = enum - PARSE_START, PARSE_PARAMS, PARSE_INTERM, PARSE_FINAL, PARSE_DONE - - AnsiCodeParser* = object - state*: AnsiCodeParseState - params: string - -proc getParam(parser: AnsiCodeParser, i: var int, colon = false): string = - while i < parser.params.len and - not (parser.params[i] == ';' or colon and parser.params[i] == ':'): - result &= parser.params[i] - inc i - if i < parser.params.len: - inc i - -template getParamU8(parser: AnsiCodeParser, i: var int, - colon = false): uint8 = - if i >= parser.params.len: - return false - let u = parseUInt8(parser.getParam(i)) - if u.isNone: - return false - u.get - -proc parseSGRDefColor(parser: AnsiCodeParser, format: var Format, - i: var int, isfg: bool): bool = - let u = parser.getParamU8(i, colon = true) - template set_color(c: CellColor) = - if isfg: - format.fgcolor = c - else: - format.bgcolor = c - if u == 2: - let param0 = parser.getParamU8(i, colon = true) - if i < parser.params.len: - let r = param0 - let g = parser.getParamU8(i, colon = true) - let b = parser.getParamU8(i, colon = true) - set_color cellColor(rgb(r, g, b)) - else: - set_color cellColor(gray(param0)) - elif u == 5: - let param0 = parser.getParamU8(i, colon = true) - if param0 in 0u8..15u8: - set_color cellColor(ANSIColor(param0)) - elif param0 in 16u8..255u8: - set_color cellColor(EightBitColor(param0)) - else: - return false - -proc parseSGRColor(parser: AnsiCodeParser, format: var Format, - i: var int, u: uint8): bool = - if u in 30u8..37u8: - format.fgcolor = cellColor(ANSIColor(u - 30)) - elif u == 38: - return parser.parseSGRDefColor(format, i, isfg = true) - elif u == 39: - format.fgcolor = defaultColor - elif u in 40u8..47u8: - format.bgcolor = cellColor(ANSIColor(u - 40)) - elif u == 48: - return parser.parseSGRDefColor(format, i, isfg = false) - elif u == 49: - format.bgcolor = defaultColor - elif u in 90u8..97u8: - format.fgcolor = cellColor(ANSIColor(u - 82)) - elif u in 100u8..107u8: - format.bgcolor = cellColor(ANSIColor(u - 92)) - else: - return false - return true - -proc parseSGRAspect(parser: AnsiCodeParser, format: var Format, - i: var int): bool = - let u = parser.getParamU8(i) - if u in FormatCodeMap: - let entry = FormatCodeMap[u] - if entry.reverse: - format.flags.excl(entry.flag) - else: - format.flags.incl(entry.flag) - return true - elif u == 0: - format = Format() - return true - else: - return parser.parseSGRColor(format, i, u) - -proc parseSGR(parser: AnsiCodeParser, format: var Format) = - if parser.params.len == 0: - format = Format() - else: - var i = 0 - while i < parser.params.len: - if not parser.parseSGRAspect(format, i): - break - -proc parseControlFunction(parser: var AnsiCodeParser, format: var Format, - f: char) = - case f - of 'm': - parser.parseSGR(format) - else: discard # unknown - -proc reset*(parser: var AnsiCodeParser) = - parser.state = PARSE_START - parser.params = "" - -proc parseAnsiCode*(parser: var AnsiCodeParser, format: var Format, - c: char): bool = - case parser.state - of PARSE_START: - if 0x40 <= int(c) and int(c) <= 0x5F: - if c != '[': - #C1, TODO? - parser.state = PARSE_DONE - else: - parser.state = PARSE_PARAMS - else: - parser.state = PARSE_DONE - return true - of PARSE_PARAMS: - if 0x30 <= int(c) and int(c) <= 0x3F: - parser.params &= c - else: - parser.state = PARSE_INTERM - return parser.parseAnsiCode(format, c) - of PARSE_INTERM: - if 0x20 <= int(c) and int(c) <= 0x2F: - discard - else: - parser.state = PARSE_FINAL - return parser.parseAnsiCode(format, c) - of PARSE_FINAL: - parser.state = PARSE_DONE - if 0x40 <= int(c) and int(c) <= 0x7E: - parser.parseControlFunction(format, c) - else: - return true - of PARSE_DONE: discard |