-- | You don't need to import this module to enable bash completion.
--
-- See
-- <http://github.com/pcapriotti/optparse-applicative/wiki/Bash-Completion the wiki>
-- for more information on bash completion.
module Options.Applicative.BashCompletion
  ( bashCompletionParser,

    bashCompletionScript,
    fishCompletionScript,
    zshCompletionScript,
  ) where

import Control.Applicative
import Prelude
import Data.Foldable ( asum )
import Data.List ( isPrefixOf )
import Data.Maybe ( fromMaybe, listToMaybe )

import Options.Applicative.Builder
import Options.Applicative.Common
import Options.Applicative.Internal
import Options.Applicative.Types
import Options.Applicative.Help.Pretty
import Options.Applicative.Help.Chunk

-- | Provide basic or rich command completions
data Richness
  = Standard
  -- ^ Add no help descriptions to the completions
  | Enriched Int Int
  -- ^ Include tab separated description for options
  --   and commands when available.
  --   Takes option description length and command
  --   description length.
  deriving (Richness -> Richness -> Bool
(Richness -> Richness -> Bool)
-> (Richness -> Richness -> Bool) -> Eq Richness
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Richness -> Richness -> Bool
== :: Richness -> Richness -> Bool
$c/= :: Richness -> Richness -> Bool
/= :: Richness -> Richness -> Bool
Eq, Eq Richness
Eq Richness =>
(Richness -> Richness -> Ordering)
-> (Richness -> Richness -> Bool)
-> (Richness -> Richness -> Bool)
-> (Richness -> Richness -> Bool)
-> (Richness -> Richness -> Bool)
-> (Richness -> Richness -> Richness)
-> (Richness -> Richness -> Richness)
-> Ord Richness
Richness -> Richness -> Bool
Richness -> Richness -> Ordering
Richness -> Richness -> Richness
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Richness -> Richness -> Ordering
compare :: Richness -> Richness -> Ordering
$c< :: Richness -> Richness -> Bool
< :: Richness -> Richness -> Bool
$c<= :: Richness -> Richness -> Bool
<= :: Richness -> Richness -> Bool
$c> :: Richness -> Richness -> Bool
> :: Richness -> Richness -> Bool
$c>= :: Richness -> Richness -> Bool
>= :: Richness -> Richness -> Bool
$cmax :: Richness -> Richness -> Richness
max :: Richness -> Richness -> Richness
$cmin :: Richness -> Richness -> Richness
min :: Richness -> Richness -> Richness
Ord, Int -> Richness -> ShowS
[Richness] -> ShowS
Richness -> String
(Int -> Richness -> ShowS)
-> (Richness -> String) -> ([Richness] -> ShowS) -> Show Richness
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Richness -> ShowS
showsPrec :: Int -> Richness -> ShowS
$cshow :: Richness -> String
show :: Richness -> String
$cshowList :: [Richness] -> ShowS
showList :: [Richness] -> ShowS
Show)

bashCompletionParser :: ParserInfo a -> ParserPrefs -> Parser CompletionResult
bashCompletionParser :: forall a. ParserInfo a -> ParserPrefs -> Parser CompletionResult
bashCompletionParser ParserInfo a
pinfo ParserPrefs
pprefs = Parser CompletionResult
complParser
  where
    returnCompletions :: (String -> IO [String]) -> CompletionResult
returnCompletions String -> IO [String]
opts =
      (String -> IO String) -> CompletionResult
CompletionResult ((String -> IO String) -> CompletionResult)
-> (String -> IO String) -> CompletionResult
forall a b. (a -> b) -> a -> b
$
        \String
progn -> [String] -> String
unlines ([String] -> String) -> IO [String] -> IO String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO [String]
opts String
progn

    scriptRequest :: ShowS -> CompletionResult
scriptRequest =
      (String -> IO String) -> CompletionResult
