diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2016-03-01 06:25:23 +0100 |
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2016-03-01 06:25:23 +0100 |
| commit | fc83a7241e27574ef2bb81de206c59a9a854efe6 (patch) | |
| tree | a6bd70a3560012b408128c2df947f3f49c7f57e0 | |
| parent | c5758391f793fc3d7d177bdacf79aac72da979d5 (diff) | |
| download | thermoprint-fc83a7241e27574ef2bb81de206c59a9a854efe6.tar thermoprint-fc83a7241e27574ef2bb81de206c59a9a854efe6.tar.gz thermoprint-fc83a7241e27574ef2bb81de206c59a9a854efe6.tar.bz2 thermoprint-fc83a7241e27574ef2bb81de206c59a9a854efe6.tar.xz thermoprint-fc83a7241e27574ef2bb81de206c59a9a854efe6.zip | |
First work on argument parsing
| -rw-r--r-- | tprint/src/Main.hs | 164 | ||||
| -rw-r--r-- | tprint/tprint.cabal | 4 | ||||
| -rw-r--r-- | tprint/tprint.nix | 7 |
3 files changed, 171 insertions, 4 deletions
diff --git a/tprint/src/Main.hs b/tprint/src/Main.hs index e9e1deb..e8d4670 100644 --- a/tprint/src/Main.hs +++ b/tprint/src/Main.hs | |||
| @@ -1,2 +1,164 @@ | |||
| 1 | {-# LANGUAGE RecordWildCards #-} | ||
| 2 | {-# LANGUAGE StandaloneDeriving #-} | ||
| 3 | {-# LANGUAGE DeriveGeneric, DeriveAnyClass #-} | ||
| 4 | |||
| 5 | import Data.Map (Map) | ||
| 6 | import qualified Data.Map as Map | ||
| 7 | import Data.Sequence (Seq) | ||
| 8 | import qualified Data.Sequence as Seq | ||
| 9 | import Data.Text (Text) | ||
| 10 | import qualified Data.Text as T | ||
| 11 | import Data.Time | ||
| 12 | |||
| 13 | import Data.Foldable | ||
| 14 | import Data.Char | ||
| 15 | import Text.Read | ||
| 16 | import Data.Maybe | ||
| 17 | import Data.List | ||
| 18 | |||
| 19 | import GHC.Generics (Generic) | ||
| 20 | |||
| 21 | import Text.Show.Pretty (Value, PrettyVal(..), dumpStr) | ||
| 22 | import qualified Text.Show.Pretty as PShow (Value(..)) | ||
| 23 | |||
| 24 | import Thermoprint.Client | ||
| 25 | import Options.Applicative | ||
| 26 | |||
| 27 | import Debug.Trace | ||
| 28 | |||
| 29 | instance PrettyVal Scheme | ||
| 30 | instance PrettyVal BaseUrl | ||
| 31 | instance PrettyVal PrinterId | ||
| 32 | instance PrettyVal JobId | ||
| 33 | instance PrettyVal DraftId | ||
| 34 | instance PrettyVal a => PrettyVal (Range a) | ||
| 35 | |||
| 36 | instance PrettyVal UTCTime where | ||
| 37 | prettyVal = PShow.String . formatTime defaultTimeLocale "%Z %F %X" | ||
| 38 | |||
| 39 | instance PrettyVal Text where | ||
| 40 | prettyVal = prettyVal . T.unpack | ||
| 41 | |||
| 42 | data TPrint = TPrint | ||
| 43 | { baseUrl :: BaseUrl | ||
| 44 | , dryRun :: Bool | ||
| 45 | , output :: Output | ||
| 46 | , operation :: Operation | ||
| 47 | } | ||
| 48 | deriving (Show, Generic, PrettyVal) | ||
| 49 | |||
| 50 | data Operation | ||
| 51 | = Printers | ||
| 52 | | Jobs | ||
| 53 | { printer :: Maybe PrinterId | ||
| 54 | , jobRange :: Maybe (Range JobId) | ||
| 55 | , timeRange :: Maybe (Range UTCTime) | ||
| 56 | } | ||
| 57 | | JobCreate | ||
| 58 | { printer :: Maybe PrinterId | ||
| 59 | , input :: Input | ||
| 60 | } | ||
| 61 | | Job { jobId :: JobId } | ||
| 62 | | JobStatus { jobId :: JobId } | ||
| 63 | | JobDelete { jobId :: JobId } | ||
| 64 | | Drafts | ||
| 65 | | DraftCreate | ||
| 66 | { draftTitle :: Maybe DraftTitle | ||
| 67 | , input :: Input | ||
| 68 | } | ||
| 69 | | DraftReplace | ||
| 70 | { draftId :: DraftId | ||
| 71 | , draftTitle :: Maybe DraftTitle | ||
| 72 | , input :: Input | ||
| 73 | } | ||
| 74 | | Draft { draftId :: DraftId } | ||
| 75 | | DraftDelete { draftId :: DraftId } | ||
| 76 | | DraftPrint | ||
| 77 | { draftId :: DraftId | ||
| 78 | , printer :: Maybe PrinterId | ||
| 79 | } | ||
| 80 | deriving (Show, Generic, PrettyVal) | ||
| 81 | |||
| 82 | type Input = (Format, Source) | ||
| 83 | type Output = (Format, Sink ) | ||
| 84 | |||
| 85 | data Format = Human | BBCode | Internal | JSON | ||
| 86 | deriving (Enum, Bounded, Show, Read, Generic, PrettyVal) | ||
| 87 | |||
| 88 | data Source = Stdin | ReadFile FilePath | ||
| 89 | deriving (Show, Generic, PrettyVal) | ||
| 90 | |||
| 91 | data Sink = Stdout | WriteFile FilePath | ||
| 92 | deriving (Show, Generic, PrettyVal) | ||
| 93 | |||
| 94 | cmdPrinters :: ParserInfo Operation | ||
| 95 | cmdPrinters = info cmdPrinters' $ mconcat [ header "List all available printers" | ||
| 96 | ] | ||
| 97 | where cmdPrinters' = pure Printers | ||
| 98 | |||
| 99 | cmdJobs :: ParserInfo Operation | ||
| 100 | cmdJobs = info cmdJobs' $ mconcat [ header "List printjobs" | ||
| 101 | ] | ||
| 102 | where | ||
| 103 | cmdJobs' = Jobs | ||
| 104 | <$> optional (option (PrinterId <$> auto) $ metavar "PRINTER" <> long "printer" <> short 'p' <> help "List only jobs associated with printer #PRINTER") | ||
| 105 | <*> pRange (JobId <$> auto) (metavar "JOB") (long "min-job" <> short 'j' <> help "List only jobs with id greater than or equal to JOB") (long "max-job" <> short 'J' <> help "List only jobs with id less than or equal to JOB") | ||
| 106 | <*> pRange rTime (metavar "TIME") (long "min-time" <> short 't' <> help "List only jobs created after or at TIME") (long "max-time" <> short 'T' <> help "List only jobs created before or at TIME") | ||
| 107 | |||
| 108 | pOperation :: Parser Operation | ||
| 109 | pOperation = hsubparser $ mconcat [ command "printers" cmdPrinters | ||
| 110 | , command "jobs" cmdJobs | ||
| 111 | ] | ||
| 112 | |||
| 113 | pTPrint :: Parser TPrint | ||
| 114 | pTPrint = TPrint <$> option (eitherReader parseBaseUrl) (metavar "URL" <> long "baseurl" <> short 'u' <> help "Server to interact with" <> value (BaseUrl Http "localhost" 3000) <> showDefaultWith showBaseUrl) | ||
| 115 | <*> switch (long "dry-run" <> short 'n' <> help "Don't send any requests that would be expected to change the servers state" <> showDefault) | ||
| 116 | <*> pOutput | ||
| 117 | <*> pOperation | ||
| 118 | |||
| 119 | pOutput :: Parser Output | ||
| 120 | pOutput = (,) <$> pOutputFormat <*> pSink | ||
| 121 | where | ||
| 122 | pOutputFormat = option ciAuto $ metavar "FORMAT" <> long "output-format" <> short 'O' <> help ("Format to use for all output (possible values: " ++ show ([minBound..maxBound] :: [Format]) ++ ")") <> value Human <> showDefault | ||
| 123 | pSink = option rSink $ metavar "PATH" <> long "output" <> short 'o' <> help "Send output to PATH (`-' means stdout)" <> value Stdout <> showDefault | ||
| 124 | rSink = rSink' <$> str | ||
| 125 | where | ||
| 126 | rSink' "-" = Stdout | ||
| 127 | rSink' x = WriteFile x | ||
| 128 | |||
| 129 | ciAuto :: (Read a, Show a) => ReadM a | ||
| 130 | ciAuto = eitherReader rRep' | ||
| 131 | where | ||
| 132 | rRep' str = case mapMaybe readMaybe $ cases str of | ||
| 133 | [] -> Left $ "Could not parse `" ++ str ++ "'" | ||
| 134 | [x] -> Right x | ||
| 135 | xs -> Left $ "Ambiguous parse for `" ++ str ++ "': " ++ show xs | ||
| 136 | cases [] = [] | ||
| 137 | cases (c:cs) = [(c':cs') | c' <- [toLower c, toUpper c], cs' <- cases cs] | ||
| 138 | |||
| 139 | rTime :: ReadM UTCTime | ||
| 140 | rTime = eitherReader rTime' | ||
| 141 | where | ||
| 142 | rTime' str = maybe (Left $ "Could not parse `" ++ str ++ "' as a specification of time -- try the output of `date -u +'%Y-%m-%d %H:%M:%S' \"" ++ str ++ "\"`") Right | ||
| 143 | . foldr (<|>) Nothing | ||
| 144 | $ map (flip (parseTimeM True defaultTimeLocale) str) ( "%c" : "%s" : perms' [ [time, date, timezone] | time <- ["%T", "%X", "%I:%M:%S", "%r", "%X%Q", "%I:%M:%S%Q %p"], date <- ["%x", "%F"], timezone <- ["%z", "%Z"]] ) | ||
| 145 | perms' :: [[String]] -> [String] | ||
| 146 | perms' = map unwords . concatMap subsequences . concatMap permutations | ||
| 147 | |||
| 148 | pRange :: ReadM a | ||
| 149 | -> Mod OptionFields a -- ^ Modifiers applied to both min & max | ||
| 150 | -> Mod OptionFields a -- ^ Modifiers for minimum | ||
| 151 | -> Mod OptionFields a -- ^ Modifiers for maximum | ||
| 152 | -> Parser (Maybe (Range a)) | ||
| 153 | pRange r both min max = toRange <$> optional (option r (both <> min)) <*> optional (option r (both <> max)) | ||
| 154 | where | ||
| 155 | toRange Nothing Nothing = Nothing | ||
| 156 | toRange (Just min) Nothing = Just $ Min min | ||
| 157 | toRange Nothing (Just max) = Just $ Max max | ||
| 158 | toRange (Just min) (Just max) = Just $ min `Through` max | ||
| 159 | |||
| 1 | main :: IO () | 160 | main :: IO () |
| 2 | main = undefined | 161 | main = customExecParser (prefs $ showHelpOnError) (info pTPrint $ header "tprint - A cli interface to Thermoprint.Client") >>= tprint |
| 162 | |||
| 163 | tprint :: TPrint -> IO () | ||
| 164 | tprint = putStrLn . dumpStr -- *DEBUG* | ||
diff --git a/tprint/tprint.cabal b/tprint/tprint.cabal index e7a5797..d61ea01 100644 --- a/tprint/tprint.cabal +++ b/tprint/tprint.cabal | |||
| @@ -24,6 +24,10 @@ executable tprint | |||
| 24 | , thermoprint-bbcode >=1.0.0 && <2 | 24 | , thermoprint-bbcode >=1.0.0 && <2 |
| 25 | , thermoprint-client ==0.0.* | 25 | , thermoprint-client ==0.0.* |
| 26 | , optparse-applicative >=0.12.1 && <1 | 26 | , optparse-applicative >=0.12.1 && <1 |
| 27 | , containers >=0.5.6 && <1 | ||
| 28 | , time >=1.5.0 && <2 | ||
| 29 | , pretty-show >=1.6.9 && <2 | ||
| 30 | , text -any | ||
| 27 | hs-source-dirs: src | 31 | hs-source-dirs: src |
| 28 | default-language: Haskell2010 | 32 | default-language: Haskell2010 |
| 29 | ghc-options: -Wall \ No newline at end of file | 33 | ghc-options: -Wall \ No newline at end of file |
diff --git a/tprint/tprint.nix b/tprint/tprint.nix index 413774a..9954b02 100644 --- a/tprint/tprint.nix +++ b/tprint/tprint.nix | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | { mkDerivation, base, optparse-applicative, stdenv | 1 | { mkDerivation, base, containers, optparse-applicative, pretty-show |
| 2 | , thermoprint-bbcode, thermoprint-client | 2 | , stdenv, thermoprint-bbcode, thermoprint-client, time |
| 3 | }: | 3 | }: |
| 4 | mkDerivation { | 4 | mkDerivation { |
| 5 | pname = "tprint"; | 5 | pname = "tprint"; |
| @@ -8,7 +8,8 @@ mkDerivation { | |||
| 8 | isLibrary = false; | 8 | isLibrary = false; |
| 9 | isExecutable = true; | 9 | isExecutable = true; |
| 10 | executableHaskellDepends = [ | 10 | executableHaskellDepends = [ |
| 11 | base optparse-applicative thermoprint-bbcode thermoprint-client | 11 | base containers optparse-applicative pretty-show thermoprint-bbcode |
| 12 | thermoprint-client time | ||
| 12 | ]; | 13 | ]; |
| 13 | homepage = "http://dirty-haskell.org/tags/thermoprint.html"; | 14 | homepage = "http://dirty-haskell.org/tags/thermoprint.html"; |
| 14 | description = "A CLI for thermoprint-client"; | 15 | description = "A CLI for thermoprint-client"; |
