mirror of
				https://github.com/ArthurSonzogni/FTXUI.git
				synced 2025-10-31 18:48:11 +08:00 
			
		
		
		
	Update doc
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -44,6 +44,7 @@ out/ | |||||||
| !doc/**/*.html | !doc/**/*.html | ||||||
| !doc/**/*.xml | !doc/**/*.xml | ||||||
| !doc/**/*.md | !doc/**/*.md | ||||||
|  | !doc/*.md | ||||||
|  |  | ||||||
| # examples directory: | # examples directory: | ||||||
| !examples/**/*.cpp | !examples/**/*.cpp | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								README.md
									
									
									
									
									
								
							| @@ -378,21 +378,7 @@ Several games using the FTXUI have been made during the Game Jam: | |||||||
| - [smoothlife](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/smoothlife.md) | - [smoothlife](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/smoothlife.md) | ||||||
| - [Consu](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/consu.md) | - [Consu](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/consu.md) | ||||||
|  |  | ||||||
| ## Advanced Usage |  | ||||||
|  |  | ||||||
| ### Piped Input Support |  | ||||||
|  |  | ||||||
| If your application reads from stdin (piped data) and also needs interactive keyboard input: |  | ||||||
|  |  | ||||||
| ```cpp |  | ||||||
| auto screen = ScreenInteractive::Fullscreen(); |  | ||||||
| screen.HandlePipedInput(true);  // Enable before Loop() |  | ||||||
| screen.Loop(component); |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| This allows commands like `cat data.txt | your_app` to work with full keyboard interaction. |  | ||||||
|  |  | ||||||
| **Note:** This feature is only available on POSIX systems (Linux/macOS). On Windows, the method call is a no-op. |  | ||||||
|  |  | ||||||
| ## Build using CMake | ## Build using CMake | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										55
									
								
								doc/posix_pipe.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								doc/posix_pipe.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | # POSIX Piped Input in FTXUI | ||||||
|  |  | ||||||
|  | ## What is a POSIX Pipe? | ||||||
|  |  | ||||||
|  | A POSIX pipe is a way for two separate programs to communicate. One program sends its output directly as input to another program. Think of it like a one-way tube for data. | ||||||
|  |  | ||||||
|  | **Example:** | ||||||
|  |  | ||||||
|  | Imagine you want to list files and then filter them interactively. | ||||||
|  |  | ||||||
|  | - `ls`: Lists files. | ||||||
|  | - `interactive_grep`: An FTXUI application that filters text and lets you type. | ||||||
|  |  | ||||||
|  | You can connect them with a pipe (`|`): | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | ls -l | interactive_grep | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Here's what happens: | ||||||
|  | 1. `ls -l` lists files with details. | ||||||
|  | 2. The `|` sends this list directly to `interactive_grep`. | ||||||
|  | 3. `interactive_grep` receives the list and displays it. Because it's an FTXUI app, you can then type to filter the list, even though it received initial data from `ls`. | ||||||
|  |  | ||||||
|  | ## How FTXUI Handles Piped Input | ||||||
|  |  | ||||||
|  | Now that you understand what a POSIX pipe is, let's look at how FTXUI uses them. | ||||||
|  |  | ||||||
|  | FTXUI lets your application read data from other programs (like from a pipe) while still allowing you to use your keyboard for interaction. This is useful for interactive command-line tools that process data. | ||||||
|  |  | ||||||
|  | Normally, FTXUI applications receive all input from `stdin`. However, when FTXUI detects that `stdin` is connected to the output of a pipe (meaning data is being piped into your application), it automatically switches to reading interactive keyboard input from `/dev/tty`. This ensures that your application can still receive user input even while processing piped data. | ||||||
|  |  | ||||||
|  | This feature is **turned on by default**. | ||||||
|  |  | ||||||
|  | If your FTXUI application needs to read piped data and also respond to keyboard input, you typically don't need to do anything special: | ||||||
|  |  | ||||||
|  | ```cpp | ||||||
|  | auto screen = ScreenInteractive::Fullscreen(); | ||||||
|  | // screen.HandlePipedInput(true); // This is enabled by default | ||||||
|  | screen.Loop(component); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | **Note:** This feature works only on Linux and macOS. It does nothing on Windows. | ||||||
|  |  | ||||||
|  | ## Turning Off Piped Input | ||||||
|  |  | ||||||
|  | If you don't need this feature, or if it conflicts with your custom input handling, you can turn it off. | ||||||
|  |  | ||||||
|  | To disable it, call `HandlePipedInput(false)` before starting your application's main loop: | ||||||
|  |  | ||||||
|  | ```cpp | ||||||
|  | auto screen = ScreenInteractive::Fullscreen(); | ||||||
|  | screen.HandlePipedInput(false); // Turn off piped input handling | ||||||
|  | screen.Loop(component); | ||||||
|  | ``` | ||||||
| @@ -144,7 +144,7 @@ class ScreenInteractive : public Screen { | |||||||
|  |  | ||||||
| #if !defined(_WIN32) && !defined(__EMSCRIPTEN__) | #if !defined(_WIN32) && !defined(__EMSCRIPTEN__) | ||||||
|   // Piped input handling state (POSIX only) |   // Piped input handling state (POSIX only) | ||||||
|   bool handle_piped_input_ = false; |   bool handle_piped_input_ = true; | ||||||
|   bool stdin_was_redirected_ = false; |   bool stdin_was_redirected_ = false; | ||||||
|   int original_stdin_fd_ = -1; |   int original_stdin_fd_ = -1; | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -376,9 +376,9 @@ void ScreenInteractive::TrackMouse(bool enable) { | |||||||
| /// When enabled, FTXUI will detect piped input and redirect stdin to /dev/tty | /// When enabled, FTXUI will detect piped input and redirect stdin to /dev/tty | ||||||
| /// for keyboard input, allowing applications to read piped data while still | /// for keyboard input, allowing applications to read piped data while still | ||||||
| /// receiving interactive keyboard events. | /// receiving interactive keyboard events. | ||||||
| /// @param enable Whether to enable piped input handling | /// @param enable Whether to enable piped input handling. Default is true. | ||||||
| /// @note This must be called before Loop(). | /// @note This must be called before Loop(). | ||||||
| /// @note This feature is disabled by default for backward compatibility. | /// @note This feature is enabled by default. | ||||||
| /// @note This feature is only available on POSIX systems (Linux/macOS). | /// @note This feature is only available on POSIX systems (Linux/macOS). | ||||||
| #if !defined(_WIN32) && !defined(__EMSCRIPTEN__) | #if !defined(_WIN32) && !defined(__EMSCRIPTEN__) | ||||||
| void ScreenInteractive::HandlePipedInput(bool enable) { | void ScreenInteractive::HandlePipedInput(bool enable) { | ||||||
|   | |||||||
| @@ -63,19 +63,23 @@ class PipedInputTest : public ::testing::Test { | |||||||
|   bool piped_stdin_setup_ = false; |   bool piped_stdin_setup_ = false; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| TEST_F(PipedInputTest, DefaultBehaviorNoChange) { | TEST_F(PipedInputTest, DefaultBehaviorEnabled) { | ||||||
|   // Test that HandlePipedInput is disabled by default |   // Test that HandlePipedInput is enabled by default | ||||||
|  |   if (!IsTtyAvailable()) { | ||||||
|  |     GTEST_SKIP() << "/dev/tty not available in this environment"; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   auto screen = ScreenInteractive::TerminalOutput(); |   auto screen = ScreenInteractive::TerminalOutput(); | ||||||
|   auto component = Renderer([] { return text("test"); }); |   auto component = Renderer([] { return text("test"); }); | ||||||
|  |  | ||||||
|   SetupPipedStdin(); |   SetupPipedStdin(); | ||||||
|   WriteToPipedStdin("test data\n"); |   WriteToPipedStdin("test data\n"); | ||||||
|  |  | ||||||
|   // Install should not redirect stdin since HandlePipedInput not called |   // Install should redirect stdin since HandlePipedInput is on by default | ||||||
|   screen.Install(); |   screen.Install(); | ||||||
|  |  | ||||||
|   // Stdin should still be the pipe (isatty should return false) |   // Stdin should be the tty | ||||||
|   EXPECT_FALSE(isatty(STDIN_FILENO)); |   EXPECT_TRUE(isatty(STDIN_FILENO)); | ||||||
|  |  | ||||||
|   screen.Uninstall(); |   screen.Uninstall(); | ||||||
| } | } | ||||||
| @@ -97,7 +101,7 @@ TEST_F(PipedInputTest, ExplicitlyDisabled) { | |||||||
|   screen.Uninstall(); |   screen.Uninstall(); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_F(PipedInputTest, PipedInputDetectionAndRedirection) { | TEST_F(PipedInputTest, ExplicitlyEnabled) { | ||||||
|   if (!IsTtyAvailable()) { |   if (!IsTtyAvailable()) { | ||||||
|     GTEST_SKIP() << "/dev/tty not available in this environment"; |     GTEST_SKIP() << "/dev/tty not available in this environment"; | ||||||
|   } |   } | ||||||
| @@ -127,7 +131,6 @@ TEST_F(PipedInputTest, PipedInputDetectionAndRedirection) { | |||||||
| TEST_F(PipedInputTest, NormalStdinUnchanged) { | TEST_F(PipedInputTest, NormalStdinUnchanged) { | ||||||
|   // Test that normal stdin (not piped) is not affected |   // Test that normal stdin (not piped) is not affected | ||||||
|   auto screen = ScreenInteractive::TerminalOutput(); |   auto screen = ScreenInteractive::TerminalOutput(); | ||||||
|   screen.HandlePipedInput(true); |  | ||||||
|   auto component = Renderer([] { return text("test"); }); |   auto component = Renderer([] { return text("test"); }); | ||||||
|  |  | ||||||
|   // Don't setup piped stdin - use normal stdin |   // Don't setup piped stdin - use normal stdin | ||||||
| @@ -150,7 +153,6 @@ TEST_F(PipedInputTest, MultipleInstallUninstallCycles) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   auto screen = ScreenInteractive::TerminalOutput(); |   auto screen = ScreenInteractive::TerminalOutput(); | ||||||
|   screen.HandlePipedInput(true); |  | ||||||
|   auto component = Renderer([] { return text("test"); }); |   auto component = Renderer([] { return text("test"); }); | ||||||
|  |  | ||||||
|   SetupPipedStdin(); |   SetupPipedStdin(); | ||||||
| @@ -192,7 +194,6 @@ TEST_F(PipedInputTest, HandlePipedInputMethodBehavior) { | |||||||
| // This test simulates environments like containers where /dev/tty might not exist | // This test simulates environments like containers where /dev/tty might not exist | ||||||
| TEST_F(PipedInputTest, GracefulFallbackWhenTtyUnavailable) { | TEST_F(PipedInputTest, GracefulFallbackWhenTtyUnavailable) { | ||||||
|   auto screen = ScreenInteractive::TerminalOutput(); |   auto screen = ScreenInteractive::TerminalOutput(); | ||||||
|   screen.HandlePipedInput(true); |  | ||||||
|   auto component = Renderer([] { return text("test"); }); |   auto component = Renderer([] { return text("test"); }); | ||||||
|  |  | ||||||
|   SetupPipedStdin(); |   SetupPipedStdin(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 ArthurSonzogni
					ArthurSonzogni