I'm building a brainfuck compiler. The executable accepts two commands $ brainfuck compile ...
and $ brainfuck run
. I want the executable to auto complete when pressing tab. E.g. writing $ brainfuck com
and then pressing tab should generate $ brainfuck compile
.
data Command = Compile CompileArgs | Run RunArgs
deriving (Show)
main :: IO ()
main = execute =<< execParser opts
where
opts = info (helper <*> argsParser) fullDesc
execute :: Command -> IO ()
execute (Compile args) = compile args
execute (Run args) = run args
argsParser :: Parser Command
argsParser = subparser (compileCommand <> runCommand)
where
compileCommand = command "compile" $ info compileOptions $ progDesc "Compile brainfuck to an executable"
runCommand = command "run" $ info runOptions $ progDesc "Execute brainfuck code"
There is a section on optparse's github page here, but I don't really understand it.
The function completeWith :: Options.Applicative.Builder.Internal.HasCompleter f => [String] -> Mod f a
looks quite similar to command :: String -> ParserInfo a -> Mod CommandFields a
which I'm already using. So I figured I could use it and just combine them with <>
but it turns out that CommandFields
is not an instance of HasCompleter
.
How are you supposed to get the auto completion to work?
After RTFM'ing a bit I found out how to configure the auto completion.
completeWith
is applied when constructing the parsers for the individual arguments.
Like so:
data CompileArgs = CompileArgs
{
debug :: Bool,
optimizations :: OptimizationLevel,
file :: String
}
deriving (Show, Read)
compileArgsParser :: Parser CompileArgs
compileArgsParser = CompileArgs
<$> switch (
long "debug" <>
help "Outputs object and assembly files")
<*> option auto (
long "optimization-level" <>
value All <>
metavar "LEVEL" <>
help "all | none, default: all" <>
completeWith ["all", "none"])
<*> argument str (
metavar "FILE" <>
help "brainfuck source code" <>
action "file")
<**> helper
action
is an instruction to bash on how auto complete. "file"
means auto complete with any file or directory. See this page for more info.
In order for these auto completions to kick in you need to generate a script and make sure that script is sourced. By convention it's placed under /etc/bash_completion.d/
when using bash.
brainfuck --bash-completion-script `which brainfuck` | sudo tee /etc/bash_completion.d/brainfuck
in my case where my program is called brainfuck
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With