import { Cell, CellType } from "./cell.ts";import { consumeWords } from "./consume_words.ts";import { stripAnsiCode, unicodeWidth } from "./deps.ts";
export function longest( index: number, rows: Array<Array<CellType>>, maxWidth?: number,): number { const cellLengths = rows.map((row) => { const cell = row[index]; const cellValue = cell instanceof Cell && cell.getColSpan() > 1 ? "" : cell?.toString() || "";
return cellValue .split("\n") .map((line: string) => { const str = typeof maxWidth === "undefined" ? line : consumeWords(maxWidth, line);
return strLength(str) || 0; }); }).flat();
return Math.max(...cellLengths);}
export const strLength = (str: string): number => { return unicodeWidth(stripAnsiCode(str));};
export const ansiRegexSource = /\x1b\[(?:(?<_0>0)|(?<_22>1|2|22)|(?<_23>3|23)|(?<_24>4|24)|(?<_27>7|27)|(?<_28>8|28)|(?<_29>9|29)|(?<_39>30|31|32|33|34|35|36|37|38;2;\d+;\d+;\d+|38;5;\d+|39|90|91|92|93|94|95|96|97)|(?<_49>40|41|42|43|44|45|46|47|48;2;\d+;\d+;\d+|48;5;\d+|49|100|101|102|103|104|105|106|107))m/ .source;
export function getUnclosedAnsiRuns(text: string) { type Token = { kind: string; content: string }; const tokens: Token[] = []; for (const { groups } of text.matchAll(new RegExp(ansiRegexSource, "g"))) { const [_kind, content] = Object.entries(groups!).find(([_, val]) => val)!; tokens.push({ kind: _kind.slice(1), content }); }
let unclosed: Token[] = []; for (const token of tokens) { unclosed = [...unclosed.filter((y) => y.kind !== token.kind), token]; }
unclosed = unclosed.filter(({ content, kind }) => content !== kind);
const currentSuffix = unclosed .map(({ kind }) => `\x1b[${kind}m`).reverse().join(""); const nextPrefix = unclosed.map(({ content }) => `\x1b[${content}m`).join("");
return { currentSuffix, nextPrefix, };}