summaryrefslogtreecommitdiff
path: root/CmdLine.hs
diff options
context:
space:
mode:
Diffstat (limited to 'CmdLine.hs')
-rw-r--r--CmdLine.hs100
1 files changed, 61 insertions, 39 deletions
diff --git a/CmdLine.hs b/CmdLine.hs
index cd7a1a986..492a3b75f 100644
--- a/CmdLine.hs
+++ b/CmdLine.hs
@@ -1,6 +1,6 @@
{- git-annex command line parsing and dispatch
-
- - Copyright 2010-2012 Joey Hess <id@joeyh.name>
+ - Copyright 2010-2015 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -13,10 +13,11 @@ module CmdLine (
shutdown
) where
+import qualified Options.Applicative as O
+import qualified Options.Applicative.Help as H
import qualified Control.Exception as E
import qualified Data.Map as M
import Control.Exception (throw)
-import System.Console.GetOpt
#ifndef mingw32_HOST_OS
import System.Posix.Signals
#endif
@@ -32,48 +33,81 @@ import Command
import Types.Messages
{- Runs the passed command line. -}
-dispatch :: Bool -> CmdParams -> [Command] -> [Option] -> [(String, String)] -> String -> IO Git.Repo -> IO ()
-dispatch fuzzyok allargs allcmds commonoptions fields header getgitrepo = do
+dispatch :: Bool -> CmdParams -> [Command] -> [GlobalOption] -> [(String, String)] -> IO Git.Repo -> String -> String -> IO ()
+dispatch fuzzyok allargs allcmds globaloptions fields getgitrepo progname progdesc = do
setupConsole
- case getOptCmd args cmd commonoptions of
- Right (flags, params) -> go flags params
- =<< (E.try getgitrepo :: IO (Either E.SomeException Git.Repo))
- Left parseerr -> error parseerr
+ go =<< (E.try getgitrepo :: IO (Either E.SomeException Git.Repo))
where
- go flags params (Right g) = do
+ go (Right g) = do
state <- Annex.new g
Annex.eval state $ do
checkEnvironment
- when fuzzy $
- inRepo $ autocorrect . Just
forM_ fields $ uncurry Annex.setField
+ (cmd, seek, globalconfig) <- parsewith cmdparser
+ (\a -> inRepo $ a . Just)
when (cmdnomessages cmd) $
Annex.setOutput QuietOutput
- sequence_ flags
+ getParsed globalconfig
whenM (annexDebug <$> Annex.getGitConfig) $
liftIO enableDebugOutput
startup
- performCommandAction cmd params $
+ performCommandAction cmd seek $
shutdown $ cmdnocommit cmd
- go _flags params (Left e) = do
- when fuzzy $
- autocorrect =<< Git.Config.global
- maybe (throw e) (\a -> a params) (cmdnorepo cmd)
- err msg = msg ++ "\n\n" ++ usage header allcmds
- cmd = Prelude.head cmds
- (fuzzy, cmds, name, args) = findCmd fuzzyok allargs allcmds err
- autocorrect = Git.AutoCorrect.prepare name cmdname cmds
+ go (Left norepo) = do
+ (_, a, _globalconfig) <- parsewith
+ (fromMaybe (throw norepo) . cmdnorepo)
+ (\a -> a =<< Git.Config.global)
+ a
+
+ parsewith getparser ingitrepo =
+ case parseCmd progname progdesc globaloptions allargs allcmds getparser of
+ O.Failure _ -> do
+ -- parse failed, so fall back to
+ -- fuzzy matching, or to showing usage
+ when fuzzy $
+ ingitrepo autocorrect
+ liftIO (O.handleParseResult (parseCmd progname progdesc globaloptions correctedargs allcmds getparser))
+ res -> liftIO (O.handleParseResult res)
+ where
+ autocorrect = Git.AutoCorrect.prepare (fromJust inputcmdname) cmdname cmds
+ (fuzzy, cmds, inputcmdname, args) = findCmd fuzzyok allargs allcmds
+ name
+ | fuzzy = case cmds of
+ (c:_) -> Just (cmdname c)
+ _ -> inputcmdname
+ | otherwise = inputcmdname
+ correctedargs = case name of
+ Nothing -> allargs
+ Just n -> n:args
+
+{- Parses command line, selecting one of the commands from the list. -}
+parseCmd :: String -> String -> [GlobalOption] -> CmdParams -> [Command] -> (Command -> O.Parser v) -> O.ParserResult (Command, v, GlobalSetter)
+parseCmd progname progdesc globaloptions allargs allcmds getparser =
+ O.execParserPure (O.prefs O.idm) pinfo allargs
+ where
+ pinfo = O.info (O.helper <*> subcmds) (O.progDescDoc (Just intro))
+ subcmds = O.hsubparser $ mconcat $ map mkcommand allcmds
+ mkcommand c = O.command (cmdname c) $ O.info (mkparser c) $ O.fullDesc
+ <> O.header (synopsis (progname ++ " " ++ cmdname c) (cmddesc c))
+ <> O.footer ("For details, run: " ++ progname ++ " help " ++ cmdname c)
+ mkparser c = (,,)
+ <$> pure c
+ <*> getparser c
+ <*> combineGlobalOptions globaloptions
+ 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
- returns the remaining params.
- Does fuzzy matching if necessary, which may result in multiple Commands. -}
-findCmd :: Bool -> CmdParams -> [Command] -> (String -> String) -> (Bool, [Command], String, CmdParams)
-findCmd fuzzyok argv cmds err
- | isNothing name = error $ err "missing command"
- | not (null exactcmds) = (False, exactcmds, fromJust name, args)
- | fuzzyok && not (null inexactcmds) = (True, inexactcmds, fromJust name, args)
- | otherwise = error $ err $ "unknown command " ++ fromJust name
+findCmd :: Bool -> CmdParams -> [Command] -> (Bool, [Command], Maybe String, CmdParams)
+findCmd fuzzyok argv cmds
+ | not (null exactcmds) = ret (False, exactcmds)
+ | fuzzyok && not (null inexactcmds) = ret (True, inexactcmds)
+ | otherwise = ret (False, [])
where
+ ret (fuzzy, matches) = (fuzzy, matches, name, args)
(name, args) = findname argv []
findname [] c = (Nothing, reverse c)
findname (a:as) c
@@ -84,18 +118,6 @@ findCmd fuzzyok argv cmds err
Nothing -> []
Just n -> Git.AutoCorrect.fuzzymatches n cmdname cmds
-{- Parses command line options, and returns actions to run to configure flags
- - and the remaining parameters for the command. -}
-getOptCmd :: CmdParams -> Command -> [Option] -> Either String ([Annex ()], CmdParams)
-getOptCmd argv cmd commonoptions = check $
- getOpt Permute (commonoptions ++ cmdoptions cmd) argv
- where
- check (flags, rest, []) = Right (flags, rest)
- check (_, _, errs) = Left $ unlines
- [ concat errs
- , commandUsage cmd
- ]
-
{- Actions to perform each time ran. -}
startup :: Annex ()
startup =