|
3 | 3 | // Demonstrates all features with modern patterns adapted from the original examples |
4 | 4 | // ----------------------------------------------------------------------- |
5 | 5 |
|
6 | | -using System.Diagnostics; |
7 | 6 | using System.IO; |
8 | 7 | using SharpConsoleUI; |
9 | 8 | using SharpConsoleUI.Builders; |
@@ -40,6 +39,8 @@ internal class Program |
40 | 39 | /// <returns>Exit code</returns> |
41 | 40 | static async Task<int> Main(string[] args) |
42 | 41 | { |
| 42 | + if (SharpConsoleUI.PtyShim.RunIfShim(args)) return 127; |
| 43 | + |
43 | 44 | try |
44 | 45 | { |
45 | 46 | // Initialize console window system with modern patterns |
@@ -224,8 +225,8 @@ private static void CreateMainMenuWindow() |
224 | 225 | "[yellow]F6[/] - [bold]Interactive Demo[/]", |
225 | 226 | " Shows modern control interactions", |
226 | 227 | "", |
227 | | - "[cyan]F7[/] - [bold]Command Window[/]", |
228 | | - " Interactive command prompt with async I/O", |
| 228 | + "[cyan]F7[/] - [bold]Terminal (bash)[/]", |
| 229 | + " PTY-backed embedded terminal", |
229 | 230 | "", |
230 | 231 | "[white]F8[/] - [bold]Dropdown Demo[/]", |
231 | 232 | " Country selection with styled dropdowns", |
@@ -285,7 +286,7 @@ private static void SetupMainWindowKeyHandlers() |
285 | 286 | e.Handled = true; |
286 | 287 | break; |
287 | 288 | case ConsoleKey.F7: |
288 | | - _ = CreateCommandWindow(); |
| 289 | + Controls.Terminal().Open(_windowSystem!); |
289 | 290 | e.Handled = true; |
290 | 291 | break; |
291 | 292 | case ConsoleKey.F8: |
@@ -620,243 +621,6 @@ private static List<string> GetSystemInformation() |
620 | 621 | return info; |
621 | 622 | } |
622 | 623 |
|
623 | | - /// <summary> |
624 | | - /// Create command window with interactive command prompt (adapted from CommandWindow.cs) |
625 | | - /// </summary> |
626 | | - private static Task CreateCommandWindow() |
627 | | - { |
628 | | - if (_windowSystem == null) |
629 | | - return Task.CompletedTask; |
630 | | - |
631 | | - var commandWindow = new WindowBuilder(_windowSystem) |
632 | | - .WithTitle("Interactive Command Window") |
633 | | - .WithSize(80, 25) |
634 | | - .AtPosition(2, 2) |
635 | | - .WithColors(SpectreColor.Grey93, SpectreColor.Grey15) |
636 | | - .Build(); |
637 | | - |
638 | | - // Create prompt control for command input |
639 | | - var promptControl = new PromptControl |
640 | | - { |
641 | | - Prompt = "CMD> ", |
642 | | - UnfocusOnEnter = false, |
643 | | - StickyPosition = StickyPosition.Top, |
644 | | - HorizontalAlignment = SharpConsoleUI.Layout.HorizontalAlignment.Stretch |
645 | | - }; |
646 | | - |
647 | | - // Create multiline output control |
648 | | - var outputControl = new MultilineEditControl |
649 | | - { |
650 | | - ViewportHeight = commandWindow.Height - 4, // Leave space for prompt and borders |
651 | | - WrapMode = WrapMode.Wrap, |
652 | | - ReadOnly = true, |
653 | | - }; |
654 | | - |
655 | | - // Add controls to window |
656 | | - commandWindow.AddControl(promptControl); |
657 | | - commandWindow.AddControl(new RuleControl { StickyPosition = StickyPosition.Top }); |
658 | | - commandWindow.AddControl(outputControl); |
659 | | - |
660 | | - // Setup window resize handler |
661 | | - commandWindow.OnResize += (sender, args) => |
662 | | - { |
663 | | - outputControl.ViewportHeight = commandWindow.Height - 4; |
664 | | - }; |
665 | | - |
666 | | - // Add initial welcome message |
667 | | - outputControl.AppendContent( |
668 | | - "Interactive command prompt started. Modern async implementation.\n" |
669 | | - ); |
670 | | - outputControl.AppendContent("Type 'help' for available commands, 'exit' to close.\n"); |
671 | | - |
672 | | - // Setup command execution with modern async patterns |
673 | | - promptControl.Entered += async (sender, command) => |
674 | | - { |
675 | | - try |
676 | | - { |
677 | | - // Display the command in output |
678 | | - outputControl.AppendContent($"\n> {command}\n"); |
679 | | - |
680 | | - // Handle built-in commands first |
681 | | - if (await HandleBuiltInCommand(command.Trim(), outputControl, commandWindow)) |
682 | | - { |
683 | | - promptControl.SetInput(string.Empty); |
684 | | - return; |
685 | | - } |
686 | | - |
687 | | - // Execute external command with proper async handling |
688 | | - await ExecuteExternalCommand(command, outputControl); |
689 | | - |
690 | | - promptControl.SetInput(string.Empty); |
691 | | - } |
692 | | - catch (Exception ex) |
693 | | - { |
694 | | - outputControl.AppendContent($"Error: {ex.Message}\n"); |
695 | | - _windowSystem?.LogService.LogError($"Error executing command: {command}", ex); |
696 | | - } |
697 | | - finally |
698 | | - { |
699 | | - outputControl.GoToEnd(); |
700 | | - } |
701 | | - }; |
702 | | - |
703 | | - // Setup ESC key handler |
704 | | - commandWindow.KeyPressed += (sender, e) => |
705 | | - { |
706 | | - if (e.KeyInfo.Key == ConsoleKey.Escape) |
707 | | - { |
708 | | - _windowSystem?.CloseWindow(commandWindow); |
709 | | - e.Handled = true; |
710 | | - } |
711 | | - }; |
712 | | - |
713 | | - _windowSystem.AddWindow(commandWindow); |
714 | | - _windowSystem?.LogService.LogInfo("Command window created with modern async patterns"); |
715 | | - |
716 | | - return Task.CompletedTask; |
717 | | - } |
718 | | - |
719 | | - /// <summary> |
720 | | - /// Handle built-in commands that don't need external process execution |
721 | | - /// </summary> |
722 | | - private static async Task<bool> HandleBuiltInCommand( |
723 | | - string command, |
724 | | - MultilineEditControl output, |
725 | | - Window window |
726 | | - ) |
727 | | - { |
728 | | - await Task.Delay(10); // Simulate async operation |
729 | | - |
730 | | - switch (command.ToLowerInvariant()) |
731 | | - { |
732 | | - case "help": |
733 | | - output.AppendContent("Built-in commands:\n"); |
734 | | - output.AppendContent(" help - Show this help\n"); |
735 | | - output.AppendContent(" clear - Clear the output\n"); |
736 | | - output.AppendContent(" date - Show current date and time\n"); |
737 | | - output.AppendContent(" version - Show application version\n"); |
738 | | - output.AppendContent(" exit - Close this window\n"); |
739 | | - output.AppendContent(" sysinfo - Show system information\n"); |
740 | | - output.AppendContent( |
741 | | - "\nAll other commands will be executed as external processes.\n" |
742 | | - ); |
743 | | - return true; |
744 | | - |
745 | | - case "clear": |
746 | | - output.SetContent(""); |
747 | | - output.AppendContent( |
748 | | - "Interactive command prompt started. Modern async implementation.\n" |
749 | | - ); |
750 | | - return true; |
751 | | - |
752 | | - case "date": |
753 | | - output.AppendContent($"{DateTime.Now:F}\n"); |
754 | | - return true; |
755 | | - |
756 | | - case "version": |
757 | | - output.AppendContent("Modern SharpConsoleUI Demo v1.0\n"); |
758 | | - output.AppendContent($".NET Version: {Environment.Version}\n"); |
759 | | - return true; |
760 | | - |
761 | | - case "exit": |
762 | | - _windowSystem?.CloseWindow(window); |
763 | | - return true; |
764 | | - |
765 | | - case "sysinfo": |
766 | | - output.AppendContent($"OS: {Environment.OSVersion}\n"); |
767 | | - output.AppendContent($"Machine: {Environment.MachineName}\n"); |
768 | | - output.AppendContent($"User: {Environment.UserName}\n"); |
769 | | - output.AppendContent($"Processors: {Environment.ProcessorCount}\n"); |
770 | | - output.AppendContent( |
771 | | - $"Working Set: {Environment.WorkingSet / (1024 * 1024):N0} MB\n" |
772 | | - ); |
773 | | - return true; |
774 | | - |
775 | | - default: |
776 | | - return false; // Not a built-in command |
777 | | - } |
778 | | - } |
779 | | - |
780 | | - /// <summary> |
781 | | - /// Execute external command using modern async patterns |
782 | | - /// </summary> |
783 | | - private static async Task ExecuteExternalCommand(string command, MultilineEditControl output) |
784 | | - { |
785 | | - try |
786 | | - { |
787 | | - using var process = new System.Diagnostics.Process(); |
788 | | - |
789 | | - // Setup process for cross-platform compatibility |
790 | | - if (Environment.OSVersion.Platform == PlatformID.Win32NT) |
791 | | - { |
792 | | - process.StartInfo.FileName = "cmd.exe"; |
793 | | - process.StartInfo.Arguments = $"/c {command}"; |
794 | | - } |
795 | | - else |
796 | | - { |
797 | | - process.StartInfo.FileName = "/bin/bash"; |
798 | | - process.StartInfo.Arguments = $"-c \"{command}\""; |
799 | | - } |
800 | | - |
801 | | - process.StartInfo.RedirectStandardOutput = true; |
802 | | - process.StartInfo.RedirectStandardError = true; |
803 | | - process.StartInfo.UseShellExecute = false; |
804 | | - process.StartInfo.CreateNoWindow = true; |
805 | | - |
806 | | - // Start process and read output asynchronously |
807 | | - process.Start(); |
808 | | - |
809 | | - // Read both output and error streams concurrently |
810 | | - var outputTask = process.StandardOutput.ReadToEndAsync(); |
811 | | - var errorTask = process.StandardError.ReadToEndAsync(); |
812 | | - |
813 | | - // Wait for process to complete with timeout |
814 | | - var processTask = process.WaitForExitAsync(); |
815 | | - var timeoutTask = Task.Delay(30000); // 30 second timeout |
816 | | - |
817 | | - var completedTask = await Task.WhenAny(processTask, timeoutTask); |
818 | | - |
819 | | - if (completedTask == timeoutTask) |
820 | | - { |
821 | | - process.Kill(); |
822 | | - output.AppendContent("Command timed out after 30 seconds.\n"); |
823 | | - return; |
824 | | - } |
825 | | - |
826 | | - // Get the results |
827 | | - var outputText = await outputTask; |
828 | | - var errorText = await errorTask; |
829 | | - |
830 | | - // Display results |
831 | | - if (!string.IsNullOrEmpty(outputText)) |
832 | | - { |
833 | | - output.AppendContent(outputText); |
834 | | - if (!outputText.EndsWith('\n')) |
835 | | - output.AppendContent("\n"); |
836 | | - } |
837 | | - |
838 | | - if (!string.IsNullOrEmpty(errorText)) |
839 | | - { |
840 | | - output.AppendContent($"Error: {errorText}"); |
841 | | - if (!errorText.EndsWith('\n')) |
842 | | - output.AppendContent("\n"); |
843 | | - } |
844 | | - |
845 | | - if (string.IsNullOrEmpty(outputText) && string.IsNullOrEmpty(errorText)) |
846 | | - { |
847 | | - output.AppendContent($"Command completed with exit code: {process.ExitCode}\n"); |
848 | | - } |
849 | | - } |
850 | | - catch (Exception ex) |
851 | | - { |
852 | | - output.AppendContent($"Failed to execute command: {ex.Message}\n"); |
853 | | - _windowSystem?.LogService.LogError( |
854 | | - $"Failed to execute external command: {command}", |
855 | | - ex |
856 | | - ); |
857 | | - } |
858 | | - } |
859 | | - |
860 | 624 | /// <summary> |
861 | 625 | /// Create dropdown demo window (adapted from DropDownWindow.cs) |
862 | 626 | /// </summary> |
|
0 commit comments