Add bash-completion support (experimental)
parent
a4e80cc8fc
commit
327f596d1d
|
@ -30,6 +30,8 @@ module UI.Butcher.Monadic
|
||||||
, addHelpCommand
|
, addHelpCommand
|
||||||
, addHelpCommand2
|
, addHelpCommand2
|
||||||
, addButcherDebugCommand
|
, addButcherDebugCommand
|
||||||
|
, addShellCompletionCommand
|
||||||
|
, addShellCompletionCommand'
|
||||||
, mapOut
|
, mapOut
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
|
@ -4,6 +4,8 @@ module UI.Butcher.Monadic.BuiltinCommands
|
||||||
, addHelpCommand2
|
, addHelpCommand2
|
||||||
, addHelpCommandShallow
|
, addHelpCommandShallow
|
||||||
, addButcherDebugCommand
|
, addButcherDebugCommand
|
||||||
|
, addShellCompletionCommand
|
||||||
|
, addShellCompletionCommand'
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
@ -22,6 +24,7 @@ import UI.Butcher.Monadic.Internal.Types
|
||||||
import UI.Butcher.Monadic.Internal.Core
|
import UI.Butcher.Monadic.Internal.Core
|
||||||
import UI.Butcher.Monadic.Pretty
|
import UI.Butcher.Monadic.Pretty
|
||||||
import UI.Butcher.Monadic.Param
|
import UI.Butcher.Monadic.Param
|
||||||
|
import UI.Butcher.Monadic.Interactive
|
||||||
|
|
||||||
import System.IO
|
import System.IO
|
||||||
|
|
||||||
|
@ -94,3 +97,70 @@ addButcherDebugCommand = addCmd "butcherdebug" $ do
|
||||||
addCmdImpl $ do
|
addCmdImpl $ do
|
||||||
print $ maybe undefined snd (_cmd_mParent desc)
|
print $ maybe undefined snd (_cmd_mParent desc)
|
||||||
|
|
||||||
|
-- | Adds the "completion" command and several subcommands.
|
||||||
|
--
|
||||||
|
-- This command can be used in the following manner:
|
||||||
|
--
|
||||||
|
-- > $ source <(foo completion bash-script foo)
|
||||||
|
addShellCompletionCommand
|
||||||
|
:: CmdParser Identity (IO ()) () -> CmdParser Identity (IO ()) ()
|
||||||
|
addShellCompletionCommand mainCmdParser = do
|
||||||
|
addCmdHidden "completion" $ do
|
||||||
|
addCmdSynopsis "utilites to enable bash-completion"
|
||||||
|
addCmd "bash-script" $ do
|
||||||
|
addCmdSynopsis "generate a bash script for completion functionality"
|
||||||
|
exeName <- addParamString "EXENAME" mempty
|
||||||
|
addCmdImpl $ do
|
||||||
|
putStr $ completionScriptBash exeName
|
||||||
|
addCmd "bash-gen" $ do
|
||||||
|
addCmdSynopsis
|
||||||
|
"generate possible completions for given input arguments"
|
||||||
|
rest <- addParamRestOfInputRaw "REALCOMMAND" mempty
|
||||||
|
addCmdImpl $ do
|
||||||
|
let (cdesc, remaining, _result) =
|
||||||
|
runCmdParserExt Nothing rest mainCmdParser
|
||||||
|
let
|
||||||
|
compls = shellCompletionWords (inputString rest)
|
||||||
|
cdesc
|
||||||
|
(inputString remaining)
|
||||||
|
let lastWord =
|
||||||
|
reverse $ takeWhile (not . Char.isSpace) $ reverse $ inputString
|
||||||
|
rest
|
||||||
|
putStrLn $ List.intercalate "\t" $ compls <&> \case
|
||||||
|
CompletionString s -> s
|
||||||
|
CompletionFile -> "$(compgen -f -- " ++ lastWord ++ ")"
|
||||||
|
CompletionDirectory -> "$(compgen -d -- " ++ lastWord ++ ")"
|
||||||
|
where
|
||||||
|
inputString (InputString s ) = s
|
||||||
|
inputString (InputArgs as) = List.unwords as
|
||||||
|
|
||||||
|
-- | Adds the "completion" command and several subcommands
|
||||||
|
--
|
||||||
|
-- This command can be used in the following manner:
|
||||||
|
--
|
||||||
|
-- > $ source <(foo completion bash-script foo)
|
||||||
|
addShellCompletionCommand'
|
||||||
|
:: (CommandDesc out -> CmdParser Identity (IO ()) ())
|
||||||
|
-> CmdParser Identity (IO ()) ()
|
||||||
|
addShellCompletionCommand' f = addShellCompletionCommand (f emptyCommandDesc)
|
||||||
|
|
||||||
|
completionScriptBash :: String -> String
|
||||||
|
completionScriptBash exeName =
|
||||||
|
List.unlines
|
||||||
|
$ [ "function _" ++ exeName ++ "()"
|
||||||
|
, "{"
|
||||||
|
, " local IFS=$'\\t'"
|
||||||
|
, " COMPREPLY=()"
|
||||||
|
, " local result=$("
|
||||||
|
++ exeName
|
||||||
|
++ " completion bash-gen \"${COMP_WORDS[@]:1}\")"
|
||||||
|
, " for r in ${result[@]}; do"
|
||||||
|
, " local IFS=$'\\n\\t '"
|
||||||
|
, " for s in $(eval echo ${r}); do"
|
||||||
|
, " COMPREPLY+=(${s})"
|
||||||
|
, " done"
|
||||||
|
, " done"
|
||||||
|
, "}"
|
||||||
|
, "complete -F _" ++ exeName ++ " " ++ exeName
|
||||||
|
]
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
-- e.g. a REPL.
|
-- e.g. a REPL.
|
||||||
module UI.Butcher.Monadic.Interactive
|
module UI.Butcher.Monadic.Interactive
|
||||||
( simpleCompletion
|
( simpleCompletion
|
||||||
|
, shellCompletionWords
|
||||||
, interactiveHelpDoc
|
, interactiveHelpDoc
|
||||||
, partDescStrings
|
, partDescStrings
|
||||||
)
|
)
|
||||||
|
@ -57,6 +58,39 @@ simpleCompletion line cdesc pcRest =
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
-- | Derives a list of completion items from a given input string and a given
|
||||||
|
-- 'CommandDesc'. Considers potential subcommands and where available the
|
||||||
|
-- completion info present in 'PartDesc's.
|
||||||
|
--
|
||||||
|
-- See 'addShellCompletion' which uses this.
|
||||||
|
shellCompletionWords
|
||||||
|
:: String -- ^ input string
|
||||||
|
-> CommandDesc () -- ^ CommandDesc obtained on that input string
|
||||||
|
-> String -- ^ "remaining" input after the last successfully parsed
|
||||||
|
-- subcommand. See 'UI.Butcher.Monadic.runCmdParserExt'.
|
||||||
|
-> [CompletionItem]
|
||||||
|
shellCompletionWords line cdesc pcRest = choices
|
||||||
|
where
|
||||||
|
_nameDesc = case _cmd_mParent cdesc of
|
||||||
|
Nothing -> cdesc
|
||||||
|
Just (_, parent) | null pcRest -> parent
|
||||||
|
Just{} -> cdesc
|
||||||
|
lastWord = reverse $ takeWhile (not . Char.isSpace) $ reverse $ line
|
||||||
|
choices :: [CompletionItem]
|
||||||
|
choices = join
|
||||||
|
[ [ CompletionString r
|
||||||
|
| (Just r, _) <- Data.Foldable.toList (_cmd_children cdesc)
|
||||||
|
, lastWord `isPrefixOf` r
|
||||||
|
]
|
||||||
|
, [ c
|
||||||
|
| c <- partDescCompletions =<< _cmd_parts cdesc
|
||||||
|
, case c of
|
||||||
|
CompletionString s -> lastWord `isPrefixOf` s
|
||||||
|
_ -> True
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
-- | Produces a 'PP.Doc' as a hint for the user during interactive command
|
-- | Produces a 'PP.Doc' as a hint for the user during interactive command
|
||||||
-- input. Takes the current (incomplete) prompt line into account. For example
|
-- input. Takes the current (incomplete) prompt line into account. For example
|
||||||
-- when you have commands (among others) \'config set-email\' and
|
-- when you have commands (among others) \'config set-email\' and
|
||||||
|
@ -124,10 +158,32 @@ partDescStrings = \case
|
||||||
PartSeq [] -> []
|
PartSeq [] -> []
|
||||||
PartSeq (x:_) -> partDescStrings x
|
PartSeq (x:_) -> partDescStrings x
|
||||||
PartDefault _ x -> partDescStrings x
|
PartDefault _ x -> partDescStrings x
|
||||||
PartSuggestion ss x -> [ s | s <- ss ] ++ partDescStrings x
|
PartSuggestion ss x -> [ s | CompletionString s <- ss ] ++ partDescStrings x
|
||||||
PartRedirect _ x -> partDescStrings x
|
PartRedirect _ x -> partDescStrings x
|
||||||
PartReorder xs -> xs >>= partDescStrings
|
PartReorder xs -> xs >>= partDescStrings
|
||||||
PartMany x -> partDescStrings x
|
PartMany x -> partDescStrings x
|
||||||
PartWithHelp _h x -> partDescStrings x -- TODO: handle help
|
PartWithHelp _h x -> partDescStrings x -- TODO: handle help
|
||||||
PartHidden{} -> []
|
PartHidden{} -> []
|
||||||
|
|
||||||
|
|
||||||
|
-- | Obtains a list of "expected"/potential strings for a command part
|
||||||
|
-- described in the 'PartDesc'. In constrast to the 'simpleCompletion'
|
||||||
|
-- function this function does not take into account any current input, and
|
||||||
|
-- consequently the output elements can in general not be appended to partial
|
||||||
|
-- input to form valid input.
|
||||||
|
partDescCompletions :: PartDesc -> [CompletionItem]
|
||||||
|
partDescCompletions = \case
|
||||||
|
PartLiteral s -> [CompletionString s]
|
||||||
|
PartVariable _ -> []
|
||||||
|
-- TODO: we could handle seq of optional and such much better
|
||||||
|
PartOptional x -> partDescCompletions x
|
||||||
|
PartAlts alts -> alts >>= partDescCompletions
|
||||||
|
PartSeq [] -> []
|
||||||
|
PartSeq (x:_) -> partDescCompletions x
|
||||||
|
PartDefault _ x -> partDescCompletions x
|
||||||
|
PartSuggestion ss x -> ss ++ partDescCompletions x
|
||||||
|
PartRedirect _ x -> partDescCompletions x
|
||||||
|
PartReorder xs -> xs >>= partDescCompletions
|
||||||
|
PartMany x -> partDescCompletions x
|
||||||
|
PartWithHelp _h x -> partDescCompletions x -- TODO: handle help
|
||||||
|
PartHidden{} -> []
|
||||||
|
|
|
@ -23,6 +23,7 @@ module UI.Butcher.Monadic.Internal.Types
|
||||||
, addSuggestion
|
, addSuggestion
|
||||||
, ManyUpperBound (..)
|
, ManyUpperBound (..)
|
||||||
, Visibility (..)
|
, Visibility (..)
|
||||||
|
, CompletionItem (..)
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
@ -140,7 +141,7 @@ data PartDesc
|
||||||
| PartSeq [PartDesc]
|
| PartSeq [PartDesc]
|
||||||
| PartDefault String -- default representation
|
| PartDefault String -- default representation
|
||||||
PartDesc
|
PartDesc
|
||||||
| PartSuggestion [String] PartDesc
|
| PartSuggestion [CompletionItem] PartDesc
|
||||||
| PartRedirect String -- name for the redirection
|
| PartRedirect String -- name for the redirection
|
||||||
PartDesc
|
PartDesc
|
||||||
| PartReorder [PartDesc]
|
| PartReorder [PartDesc]
|
||||||
|
@ -149,10 +150,18 @@ data PartDesc
|
||||||
| PartHidden PartDesc
|
| PartHidden PartDesc
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
addSuggestion :: Maybe [String] -> PartDesc -> PartDesc
|
addSuggestion :: Maybe [CompletionItem] -> PartDesc -> PartDesc
|
||||||
addSuggestion Nothing = id
|
addSuggestion Nothing = id
|
||||||
addSuggestion (Just sugs) = PartSuggestion sugs
|
addSuggestion (Just sugs) = PartSuggestion sugs
|
||||||
|
|
||||||
|
|
||||||
|
data CompletionItem
|
||||||
|
= CompletionString String
|
||||||
|
| CompletionDirectory
|
||||||
|
| CompletionFile
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
|
||||||
{-
|
{-
|
||||||
command documentation structure
|
command documentation structure
|
||||||
1. terminals. e.g. "--dry-run"
|
1. terminals. e.g. "--dry-run"
|
||||||
|
@ -174,6 +183,7 @@ deriving instance Functor CommandDesc
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
||||||
|
-- | Empty 'CommandDesc' value. Mostly for butcher-internal usage.
|
||||||
emptyCommandDesc :: CommandDesc out
|
emptyCommandDesc :: CommandDesc out
|
||||||
emptyCommandDesc =
|
emptyCommandDesc =
|
||||||
CommandDesc Nothing Nothing Nothing [] Nothing mempty Visible
|
CommandDesc Nothing Nothing Nothing [] Nothing mempty Visible
|
||||||
|
|
|
@ -9,6 +9,8 @@ module UI.Butcher.Monadic.Param
|
||||||
, paramHelpStr
|
, paramHelpStr
|
||||||
, paramDefault
|
, paramDefault
|
||||||
, paramSuggestions
|
, paramSuggestions
|
||||||
|
, paramFile
|
||||||
|
, paramDirectory
|
||||||
, addParamRead
|
, addParamRead
|
||||||
, addParamReadOpt
|
, addParamReadOpt
|
||||||
, addParamString
|
, addParamString
|
||||||
|
@ -18,6 +20,7 @@ module UI.Butcher.Monadic.Param
|
||||||
, addParamNoFlagStringOpt
|
, addParamNoFlagStringOpt
|
||||||
, addParamNoFlagStrings
|
, addParamNoFlagStrings
|
||||||
, addParamRestOfInput
|
, addParamRestOfInput
|
||||||
|
, addParamRestOfInputRaw
|
||||||
, -- * Deprecated for more consistent naming
|
, -- * Deprecated for more consistent naming
|
||||||
addReadParam
|
addReadParam
|
||||||
, addReadParamOpt
|
, addReadParamOpt
|
||||||
|
@ -49,7 +52,7 @@ import UI.Butcher.Monadic.Internal.Core
|
||||||
data Param p = Param
|
data Param p = Param
|
||||||
{ _param_default :: Maybe p
|
{ _param_default :: Maybe p
|
||||||
, _param_help :: Maybe PP.Doc
|
, _param_help :: Maybe PP.Doc
|
||||||
, _param_suggestions :: Maybe [p]
|
, _param_suggestions :: Maybe [CompletionItem]
|
||||||
}
|
}
|
||||||
|
|
||||||
instance Monoid (Param p) where
|
instance Monoid (Param p) where
|
||||||
|
@ -77,8 +80,17 @@ paramDefault :: p -> Param p
|
||||||
paramDefault d = mempty { _param_default = Just d }
|
paramDefault d = mempty { _param_default = Just d }
|
||||||
|
|
||||||
-- | Create a 'Param' with just a list of suggestion values.
|
-- | Create a 'Param' with just a list of suggestion values.
|
||||||
paramSuggestions :: [p] -> Param p
|
paramSuggestions :: [String] -> Param p
|
||||||
paramSuggestions ss = mempty { _param_suggestions = Just ss }
|
paramSuggestions ss =
|
||||||
|
mempty { _param_suggestions = Just $ CompletionString <$> ss }
|
||||||
|
|
||||||
|
-- | Create a 'Param' that is a file path.
|
||||||
|
paramFile :: Param p
|
||||||
|
paramFile = mempty { _param_suggestions = Just [CompletionFile] }
|
||||||
|
|
||||||
|
-- | Create a 'Param' that is a directory path.
|
||||||
|
paramDirectory :: Param p
|
||||||
|
paramDirectory = mempty { _param_suggestions = Just [CompletionDirectory] }
|
||||||
|
|
||||||
-- | Add a parameter to the 'CmdParser' by making use of a 'Text.Read.Read'
|
-- | Add a parameter to the 'CmdParser' by making use of a 'Text.Read.Read'
|
||||||
-- instance. Take care not to use this to return Strings unless you really
|
-- instance. Take care not to use this to return Strings unless you really
|
||||||
|
@ -99,7 +111,8 @@ addReadParam :: forall f out a
|
||||||
addReadParam name par = addCmdPart desc parseF
|
addReadParam name par = addCmdPart desc parseF
|
||||||
where
|
where
|
||||||
desc :: PartDesc
|
desc :: PartDesc
|
||||||
desc = (maybe id PartWithHelp $ _param_help par)
|
desc = addSuggestion (_param_suggestions par)
|
||||||
|
$ (maybe id PartWithHelp $ _param_help par)
|
||||||
$ (maybe id (PartDefault . show) $ _param_default par)
|
$ (maybe id (PartDefault . show) $ _param_default par)
|
||||||
$ PartVariable name
|
$ PartVariable name
|
||||||
parseF :: String -> Maybe (a, String)
|
parseF :: String -> Maybe (a, String)
|
||||||
|
@ -124,7 +137,8 @@ addReadParamOpt :: forall f out a
|
||||||
addReadParamOpt name par = addCmdPart desc parseF
|
addReadParamOpt name par = addCmdPart desc parseF
|
||||||
where
|
where
|
||||||
desc :: PartDesc
|
desc :: PartDesc
|
||||||
desc = PartOptional
|
desc = addSuggestion (_param_suggestions par)
|
||||||
|
$ PartOptional
|
||||||
$ (maybe id PartWithHelp $ _param_help par)
|
$ (maybe id PartWithHelp $ _param_help par)
|
||||||
$ PartVariable name
|
$ PartVariable name
|
||||||
parseF :: String -> Maybe (Maybe a, String)
|
parseF :: String -> Maybe (Maybe a, String)
|
||||||
|
@ -180,7 +194,8 @@ addStringParamOpt
|
||||||
addStringParamOpt name par = addCmdPartInp desc parseF
|
addStringParamOpt name par = addCmdPartInp desc parseF
|
||||||
where
|
where
|
||||||
desc :: PartDesc
|
desc :: PartDesc
|
||||||
desc = PartOptional
|
desc = addSuggestion (_param_suggestions par)
|
||||||
|
$ PartOptional
|
||||||
$ (maybe id PartWithHelp $ _param_help par)
|
$ (maybe id PartWithHelp $ _param_help par)
|
||||||
$ PartVariable name
|
$ PartVariable name
|
||||||
parseF :: Input -> Maybe (Maybe String, Input)
|
parseF :: Input -> Maybe (Maybe String, Input)
|
||||||
|
@ -213,7 +228,10 @@ addStringParams
|
||||||
addStringParams name par = addCmdPartManyInp ManyUpperBoundN desc parseF
|
addStringParams name par = addCmdPartManyInp ManyUpperBoundN desc parseF
|
||||||
where
|
where
|
||||||
desc :: PartDesc
|
desc :: PartDesc
|
||||||
desc = (maybe id PartWithHelp $ _param_help par) $ PartVariable name
|
desc =
|
||||||
|
addSuggestion (_param_suggestions par)
|
||||||
|
$ (maybe id PartWithHelp $ _param_help par)
|
||||||
|
$ PartVariable name
|
||||||
parseF :: Input -> Maybe (String, Input)
|
parseF :: Input -> Maybe (String, Input)
|
||||||
parseF (InputString str) =
|
parseF (InputString str) =
|
||||||
case break Char.isSpace $ dropWhile Char.isSpace str of
|
case break Char.isSpace $ dropWhile Char.isSpace str of
|
||||||
|
@ -284,7 +302,10 @@ addParamNoFlagStrings
|
||||||
addParamNoFlagStrings name par = addCmdPartManyInp ManyUpperBoundN desc parseF
|
addParamNoFlagStrings name par = addCmdPartManyInp ManyUpperBoundN desc parseF
|
||||||
where
|
where
|
||||||
desc :: PartDesc
|
desc :: PartDesc
|
||||||
desc = (maybe id PartWithHelp $ _param_help par) $ PartVariable name
|
desc =
|
||||||
|
addSuggestion (_param_suggestions par)
|
||||||
|
$ (maybe id PartWithHelp $ _param_help par)
|
||||||
|
$ PartVariable name
|
||||||
parseF :: Input -> Maybe (String, Input)
|
parseF :: Input -> Maybe (String, Input)
|
||||||
parseF (InputString str) =
|
parseF (InputString str) =
|
||||||
case break Char.isSpace $ dropWhile Char.isSpace str of
|
case break Char.isSpace $ dropWhile Char.isSpace str of
|
||||||
|
@ -307,15 +328,38 @@ addParamRestOfInput
|
||||||
addParamRestOfInput = addRestOfInputStringParam
|
addParamRestOfInput = addRestOfInputStringParam
|
||||||
{-# DEPRECATED addRestOfInputStringParam "use 'addParamRestOfInput'" #-}
|
{-# DEPRECATED addRestOfInputStringParam "use 'addParamRestOfInput'" #-}
|
||||||
addRestOfInputStringParam
|
addRestOfInputStringParam
|
||||||
:: forall f out . (Applicative f)
|
:: forall f out
|
||||||
|
. (Applicative f)
|
||||||
=> String
|
=> String
|
||||||
-> Param Void
|
-> Param Void
|
||||||
-> CmdParser f out String
|
-> CmdParser f out String
|
||||||
addRestOfInputStringParam name par = addCmdPartInp desc parseF
|
addRestOfInputStringParam name par = addCmdPartInp desc parseF
|
||||||
where
|
where
|
||||||
desc :: PartDesc
|
desc :: PartDesc
|
||||||
desc = (maybe id PartWithHelp $ _param_help par)
|
desc =
|
||||||
$ PartVariable name
|
addSuggestion (_param_suggestions par)
|
||||||
parseF :: Input -> Maybe (String, Input)
|
$ (maybe id PartWithHelp $ _param_help par)
|
||||||
parseF (InputString str) = Just (str, InputString "")
|
$ PartVariable name
|
||||||
parseF (InputArgs args) = Just (List.unwords args, InputArgs [])
|
parseF :: Input -> Maybe (String, Input)
|
||||||
|
parseF (InputString str ) = Just (str, InputString "")
|
||||||
|
parseF (InputArgs args) = Just (List.unwords args, InputArgs [])
|
||||||
|
|
||||||
|
|
||||||
|
-- | Add a parameter that consumes _all_ remaining input, returning a raw
|
||||||
|
-- 'Input' value.
|
||||||
|
addParamRestOfInputRaw
|
||||||
|
:: forall f out . (Applicative f)
|
||||||
|
=> String
|
||||||
|
-> Param Void
|
||||||
|
-> CmdParser f out Input
|
||||||
|
addParamRestOfInputRaw name par = addCmdPartInp desc parseF
|
||||||
|
where
|
||||||
|
desc :: PartDesc
|
||||||
|
desc =
|
||||||
|
addSuggestion (_param_suggestions par)
|
||||||
|
$ (maybe id PartWithHelp $ _param_help par)
|
||||||
|
$ PartVariable name
|
||||||
|
parseF :: Input -> Maybe (Input, Input)
|
||||||
|
parseF i@InputString{} = Just (i, InputString "")
|
||||||
|
parseF i@InputArgs{} = Just (i, InputArgs [])
|
||||||
|
|
||||||
|
|
|
@ -318,9 +318,13 @@ ppPartDescUsage = \case
|
||||||
, not (null ds)
|
, not (null ds)
|
||||||
]
|
]
|
||||||
PartSeq ps -> [ PP.fsep ds | let ds = Maybe.mapMaybe rec ps, not (null ds) ]
|
PartSeq ps -> [ PP.fsep ds | let ds = Maybe.mapMaybe rec ps, not (null ds) ]
|
||||||
PartDefault _ p -> PP.brackets <$> rec p
|
PartDefault _ p -> PP.brackets <$> rec p
|
||||||
PartSuggestion s p -> rec p <&> \d ->
|
PartSuggestion sgs p -> rec p <&> \d ->
|
||||||
PP.parens $ PP.fcat $ PP.punctuate (PP.text "|") $ fmap PP.text s ++ [d]
|
PP.parens
|
||||||
|
$ PP.fcat
|
||||||
|
$ PP.punctuate (PP.text "|")
|
||||||
|
$ [ PP.text s | CompletionString s <- sgs ]
|
||||||
|
++ [d]
|
||||||
PartRedirect s _ -> Just $ PP.text s
|
PartRedirect s _ -> Just $ PP.text s
|
||||||
PartMany p -> rec p <&> (<> PP.text "+")
|
PartMany p -> rec p <&> (<> PP.text "+")
|
||||||
PartWithHelp _ p -> rec p
|
PartWithHelp _ p -> rec p
|
||||||
|
|
|
@ -8,6 +8,7 @@ module UI.Butcher.Monadic.Types
|
||||||
, Input (..)
|
, Input (..)
|
||||||
, ParsingError (..)
|
, ParsingError (..)
|
||||||
, PartDesc(..)
|
, PartDesc(..)
|
||||||
|
, emptyCommandDesc
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue