Command Line Subcommands in Idris

Here’s the translated Idris code for the Command-Line Subcommands example:

Our program demonstrates how to create subcommands with their own set of flags, similar to tools like git or npm. In Idris, we’ll use the System module for command-line arguments and the Data.String module for string operations.

module Main

import System
import Data.String

data Command = Foo Bool String | Bar Int

parseArgs : List String -> Maybe Command
parseArgs ("foo" :: args) = parseFoo args
parseArgs ("bar" :: args) = parseBar args
parseArgs _ = Nothing

parseFoo : List String -> Maybe Command
parseFoo args =
  let enable = "-enable" `elem` args
      name = findName args
  in Just (Foo enable (fromMaybe "" name))
  where
    findName : List String -> Maybe String
    findName [] = Nothing
    findName (x :: xs) = 
      if isPrefixOf "-name=" x
        then Just (substr 6 (length x) x)
        else findName xs

parseBar : List String -> Maybe Command
parseBar args =
  case findLevel args of
    Just level -> Just (Bar level)
    Nothing -> Nothing
  where
    findLevel : List String -> Maybe Int
    findLevel [] = Nothing
    findLevel (x :: xs) = 
      if isPrefixOf "-level=" x
        then parseInteger (substr 7 (length x) x)
        else findLevel xs

main : IO ()
main = do
  args <- getArgs
  case parseArgs (drop 1 args) of
    Just (Foo enable name) -> do
      putStrLn "subcommand 'foo'"
      putStrLn $ "  enable: " ++ show enable
      putStrLn $ "  name: " ++ name
    Just (Bar level) -> do
      putStrLn "subcommand 'bar'"
      putStrLn $ "  level: " ++ show level
    Nothing -> 
      putStrLn "expected 'foo' or 'bar' subcommands"

To run the program, compile it and then execute it with the desired subcommand and flags:

$ idris -o cli-subcommands cli-subcommands.idr
$ ./cli-subcommands foo -enable -name=joe
subcommand 'foo'
  enable: True
  name: joe
$ ./cli-subcommands bar -level=8
subcommand 'bar'
  level: 8

This Idris implementation uses pattern matching and custom data types to handle subcommands and their arguments. The Command data type represents the two possible subcommands, Foo and Bar, with their respective arguments.

The parseArgs function determines which subcommand was invoked and delegates to the appropriate parsing function. parseFoo and parseBar handle the specific flags for each subcommand.

Note that Idris doesn’t have a built-in command-line parsing library like Go’s flag package, so we’ve implemented a simple parsing mechanism manually. In a real-world application, you might want to use a more robust command-line parsing library if available for Idris.

The main function retrieves the command-line arguments, parses them, and then prints the appropriate output based on the subcommand and its arguments.

This example demonstrates how to create a basic command-line interface with subcommands in Idris, showcasing pattern matching, custom data types, and string manipulation.