CompletionResult ((String -> IO String) -> CompletionResult)
-> (ShowS -> String -> IO String) -> ShowS -> CompletionResult
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> IO String) -> ShowS -> String -> IO String
forall a b. (a -> b) -> (String -> a) -> String -> b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> IO String
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure

    complParser :: Parser CompletionResult
complParser = [Parser CompletionResult] -> Parser CompletionResult
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum
      [ (String -> IO [String]) -> CompletionResult
returnCompletions ((String -> IO [String]) -> CompletionResult)
-> Parser (String -> IO [String]) -> Parser CompletionResult
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
        (  ParserInfo a
-> ParserPrefs
-> Richness
-> [String]
-> Int
-> String
-> IO [String]
forall a.
ParserInfo a
-> ParserPrefs
-> Richness
-> [String]
-> Int
-> String
-> IO [String]
bashCompletionQuery ParserInfo a
pinfo ParserPrefs
pprefs
        -- To get rich completions, one just needs the first
        -- command. To customise the lengths, use either of
        -- the `desc-length` options.
        -- zsh commands can go on a single line, so they might
        -- want to be longer.
        (Richness -> [String] -> Int -> String -> IO [String])
-> Parser Richness
-> Parser ([String] -> Int -> String -> IO [String])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ( (Int -> Int -> Richness)
-> Mod FlagFields (Int -> Int -> Richness)
-> Parser (Int -> Int -> Richness)
forall a. a -> Mod FlagFields a -> Parser a
flag' Int -> Int -> Richness
Enriched (String -> Mod FlagFields (Int -> Int -> Richness)
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"bash-completion-enriched" Mod FlagFields (Int -> Int -> Richness)
-> Mod FlagFields (Int -> Int -> Richness)
-> Mod FlagFields (Int -> Int -> Richness)
forall a. Monoid a => a -> a -> a
`mappend` Mod FlagFields (Int -> Int -> Richness)
forall (f :: * -> *) a. Mod f a
internal)
                Parser (Int -> Int -> Richness)
-> Parser Int -> Parser (Int -> Richness)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM Int -> Mod OptionFields Int -> Parser Int
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM Int
forall a. Read a => ReadM a
auto (String -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"bash-completion-option-desc-length" Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Monoid a => a -> a -> a
`mappend` Mod OptionFields Int
forall (f :: * -> *) a. Mod f a
internal Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Monoid a => a -> a -> a
`mappend` Int -> Mod OptionFields Int
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value Int
40)
                Parser (Int -> Richness) -> Parser Int -> Parser Richness
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM Int -> Mod OptionFields Int -> Parser Int
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM Int
forall a. Read a => ReadM a
auto (String -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"bash-completion-command-desc-length" Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Monoid a => a -> a -> a
`mappend` Mod OptionFields Int
forall (f :: * -> *) a. Mod f a
internal Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Monoid a => a -> a -> a
`mappend` Int -> Mod OptionFields Int
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value Int
40)
          Parser Richness -> Parser Richness -> Parser Richness
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Richness -> Parser Richness
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Richness
Standard
          )
        Parser ([String] -> Int -> String -> IO [String])
-> Parser [String] -> Parser (Int -> String -> IO [String])
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Parser String -> Parser [String]
forall a. Parser a -> Parser [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (Parser String -> Parser [String])
-> (Mod OptionFields String -> Parser String)
-> Mod OptionFields String
-> Parser [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption) (String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"bash-completion-word"
                                  Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Monoid a => a -> a -> a
`mappend` Mod OptionFields String
forall (f :: * -> *) a. Mod f a
internal)
        Parser (Int -> String -> IO [String])
-> Parser Int -> Parser (String -> IO [String])
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM Int -> Mod OptionFields Int -> Parser Int
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM Int
forall a. Read a => ReadM a
auto (String -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"bash-completion-index" Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Monoid a => a -> a -> a
`mappend` Mod OptionFields Int
forall (f :: * -> *) a. Mod f a
internal) )

      , ShowS -> CompletionResult
scriptRequest (ShowS -> CompletionResult)
-> (String -> ShowS) -> String -> CompletionResult
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
bashCompletionScript (String -> CompletionResult)
-> Parser String -> Parser CompletionResult
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
            Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption (String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"bash-completion-script" Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Monoid a => a -> a -> a
`mappend` Mod OptionFields String
forall (f :: * -> *) a. Mod f a
internal)
      , ShowS -> CompletionResult
scriptRequest (ShowS -> CompletionResult)
-> (String -> ShowS) -> String -> CompletionResult
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
fishCompletionScript (String -> CompletionResult)
-> Parser String -> Parser CompletionResult
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
            Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption (String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"fish-completion-script" Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Monoid a => a -> a -> a
`mappend` Mod OptionFields String
forall (f :: * -> *) a. Mod f a
internal)
      , ShowS -> CompletionResult
scriptRequest (ShowS -> CompletionResult)
-> (String -> ShowS) -> String -> CompletionResult
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
zshCompletionScript (String -> CompletionResult)
-> Parser String -> Parser CompletionResult
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
            Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption (String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"zsh-completion-script" Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Monoid a => a -> a -> a
`mappend` Mod OptionFields String
forall (f :: * -> *) a. Mod f a
internal)
      ]

bashCompletionQuery :: ParserInfo a -> ParserPrefs -> Richness -> [String] -> Int -> String -> IO [String]
bashCompletionQuery :: forall a.
ParserInfo a
-> ParserPrefs
-> Richness
-> [String]
-> Int
-> String
-> IO [String]
bashCompletionQuery ParserInfo a
pinfo ParserPrefs
pprefs Richness
richness [String]
ws Int
i String
_ = case Completion a
-> ParserPrefs -> Maybe (Either (SomeParser, ArgPolicy) Completer)
forall r.
Completion r
-> ParserPrefs -> Maybe (Either (SomeParser, ArgPolicy) Completer)
runCompletion Completion a
compl ParserPrefs
pprefs of
  Just (Left (SomeParser Parser a
p, ArgPolicy
a))
    -> ArgPolicy -> Parser a -> IO [String]
forall {a}. ArgPolicy -> Parser a -> IO [String]
list_options ArgPolicy
a Parser a
p
  Just (Right Completer
c)
    -> Completer -> IO [String]
run_completer Completer
c
  Maybe (Either (SomeParser, ArgPolicy) Completer)
Nothing
    -> [String] -> IO [String]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return []
  where
    compl :: Completion a
compl = ParserInfo a -> [String] -> Completion a
forall (m :: * -> *) a. MonadP m => ParserInfo a -> [String] -> m a
runParserInfo ParserInfo a
pinfo (Int -> [String] -> [String]
forall a. Int -> [a] -> [a]
drop Int
1 [String]
ws')

    list_options :: ArgPolicy -> Parser a -> IO [String]
list_options ArgPolicy
a
      = ([[String]] -> [String]) -> IO [[String]] -> IO [String]
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
      (IO [[String]] -> IO [String])
-> (Parser a -> IO [[String]]) -> Parser a -> IO [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [IO [String]] -> IO [[String]]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence
      ([IO [String]] -> IO [[String]])
-> (Parser a -> [IO [String]]) -> Parser a -> IO [[String]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall x. ArgumentReachability -> Option x -> IO [String])
-> Parser a -> [IO [String]]
forall b a.
(forall x. ArgumentReachability -> Option x -> b)
-> Parser a -> [b]
mapParser (ArgPolicy -> ArgumentReachability -> Option x -> IO [String]
forall {a}.
ArgPolicy -> ArgumentReachability -> Option a -> IO [String]
opt_completions ArgPolicy
a)

    --
    -- Prior to 0.14 there was a subtle bug which would
    -- mean that completions from positional arguments
    -- further into the parse would be shown.
    --
    -- We therefore now check to see that
    -- hinfoUnreachableArgs is off before running the
    -- completion for position arguments.
    --
    -- For options and flags, ensure that the user
    -- hasn't disabled them with `--`.
    opt_completions :: ArgPolicy -> ArgumentReachability -> Option a -> IO [String]
opt_completions ArgPolicy
argPolicy ArgumentReachability
reachability Option a
opt = case Option a -> OptReader a
forall a. Option a -> OptReader a
optMain Option a
opt of
      OptReader [OptName]
ns CReader a
_ String -> ParseError
_
         | ArgPolicy
argPolicy ArgPolicy -> ArgPolicy -> Bool
forall a. Eq a => a -> a -> Bool
/= ArgPolicy
AllPositionals
        -> [String] -> IO [String]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([String] -> IO [String])
-> ([String] -> [String]) -> [String] -> IO [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Option a -> [String] -> [String]
forall (f :: * -> *) a.
Functor f =>
Option a -> f String -> f String
add_opt_help Option a
opt ([String] -> IO [String]) -> [String] -> IO [String]
forall a b. (a -> b) -> a -> b
$ [OptName] -> [String]
show_names [OptName]
ns
         | Bool
otherwise
        -> [String] -> IO [String]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return []
      FlagReader [OptName]
ns a
_
         | ArgPolicy
argPolicy ArgPolicy -> ArgPolicy -> Bool
forall a. Eq a => a -> a -> Bool
/= ArgPolicy
AllPositionals
        -> [String] -> IO [String]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([String] -> IO [String])
-> ([String] -> [String]) -> [String] -> IO [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Option a -> [String] -> [String]
forall (f :: * -> *) a.
Functor f =>
Option a -> f String -> f String
add_opt_help Option a
opt ([String] -> IO [String]) -> [String] -> IO [String]
forall a b. (a -> b) -> a -> b
$ [OptName] -> [String]
show_names [OptName]
ns
         | Bool
otherwise
        -> [String] -> IO [String]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return []
      ArgReader CReader a
rdr
         | ArgumentReachability -> Bool
argumentIsUnreachable ArgumentReachability
reachability
        -> [String] -> IO [String]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return []
         | Bool
otherwise
        -> Completer -> IO [String]
run_completer (CReader a -> Completer
forall a. CReader a -> Completer
crCompleter CReader a
rdr)
      CmdReader Maybe String
_ [(String, ParserInfo a)]
ns
         | ArgumentReachability -> Bool
argumentIsUnreachable ArgumentReachability
reachability
        -> [String] -> IO [String]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return []
         | Bool
otherwise
        -> [String] -> IO [String]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([String] -> IO [String])
-> ([(String, ParserInfo a)] -> [String])
-> [(String, ParserInfo a)]
-> IO [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(String, ParserInfo a)] -> [String]
forall (f :: * -> *) a.
Functor f =>
f (String, ParserInfo a) -> f String
with_cmd_help ([(String, ParserInfo a)] -> IO [String])
-> [(String, ParserInfo a)] -> IO [String]
forall a b. (a -> b) -> a -> b
$ ((String, ParserInfo a) -> Bool)
-> [(String, ParserInfo a)] -> [(String, ParserInfo a)]
forall a. (a -> Bool) -> [a] -> [a]
filter (String -> Bool
is_completion (String -> Bool)
-> ((String, ParserInfo a) -> String)
-> (String, ParserInfo a)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String, ParserInfo a) -> String
forall a b. (a, b) -> a
fst) [(String, ParserInfo a)]
ns

    -- When doing enriched completions, add any help specified
    -- to the completion variables (tab separated).
    add_opt_help :: Functor f => Option a -> f String -> f String
    add_opt_help :: forall (f :: * -> *) a.
Functor f =>
Option a -> f String -> f String
add_opt_help Option a
opt = case Richness
richness of
      Richness
Standard ->
        f String -> f String
forall a. a -> a
id
      Enriched Int
len Int
_ ->
        ShowS -> f String -> f String
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ShowS -> f String -> f String) -> ShowS -> f String -> f String
forall a b. (a -> b) -> a -> b
$ \String
o ->
          let h :: Maybe Doc
h = Chunk Doc -> Maybe Doc
forall a. Chunk a -> Maybe a
unChunk (Chunk Doc -> Maybe Doc) -> Chunk Doc -> Maybe Doc
forall a b. (a -> b) -> a -> b
$ Option a -> Chunk Doc
forall a. Option a -> Chunk Doc
optHelp Option a
opt
          in  String -> (Doc -> String) -> Maybe Doc -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
o (\Doc
h' -> String
o String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\t" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Doc -> String
render_line Int
len Doc
h') Maybe Doc
h

    -- When doing enriched completions, add the command description
    -- to the completion variables (tab separated).
    with_cmd_help :: Functor f => f (String, ParserInfo a) -> f String
    with_cmd_help :: forall (f :: * -> *) a.
Functor f =>
f (String, ParserInfo a) -> f String
with_cmd_help =
      case Richness
richness of
        Richness
Standard ->
          ((String, ParserInfo a) -> String)
-> f (String, ParserInfo a) -> f String
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String, ParserInfo a) -> String
forall a b. (a, b) -> a
fst
        Enriched Int
_ Int
len ->
          ((String, ParserInfo a) -> String)
-> f (String, ParserInfo a) -> f String
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((String, ParserInfo a) -> String)
 -> f (String, ParserInfo a) -> f String)
-> ((String, ParserInfo a) -> String)
-> f (String, ParserInfo a)
-> f String
forall a b. (a -> b) -> a -> b
$ \(String
cmd, ParserInfo a
cmdInfo) ->
            let h :: Maybe Doc
h = Chunk Doc -> Maybe Doc
forall a. Chunk a -> Maybe a
unChunk (ParserInfo a -> Chunk Doc
forall a. ParserInfo a -> Chunk Doc
infoProgDesc ParserInfo a
cmdInfo)
            in  String -> (Doc -> String) -> Maybe Doc -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
cmd (\Doc
h' -> String
cmd String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\t" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Doc -> String
render_line Int
len Doc
h') Maybe Doc
h

    show_names :: [OptName] -> [String]
    show_names :: [OptName] -> [String]
show_names = (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
filter String -> Bool
is_completion ([String] -> [String])
-> ([OptName] -> [String]) -> [OptName] -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (OptName -> String) -> [OptName] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map OptName -> String
showOption

    -- We only want to show a single line in the completion results description.
    -- If there was a line break, it would come across as a different completion
    -- possibility.
    render_line :: Int -> Doc -> String
    render_line :: Int -> Doc -> String
render_line Int
len Doc
doc = case String -> [String]
lines (Double -> Int -> Doc -> String
prettyString Double
1 Int
len Doc
doc) of
      [] -> String
""
      [String
x] -> String
x
      String
x : [String]
_ -> String
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"..."

    run_completer :: Completer -> IO [String]
    run_completer :: Completer -> IO [String]
run_completer Completer
c = Completer -> String -> IO [String]
runCompleter Completer
c (String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
"" ([String] -> Maybe String
forall a. [a] -> Maybe a
listToMaybe [String]
ws''))

    ([String]
ws', [String]
ws'') = Int -> [String] -> ([String], [String])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
i [String]
ws

    is_completion :: String -> Bool
    is_completion :: String -> Bool
is_completion =
      case [String]
ws'' of
        String
w:[String]
_ -> String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isPrefixOf String
w
        [String]
_ -> Bool -> String -> Bool
forall a b. a -> b -> a
const Bool
True

-- | Generated bash shell completion script
bashCompletionScript :: String -> String -> String
bashCompletionScript :: String -> ShowS
bashCompletionScript String
prog String
progn = [String] -> String
unlines
  [ String
"_" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
progn String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"()"
  , String
"{"
  , String
"    local CMDLINE"
  , String
"    local IFS=$'\\n'"
  , String
"    CMDLINE=(--bash-completion-index $COMP_CWORD)"
  , String
""
  , String
"    for arg in ${COMP_WORDS[@]}; do"
  , String
"        CMDLINE=(${CMDLINE[@]} --bash-completion-word $arg)"
  , String
"    done"
  , String
""
  , String
"    COMPREPLY=( $(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
prog String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" \"${CMDLINE[@]}\") )"
  , String
"}"
  , String
""
  , String
"complete -o filenames -F _" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
progn String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
progn ]

{-
/Note/: Fish Shell

Derived from Drezil's post in #169.

@
commandline
-c or --cut-at-cursor only print selection up until the current cursor position
-o or --tokenize tokenize the selection and print one string-type token per line
@

We tokenize so that the call to count (and hence --bash-completion-index)
gets the right number use cut-at-curstor to not bother sending anything
after the cursor position, which allows for completion of the middle of
words.

Tab characters separate items from descriptions.
-}

-- | Generated fish shell completion script 
fishCompletionScript :: String -> String -> String
fishCompletionScript :: String -> ShowS
fishCompletionScript String
prog String
progn = [String] -> String
unlines
  [ String
" function _" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
progn
  , String
"    set -l cl (commandline --tokenize --current-process)"
  , String
"    # Hack around fish issue #3934"
  , String
"    set -l cn (commandline --tokenize --cut-at-cursor --current-process)"
  , String
"    set -l cn (count $cn)"
  , String
"    set -l tmpline --bash-completion-enriched --bash-completion-index $cn"
  , String
"    for arg in $cl"
  , String
"      set tmpline $tmpline --bash-completion-word $arg"
  , String
"    end"
  , String
"    for opt in (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
prog String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" $tmpline)"
  , String
"      if test -d $opt"
  , String
"        echo -E \"$opt/\""
  , String
"      else"
  , String
"        echo -E \"$opt\""
  , String
"      end"
  , String
"    end"
  , String
"end"
  , String
""
  , String
"complete --no-files --command " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
progn String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" --arguments '(_"  String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
progn String -> ShowS
forall a. [a] -> [a] -> [a]
++  String
")'"
  ]

-- | Generated zsh shell completion script
zshCompletionScript :: String -> String -> String
zshCompletionScript :: String -> ShowS
zshCompletionScript String
prog String
progn = [String] -> String
unlines
  [ String
"#compdef " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
progn
  , String
""
  , String
"local request"
  , String
"local completions"
  , String
"local word"
  , String
"local index=$((CURRENT - 1))"
  , String
""
  , String
"request=(--bash-completion-enriched --bash-completion-index $index)"
  , String
"for arg in ${words[@]}; do"
  , String
"  request=(${request[@]} --bash-completion-word $arg)"
  , String
"done"
  , String
""
  , String
"IFS=$'\\n' completions=($( " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
prog String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" \"${request[@]}\" ))"
  , String
""
  , String
"for word in $completions; do"
  , String
"  local -a parts"
  , String
""
  , String
"  # Split the line at a tab if there is one."
  , String
"  IFS=$'\\t' parts=($( echo $word ))"
  , String
""
  , String
"  if [[ -n $parts[2] ]]; then"
  , String
"     if [[ $word[1] == \"-\" ]]; then"
  , String
"       local desc=(\"$parts[1] ($parts[2])\")"
  , String
"       compadd -d desc -- $parts[1]"
  , String
"     else"
  , String
"       local desc=($(print -f  \"%-019s -- %s\" $parts[1] $parts[2]))"
  , String
"       compadd -l -d desc -- $parts[1]"
  , String
"     fi"
  , String
"  else"
  , String
"    compadd -f -- $word"
  , String
"  fi"
  , String
"done"
  ]