Skip to content

Commit

Permalink
Bash completion for targets, flags, exec cmds #1343
Browse files Browse the repository at this point in the history
  • Loading branch information
mgsloan committed Mar 22, 2017
1 parent e35653b commit ae233be
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 28 deletions.
3 changes: 2 additions & 1 deletion ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ Other enhancements:
See [#3063](https://github.com/commercialhaskell/stack/issues/3063)
* Can now use relative paths for `extra-include-dirs` and `extra-lib-dirs`.
See [#2830](https://github.com/commercialhaskell/stack/issues/2830)
* Improved bash completion for many options, including `--ghc-options`.
* Improved bash completion for many options, including `--ghc-options`,
--flag`, targets, and project executables for `exec`.

Bug fixes:

Expand Down
23 changes: 4 additions & 19 deletions src/Stack/Options/BuildParser.hs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}

module Stack.Options.BuildParser where

import Data.Char (isSpace)
import Data.List (isPrefixOf)
import qualified Data.Map as Map
import Data.Monoid.Extra
import Data.Text (Text)
Expand All @@ -13,12 +10,11 @@ import Options.Applicative
import Options.Applicative.Args
import Options.Applicative.Builder.Extra
import Paths_stack as Meta
import Stack.Options.Completion
import Stack.Options.PackageParser (readFlag)
import Stack.Types.Config
import Stack.Types.FlagName
import Stack.Types.PackageName
import System.Process (readProcess)
import Language.Haskell.TH.Syntax (runIO, lift)

-- | Parser for CLI-only build arguments
buildOptsParser :: BuildCommand
Expand All @@ -45,7 +41,7 @@ buildOptsParser cmd =
(textOption
(long "ghc-options" <>
metavar "OPTIONS" <>
completer ghcCompleter <>
completer ghcOptsCompleter <>
help "Additional options passed to GHC"))) <*>
flagsParser <*>
(flag'
Expand Down Expand Up @@ -93,6 +89,7 @@ targetsParser =
many
(textArgument
(metavar "TARGET" <>
completer targetCompleter <>
help ("If none specified, use all local packages. " <>
"See https://docs.haskellstack.org/en/v" <>
showVersion Meta.version <>
Expand All @@ -105,20 +102,8 @@ flagsParser =
(option
readFlag
(long "flag" <>
completer flagCompleter <>
metavar "PACKAGE:[-]FLAG" <>
help
("Override flags set in stack.yaml " <>
"(applies to local packages and extra-deps)")))

ghcCompleter :: Completer
ghcCompleter = mkCompleter $ \inputRaw -> return $
let input = unescapeBashArg inputRaw
(curArgReversed, otherArgsReversed) = break isSpace (reverse input)
curArg = reverse curArgReversed
otherArgs = reverse otherArgsReversed
in if null curArg then [] else
map (otherArgs ++) $
filter (curArg `isPrefixOf`)
-- Technically, we should be consulting the user's current ghc,
-- but that would require loading up a BuildConfig.
$(runIO (readProcess "ghc" ["--show-options"] "") >>= lift . lines)
6 changes: 3 additions & 3 deletions src/Stack/Options/ExecParser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Data.Monoid.Extra
import Options.Applicative
import Options.Applicative.Builder.Extra
import Options.Applicative.Args
import Stack.Options.Completion
import Stack.Types.Config

-- | Parser for exec command
Expand All @@ -14,7 +15,7 @@ execOptsParser mcmd =
<*> eoArgsParser
<*> execOptsExtraParser
where
eoCmdParser = ExecCmd <$> strArgument (metavar "CMD")
eoCmdParser = ExecCmd <$> strArgument (metavar "CMD" <> completer projectExeCompleter)
eoArgsParser = many (strArgument (metavar "-- ARGS (e.g. stack ghc -- X.hs -o x)"))

evalOptsParser :: String -- ^ metavar
Expand Down Expand Up @@ -52,7 +53,7 @@ execOptsExtraParser = eoPlainParser <|>
eoPackagesParser = many (strOption (long "package" <> help "Additional packages that must be installed"))

eoRtsOptionsParser :: Parser [String]
eoRtsOptionsParser = concat <$> many (argsOption
eoRtsOptionsParser = concat <$> many (argsOption
( long "rts-options"
<> help "Explicit RTS options to pass to application"
<> metavar "RTSFLAG"))
Expand All @@ -61,4 +62,3 @@ execOptsExtraParser = eoPlainParser <|>
eoPlainParser = flag' ExecOptsPlain
(long "plain" <>
help "Use an unmodified environment (only useful with Docker)")

10 changes: 6 additions & 4 deletions src/Stack/Options/GhciParser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,30 @@ import Options.Applicative.Builder.Extra
import Paths_stack as Meta
import Stack.Config (packagesParser)
import Stack.Ghci (GhciOpts (..))
import Stack.Options.BuildParser (flagsParser, ghcCompleter)
import Stack.Options.BuildParser (flagsParser)
import Stack.Options.Completion

-- | Parser for GHCI options
ghciOptsParser :: Parser GhciOpts
ghciOptsParser = GhciOpts
<$> many
(textArgument
(metavar "TARGET/FILE" <>
completer (fileExtCompleter [".hs", ".lhs"]) <>
completer (targetCompleter <> fileExtCompleter [".hs", ".lhs"]) <>
help ("If none specified, use all local packages. " <>
"See https://docs.haskellstack.org/en/v" <>
showVersion Meta.version <>
"/build_command/#target-syntax for details. " <>
"If a path to a .hs or .lhs file is specified, it will be loaded.")))
<*> fmap concat (many (argsOption (long "ghci-options" <>
metavar "OPTIONS" <>
completer ghcCompleter <>
completer ghcOptsCompleter <>
help "Additional options passed to GHCi")))
<*> many
(textOption
(long "ghc-options" <>
metavar "OPTIONS" <>
completer ghcCompleter <>
completer ghcOptsCompleter <>
help "Additional options passed to both GHC and GHCi"))
<*> flagsParser
<*> optional
Expand All @@ -43,6 +44,7 @@ ghciOptsParser = GhciOpts
(textOption
(long "main-is" <>
metavar "TARGET" <>
completer targetCompleter <>
help "Specify which target should contain the main \
\module to load, such as for an executable for \
\test suite or benchmark."))
Expand Down
4 changes: 3 additions & 1 deletion src/Stack/Options/HpcReportParser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import Options.Applicative
import Options.Applicative.Builder.Extra
import Options.Applicative.Types (readerAsk)
import Stack.Coverage (HpcReportOpts (..))
import Stack.Options.Completion (targetCompleter)
import Stack.Types.Config

-- | Parser for @stack hpc report@.
hpcReportOptsParser :: Parser HpcReportOpts
hpcReportOptsParser = HpcReportOpts
<$> many (textArgument $ metavar "TARGET_OR_TIX")
<$> many (textArgument $ metavar "TARGET_OR_TIX" <>
completer (targetCompleter <> fileExtCompleter [".tix"]))
<*> switch (long "all" <> help "Use results from all packages and components involved in previous --coverage run")
<*> optional (strOption (long "destdir" <>
metavar "DIR" <>
Expand Down
1 change: 1 addition & 0 deletions stack.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ library
Stack.Options.BuildParser
Stack.Options.CleanParser
Stack.Options.ConfigParser
Stack.Options.Completion
Stack.Options.DockerParser
Stack.Options.DotParser
Stack.Options.ExecParser
Expand Down

0 comments on commit ae233be

Please # to comment.