4 module Main (main) where
5 import Control.Applicative
7 import qualified Data.Ascii as A
10 import Language.Haskell.TH.PprLib
11 import Language.Haskell.TH.Syntax
12 import Network.HTTP.Lucu.ETag
13 import Network.HTTP.Lucu.Implant
14 import Network.HTTP.Lucu.Implant.PrettyPrint
15 import Network.HTTP.Lucu.MIMEType
16 import Prelude.Unicode
17 import System.Console.GetOpt
18 import System.Environment
31 options ∷ [OptDescr CmdOpt]
32 options = [ Option "o" ["output"]
33 (ReqArg OptOutput "FILE")
36 , Option "m" ["module"]
37 (ReqArg OptModName "MODULE")
38 "Specify the resulting module name. (required)"
40 , Option "s" ["symbol"]
41 (ReqArg OptSymName "SYMBOL")
42 "Specify the resulting symbol name."
44 , Option "t" ["mime-type"]
45 (ReqArg OptMIMEType "TYPE")
46 "Specify the MIME Type of the file."
49 (ReqArg OptETag "TAG")
50 "Specify the ETag of the file."
58 printUsage = do mapM_ putStrLn msg
59 putStr $ usageInfo "Options:" options
64 , concat [ " lucu-implant-file is an utility that generates "
65 , "Haskell code containing an arbitrary file to "
66 , "compile it directly into programs and serve it "
67 , "statically with the Lucu HTTP server."
71 , " lucu-implant-file [OPTIONS...] FILE"
76 main = do (opts, sources, errors) ← getOpt Permute options <$> getArgs
79 $ do mapM_ putStr errors
80 exitWith $ ExitFailure 1
82 when (any (≡ OptHelp) opts)
88 exitWith $ ExitFailure 1
90 when (length sources ≥ 2)
91 $ fail "too many input files."
93 generateHaskellSource opts (head sources)
95 getMIMEType ∷ [CmdOpt] → Maybe MIMEType
97 = case mimeTypeOpts of
100 → case A.fromChars ty of
101 Just a → Just $ parseMIMEType a
102 Nothing → error "MIME types must not contain any non-ASCII letters."
103 _ → error "too many --mime-type options."
105 mimeTypeOpts ∷ [CmdOpt]
107 = filter (\ x → case x of
111 getETag ∷ [CmdOpt] → Maybe ETag
115 OptETag str:[] → Just $ strToETag str
116 _ → error "too many --etag options."
119 eTagOpts = filter (\ x → case x of
123 strToETag ∷ String → ETag
125 = case A.fromChars str of
126 Just a → strongETag a
127 Nothing → error "ETag must not contain any non-ASCII letters."
129 openOutput ∷ [CmdOpt] → IO Handle
133 OptOutput fpath:[] → do h ← openFile fpath WriteMode
136 _ → fail "two many --output options."
138 outputOpts ∷ [CmdOpt]
139 outputOpts = filter (\ x → case x of
143 getModuleName ∷ [CmdOpt] → ModName
145 = case modNameOpts of
146 [] → error "a module name must be given."
147 OptModName name:[] → mkModName name
148 _ → error "too many --module options."
150 modNameOpts ∷ [CmdOpt]
151 modNameOpts = filter (\ x → case x of
155 getSymbolName ∷ [CmdOpt] → Maybe Name
157 = case symNameOpts of
159 OptSymName name:[] → Just $ mkName name
160 _ → fail "too many --symbol options."
162 symNameOpts ∷ [CmdOpt]
163 symNameOpts = filter (\ x → case x of
167 defaultSymName ∷ ModName → Name
168 defaultSymName = headToLower ∘ getLastComp
170 headToLower ∷ String → Name
171 headToLower [] = error "module name must not be empty"
172 headToLower (x:xs) = mkName (toLower x:xs)
174 getLastComp ∷ ModName → String
175 getLastComp = reverse ∘ fst ∘ break (≡ '.') ∘ reverse ∘ modString
177 generateHaskellSource ∷ [CmdOpt] → FilePath → IO ()
178 generateHaskellSource opts srcFile
179 = do i ← openInput srcFile (getMIMEType opts) (getETag opts)
181 doc ← pprInput i modName symName
182 hPutStrLn o ∘ show $ to_HPJ_Doc doc
186 modName = getModuleName opts
189 symName = fromMaybe (defaultSymName modName)