Get output of a command that uses curses
If I try to get the output (stdout) of a python program into a variable I do this:
set zpath (python something.py "$argv")
But if the program spawns a curses interface, it won’t show.
The program displays a curses interface temporarily to select something, it exits the curses before the program ends. It prints something to stdout which is the useful data.
I read that I can I add 2>&1 >/dev/tty
to the end of the command.
That does make the curses interface show but the output is not saved to the variable.
If I print something to test, it just prints it to the shell instead of into the variable.
How can I make the curses interface work, but also the stdout capture work?
I’m specially looking for a simple solution since the redirections to /dev/tty look messy,
and I need to make it work for different shells.
I read that I can I add 2>&1 >/dev/tty to the end of the command.
This redirects stdout to the terminal (and stderr to where stdout originally went – the command substitution buffer).
If that shows the interface, and running it without redirections doesn’t, that means the program uses stdout to display it.
That means, if
It prints something to stdout which is the useful data.
That output will also end up at the terminal.
I’m afraid if the program wants to use a tty on stdout to display its interface and then print the useful output to that same file descriptor, to stdout, then you can’t redirect these two things separately. The shell can’t separate them because they aren’t separate.
What you would have to do is to modify the program so that it displays its interface on one file like /dev/tty, and print the useful output to another, like stdout.
This is also how fzf, which does open an interactive terminal interface and print something to stdout, operates – on unix it opens /dev/tty – see https://github.com/junegunn/fzf/blob/ef67a45702c01ff93e0ea99a51594c8160f66cc1/src/tui/light_unix.go#L50-L63 and https://github.com/junegunn/fzf/blob/b3ab6311c587e18ee202c5205afc658a33f2a23c/src/tui/light.go#L29
Or it could put the display on stdout and print the useful information on stderr – that would make that 2>&1 >/dev/tty
trick work.
Sidenote:
set zpath (python something.py "$argv")
In fish, you most likely do not want to quote that $argv
– if it’s set to multiple arguments you’ve now squashed them together into something nonsensical. It also won’t help with e.g. spaces because fish does not perform word splitting like bash does. Once a variable has been set to X elements expanding it outside of quotes expands it to those X elements without splitting them apart again.