none none
none none

Reputation: 343

Piping the final output of a ratatui rust app while still showing the TUI application

I built a small rust TUI application using the ratatui library. It walks the user through building a sentence and when the app closes and the terminal window is restored it prints the resulting phrase to screen. I would like to be able to pass the resulting phrase to another application (say rev for example) using a pipe, but when i try to do that with my_app | rev it passes the entire program output (including the ratatui sequence of printed screens and the control characters it employs).

This also means that the TUI app will not get rendered, as the output needed for the rendering is instead passed to the pipe.

This is the general anatomy of my program, it roughly follows the ratatui counter app tutorial:

fn main() -> io::Result<()> {
    let mut terminal = ratatui::init();
    let app_result = App::default().run(&mut terminal); // TUI loop
    ratatui::restore();
    println!("{}",app_result); // Only this should be piped
    app_result
}

The line that prints app_result is the only thing i want passed to the next program, the rest should still be rendered on-screen.

How do I pipe only the final output of the program and leave the application able to render its TUI?

Upvotes: 0

Views: 140

Answers (2)

Joshka
Joshka

Reputation: 886

The easiest way to make this work is to render the TUI to stderr instead of stdout (see the backend methods which accept a writer e.g. https://docs.rs/ratatui/latest/ratatui/backend/struct.CrosstermBackend.html#method.new). The second easiest is to write explicitly to the tty device instead of stdin / stdout. E.g. open the /dev/tty file and use that as the writer. (Notably, the Termwiz backend uses the tty by default IIRC).

Upvotes: 0

true equals false
true equals false

Reputation: 793

If you have tmux installed, you can do something like this in bash

mkfifo outputfifo && tmux new-session -x 100 -y 100 -d 'yourprogram; tmux capture-pane -pJ -S- "-E#{e|-:#{cursor_y},1}">outputfifo' && (cat outputfifo; rm outputfifo) | reciever

The idea is to create a virtual terminal. Inside this terminal the program is executed. When the program has ended, everything visible on the virtual terminal up until the line before the cursor will be sent to outside the virtual terminal using a fifo. The fifo will at the same time be read from, and lastly removed.

Note that the previous code will only work if the tui doesn't rely on user input. Otherwise, a temporary file will have to be used instead of a fifo, which will be read from after the program has finished executing:

tmux new-session 'yourprogram; tmux capture-pane -pJ -S- "-E#{e|-:#{cursor_y},1}">output' && (cat output; rm output) | reciever

Upvotes: 1

Related Questions