Skip to content
This repository was archived by the owner on May 1, 2020. It is now read-only.

Commit 20eda91

Browse files
committed
Refactoring options
Using a typeclass approach for generating command line arguments from options.
1 parent ed6f8cf commit 20eda91

File tree

1 file changed

+80
-70
lines changed

1 file changed

+80
-70
lines changed

src/Options.purs

Lines changed: 80 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ newtype Psc
9696
, output :: NullOrUndefined String
9797
, externs :: NullOrUndefined String
9898
, noPrefix :: NullOrUndefined Boolean
99-
, ffi :: NullOrUndefined [String]
99+
, ffi :: NullOrUndefined PathArray
100100
}
101101

102102
newtype PscMake
@@ -108,14 +108,18 @@ newtype PscMake
108108
, comments :: NullOrUndefined Boolean
109109
, noPrefix :: NullOrUndefined Boolean
110110
, output :: NullOrUndefined String
111-
, ffi :: NullOrUndefined [String]
111+
, ffi :: NullOrUndefined PathArray
112112
}
113113

114114
newtype PscDocs
115115
= PscDocs { format :: NullOrUndefined Format
116-
, docgen :: NullOrUndefined Foreign
116+
, docgen :: NullOrUndefined Docgen
117117
}
118118

119+
newtype Docgen = Docgen Foreign
120+
121+
newtype PathArray = PathArray [String]
122+
119123
data Format = Markdown | ETags | CTags
120124

121125
instance isForeignEither :: (IsForeign a, IsForeign b) => IsForeign (Either a b) where
@@ -181,53 +185,39 @@ instance isForeignPscDocs :: IsForeign PscDocs where
181185
} <$> readProp formatKey obj
182186
<*> readProp docgenOpt obj)
183187

188+
instance isForeignPathArray :: IsForeign PathArray where
189+
read val = PathArray <$> read val
190+
191+
instance isForeignDocgen :: IsForeign Docgen where
192+
read val = Docgen <$> read val
193+
184194
instance isForeignFormat :: IsForeign Format where
185195
read val = read val >>= (\a -> case a of
186196
"markdown" -> Right Markdown
187197
"etags" -> Right ETags
188198
"ctags" -> Right CTags
189199
a -> Left $ TypeMismatch "Format" a)
190200

191-
mkBoolean :: String -> NullOrUndefined Boolean -> [String]
192-
mkBoolean key opt = maybe [] (\a -> if a then ["--" ++ key] else []) (runNullOrUndefined opt)
193-
194-
mkString :: String -> NullOrUndefined String -> [String]
195-
mkString key opt = maybe [] (\a -> ["--" ++ key ++ "=" ++ a]) (runNullOrUndefined opt)
196-
197-
mkBooleanString :: String -> NullOrUndefined (Either Boolean String) -> [String]
198-
mkBooleanString key opt = maybe [] (either (\a -> mkBoolean key (NullOrUndefined $ Just a))
199-
(\a -> mkString key (NullOrUndefined $ Just a)))
200-
(runNullOrUndefined opt)
201-
202-
mkStringArray :: String -> NullOrUndefined [String] -> [String]
203-
mkStringArray key opt = concat $ mkString key <$> (NullOrUndefined <<< Just)
204-
<$> (fromMaybe [] $ runNullOrUndefined opt)
201+
class CommandLineOption a where
202+
opt :: String -> NullOrUndefined a -> [String]
205203

206-
mkPathArray :: String -> NullOrUndefined [String] -> [String]
207-
mkPathArray key opt = concat $ mkString key <$> (NullOrUndefined <<< Just)
208-
<$> (fromMaybe [] (runNullOrUndefined opt) >>= expandGlob)
204+
instance commandLineOptionBoolean :: CommandLineOption Boolean where
205+
opt key val = maybe [] (\a -> if a then ["--" ++ key] else []) (runNullOrUndefined val)
209206

210-
mkDocgen :: String -> NullOrUndefined Foreign -> [String]
211-
mkDocgen key opt = concat $ mkString key <$> (NullOrUndefined <<< Just)
212-
<$> (maybe [] parse (runNullOrUndefined opt))
213-
where
214-
parse :: Foreign -> [String]
215-
parse obj = either (const []) id $ parseName obj
216-
<|> parseList obj
217-
<|> parseObj obj
218-
<|> pure []
219-
220-
parseName :: Foreign -> F [String]
221-
parseName obj = singleton <$> read obj
207+
instance commandLineOptionString :: CommandLineOption String where
208+
opt key val = maybe [] (\a -> ["--" ++ key ++ "=" ++ a]) (runNullOrUndefined val)
222209

223-
parseList :: Foreign -> F [String]
224-
parseList obj = read obj
210+
instance commandLineOptionEither :: (CommandLineOption a, CommandLineOption b) => CommandLineOption (Either a b) where
211+
opt key val = maybe [] (either (\a -> opt key (NullOrUndefined $ Just a))
212+
(\a -> opt key (NullOrUndefined $ Just a)))
213+
(runNullOrUndefined val)
225214

226-
parseObj :: Foreign -> F [String]
227-
parseObj obj = do
228-
modules <- keys obj
229-
for modules \m -> (\f -> m ++ ":" ++ f) <$> readProp m obj
215+
instance commandLineOptionArray :: (CommandLineOption a) => CommandLineOption [a] where
216+
opt key val = concat $ opt key <$> (NullOrUndefined <<< Just)
217+
<$> (fromMaybe [] $ runNullOrUndefined val)
230218

