let optparse-applicative handle the usage display when run w/o command or bad command
Still generating the list of commands myself, to get it sorted into sections and with short synopses.
This commit is contained in:
parent
6204dcbd7b
commit
8a9d2a6e9d
5 changed files with 42 additions and 30 deletions
45
CmdLine.hs
45
CmdLine.hs
|
@ -14,6 +14,7 @@ module CmdLine (
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import qualified Options.Applicative as O
|
import qualified Options.Applicative as O
|
||||||
|
import qualified Options.Applicative.Help as H
|
||||||
import qualified Control.Exception as E
|
import qualified Control.Exception as E
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
import Control.Exception (throw)
|
import Control.Exception (throw)
|
||||||
|
@ -32,8 +33,8 @@ import Command
|
||||||
import Types.Messages
|
import Types.Messages
|
||||||
|
|
||||||
{- Runs the passed command line. -}
|
{- Runs the passed command line. -}
|
||||||
dispatch :: Bool -> CmdParams -> [Command] -> [Option] -> [(String, String)] -> String -> IO Git.Repo -> IO ()
|
dispatch :: Bool -> CmdParams -> [Command] -> [Option] -> [(String, String)] -> IO Git.Repo -> String -> String -> IO ()
|
||||||
dispatch fuzzyok allargs allcmds commonoptions fields header getgitrepo = do
|
dispatch fuzzyok allargs allcmds commonoptions fields getgitrepo progname progdesc = do
|
||||||
setupConsole
|
setupConsole
|
||||||
go =<< (E.try getgitrepo :: IO (Either E.SomeException Git.Repo))
|
go =<< (E.try getgitrepo :: IO (Either E.SomeException Git.Repo))
|
||||||
where
|
where
|
||||||
|
@ -59,46 +60,52 @@ dispatch fuzzyok allargs allcmds commonoptions fields header getgitrepo = do
|
||||||
a
|
a
|
||||||
|
|
||||||
parsewith getparser ingitrepo =
|
parsewith getparser ingitrepo =
|
||||||
case parseCmd allargs allcmds getparser of
|
case parseCmd progname progdesc allargs allcmds getparser of
|
||||||
O.Failure _ -> do
|
O.Failure _ -> do
|
||||||
-- parse failed, so fall back to
|
-- parse failed, so fall back to
|
||||||
-- fuzzy matching, or to showing usage
|
-- fuzzy matching, or to showing usage
|
||||||
when fuzzy $
|
when fuzzy $
|
||||||
ingitrepo autocorrect
|
ingitrepo autocorrect
|
||||||
liftIO (O.handleParseResult (parseCmd (name:args) allcmds getparser))
|
liftIO (O.handleParseResult (parseCmd progname progdesc correctedargs allcmds getparser))
|
||||||
res -> liftIO (O.handleParseResult res)
|
res -> liftIO (O.handleParseResult res)
|
||||||
where
|
where
|
||||||
autocorrect = Git.AutoCorrect.prepare inputcmdname cmdname cmds
|
autocorrect = Git.AutoCorrect.prepare (fromJust inputcmdname) cmdname cmds
|
||||||
err msg = msg ++ "\n\n" ++ usage header allcmds
|
(fuzzy, cmds, inputcmdname, args) = findCmd fuzzyok allargs allcmds
|
||||||
(fuzzy, cmds, inputcmdname, args) = findCmd fuzzyok allargs allcmds err
|
|
||||||
name
|
name
|
||||||
| fuzzy = case cmds of
|
| fuzzy = case cmds of
|
||||||
(c:_) -> cmdname c
|
(c:_) -> Just (cmdname c)
|
||||||
_ -> inputcmdname
|
_ -> inputcmdname
|
||||||
| otherwise = inputcmdname
|
| otherwise = inputcmdname
|
||||||
|
correctedargs = case name of
|
||||||
|
Nothing -> allargs
|
||||||
|
Just n -> n:args
|
||||||
|
|
||||||
{- Parses command line, selecting one of the commands from the list. -}
|
{- Parses command line, selecting one of the commands from the list. -}
|
||||||
parseCmd :: CmdParams -> [Command] -> (Command -> O.Parser v) -> O.ParserResult (Command, v)
|
parseCmd :: String -> String -> CmdParams -> [Command] -> (Command -> O.Parser v) -> O.ParserResult (Command, v)
|
||||||
parseCmd allargs allcmds getparser = O.execParserPure (O.prefs O.idm) pinfo allargs
|
parseCmd progname progdesc allargs allcmds getparser = O.execParserPure (O.prefs O.idm) pinfo allargs
|
||||||
where
|
where
|
||||||
pinfo = O.info (O.helper <*> subcmds) O.fullDesc
|
pinfo = O.info (O.helper <*> subcmds) (O.progDescDoc (Just intro))
|
||||||
subcmds = O.hsubparser $ mconcat $ map mkcommand allcmds
|
subcmds = O.hsubparser $ mconcat $ map mkcommand allcmds
|
||||||
mkcommand c = O.command (cmdname c) $ O.info (mkparser c)
|
mkcommand c = O.command (cmdname c) $ O.info (mkparser c) $ O.fullDesc
|
||||||
(O.fullDesc <> O.header (cmddesc c) <> O.progDesc (cmddesc c))
|
<> O.header (synopsis (progname ++ " " ++ cmdname c) (cmddesc c))
|
||||||
|
<> O.footer ("For details, run: " ++ progname ++ " help " ++ cmdname c)
|
||||||
mkparser c = (,)
|
mkparser c = (,)
|
||||||
<$> pure c
|
<$> pure c
|
||||||
<*> getparser c
|
<*> getparser c
|
||||||
|
synopsis n d = n ++ " - " ++ d
|
||||||
|
intro = mconcat $ concatMap (\l -> [H.text l, H.line])
|
||||||
|
(synopsis progname progdesc : commandList allcmds)
|
||||||
|
|
||||||
{- Parses command line params far enough to find the Command to run, and
|
{- Parses command line params far enough to find the Command to run, and
|
||||||
- returns the remaining params.
|
- returns the remaining params.
|
||||||
- Does fuzzy matching if necessary, which may result in multiple Commands. -}
|
- Does fuzzy matching if necessary, which may result in multiple Commands. -}
|
||||||
findCmd :: Bool -> CmdParams -> [Command] -> (String -> String) -> (Bool, [Command], String, CmdParams)
|
findCmd :: Bool -> CmdParams -> [Command] -> (Bool, [Command], Maybe String, CmdParams)
|
||||||
findCmd fuzzyok argv cmds err
|
findCmd fuzzyok argv cmds
|
||||||
| isNothing name = error $ err "missing command"
|
| not (null exactcmds) = ret (False, exactcmds)
|
||||||
| not (null exactcmds) = (False, exactcmds, fromJust name, args)
|
| fuzzyok && not (null inexactcmds) = ret (True, inexactcmds)
|
||||||
| fuzzyok && not (null inexactcmds) = (True, inexactcmds, fromJust name, args)
|
| otherwise = ret (False, [])
|
||||||
| otherwise = error $ err $ "unknown command " ++ fromJust name
|
|
||||||
where
|
where
|
||||||
|
ret (fuzzy, matches) = (fuzzy, matches, name, args)
|
||||||
(name, args) = findname argv []
|
(name, args) = findname argv []
|
||||||
findname [] c = (Nothing, reverse c)
|
findname [] c = (Nothing, reverse c)
|
||||||
findname (a:as) c
|
findname (a:as) c
|
||||||
|
|
|
@ -19,6 +19,7 @@ import qualified Command.Add
|
||||||
import qualified Command.Unannex
|
import qualified Command.Unannex
|
||||||
import qualified Command.Fsck
|
import qualified Command.Fsck
|
||||||
{-
|
{-
|
||||||
|
import qualified Command.Help
|
||||||
import qualified Command.Drop
|
import qualified Command.Drop
|
||||||
import qualified Command.Move
|
import qualified Command.Move
|
||||||
import qualified Command.Copy
|
import qualified Command.Copy
|
||||||
|
@ -97,7 +98,6 @@ import qualified Command.Proxy
|
||||||
import qualified Command.DiffDriver
|
import qualified Command.DiffDriver
|
||||||
import qualified Command.Undo
|
import qualified Command.Undo
|
||||||
import qualified Command.Version
|
import qualified Command.Version
|
||||||
import qualified Command.Help
|
|
||||||
#ifdef WITH_ASSISTANT
|
#ifdef WITH_ASSISTANT
|
||||||
import qualified Command.Watch
|
import qualified Command.Watch
|
||||||
import qualified Command.Assistant
|
import qualified Command.Assistant
|
||||||
|
@ -124,6 +124,7 @@ cmds =
|
||||||
[ Command.Add.cmd
|
[ Command.Add.cmd
|
||||||
, Command.Fsck.cmd
|
, Command.Fsck.cmd
|
||||||
{-
|
{-
|
||||||
|
, Command.Help.cmd
|
||||||
, Command.Get.cmd
|
, Command.Get.cmd
|
||||||
, Command.Drop.cmd
|
, Command.Drop.cmd
|
||||||
, Command.Move.cmd
|
, Command.Move.cmd
|
||||||
|
@ -204,7 +205,6 @@ cmds =
|
||||||
, Command.DiffDriver.cmd
|
, Command.DiffDriver.cmd
|
||||||
, Command.Undo.cmd
|
, Command.Undo.cmd
|
||||||
, Command.Version.cmd
|
, Command.Version.cmd
|
||||||
, Command.Help.cmd
|
|
||||||
#ifdef WITH_ASSISTANT
|
#ifdef WITH_ASSISTANT
|
||||||
, Command.Watch.cmd
|
, Command.Watch.cmd
|
||||||
, Command.Assistant.cmd
|
, Command.Assistant.cmd
|
||||||
|
@ -224,9 +224,6 @@ cmds =
|
||||||
-}
|
-}
|
||||||
]
|
]
|
||||||
|
|
||||||
header :: String
|
|
||||||
header = "git-annex command [option ...]"
|
|
||||||
|
|
||||||
run :: [String] -> IO ()
|
run :: [String] -> IO ()
|
||||||
run args = do
|
run args = do
|
||||||
#ifdef WITH_EKG
|
#ifdef WITH_EKG
|
||||||
|
@ -234,7 +231,9 @@ run args = do
|
||||||
#endif
|
#endif
|
||||||
go envmodes
|
go envmodes
|
||||||
where
|
where
|
||||||
go [] = dispatch True args cmds gitAnnexOptions [] header Git.CurrentRepo.get
|
go [] = dispatch True args cmds gitAnnexOptions [] Git.CurrentRepo.get
|
||||||
|
"git-annex"
|
||||||
|
"manage files with git, without checking their contents in"
|
||||||
go ((v, a):rest) = maybe (go rest) a =<< getEnv v
|
go ((v, a):rest) = maybe (go rest) a =<< getEnv v
|
||||||
envmodes =
|
envmodes =
|
||||||
[ (sshOptionsEnv, runSshOptions args)
|
[ (sshOptionsEnv, runSshOptions args)
|
||||||
|
|
|
@ -101,7 +101,9 @@ builtin cmd dir params = do
|
||||||
let (params', fieldparams, opts) = partitionParams params
|
let (params', fieldparams, opts) = partitionParams params
|
||||||
rsyncopts = ("RsyncOptions", unwords opts)
|
rsyncopts = ("RsyncOptions", unwords opts)
|
||||||
fields = rsyncopts : filter checkField (parseFields fieldparams)
|
fields = rsyncopts : filter checkField (parseFields fieldparams)
|
||||||
dispatch False (cmd : params') cmds options fields header mkrepo
|
dispatch False (cmd : params') cmds options fields mkrepo
|
||||||
|
"git-annex-shell"
|
||||||
|
"Restricted login shell for git-annex only SSH access"
|
||||||
where
|
where
|
||||||
mkrepo = do
|
mkrepo = do
|
||||||
r <- Git.Construct.repoAbsPath dir >>= Git.Construct.fromAbsPath
|
r <- Git.Construct.repoAbsPath dir >>= Git.Construct.fromAbsPath
|
||||||
|
|
|
@ -13,9 +13,12 @@ import Types.Command
|
||||||
usageMessage :: String -> String
|
usageMessage :: String -> String
|
||||||
usageMessage s = "Usage: " ++ s
|
usageMessage s = "Usage: " ++ s
|
||||||
|
|
||||||
{- Usage message with lists of commands by section. -}
|
|
||||||
usage :: String -> [Command] -> String
|
usage :: String -> [Command] -> String
|
||||||
usage header cmds = unlines $ usageMessage header : concatMap go [minBound..]
|
usage header cmds = unlines $ usageMessage header : commandList cmds
|
||||||
|
|
||||||
|
{- Commands listed by section, with breif usage and description. -}
|
||||||
|
commandList :: [Command] -> [String]
|
||||||
|
commandList cmds = concatMap go [minBound..]
|
||||||
where
|
where
|
||||||
go section
|
go section
|
||||||
| null cs = []
|
| null cs = []
|
||||||
|
@ -39,6 +42,7 @@ usage header cmds = unlines $ usageMessage header : concatMap go [minBound..]
|
||||||
longest f = foldl max 0 $ map (length . f) cmds
|
longest f = foldl max 0 $ map (length . f) cmds
|
||||||
scmds = sort cmds
|
scmds = sort cmds
|
||||||
|
|
||||||
|
|
||||||
{- Descriptions of params used in usage messages. -}
|
{- Descriptions of params used in usage messages. -}
|
||||||
paramPaths :: String
|
paramPaths :: String
|
||||||
paramPaths = paramRepeating paramPath -- most often used
|
paramPaths = paramRepeating paramPath -- most often used
|
||||||
|
|
|
@ -56,8 +56,8 @@ showGeneralHelp = putStrLn $ unlines
|
||||||
, Command.Whereis.cmd
|
, Command.Whereis.cmd
|
||||||
, Command.Fsck.cmd
|
, Command.Fsck.cmd
|
||||||
]
|
]
|
||||||
, "Run 'git-annex' for a complete command list."
|
, "For a complete command list, run: git-annex"
|
||||||
, "Run 'git-annex help command' for help on a specific command."
|
, "For help on a specific command, run: git-annex help COMMAND"
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
cmdline c = "\t" ++ cmdname c ++ "\t" ++ cmddesc c
|
cmdline c = "\t" ++ cmdname c ++ "\t" ++ cmddesc c
|
||||||
|
|
Loading…
Reference in a new issue