10 | constructor MkModOpts
14 | record PkgOpts where
15 | constructor MkPkgOpts
46 | show (Required a) = "<" ++ a ++ ">"
47 | show (Optional a) = "[" ++ a ++ "]"
48 | show (Flag a) = "[--" ++ a ++ "]"
50 | ActType : List OptType -> Type
51 | ActType [] = List CLOpt
52 | ActType (Required a :: as) = String -> ActType as
53 | ActType (Optional a :: as) = Maybe String -> ActType as
54 | ActType (Flag a :: as) = Bool -> ActType as
56 | record OptDesc where
59 | argdescs : List OptType
60 | action : ActType argdescs
63 | optSeparator : OptDesc
64 | optSeparator = MkOpt [] [] [] Nothing
66 | showDefault : Show a => a -> String
67 | showDefault x = "(default " ++ show x ++ ")"
69 | options : List OptDesc
71 | [ MkOpt ["package", "pkg", "p"] [Flag "local-only"]
72 | (\localOnly => [Package $
MkPkgOpts {localOnly}])
73 | (Just "(default) Generate a package dependency graph")
74 | , MkOpt ["module", "mod", "m"] [Flag "with-external"]
75 | (\withExternal => [Module $
MkModOpts {withExternal}])
76 | (Just "Generate a module import graph")
77 | , MkOpt ["--help", "-h", "-?"] [] [Help]
78 | (Just "Display help text")
79 | , MkOpt ["--version", "-v"] [] [Version]
80 | (Just "Display version string")
83 | optShow : OptDesc -> (String, Maybe String)
84 | optShow (MkOpt [] _ _ _) = ("", Just "")
85 | optShow (MkOpt flags argdescs action help) =
86 | (showSep ", " flags ++ " " ++ showSep " " (map show argdescs), help)
88 | showSep : String -> List String -> String
91 | showSep sep (x :: xs) = x ++ sep ++ showSep sep xs
93 | firstColumnWidth : Nat
94 | firstColumnWidth = foldr max 0 $
map (length . fst . optShow) options
96 | makeTextFromOptionsOrEnvs : List (String, Maybe String) -> String
97 | makeTextFromOptionsOrEnvs rows = concatMap (optUsage firstColumnWidth) rows
99 | optUsage : Nat -> (String, Maybe String) -> String
100 | optUsage maxOpt (optshow, help) =
106 | pack (List.replicate (minus (maxOpt + 2) (length optshow)) ' ') ++
111 | optsUsage = makeTextFromOptionsOrEnvs $
map optShow options
115 | versionMsg : String
116 | versionMsg = "Dep-graph version 0.1.0"
122 | Usage: dep-graph [options] [ipkg file...]
128 | processArgs : String -> (args : List OptType) -> List String -> ActType args ->
129 | Either String (List CLOpt, List String)
130 | processArgs flag [] xs f = Right (f, xs)
132 | processArgs flag (opt@(Required _) :: as) [] f =
133 | Left $
"Missing required argument " ++ show opt ++ " for flag " ++ flag
134 | processArgs flag (Optional a :: as) [] f =
135 | processArgs flag as [] (f Nothing)
136 | processArgs flag (Flag a :: as) [] f =
137 | processArgs flag as [] (f False)
139 | processArgs flag (Required a :: as) (x :: xs) f =
140 | processArgs flag as xs (f x)
141 | processArgs flag (Optional a :: as) (x :: xs) f =
142 | if isPrefixOf "-" x
143 | then processArgs flag as (x :: xs) (f Nothing)
144 | else processArgs flag as xs (f $
Just x)
145 | processArgs flag (Flag a :: as) (x :: xs) f =
147 | then processArgs flag as xs (f True)
148 | else processArgs flag as (x :: xs) (f False)
150 | matchFlag : (d : OptDesc) -> List String ->
151 | Either String (Maybe (List CLOpt, List String))
152 | matchFlag d [] = Right Nothing
153 | matchFlag d (x :: xs) =
154 | if x `elem` flags d
156 | args <- processArgs x (argdescs d) xs (action d)
160 | findMatch : List OptDesc -> List String ->
161 | Either String (List CLOpt, List String)
162 | findMatch [] [] = Right ([], [])
163 | findMatch [] (f :: args) =
165 | '-' :: '-' :: _ => Left "Unknown flag \{f}"
166 | _ => Right ([InputFile f], args)
167 | findMatch (d :: ds) args =
168 | case !(matchFlag d args) of
169 | Nothing => findMatch ds args
170 | Just res => Right res
172 | parseOpts : List OptDesc -> List String -> Either String (List CLOpt)
173 | parseOpts opts [] = Right []
174 | parseOpts opts args = do
175 | (cl, rest) <- findMatch opts args
176 | cls <- assert_total (parseOpts opts rest)
180 | getCmdOpts : IO (Either String (List CLOpt))
182 | (_ :: opts) <- getArgs
183 | | _ => pure (Left "Invalid command line")
184 | pure $
parseOpts options opts
187 | findInputs : List CLOpt -> List String
189 | findInputs (InputFile f :: fs) = f :: findInputs fs
190 | findInputs (_ :: fs) = findInputs fs
193 | quitOpts : List CLOpt -> IO Bool
194 | quitOpts [] = pure True
195 | quitOpts (Version :: _) = do
196 | putStrLn versionMsg
198 | quitOpts (Help :: _) = do
201 | quitOpts (_ :: opts) = quitOpts opts
204 | subCmd : List CLOpt -> SubCmd
205 | subCmd [] = SubCmdPkg $
MkPkgOpts {localOnly = False}
206 | subCmd (Module opts :: _) = SubCmdMod opts
207 | subCmd (Package opts :: _) = SubCmdPkg opts
208 | subCmd (f :: fs) = subCmd fs