219+
instance commandLineOptionPathArray :: CommandLineOption PathArray where
220+
opt key val = opt key (NullOrUndefined ((\(PathArray a) -> a >>= expandGlob) <$> (runNullOrUndefined val)))
231221

232222
foreign import expandGlob
233223
"""
@@ -239,29 +229,49 @@ foreign import expandGlob
239229
}());
240230
""" :: String -> [String]
241231

242-
mkFormat :: String -> NullOrUndefined Format -> [String]
243-
mkFormat key opt = mkString key (maybe j (\a -> case a of
244-
Markdown -> i "markdown"
245-
ETags -> i "etags"
246-
CTags -> i "ctags") $ runNullOrUndefined opt)
247-
where i a = NullOrUndefined $ Just a
248-
j = NullOrUndefined Nothing
232+
instance commandLineOptionDocgen :: CommandLineOption Docgen where
233+
opt key val = opt key (NullOrUndefined (parseDocgen <$> (runNullOrUndefined val)))
234+
235+
parseDocgen :: Docgen -> [String]
236+
parseDocgen (Docgen obj) = either (const []) id $ parseName obj
237+
<|> parseList obj
238+
<|> parseObj obj
239+
<|> pure []
240+
where
241+
parseName :: Foreign -> F [String]
242+
parseName obj = singleton <$> read obj
243+
244+
parseList :: Foreign -> F [String]
245+
parseList obj = read obj
246+
247+
parseObj :: Foreign -> F [String]
248+
parseObj obj = do
249+
modules <- keys obj
250+
for modules \m -> (\f -> m ++ ":" ++ f) <$> readProp m obj
251+
252+
instance commandLineOptionFormat :: CommandLineOption Format where
253+
opt key val = opt key (maybe (NullOrUndefined Nothing)
254+
(\a -> case a of
255+
Markdown -> NullOrUndefined (Just "markdown")
256+
ETags -> NullOrUndefined (Just "etags")
257+
CTags -> NullOrUndefined (Just "ctags"))
258+
(runNullOrUndefined val))
249259

250260
foldPscOptions :: Psc -> [String]
251-
foldPscOptions (Psc a) = mkBoolean noPreludeOpt a.noPrelude <>
252-
mkBoolean noTcoOpt a.noTco <>
253-
mkBoolean noMagicDoOpt a.noMagicDo <>
254-
mkBooleanString mainOpt a.main <>
255-
mkBoolean noOptsOpt a.noOpts <>
256-
mkBoolean verboseErrorsOpt a.verboseErrors <>
257-
mkBoolean commentsOpt a.comments <>
258-
mkString browserNamespaceOpt a.browserNamespace <>
259-
mkStringArray moduleOpt a."module" <>
260-
mkStringArray codegenOpt a.codegen <>
261-
mkString outputOpt a.output <>
262-
mkString externsOpt a.externs <>
263-
mkBoolean noPrefixOpt a.noPrefix <>
264-
mkPathArray ffiOpt a.ffi
261+
foldPscOptions (Psc a) = opt noPreludeOpt a.noPrelude <>
262+
opt noTcoOpt a.noTco <>
263+
opt noMagicDoOpt a.noMagicDo <>
264+
opt mainOpt a.main <>
265+
opt noOptsOpt a.noOpts <>
266+
opt verboseErrorsOpt a.verboseErrors <>
267+
opt commentsOpt a.comments <>
268+
opt browserNamespaceOpt a.browserNamespace <>
269+
opt moduleOpt a."module" <>
270+
opt codegenOpt a.codegen <>
271+
opt outputOpt a.output <>
272+
opt externsOpt a.externs <>
273+
opt noPrefixOpt a.noPrefix <>
274+
opt ffiOpt a.ffi
265275

266276
pscOptions :: Foreign -> Either ForeignError [String]
267277
pscOptions opts = foldPscOptions <$> (read opts :: F Psc)
@@ -275,18 +285,18 @@ pscOptionsNoOutput opts = fold <$> parsed
275285
pscMakeOptions :: Foreign -> Either ForeignError [String]
276286
pscMakeOptions opts = fold <$> parsed
277287
where parsed = read opts :: F PscMake
278-
fold (PscMake a) = mkString outputOpt a.output <>
279-
mkBoolean noPreludeOpt a.noPrelude <>
280-
mkBoolean noTcoOpt a.noTco <>
281-
mkBoolean noMagicDoOpt a.noMagicDo <>
282-
mkBoolean noOptsOpt a.noOpts <>
283-
mkBoolean verboseErrorsOpt a.verboseErrors <>
284-
mkBoolean commentsOpt a.comments <>
285-
mkBoolean noPrefixOpt a.noPrefix <>
286-
mkPathArray ffiOpt a.ffi
288+
fold (PscMake a) = opt outputOpt a.output <>
289+
opt noPreludeOpt a.noPrelude <>
290+
opt noTcoOpt a.noTco <>
291+
opt noMagicDoOpt a.noMagicDo <>
292+
opt noOptsOpt a.noOpts <>
293+
opt verboseErrorsOpt a.verboseErrors <>
294+
opt commentsOpt a.comments <>
295+
opt noPrefixOpt a.noPrefix <>
296+
opt ffiOpt a.ffi
287297

288298
pscDocsOptions :: Foreign -> Either ForeignError [String]
289299
pscDocsOptions opts = fold <$> parsed
290300
where parsed = read opts :: F PscDocs
291-
fold (PscDocs a) = mkFormat formatOpt a.format <>
292-
mkDocgen docgenOpt a.docgen
301+
fold (PscDocs a) = opt formatOpt a.format <>
302+
opt docgenOpt a.docgen

0 commit comments

Comments
 (0)