"""Unicode character lookup tables for box-drawing, block elements, braille, and indicators.""" from __future__ import annotations from uframe.ir import BorderWeight # --------------------------------------------------------------------------- # Box-drawing characters by weight # --------------------------------------------------------------------------- # Keys: (weight) → dict of part names → char BOX_CHARS: dict[BorderWeight, dict[str, str]] = { BorderWeight.LIGHT: { "tl": "┌", "tr": "┐", "bl": "└", "br": "┘", "h": "─", "v": "│", "t_down": "┬", "t_up": "┴", "t_right": "├", "t_left": "┤", "cross": "┼", }, BorderWeight.HEAVY: { "tl": "┏", "tr": "┓", "bl": "┗", "br": "┛", "h": "━", "v": "┃", "t_down": "┳", "t_up": "┻", "t_right": "┣", "t_left": "┫", "cross": "╋", }, BorderWeight.DOUBLE: { "tl": "╔", "tr": "╗", "bl": "╚", "br": "╝", "h": "═", "v": "║", "t_down": "╦", "t_up": "╩", "t_right": "╠", "t_left": "╣", "cross": "╬", }, BorderWeight.ROUNDED: { "tl": "╭", "tr": "╮", "bl": "╰", "br": "╯", "h": "─", "v": "│", "t_down": "┬", "t_up": "┴", "t_right": "├", "t_left": "┤", "cross": "┼", }, } # --------------------------------------------------------------------------- # Block elements for gauges and bars # --------------------------------------------------------------------------- # Horizontal fill blocks: full → 1/8 HFILL = "█▉▊▋▌▍▎▏" # Vertical fill blocks: 1/8 → full (bottom-up) VFILL = "▁▂▃▄▅▆▇█" # Shade blocks: 25% → 100% SHADE = "░▒▓█" # Gauge characters GAUGE_FILLED = "█" GAUGE_EMPTY = "░" # --------------------------------------------------------------------------- # Braille patterns for sparklines # --------------------------------------------------------------------------- # Braille base: U+2800. Each character is a 2×4 dot matrix. # Dot positions (bit index): # 0 3 # 1 4 # 2 5 # 6 7 BRAILLE_BASE = 0x2800 # Row dot bits for left column (bits 0,1,2,6) and right column (bits 3,4,5,7) BRAILLE_LEFT = [0x01, 0x02, 0x04, 0x40] # rows 0-3 BRAILLE_RIGHT = [0x08, 0x10, 0x20, 0x80] # rows 0-3 def braille_char(dots: list[tuple[int, int]]) -> str: """Build a braille character from a list of (col, row) positions. col: 0 (left) or 1 (right) row: 0 (top) to 3 (bottom) """ code = BRAILLE_BASE for col, row in dots: if 0 <= row <= 3: if col == 0: code |= BRAILLE_LEFT[row] else: code |= BRAILLE_RIGHT[row] return chr(code) def sparkline_chars(values: list[float], width: int) -> list[str]: """Convert a list of values into braille sparkline characters. Each output character represents two consecutive values (left + right columns). Values are normalized to 0–7 (mapping to 4 braille rows × 2 resolution). """ if not values: return [] lo = min(values) hi = max(values) span = hi - lo if hi != lo else 1.0 # Normalize to 0–7 range (8 vertical positions: 4 rows × 2 resolution) norm = [int((v - lo) / span * 7) for v in values] # Pad to even length if len(norm) % 2: norm.append(norm[-1]) chars = [] for i in range(0, min(len(norm), width * 2), 2): left_val = norm[i] right_val = norm[i + 1] if i + 1 < len(norm) else norm[i] dots = [] # Fill dots from bottom up for each column for row in range(3, -1, -1): threshold = (3 - row) * 2 # row 3=0, row 2=2, row 1=4, row 0=6 if left_val >= threshold: dots.append((0, row)) if right_val >= threshold: dots.append((1, row)) chars.append(braille_char(dots)) return chars[:width] # --------------------------------------------------------------------------- # Status indicators # --------------------------------------------------------------------------- STATUS_CHARS: dict[str, str] = { "online": "●", "offline": "○", "degraded": "◐", "unknown": "◌", "alert": "⚠", } STATUS_COLORS: dict[str, str] = { "online": "0f0", "offline": "f00", "degraded": "ff0", "unknown": "888", "alert": "f00", } # --------------------------------------------------------------------------- # Divider characters # --------------------------------------------------------------------------- DIVIDER_CHARS: dict[str, str] = { "light": "─", "heavy": "━", "double": "═", "dash": "╌", "dot": "┄", }