Exit code 1 and no results when run without `.` path indication in Neovim
Closed this issue · 4 comments
Hi,
I noticed a somewhat weird problem when running sift
in Neovim. Initially I thought it's connected with vim-grepper
so I opened an issue there.
Marco Hinz noticed that running sift
in Neovim doesn't work even without vim-grepper
when there's no search path indication.
Basically: :!sift -n foo
yields shell returned 1
and no results. :!sift -n foo .
works just fine. There is no problem with 'vanilla' Vim.
I tracked the issue to a4bc2b9 - sift
built at this point yields the aforementioned error, e109c32 works ok.
My sift
binaries were built with go version go1.5.1 linux/amd64
(git checkout COMMIT_ID; rm ./sift; go build
).
Neovim relies on libuv for running processes. Due to libuv's asynchronous nature, processes run "in the background" and after exiting their output can be read from a named pipe. And that's the "issue" in this case: https://github.com/svent/sift/blob/master/sift.go#L644-L648
For quick testing put the following into /tmp/test.go
, switch to /tmp
, and execute :!go run test.go
in Vim and Neovim. The output won't be the same.
package main
import (
"fmt"
"os"
"golang.org/x/crypto/ssh/terminal"
)
func main() {
if terminal.IsTerminal(int(os.Stdin.Fd())) {
fmt.Println("terminal")
} else {
fmt.Println("pipe")
}
}
It can't be fixed in Neovim since it's because of libuv. Then again I'm not sure if there's a way to fix this in sift. Maybe people should just explicitly append the .
on their own in this case. For those who don't, the behaviour will be confusing, though.
@mhinz Thanks for the analysis!
While this somehow worked with an earlier version of sift, I still consider the improved terminal detection correct. Unfortunately, I also do not see a simple fix for this and somehow sift works as expected in this scenario.
I would expect that other grep alternatives have similar problems with this - although "terminal detection" is an intricate problem and they might handle it somehow different.
As I do not want to change existing behavior and other uses cases (CLI) are more important I fear this issue will not get solved at the moment.
Okay, I fixed this in the plugin. Here a short summary of how to use Neovim:
:!
and system()
both use pipes. This is a result of Neovim's new client/server architecture where every UI is basically just a plugin that can be attached to an instance. It's a means to get consistent output across all attached UIs.
It prevents using interactive programs, though. E.g. git add -p
. But for those cases there's another new Neovim feature: a real (opposed to what Emacs provides) built in terminal emulator that can be called with :term <optional command>
. :te sift foo
works as expected.
:term
is basically built atop of jobstart()
which my plugin uses. What I didn't know so far, you can simply tell it to allocate a pseudo terminal that the process connects to. Everything's working fine afterwards!
I still consider the improved terminal detection correct
I agree. :)
This issue can be closed.
Thanks for your efforts - great to hear that you found a solution to this problem.