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 /tprint | |
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
Diffstat (limited to 'tprint')
-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"; |