{-# LANGUAGE ScopedTypeVariables, CPP #-}
module System.Console.CmdArgs.Explicit(
process, processArgs, processValue, processValueIO,
module System.Console.CmdArgs.Explicit.Type,
flagHelpSimple, flagHelpFormat, flagVersion, flagNumericVersion, flagsVerbosity,
module System.Console.CmdArgs.Explicit.Help,
module System.Console.CmdArgs.Explicit.ExpandArgsAt,
module System.Console.CmdArgs.Explicit.SplitJoin,
Complete(..), complete
) where
import System.Console.CmdArgs.Explicit.Type
import System.Console.CmdArgs.Explicit.Process
import System.Console.CmdArgs.Explicit.Help
import System.Console.CmdArgs.Explicit.ExpandArgsAt
import System.Console.CmdArgs.Explicit.SplitJoin
import System.Console.CmdArgs.Explicit.Complete
import System.Console.CmdArgs.Default
import System.Console.CmdArgs.Helper
import System.Console.CmdArgs.Text
import System.Console.CmdArgs.Verbosity
import Control.Monad
import Data.Char
import Data.Maybe
import System.Environment
import System.Exit
import System.IO
processArgs :: Mode a -> IO a
processArgs :: Mode a -> IO a
processArgs Mode a
m = do
[(String, String)]
env <- IO [(String, String)]
getEnvironment
case String -> [(String, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"CMDARGS_COMPLETE" [(String, String)]
env of
Just String
x -> do
[String]
args <- IO [String]
getArgs
let argInd :: Int
argInd = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
args Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (Maybe Int -> Int) -> Maybe Int -> Int
forall a b. (a -> b) -> a -> b
$ String -> Maybe Int
forall a. Read a => String -> Maybe a
readMay String
x
argPos :: Int
argPos = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe (if Int
argInd Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
argInd Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
args then String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String]
args [String] -> Int -> String
forall a. [a] -> Int -> a
!! Int
argInd) else Int
0) (Maybe Int -> Int) -> Maybe Int -> Int
forall a b. (a -> b) -> a -> b
$
String -> Maybe Int
forall a. Read a => String -> Maybe a
readMay (String -> Maybe Int) -> Maybe String -> Maybe Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< String -> [(String, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"CMDARGS_COMPLETE_POS" [(String, String)]
env
[Complete] -> IO ()
forall a. Show a => a -> IO ()
print ([Complete] -> IO ()) -> [Complete] -> IO ()
forall a b. (a -> b) -> a -> b
$ Mode a -> [String] -> (Int, Int) -> [Complete]
forall a. Mode a -> [String] -> (Int, Int) -> [Complete]
complete Mode a
m ((String -> [String]) -> [String] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap String -> [String]
words [String]
args) (Int
argInd,Int
argPos)
ExitCode -> IO a
forall a. ExitCode -> IO a
exitWith ExitCode
ExitSuccess
Maybe String
Nothing -> do
String
nam <- IO String
getProgName
let var :: Maybe String
var = Maybe String -> Maybe String -> Maybe String
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus (String -> [(String, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (String
"CMDARGS_HELPER_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
forall a. Show a => a -> String
show ((Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toUpper (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall a. [a] -> a
head ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ Mode a -> [String]
forall a. Mode a -> [String]
modeNames Mode a
m [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
nam])) [(String, String)]
env)
(String -> [(String, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"CMDARGS_HELPER" [(String, String)]
env)
case Maybe String
var of
Maybe String
Nothing -> Mode a -> [String] -> IO a
forall a. Mode a -> [String] -> IO a
processValueIO Mode a
m ([String] -> IO a) -> IO [String] -> IO a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (if Mode a -> Bool
forall a. Mode a -> Bool
modeExpandAt Mode a
m then [String] -> IO [String]
expandArgsAt else [String] -> IO [String]
forall (m :: * -> *) a. Monad m => a -> m a
return) ([String] -> IO [String]) -> IO [String] -> IO [String]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO [String]
getArgs
Just String
cmd -> do
Either String [String]
res <- String -> Mode a -> [String] -> IO (Either String [String])
forall a.
String -> Mode a -> [String] -> IO (Either String [String])
execute String
cmd Mode a
m []
case Either String [String]
res of
Left String
err -> do
Handle -> String -> IO ()
hPutStrLn Handle
stderr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Error when running helper " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cmd
Handle -> String -> IO ()
hPutStrLn Handle
stderr String
err
IO a
forall a. IO a
exitFailure
Right [String]
args -> Mode a -> [String] -> IO a
forall a. Mode a -> [String] -> IO a
processValueIO Mode a
m [String]
args
readMay :: Read a => String -> Maybe a
readMay :: String -> Maybe a
readMay String
s = case [a
x | (a
x,String
t) <- ReadS a
forall a. Read a => ReadS a
reads String
s, (String
"",String
"") <- ReadS String
lex String
t] of
[a
x] -> a -> Maybe a
forall a. a -> Maybe a
Just a
x
[a]
_ -> Maybe a
forall a. Maybe a
Nothing
#if __GLASGOW_HASKELL__ < 800
errorWithoutStackTrace :: String -> a
errorWithoutStackTrace = error
#endif
processValue :: Mode a -> [String] -> a
processValue :: Mode a -> [String] -> a
processValue Mode a
m [String]
xs = case Mode a -> [String] -> Either String a
forall a. Mode a -> [String] -> Either String a
process Mode a
m [String]
xs of
Left String
x -> String -> a
forall a. String -> a
errorWithoutStackTrace String
x
Right a
x -> a
x
processValueIO :: Mode a -> [String] -> IO a
processValueIO :: Mode a -> [String] -> IO a
processValueIO Mode a
m [String]
xs = case Mode a -> [String] -> Either String a
forall a. Mode a -> [String] -> Either String a
process Mode a
m [String]
xs of
Left String
x -> do Handle -> String -> IO ()
hPutStrLn Handle
stderr String
x; IO a
forall a. IO a
exitFailure
Right a
x -> a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x
flagHelpSimple :: (a -> a) -> Flag a
flagHelpSimple :: (a -> a) -> Flag a
flagHelpSimple a -> a
f = [String] -> (a -> a) -> String -> Flag a
forall a. [String] -> (a -> a) -> String -> Flag a
flagNone [String
"help",String
"?"] a -> a
f String
"Display help message"
flagHelpFormat :: (HelpFormat -> TextFormat -> a -> a) -> Flag a
flagHelpFormat :: (HelpFormat -> TextFormat -> a -> a) -> Flag a
flagHelpFormat HelpFormat -> TextFormat -> a -> a
f = (String -> [String] -> Update a -> String -> String -> Flag a
forall a.
String -> [String] -> Update a -> String -> String -> Flag a
flagOpt String
"" [String
"help",String
"?"] Update a
upd String
"" String
"Display help message"){flagInfo :: FlagInfo
flagInfo = String -> FlagInfo
FlagOptRare String
""}
where
upd :: Update a
upd String
s a
v = case String -> Either String (HelpFormat, TextFormat)
format String
s of
Left String
e -> String -> Either String a
forall a b. a -> Either a b
Left String
e
Right (HelpFormat
a,TextFormat
b) -> a -> Either String a
forall a b. b -> Either a b
Right (a -> Either String a) -> a -> Either String a
forall a b. (a -> b) -> a -> b
$ HelpFormat -> TextFormat -> a -> a
f HelpFormat
a TextFormat
b a
v
format :: String -> Either String (HelpFormat,TextFormat)
format :: String -> Either String (HelpFormat, TextFormat)
format String
xs = (Either String (HelpFormat, TextFormat)
-> String -> Either String (HelpFormat, TextFormat))
-> Either String (HelpFormat, TextFormat)
-> [String]
-> Either String (HelpFormat, TextFormat)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\Either String (HelpFormat, TextFormat)
acc String
x -> (String -> Either String (HelpFormat, TextFormat))
-> ((HelpFormat, TextFormat)
-> Either String (HelpFormat, TextFormat))
-> Either String (HelpFormat, TextFormat)
-> Either String (HelpFormat, TextFormat)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Either String (HelpFormat, TextFormat)
forall a b. a -> Either a b
Left (String
-> (HelpFormat, TextFormat)
-> Either String (HelpFormat, TextFormat)
f String
x) Either String (HelpFormat, TextFormat)
acc) ((HelpFormat, TextFormat) -> Either String (HelpFormat, TextFormat)
forall a b. b -> Either a b
Right (HelpFormat, TextFormat)
forall a. Default a => a
def) (String -> [String]
sep String
xs)
where
sep :: String -> [String]
sep = String -> [String]
words (String -> [String]) -> (String -> String) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map (\Char
x -> if Char
x Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
":," then Char
' ' else Char -> Char
toLower Char
x)
f :: String
-> (HelpFormat, TextFormat)
-> Either String (HelpFormat, TextFormat)
f String
x (HelpFormat
a,TextFormat
b) = case String
x of
String
"all" -> (HelpFormat, TextFormat) -> Either String (HelpFormat, TextFormat)
forall a b. b -> Either a b
Right (HelpFormat
HelpFormatAll,TextFormat
b)
String
"one" -> (HelpFormat, TextFormat) -> Either String (HelpFormat, TextFormat)
forall a b. b -> Either a b
Right (HelpFormat
HelpFormatOne,TextFormat
b)
String
"def" -> (HelpFormat, TextFormat) -> Either String (HelpFormat, TextFormat)
forall a b. b -> Either a b
Right (HelpFormat
HelpFormatDefault,TextFormat
b)
String
"html" -> (HelpFormat, TextFormat) -> Either String (HelpFormat, TextFormat)
forall a b. b -> Either a b
Right (HelpFormat
a,TextFormat
HTML)
String
"text" -> (HelpFormat, TextFormat) -> Either String (HelpFormat, TextFormat)
forall a b. b -> Either a b
Right (HelpFormat
a,TextFormat
defaultWrap)
String
"bash" -> (HelpFormat, TextFormat) -> Either String (HelpFormat, TextFormat)
forall a b. b -> Either a b
Right (HelpFormat
HelpFormatBash,Int -> TextFormat
Wrap Int
1000000)
String
"zsh" -> (HelpFormat, TextFormat) -> Either String (HelpFormat, TextFormat)
forall a b. b -> Either a b
Right (HelpFormat
HelpFormatZsh ,Int -> TextFormat
Wrap Int
1000000)
String
_ | (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isDigit String
x -> (HelpFormat, TextFormat) -> Either String (HelpFormat, TextFormat)
forall a b. b -> Either a b
Right (HelpFormat
a,Int -> TextFormat
Wrap (Int -> TextFormat) -> Int -> TextFormat
forall a b. (a -> b) -> a -> b
$ String -> Int
forall a. Read a => String -> a
read String
x)
String
_ -> String -> Either String (HelpFormat, TextFormat)
forall a b. a -> Either a b
Left String
"unrecognised help format, expected one of: all one def html text <NUMBER>"
flagVersion :: (a -> a) -> Flag a
flagVersion :: (a -> a) -> Flag a
flagVersion a -> a
f = [String] -> (a -> a) -> String -> Flag a
forall a. [String] -> (a -> a) -> String -> Flag a
flagNone [String
"version",String
"V"] a -> a
f String
"Print version information"
flagNumericVersion :: (a -> a) -> Flag a
flagNumericVersion :: (a -> a) -> Flag a
flagNumericVersion a -> a
f = [String] -> (a -> a) -> String -> Flag a
forall a. [String] -> (a -> a) -> String -> Flag a
flagNone [String
"numeric-version"] a -> a
f String
"Print just the version number"
flagsVerbosity :: (Verbosity -> a -> a) -> [Flag a]
flagsVerbosity :: (Verbosity -> a -> a) -> [Flag a]
flagsVerbosity Verbosity -> a -> a
f =
[[String] -> (a -> a) -> String -> Flag a
forall a. [String] -> (a -> a) -> String -> Flag a
flagNone [String
"verbose",String
"v"] (Verbosity -> a -> a
f Verbosity
Loud) String
"Loud verbosity"
,[String] -> (a -> a) -> String -> Flag a
forall a. [String] -> (a -> a) -> String -> Flag a
flagNone [String
"quiet",String
"q"] (Verbosity -> a -> a
f Verbosity
Quiet) String
"Quiet verbosity"]