selecta icon indicating copy to clipboard operation
selecta copied to clipboard

fish-shell: selecta doesn't work in subshell

Open timbertson opened this issue 10 years ago • 12 comments

I haven't dug into this too hard yet, I will probably try and get strace on it if nobody knows why this isn't working:

$ echo -e '1\n2\n3' | selecta
# ui appears; I select "2"
2

$ set -x RESULT (echo -e '1\n2\n3' | selecta)
# nothing happens; next prompt immediately shown

# just to show that this is how you normally set something from a subshell in fish:
$ set -x RESULT (echo -e '1\n2\n3')
$ echo $RESULT
1 2 3

I'm guessing it's failing to get /dev/tty from within the subshell for some reason?

timbertson avatar Oct 08 '15 22:10 timbertson

That seems like a reasonable guess, though Selecta should print an error to stderr if it can't get a TTY.

garybernhardt avatar Oct 08 '15 23:10 garybernhardt

Actually, here's the problem:

gsj@the-brick ~> set -x RESULT (cat .zshrc | hs)
gsj@the-brick ~> jobs
Job Group   State   Command
2   74396   stopped cat .zshrc | hs

rschmitt avatar Oct 09 '15 00:10 rschmitt

No no no, HERE's the problem:

In fish, (foo) means $(foo) or foo.

Fish doesn't even have subshells, according to a quick google search. Mystery solved!

rschmitt avatar Oct 09 '15 00:10 rschmitt

I believe it's not the same as a bash subshell, but it's still a sub-pipeline:

$ set x (echo -e '1\n2\n3' | grep 2)
$ echo $x
2

Whatever you want to call it, I don't see why selecta shouldn't work in place of grep.

I think your jobs thought is much more likely to be the culprit. Not sure how that happens, though.

timbertson avatar Oct 09 '15 03:10 timbertson

Or, maybe I just shouldn't have called it a "subshell" in the issue - it's equivalent to $(...) in bash, in which selecta works fine.

timbertson avatar Oct 09 '15 03:10 timbertson

My best guess is that selecta somehow starts up in a background process group, and it receives SIGTTIN or SIGTTOU when it tries to access the terminal.

rschmitt avatar Oct 09 '15 04:10 rschmitt

OK, I've straced it which may help a little. Doing a diff, it looks like it's to do with the stty process - but maybe that was already obvious.

Here are the strace logs from a subpipeline (inside brackets) vs a top-level pipeline (which works). Both are just from the execv on stty onwards:

https://gist.github.com/gfxmonk/57c7e37d61baf0c48c86

Looks a lot like stty just doesn't do anything, but I have no idea how it works, or why it might decide not to do its thing...

timbertson avatar Oct 09 '15 11:10 timbertson

That gist seems to have disappeared, @timbertson. However, it seems like stty must do something in fish; otherwise most tools with complex UIs would break. I haven't used fish myself and don't want to dive into a whole new shell to diagnose this, but I'm happy to provide a bit of support if someone else wants to look deeper.

garybernhardt avatar Feb 07 '16 22:02 garybernhardt

Apologies, looks like it moved to https://gist.github.com/timbertson/57c7e37d61baf0c48c86 when I renamed myself on github (gists don't redirect)

timbertson avatar Feb 08 '16 02:02 timbertson

stty must do something in fish; otherwise most tools with complex UIs would break

I suspect that tools which (a) have complex terminal UIs and (b) are used inside a shell pipeline are rare - I can't think of any others aside from selecta that I'd use.

Maybe I'll ping the fish mailing list and see if anyone knows of ways in which sub-commands differ from top-level commands in terms of interacting with the TTY.

timbertson avatar Feb 08 '16 02:02 timbertson

I did a bit of googling and, as it turns out, fish just ignores stty entirely. stty is certainly a mess of legacy badness, but that seems a bit strong! See this thread where ridiculousfish says that stty "doesn't do anything in fish". There's been no resolution there, so I guess it's still an open problem.

I assume that other interactive tools (vim, emacs, etc.) work properly because they use the underlying C functions, rather than stty.

garybernhardt avatar Feb 08 '16 20:02 garybernhardt

I happened to come across this again today with another program, and since I understand it more now, I thought I'd summarize here:

As mentioned in https://github.com/fish-shell/fish-shell/issues/1949, fish runs process substitutions in a background process group, which does cause selecta to receive SIGTTOU when it tries to control the terminal (fish isn't lying - fd 0 is a tty, you're just not allowed to mess with it). It's no fault of stty, using the underlying system calls has the same issue.

A workaround is to run selecta more awkwardly so that it's a foreground process - e.g:

echo -e '1\n2\n3' | selecta | read --local result; echo "You picked: $result"

This might be a bit more robust if selecta supported null-terminating its result - then you could read --null which would not be confused by whitespace.

Also, it would be great if selecta could handle SIGTTOU and quit with a relevant message about not being able to modify the TTY. That way the error would become much more google-able instead of the process being mysteriously suspended :)

timbertson avatar Nov 13 '16 12:11 timbertson