SPB Git

spb/khaelor Public

KHAELOR — a terminal-native autonomous engineering agent powered by Anthropic.

TypeScript 82.9% HTML 14.9% CSS 1.1% JavaScript 0.7%
1.8 KB · 66 lines typescript
Raw Blame History
1/**2 * KHAELOR3 * File: prototypes/tui-spike/shared/ansi.ts4 * Description: ANSI helpers shared by both spike candidates — strip, width, wrap, truncate.5 *6 * Author: Simon-Pierre Boucher7 * Contact: contact@spboucher.ai8 */910export const CSI = "\x1b[";11export const SYNC_ON = "\x1b[?2026h";12export const SYNC_OFF = "\x1b[?2026l";13export const HIDE_CURSOR = "\x1b[?25l";14export const SHOW_CURSOR = "\x1b[?25h";1516const ANSI_RE = /\x1b\[[0-9;?]*[A-Za-z]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b./g;1718export function stripAnsi(s: string): string {19  return s.replace(ANSI_RE, "");20}2122/** Visible width in columns. Demo content is width-1 code points only, so code-point count is exact here. */23export function visibleWidth(s: string): number {24  return [...stripAnsi(s)].length;25}2627export function truncate(s: string, w: number): string {28  const cp = [...s];29  return cp.length <= w ? s : cp.slice(0, w).join("");30}3132/** Greedy word wrap; hard-splits words longer than the width. Splits embedded newlines first. */33export function wrapText(text: string, w: number): string[] {34  const out: string[] = [];35  for (const raw of text.split("\n")) {36    if ([...raw].length <= w) {37      out.push(raw);38      continue;39    }40    let line = "";41    for (const word of raw.split(" ")) {42      const candidate = line === "" ? word : line + " " + word;43      if ([...candidate].length <= w) {44        line = candidate;45      } else {46        if (line !== "") out.push(line);47        let rest = word;48        while ([...rest].length > w) {49          out.push([...rest].slice(0, w).join(""));50          rest = [...rest].slice(w).join("");51        }52        line = rest;53      }54    }55    out.push(line);56  }57  return out;58}5960export function countMatches(s: string, re: RegExp): number {61  let n = 0;62  re.lastIndex = 0;63  while (re.exec(s) !== null) n++;64  return n;65}66