# Commander: A Haskell Library for parsing commands This library aims to make it super easy to create and use nested commands with flags in the form of an object that is easy to traverse and run custom actions on, and easy to extend with handling for safe casting to values from their input strings. As an example of usage (take a look in the _examples_ folder for more) we can define commands as follows: ``` someCommands :: Command (IO ()) someCommands = commands $ do command "repeat" $ do help "Repeat a string n times" run $ \(Value str :: Value "value to repeat" String) (Flag n :: Flag '["n"] "times to repeat" Int) -> sequence_ $ replicate n (putStrLn str) command "calculate" $ do help "perform calculations" command "add" $ do help "add two numbers" run $ \(Value n1 :: Value "number 1" Int) (Value n2 :: Value "number 2" Int) (Flag verbose :: Flag '["v", "verbose"] "verbose mode" Bool) -> if verbose then putStrLn $ (show n1) ++ " + " ++ (show n2) ++ " = " ++ (show $ n1 + n2) else putStrLn (show $ n1 + n2) command "multiply" $ do help "multiply two numbers" run $ \(Value n1 :: Value "number 1" Int) (Value n2 :: Value "number 2" Int) -> putStrLn $ (show n1) ++ " x " ++ (show n2) ++ " = " ++ (show $ n1 * n2) ``` And this leads to `someCommands` being a nested record of type `Command (IO ())` (where `IO ()` corresponds to the output from the functions you provide). This record can then be traversed and interacted with. The novelty of this approach (compared to others I have seen, which is a non exhaustive list!) is the use of the functions input parameter types to cast-from-string and inject the appropriate values into the function safely at runtime, as well as to generate documentation. This means that we only declare the flags and values each command requires in one place, and do not execute any of the output unless all parameters are fully satisfied. These functions are then safely hidden away inside an existential type, and so we don't need any other type level magic or handling to work with the output. # Installation 1. Add this repository to your stack.yaml file under the packages folder, so we end up with something that looks a bit like: ``` packages: - '.' - location: git: https://github.com/jsdw/hs-commander commit: abcdef123456789abcdef1234 ``` 2. run `stack install`. 3. import `Commander` into your library. you can run the example code by running `stack install :example1 && example1` assuming that the directory stack copies binaries to is present in your `PATH`. # Documentation if you clone this repository locally somewhere, you can use `stack haddock` inside its folder in order to generate haddock documentation for it. # Disclaimer This project is still under heavy development and could well change drastically!