|
6 | 6 | // License: MIT |
7 | 7 | // ----------------------------------------------------------------------- |
8 | 8 |
|
9 | | -using SharpConsoleUI.Configuration; |
10 | 9 | using SharpConsoleUI.Drivers.Input; |
11 | 10 | using SharpConsoleUI.Helpers; |
12 | 11 | using SharpConsoleUI.Themes; |
@@ -343,44 +342,6 @@ public void Start() |
343 | 342 | bool isUnix = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows); |
344 | 343 | _useDirectAnsi = isUnix; |
345 | 344 |
|
346 | | - // Fail fast if stdin or stdout is not a TTY (piped/redirected) |
347 | | - if (isUnix) |
348 | | - { |
349 | | - var (stdinIsTty, stdoutIsTty) = TerminalRawMode.CheckTtyStatus(); |
350 | | - |
351 | | - if (!stdinIsTty || !stdoutIsTty) |
352 | | - { |
353 | | - // Restore signals suppressed in constructor so caller's terminal works |
354 | | - RestoreUnixSignal(SigInt); |
355 | | - RestoreUnixSignal(SigTstp); |
356 | | - if (_processExitHandler != null) |
357 | | - { |
358 | | - AppDomain.CurrentDomain.ProcessExit -= _processExitHandler; |
359 | | - _processExitHandler = null; |
360 | | - } |
361 | | - |
362 | | - var term = Environment.GetEnvironmentVariable("TERM") ?? "(unset)"; |
363 | | - var details = new StringBuilder(); |
364 | | - details.AppendLine("SharpConsoleUI cannot start: interactive terminal required."); |
365 | | - details.AppendLine(); |
366 | | - details.AppendLine("Current environment:"); |
367 | | - details.AppendLine($" TERM = {term}"); |
368 | | - details.AppendLine($" stdin is TTY: {stdinIsTty}"); |
369 | | - details.AppendLine($" stdout is TTY: {stdoutIsTty}"); |
370 | | - details.AppendLine(); |
371 | | - if (!stdinIsTty) |
372 | | - details.AppendLine("Problem: stdin is not connected to a terminal (it appears to be piped or redirected)."); |
373 | | - if (!stdoutIsTty) |
374 | | - details.AppendLine("Problem: stdout is not connected to a terminal (it appears to be piped or redirected)."); |
375 | | - details.AppendLine(); |
376 | | - details.AppendLine("How to fix:"); |
377 | | - details.AppendLine(" - Run the application directly in a terminal emulator (e.g., Terminal, iTerm2, Alacritty, Windows Terminal)"); |
378 | | - details.AppendLine(" - Do not pipe input/output (avoid: echo | app, app | cat, app > file)"); |
379 | | - details.AppendLine(" - If using an IDE, run in the integrated terminal, not as a background process"); |
380 | | - throw new TerminalNotSupportedException(details.ToString()); |
381 | | - } |
382 | | - } |
383 | | - |
384 | 345 | // Enter raw mode before creating console buffer (so ioctl is available) |
385 | 346 | if (_useDirectAnsi) |
386 | 347 | { |
@@ -446,52 +407,6 @@ public void Start() |
446 | 407 | // Uses DSR cursor position query to measure actual emoji width. |
447 | 408 | ProbeTerminalCapabilities(); |
448 | 409 |
|
449 | | - // Mandatory terminal verification: ensure terminal responds to escape sequences. |
450 | | - // ProbeTerminalCapabilities (above) swallows failures — this is a hard check. |
451 | | - if (_useDirectAnsi) |
452 | | - { |
453 | | - TerminalRawMode.FlushStdin(); |
454 | | - |
455 | | - bool responds = TerminalCapabilities.VerifyTerminalResponds( |
456 | | - write: text => TerminalRawMode.WriteStdout(text), |
457 | | - readByte: () => TerminalRawMode.ReadByteWithTimeout( |
458 | | - SystemDefaults.TerminalVerificationTimeoutMs)); |
459 | | - |
460 | | - if (!responds) |
461 | | - { |
462 | | - var term = Environment.GetEnvironmentVariable("TERM") ?? "(unset)"; |
463 | | - _consoleWindowSystem?.LogService?.Log( |
464 | | - Logging.LogLevel.Error, |
465 | | - $"Terminal (TERM={term}) did not respond to DSR verification query. " + |
466 | | - "Emergency exit: Ctrl+\\ (SIGQUIT).", |
467 | | - "System"); |
468 | | - |
469 | | - // Roll back: Stop() handles partial initialization (Task 5 guards) |
470 | | - Stop(); |
471 | | - |
472 | | - var details = new StringBuilder(); |
473 | | - details.AppendLine("SharpConsoleUI cannot start: terminal is not responding to escape sequences."); |
474 | | - details.AppendLine(); |
475 | | - details.AppendLine("Current environment:"); |
476 | | - details.AppendLine($" TERM = {term}"); |
477 | | - details.AppendLine($" Verification: sent DSR query (ESC[6n), no response within {SystemDefaults.TerminalVerificationTimeoutMs}ms"); |
478 | | - details.AppendLine(); |
479 | | - details.AppendLine("This means the terminal is not processing ANSI escape sequences, which are"); |
480 | | - details.AppendLine("required for rendering the UI. The alternate screen buffer likely did not activate."); |
481 | | - details.AppendLine(); |
482 | | - details.AppendLine("Common causes:"); |
483 | | - details.AppendLine(" - Embedded terminal that does not fully support ANSI (e.g., some IDE terminals)"); |
484 | | - details.AppendLine(" - Terminal multiplexer misconfiguration (tmux, screen)"); |
485 | | - details.AppendLine(" - TERM environment variable set incorrectly"); |
486 | | - details.AppendLine(); |
487 | | - details.AppendLine("How to fix:"); |
488 | | - details.AppendLine(" - Run in a standard terminal emulator (Terminal, iTerm2, Alacritty, Windows Terminal)"); |
489 | | - details.AppendLine(" - Ensure TERM is set correctly (e.g., xterm-256color)"); |
490 | | - details.AppendLine(" - If stuck, press Ctrl+\\ (SIGQUIT) to force exit"); |
491 | | - throw new TerminalNotSupportedException(details.ToString()); |
492 | | - } |
493 | | - } |
494 | | - |
495 | 410 | _lastConsoleWidth = screenSize.Width; |
496 | 411 | _lastConsoleHeight = screenSize.Height; |
497 | 412 |
|
@@ -618,20 +533,15 @@ public void Stop() |
618 | 533 | Console.Error.Flush(); |
619 | 534 | } |
620 | 535 |
|
621 | | - // Post-restore Console calls — may fail if Start() partially completed |
622 | | - try |
623 | | - { |
624 | | - Console.Out.Write(cleanupSequence); |
625 | | - Console.Out.Flush(); |
626 | | - Console.ResetColor(); |
627 | | - } |
628 | | - catch { } |
| 536 | + Console.Out.Write(cleanupSequence); |
| 537 | + Console.Out.Flush(); |
| 538 | + Console.ResetColor(); |
629 | 539 |
|
630 | 540 | Thread.Sleep(50); |
631 | 541 |
|
632 | 542 | Cleanup(); |
633 | 543 |
|
634 | | - try { Console.Clear(); } catch { } |
| 544 | + Console.Clear(); |
635 | 545 |
|
636 | 546 | // Restore cursor visibility on shutdown |
637 | 547 | SetCursorVisible(true); |
@@ -954,21 +864,12 @@ private void ProbeTerminalCapabilities() |
954 | 864 | private static extern bool SetConsoleMode(nint hConsoleHandle, uint dwMode); |
955 | 865 |
|
956 | 866 | // Unix signal constants for direct suppression via libc signal() |
957 | | - // SIGINT (2, Ctrl+C) and SIGTSTP (20, Ctrl+Z) are suppressed to prevent |
958 | | - // accidental interruption of the UI. |
959 | | - // SIGQUIT (3, Ctrl+\) is intentionally NOT suppressed — it serves as |
960 | | - // an emergency exit when the application is stuck. |
961 | | - private const int SigInt = 2; // Ctrl+C — suppressed |
962 | | - private const int SigTstp = 20; // Ctrl+Z — suppressed |
| 867 | + private const int SigInt = 2; // Ctrl+C |
| 868 | + private const int SigTstp = 20; // Ctrl+Z |
963 | 869 |
|
964 | 870 | private static void SuppressUnixSignal(int signum) |
965 | 871 | { |
966 | | - try { _unixSignal(signum, new IntPtr(1)); } catch { } // SIG_IGN = 1 |
967 | | - } |
968 | | - |
969 | | - private static void RestoreUnixSignal(int signum) |
970 | | - { |
971 | | - try { _unixSignal(signum, IntPtr.Zero); } catch { } // SIG_DFL = 0 |
| 872 | + try { _unixSignal(signum, new IntPtr(1)); } catch { } |
972 | 873 | } |
973 | 874 |
|
974 | 875 | [DllImport("libc", EntryPoint = "signal")] |
|
0 commit comments