Created
October 17, 2025 22:36
-
-
Save thelissimus/cf9c6cc2fac56062a250d797476d677e to your computer and use it in GitHub Desktop.
Reference: https://github.com/clap-rs/clap/blob/0bb3ad7e12e729be9f152391558689ac4fdd31ec/examples/pacman.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {-# LANGUAGE ApplicativeDo #-} | |
| module Main (main) where | |
| import Data.List | |
| import Options.Applicative | |
| import System.Exit | |
| data Cmd | |
| = Query QueryOpts | |
| | Sync SyncOpts | |
| deriving stock (Show) | |
| data QueryOpts = MkQueryOpts | |
| { info :: [String] | |
| , search :: [String] | |
| } | |
| deriving stock (Show) | |
| data SyncOpts = MkSyncOpts | |
| { search :: [String] | |
| , info :: Bool | |
| , packages :: [String] | |
| } | |
| deriving stock (Show) | |
| parseQueryOpts :: Parser QueryOpts | |
| parseQueryOpts = do | |
| info' <- many $ strOption (long "info" <> short 'i' <> help "view package information") | |
| search <- many $ strOption (long "search" <> short 's' <> help "search locally installed packages for matching strings") | |
| pure MkQueryOpts{info = info', search} | |
| parseSyncOpts :: Parser SyncOpts | |
| parseSyncOpts = do | |
| search <- many $ strOption (long "search" <> short 's' <> help "search remote repositories for matching strings") | |
| info' <- switch (long "info" <> short 'i' <> help "view package information") | |
| packages <- many $ strArgument (help "packages") | |
| pure MkSyncOpts{search, info = info', packages} | |
| parseCmd :: Parser Cmd | |
| parseCmd = | |
| hsubparser . mconcat | |
| $ [ command "query" (info (Query <$> parseQueryOpts) (progDesc "Query the package database.")) | |
| , command "Q" (info (Query <$> parseQueryOpts) (progDesc "Query the package database.")) | |
| , command "sync" (info (Sync <$> parseSyncOpts) (progDesc "Synchronize packages.")) | |
| , command "S" (info (Sync <$> parseSyncOpts) (progDesc "Synchronize packages.")) | |
| ] | |
| parserInfo :: ParserInfo Cmd | |
| parserInfo = info (helper <*> infoOption "5.2.1" (long "version") <*> parseCmd) (progDesc "package manager utility") | |
| runQuery :: QueryOpts -> IO () | |
| runQuery opt = case (opt.info, opt.search) of | |
| ([], []) -> putStrLn "Displaying all locally installed packages..." | |
| (_ : _, _ : _) -> putStrLn "error: --info conflicts with --search" >> exitFailure | |
| (xs, []) -> putStrLn $ "Retrieving info for " <> intercalate ", " xs <> "..." | |
| ([], qs) -> putStrLn $ "Searching Locally for " <> intercalate ", " qs <> "..." | |
| runSync :: SyncOpts -> IO () | |
| runSync opt = case (opt.search, opt.info, opt.packages) of | |
| (_ : _, True, _) -> putStrLn "error: --search conflicts with --info and PACKAGE..." >> exitFailure | |
| (_ : _, _, _ : _) -> putStrLn "error: --search conflicts with --info and PACKAGE..." >> exitFailure | |
| (qs@(_ : _), _, []) -> putStrLn $ "Searching for " <> intercalate ", " qs <> "..." | |
| ([], _, []) -> putStrLn "error: PACKAGE... is required unless --search is used" >> exitFailure | |
| ([], True, xs) -> putStrLn $ "Retrieving info for " <> intercalate ", " xs <> "..." | |
| ([], False, xs) -> putStrLn $ "Installing " <> intercalate ", " xs <> "..." | |
| main :: IO () | |
| main = | |
| execParser parserInfo >>= \case | |
| Sync o -> runSync o | |
| Query o -> runQuery o |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment