ascii-chat 0.8.38
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
platform/terminal.c
Go to the documentation of this file.
1
7#include <ascii-chat/platform/terminal.h>
8#include <ascii-chat/platform/abstraction.h>
9#include <ascii-chat/options/options.h>
10#include <ascii-chat/options/rcu.h>
11#include <ascii-chat/common.h>
12#include <ascii-chat/log/logging.h>
13#ifndef _WIN32
14#include <unistd.h>
15#endif
16#include <string.h>
17
32 // Check color_mode setting - if explicitly set to NONE, disable colors
33 int color_mode = GET_OPTION(color_mode);
34 if (color_mode == COLOR_MODE_NONE) {
35 return false; // Color mode explicitly disabled
36 }
37
38 // Get current color setting (auto/true/false)
39 int color_setting = GET_OPTION(color);
40
41 // Priority 1: --color=true - Force colors ON (overrides everything)
42 if (color_setting == COLOR_SETTING_TRUE) {
43 return true; // ALWAYS colorize
44 }
45
46 // Priority 2: --color=false - Force colors OFF (overrides everything)
47 if (color_setting == COLOR_SETTING_FALSE) {
48 return false; // NEVER colorize
49 }
50
51 // Priority 3: --color=auto (default) - Smart detection
52 // Special case: Show colors for --help and --version even if not a TTY
53 // Check for help/version in global argv (set by main.c early)
54 extern int g_argc;
55 extern char **g_argv;
56 if (g_argc > 1 && g_argv) {
57 for (int i = 1; i < g_argc; i++) {
58 if (strcmp(g_argv[i], "--help") == 0 || strcmp(g_argv[i], "-h") == 0 || strcmp(g_argv[i], "--version") == 0 ||
59 strcmp(g_argv[i], "-v") == 0 || strcmp(g_argv[i], "--show-capabilities") == 0) {
60 // For help/version/show-capabilities, use colors only if output is a TTY
61 // (respect piping convention: no colors unless --color=true)
62 int is_tty = platform_isatty(fd);
63 if (!is_tty) {
64 // Piping detected - fall through to check environment overrides
65 break;
66 }
67
68 // It's a TTY - show colors for help. Check environment overrides.
69 if (SAFE_GETENV("ASCII_CHAT_COLOR")) {
70 return true; // ASCII_CHAT_COLOR env var forces colors
71 }
72
73 // CLAUDECODE environment variable (LLM automation) - disable colors
74 if (SAFE_GETENV("CLAUDECODE")) {
75 return false; // NO colors in Claude Code environment
76 }
77
78 // For help output to TTY, show colors by default
79 return true;
80 }
81 }
82 }
83
84 // Check environment variable overrides
85 if (SAFE_GETENV("ASCII_CHAT_COLOR")) {
86 return true; // ASCII_CHAT_COLOR env var forces colors
87 }
88
89 // CLAUDECODE environment variable (LLM automation) - disable colors
90 if (SAFE_GETENV("CLAUDECODE")) {
91 return false; // NO colors in Claude Code environment
92 }
93
94 // Check if output is a TTY (pipe detection)
95 int is_tty = platform_isatty(fd);
96 if (!is_tty) {
97 return false; // NO colors when piping/redirecting
98 }
99
100 // Default: Use colors (we have TTY and no environment overrides)
101 return true;
102}
103
114terminal_color_mode_t terminal_get_effective_color_mode(void) {
115 // If colors are disabled entirely by terminal_should_color_output(), return NONE
116 if (!terminal_should_color_output(STDOUT_FILENO)) {
117 return TERM_COLOR_NONE;
118 }
119
120 // If --color-mode is set to specific value, use it
121 terminal_color_mode_t color_mode = GET_OPTION(color_mode);
122 if (color_mode != TERM_COLOR_AUTO) {
123 return color_mode;
124 }
125
126 // Otherwise auto-detect from terminal capabilities
127 // For now, return the detected color mode from terminal capabilities
128 // This will be used by apply_color_mode_override() if needed
129 return TERM_COLOR_AUTO; // Let the calling code handle auto-detection
130}
131
132/* ============================================================================
133 * Interactive Mode and TTY State Detection
134 * ============================================================================ */
135
137 return platform_isatty(STDIN_FILENO) != 0;
138}
139
141 return platform_isatty(STDOUT_FILENO) != 0;
142}
143
145 return platform_isatty(STDERR_FILENO) != 0;
146}
147
151
153 return !terminal_is_stdout_tty();
154}
155
157 // If stdout is piped/redirected, force logs to stderr to avoid corruption
159 // Unless in TESTING environment where test framework may capture stdout
160 const char *testing = SAFE_GETENV("TESTING");
161 if (testing && strcmp(testing, "1") == 0) {
162 return false; // Allow stdout in test environments
163 }
164 return true; // Force stderr when piped
165 }
166 return false; // stdout is TTY, no need to force stderr
167}
168
170 // Must be fully interactive (stdin and stdout are TTYs)
172 return false;
173 }
174
175 // Must not be in snapshot mode (non-interactive capture)
176 if (GET_OPTION(snapshot_mode)) {
177 return false;
178 }
179
180 // Must not have automated prompt responses configured
181 const char *auto_response = SAFE_GETENV("ASCII_CHAT_QUESTION_PROMPT_RESPONSE");
182 if (auto_response && *auto_response != '\0') {
183 return false; // Automated responses configured, not interactive
184 }
185
186 // All checks passed, interactive prompts are appropriate
187 return true;
188}
189
190int terminal_choose_log_fd(log_level_t level) {
191 // When force_stderr is enabled (client mode), send ALL logs to stderr
192 // When terminal is NOT interactive (piped/redirected), send ALL logs to stderr
193 // to keep stdout clean for piped data (JSON, frames, etc.)
195 return STDERR_FILENO;
196 }
197
198 // In interactive mode, route based on level:
199 // WARN and above (ERROR, FATAL) go to stderr
200 // Others (DEV, DEBUG, INFO) go to stdout
201 if (level >= LOG_WARN) {
202 return STDERR_FILENO;
203 }
204
205 return STDOUT_FILENO;
206}
ASCIICHAT_API char ** g_argv
Definition common.c:46
ASCIICHAT_API int g_argc
Definition common.c:45
bool log_get_force_stderr(void)
bool terminal_can_prompt_user(void)
bool terminal_is_interactive(void)
bool terminal_is_stdin_tty(void)
int terminal_choose_log_fd(log_level_t level)
bool terminal_is_stderr_tty(void)
bool terminal_is_stdout_tty(void)
bool terminal_should_force_stderr(void)
bool terminal_is_piped_output(void)
terminal_color_mode_t terminal_get_effective_color_mode(void)
Get current color mode considering all overrides.
bool terminal_should_color_output(int fd)
Determine if color output should be used.
int platform_isatty(int fd)
Definition util.c:61