


























@@ -9,7 +9,6 @@ import { getCapabilities } from "@earendil-works/pi-tui";
99import chalk from "chalk";
1010import { type Static, Type } from "typebox";
1111import { Compile } from "typebox/compile";
12-import { parseStrictNonNegativeInteger } from "../../../../infra/parse-finite-number.js";
1312import { getCustomThemesDir, getThemesDir } from "../../../config.js";
1413import type { SourceInfo } from "../../../sessions/source-info.js";
1514import { closeWatcher, watchWithErrorHandler } from "../../../utils/fs-watch.js";
@@ -576,75 +575,6 @@ function loadTheme(name: string, mode?: ColorMode): Theme {
576575return createTheme(themeJson, mode);
577576}
578577579-export type TerminalTheme = "dark" | "light";
580-581-export interface RgbColor {
582-r: number;
583-g: number;
584-b: number;
585-}
586-587-export interface TerminalThemeDetection {
588-theme: TerminalTheme;
589-source: "terminal background" | "COLORFGBG" | "fallback";
590-detail: string;
591-confidence: "high" | "low";
592-}
593-594-export interface TerminalThemeDetectionOptions {
595-env?: NodeJS.ProcessEnv;
596-}
597-598-function getColorFgBgBackgroundIndex(colorfgbg: string): number | undefined {
599-const parts = colorfgbg.split(";");
600-for (let i = parts.length - 1; i >= 0; i--) {
601-const bg = parseStrictNonNegativeInteger(parts[i].trim());
602-if (bg !== undefined && bg <= 255) {
603-return bg;
604-}
605-}
606-return undefined;
607-}
608-609-function getRgbColorLuminance({ r, g, b }: RgbColor): number {
610-const toLinear = (channel: number) => {
611-const value = channel / 255;
612-return value <= 0.03928 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;
613-};
614-return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
615-}
616-617-function getAnsiColorLuminance(index: number): number {
618-return getRgbColorLuminance(hexToRgb(ansi256ToHex(index)));
619-}
620-621-export function detectTerminalBackground(
622-options: TerminalThemeDetectionOptions = {},
623-): TerminalThemeDetection {
624-const env = options.env ?? process.env;
625-const colorfgbg = env.COLORFGBG || "";
626-const bg = getColorFgBgBackgroundIndex(colorfgbg);
627-if (bg !== undefined) {
628-return {
629-theme: getAnsiColorLuminance(bg) >= 0.5 ? "light" : "dark",
630-source: "COLORFGBG",
631-detail: `background color index ${bg}`,
632-confidence: "high",
633-};
634-}
635-636-return {
637-theme: "dark",
638-source: "fallback",
639-detail: "no terminal background hint found",
640-confidence: "low",
641-};
642-}
643-644-export function getDefaultTheme(): string {
645-return detectTerminalBackground().theme;
646-}
647-648578// ============================================================================
649579// Global Theme Instance
650580// ============================================================================
@@ -658,7 +588,7 @@ export const theme: Theme = new Proxy({} as Theme, {
658588get(_target, prop) {
659589const t = (globalThis as Record<symbol, Theme>)[THEME_KEY];
660590if (!t) {
661-throw new Error("Theme not initialized. Call initTheme() first.");
591+throw new Error("Theme not initialized. Call setTheme() first.");
662592}
663593return (t as unknown as Record<string | symbol, unknown>)[prop];
664594},
@@ -673,22 +603,6 @@ let themeWatcher: fs.FSWatcher | undefined;
673603let themeReloadTimer: NodeJS.Timeout | undefined;
674604const registeredThemes = new Map<string, Theme>();
675605676-export function initTheme(themeName?: string, enableWatcher = false): void {
677-const name = themeName ?? getDefaultTheme();
678-currentThemeName = name;
679-try {
680-setGlobalTheme(loadTheme(name));
681-if (enableWatcher) {
682-startThemeWatcher();
683-}
684-} catch {
685-// Theme is invalid - fall back to dark theme silently
686-currentThemeName = "dark";
687-setGlobalTheme(loadTheme("dark"));
688-// Don't start watcher for fallback theme
689-}
690-}
691-692606export function setTheme(
693607name: string,
694608enableWatcher = false,
@@ -794,52 +708,6 @@ export function stopThemeWatcher(): void {
794708// HTML Export Helpers
795709// ============================================================================
796710797-/**
798- * Convert a 256-color index to hex string.
799- * Indices 0-15: basic colors (approximate)
800- * Indices 16-231: 6x6x6 color cube
801- * Indices 232-255: grayscale ramp
802- */
803-function ansi256ToHex(index: number): string {
804-// Basic colors (0-15) - approximate common terminal values
805-const basicColors = [
806-"#000000",
807-"#800000",
808-"#008000",
809-"#808000",
810-"#000080",
811-"#800080",
812-"#008080",
813-"#c0c0c0",
814-"#808080",
815-"#ff0000",
816-"#00ff00",
817-"#ffff00",
818-"#0000ff",
819-"#ff00ff",
820-"#00ffff",
821-"#ffffff",
822-];
823-if (index < 16) {
824-return basicColors[index];
825-}
826-827-// Color cube (16-231): 6x6x6 = 216 colors
828-if (index < 232) {
829-const cubeIndex = index - 16;
830-const r = Math.floor(cubeIndex / 36);
831-const g = Math.floor((cubeIndex % 36) / 6);
832-const b = cubeIndex % 6;
833-const toHex = (n: number) => (n === 0 ? 0 : 55 + n * 40).toString(16).padStart(2, "0");
834-return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
835-}
836-837-// Grayscale (232-255): 24 shades
838-const gray = 8 + (index - 232) * 10;
839-const grayHex = gray.toString(16).padStart(2, "0");
840-return `#${grayHex}${grayHex}${grayHex}`;
841-}
842-843711// ============================================================================
844712// TUI Helpers
845713// ============================================================================
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。