diff --git a/src/Options/Applicative/Builder/Completer.hs b/src/Options/Applicative/Builder/Completer.hs index 5da556e7..14135b28 100644 --- a/src/Options/Applicative/Builder/Completer.hs +++ b/src/Options/Applicative/Builder/Completer.hs @@ -15,7 +15,9 @@ import Prelude import Control.Exception (IOException, try) import Data.List (isPrefixOf) #ifdef MIN_VERSION_process +import Data.List (isSuffixOf) import System.Process (readProcess) +import System.Environment (lookupEnv) #endif import Options.Applicative.Types @@ -40,8 +42,23 @@ bashCompleter :: String -> Completer #ifdef MIN_VERSION_process bashCompleter action = Completer $ \word -> do let cmd = unwords ["compgen", "-A", action, "--", requote word] - result <- tryIO $ readProcess "bash" ["-c", cmd] "" + bash <- getBash + result <- tryIO $ readProcess bash ["-c", cmd] "" return . lines . either (const []) id $ result + +-- | Determines the bash executable. Ideally we'd invoke the same bash that +-- is currently active. If $SHELL does not seem to be set to a bash executable +-- we don't assume $SHELL is bash and we take bash from the $PATH. +-- This fixes file completion in cases where a virtual environment with a +-- non-interactive bash is loaded with direnv, nix-shell or similar. +getBash :: IO String +getBash = do + shellEnv <- lookupEnv "SHELL" + pure (case shellEnv of + Just exe | "/bash" `isSuffixOf` exe -> exe + _ -> "bash" + ) + #else bashCompleter = const $ Completer $ const $ return [] #endif