module Shebanger.Cli
( parseCliOpts
, Command (..)
, TranslateArgs (..)
, ExecArgs (..)
) where
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as ByteString.Char8
import Data.ByteString.Base64 (decode)
import Data.Version (showVersion)
import Control.Applicative ((<**>), Alternative (many, (<|>)))
import Options.Applicative
( action, argument, command, eitherReader, fullDesc, header, help, info,
metavar, progDesc, strArgument, execParser, helper, hsubparser,
simpleVersioner, CommandFields, Mod, Parser, ParserInfo
)
import Paths_shebanger (version)
data TranslateArgs = TranslateArgs { TranslateArgs -> String
scriptFilePath :: FilePath }
deriving stock Int -> TranslateArgs -> ShowS
[TranslateArgs] -> ShowS
TranslateArgs -> String
(Int -> TranslateArgs -> ShowS)
-> (TranslateArgs -> String)
-> ([TranslateArgs] -> ShowS)
-> Show TranslateArgs
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TranslateArgs -> ShowS
showsPrec :: Int -> TranslateArgs -> ShowS
$cshow :: TranslateArgs -> String
show :: TranslateArgs -> String
$cshowList :: [TranslateArgs] -> ShowS
showList :: [TranslateArgs] -> ShowS
Show
data ExecArgs = ExecArgs
{ ExecArgs -> ByteString
shebangScriptPart :: ByteString
, ExecArgs -> String
shebangScriptFilePath :: FilePath
, ExecArgs -> [String]
additionalArgs :: [String]
}
deriving stock Int -> ExecArgs -> ShowS
[ExecArgs] -> ShowS
ExecArgs -> String
(Int -> ExecArgs -> ShowS)
-> (ExecArgs -> String) -> ([ExecArgs] -> ShowS) -> Show ExecArgs
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ExecArgs -> ShowS
showsPrec :: Int -> ExecArgs -> ShowS
$cshow :: ExecArgs -> String
show :: ExecArgs -> String
$cshowList :: [ExecArgs] -> ShowS
showList :: [ExecArgs] -> ShowS
Show
data Command
= Translate TranslateArgs
| Exec ExecArgs
deriving stock Int -> Command -> ShowS
[Command] -> ShowS
Command -> String
(Int -> Command -> ShowS)
-> (Command -> String) -> ([Command] -> ShowS) -> Show Command
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Command -> ShowS
showsPrec :: Int -> Command -> ShowS
$cshow :: Command -> String
show :: Command -> String
$cshowList :: [Command] -> ShowS
showList :: [Command] -> ShowS
Show
parseCliOpts :: IO Command
parseCliOpts :: IO Command
parseCliOpts = ParserInfo Command -> IO Command
forall a. ParserInfo a -> IO a
execParser ParserInfo Command
cliCmdParserInfo
cliCmdParserInfo :: ParserInfo Command
cliCmdParserInfo :: ParserInfo Command
cliCmdParserInfo =
Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
info
( Parser Command
cliCmdParser Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**>
Parser (Command -> Command)
forall a. Parser (a -> a)
helper Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**>
String -> Parser (Command -> Command)
forall a. String -> Parser (a -> a)
simpleVersioner (Version -> String
showVersion Version
version)
)
( InfoMod Command
forall a. InfoMod a
fullDesc InfoMod Command -> InfoMod Command -> InfoMod Command
forall a. Semigroup a => a -> a -> a
<>
String -> InfoMod Command
forall a. String -> InfoMod a
header String
"shebanger - translate a shell script into a series of shebang lines"
)
cliCmdParser :: Parser Command
cliCmdParser :: Parser Command
cliCmdParser = Mod CommandFields Command -> Parser Command
forall a. Mod CommandFields a -> Parser a
hsubparser (Mod CommandFields Command
translateCommandMod Mod CommandFields Command
-> Mod CommandFields Command -> Mod CommandFields Command
forall a. Semigroup a => a -> a -> a
<> Mod CommandFields Command
execCommandMod) Parser Command -> Parser Command -> Parser Command
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Command
translateCommandParser
where
translateCommandMod :: Mod CommandFields Command
translateCommandMod :: Mod CommandFields Command
translateCommandMod =
String -> ParserInfo Command -> Mod CommandFields Command
forall a. String -> ParserInfo a -> Mod CommandFields a
command
String
"translate"
( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
info
Parser Command
translateCommandParser
(String -> InfoMod Command
forall a. String -> InfoMod a
progDesc String
"Translate a shell script into a series of scripts with only shebang lines")
)
execCommandMod :: Mod CommandFields Command
execCommandMod :: Mod CommandFields Command
execCommandMod =
String -> ParserInfo Command -> Mod CommandFields Command
forall a. String -> ParserInfo a -> Mod CommandFields a
command
String
"exec"
( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
info
((ExecArgs -> Command) -> Parser ExecArgs -> Parser Command
forall a b. (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ExecArgs -> Command
Exec Parser ExecArgs
execArgsParser)
(String -> InfoMod Command
forall a. String -> InfoMod a
progDesc String
"Execute shebanged shell scripts")
)
translateCommandParser :: Parser Command
translateCommandParser :: Parser Command
translateCommandParser = (TranslateArgs -> Command)
-> Parser TranslateArgs -> Parser Command
forall a b. (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap TranslateArgs -> Command
Translate Parser TranslateArgs
translateArgsParser
translateArgsParser :: Parser TranslateArgs
translateArgsParser :: Parser TranslateArgs
translateArgsParser = String -> TranslateArgs
TranslateArgs (String -> TranslateArgs) -> Parser String -> Parser TranslateArgs
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser String
inputFileParser
inputFileParser :: Parser FilePath
inputFileParser :: Parser String
inputFileParser =
Mod ArgumentFields String -> Parser String
forall s. IsString s => Mod ArgumentFields s -> Parser s
strArgument
( String -> Mod ArgumentFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FILE" Mod ArgumentFields String
-> Mod ArgumentFields String -> Mod ArgumentFields String
forall a. Semigroup a => a -> a -> a
<>
String -> Mod ArgumentFields String
forall (f :: * -> *) a. String -> Mod f a
help String
"Input shell scripts to shebang" Mod ArgumentFields String
-> Mod ArgumentFields String -> Mod ArgumentFields String
forall a. Semigroup a => a -> a -> a
<>
String -> Mod ArgumentFields String
forall (f :: * -> *) a. HasCompleter f => String -> Mod f a
action String
"file"
)
execArgsParser :: Parser ExecArgs
execArgsParser :: Parser ExecArgs
execArgsParser =
ByteString -> String -> [String] -> ExecArgs
ExecArgs
(ByteString -> String -> [String] -> ExecArgs)
-> Parser ByteString -> Parser (String -> [String] -> ExecArgs)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString
shebangedScriptParser
Parser (String -> [String] -> ExecArgs)
-> Parser String -> Parser ([String] -> ExecArgs)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser String
shebangScriptFilePathParser
Parser ([String] -> ExecArgs) -> Parser [String] -> Parser ExecArgs
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser [String]
additionalArgsParser
shebangedScriptParser :: Parser ByteString
shebangedScriptParser :: Parser ByteString
shebangedScriptParser =
ReadM ByteString
-> Mod ArgumentFields ByteString -> Parser ByteString
forall a. ReadM a -> Mod ArgumentFields a -> Parser a
argument
((String -> Either String ByteString) -> ReadM ByteString
forall a. (String -> Either String a) -> ReadM a
eitherReader String -> Either String ByteString
b64Reader)
( String -> Mod ArgumentFields ByteString
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"SHEBANG_SCRIPT_PART" Mod ArgumentFields ByteString
-> Mod ArgumentFields ByteString -> Mod ArgumentFields ByteString
forall a. Semigroup a => a -> a -> a
<>
String -> Mod ArgumentFields ByteString
forall (f :: * -> *) a. String -> Mod f a
help String
"Part of a shebang translated script file. Expected to be in base 64."
)
where
b64Reader :: String -> Either String ByteString
b64Reader :: String -> Either String ByteString
b64Reader String
b64Str = ByteString -> Either String ByteString
decode (ByteString -> Either String ByteString)
-> ByteString -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ String -> ByteString
ByteString.Char8.pack String
b64Str
shebangScriptFilePathParser :: Parser FilePath
shebangScriptFilePathParser :: Parser String
shebangScriptFilePathParser =
Mod ArgumentFields String -> Parser String
forall s. IsString s => Mod ArgumentFields s -> Parser s
strArgument
( String -> Mod ArgumentFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FILE" Mod ArgumentFields String
-> Mod ArgumentFields String -> Mod ArgumentFields String
forall a. Semigroup a => a -> a -> a
<>
String -> Mod ArgumentFields String
forall (f :: * -> *) a. String -> Mod f a
help String
"Input shebanged script name. Normally passed automatically by kernel." Mod ArgumentFields String
-> Mod ArgumentFields String -> Mod ArgumentFields String
forall a. Semigroup a => a -> a -> a
<>
String -> Mod ArgumentFields String
forall (f :: * -> *) a. HasCompleter f => String -> Mod f a
action String
"file"
)
additionalArgsParser :: Parser [String]
additionalArgsParser :: Parser [String]
additionalArgsParser =
Parser String -> Parser [String]
forall a. Parser a -> Parser [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (Parser String -> Parser [String])
-> Parser String -> Parser [String]
forall a b. (a -> b) -> a -> b
$
Mod ArgumentFields String -> Parser String
forall s. IsString s => Mod ArgumentFields s -> Parser s
strArgument
( String -> Mod ArgumentFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"ARG" Mod ArgumentFields String
-> Mod ArgumentFields String -> Mod ArgumentFields String
forall a. Semigroup a => a -> a -> a
<>
String -> Mod ArgumentFields String
forall (f :: * -> *) a. String -> Mod f a
help String
"arguments to pass to the underlying script being called"
)