git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge pull request #736 from anthoq88/master

Move from cmdtheline to optparse-applicative #690

commitfc6e344643093f6c0660b236615889e1d2a160d1 authorPhil Freeman <paf31@cantab.net> dateFri 28 Nov 2014, 09:23 (12 years ago) parent98dbf636eb1982
6 files changed+320−213
hierarchy/Main.hs+32−22 psc-docs/Main.hs+30−17 psc-make/Main.hs+77−49 psc/Main.hs+125−75 psci/Main.hs+43−37 purescript.cabal+13−13
hierarchy/Main.hs+32−22
@@ -15,25 +15,30 @@
1515
1616module Main where
1717
18−import Control.Applicative ((<*>), (<$>))
1918import Control.Monad (unless)
2019
2120import Data.List (intercalate,nub,sort)
2221import Data.Foldable (for_)
2322import Data.Version (showVersion)
2423
25−import System.Console.CmdTheLine
24+import Options.Applicative
2625import System.Directory (createDirectoryIfMissing)
2726import System.FilePath ((</>))
2827import System.Exit (exitFailure, exitSuccess)
2928import System.IO (stderr)
3029
31−import Text.Parsec (ParseError)
30+import Text.Parsec as Par (ParseError)
3231
3332import qualified Language.PureScript as P
3433import qualified Paths_purescript as Paths
3534import qualified System.IO.UTF8 as U
3635
36+
37+data HierarchyOptions = HierarchyOptions
38+ { hierachyInput :: FilePath
39+ , hierarchyOutput :: Maybe FilePath
40+ }
41+
3742newtype SuperMap = SuperMap { unSuperMap :: Either P.ProperName (P.ProperName, P.ProperName) }
3843 deriving Eq
3944
@@ -49,13 +54,13 @@ instance Ord SuperMap where
4954runModuleName :: P.ModuleName -> String
5055runModuleName (P.ModuleName pns) = intercalate "_" (P.runProperName `map` pns)
5156
52−readInput :: FilePath -> IO (Either ParseError [P.Module])
57+readInput :: FilePath -> IO (Either Par.ParseError [P.Module])
5358readInput p = do
5459 text <- U.readFile p
5560 return $ P.runIndentParser p P.parseModules text
5661
57−compile :: FilePath -> Maybe FilePath -> IO ()
58−compile input mOutput = do
62+compile :: HierarchyOptions -> IO ()
63+compile (HierarchyOptions input mOutput) = do
5964 modules <- readInput input
6065 case modules of
6166 Left err -> U.hPutStr stderr (show err) >> exitFailure
@@ -82,23 +87,28 @@ superClasses (P.TypeClassDeclaration sub _ _ _) = [SuperMap (Left sub)]
8287superClasses (P.PositionedDeclaration _ decl) = superClasses decl
8388superClasses _ = []
8489
85−outputFile :: Term (Maybe FilePath)
86−outputFile = value $ opt Nothing $ (optInfo [ "o", "output" ])
87− { optDoc = "The output directory" }
90+inputFile :: Parser FilePath
91+inputFile = strArgument $
92+ metavar "FILE"
93+ <> value "main.purs"
94+ <> showDefault
95+ <> help "The input file to generate a hierarchy from"
8896
89−inputFile :: Term FilePath
90−inputFile = value $ pos 0 "main.purs" $ posInfo
91− { posDoc = "The input file to generate a hierarchy from" }
97+outputFile :: Parser (Maybe FilePath)
98+outputFile = optional . strOption $
99+ short 'o'
100+ <> long "output"
101+ <> help "The output directory"
92102
93−term :: Term (IO ())
94−term = compile <$> inputFile <*> outputFile
95−
96−termInfo :: TermInfo
97−termInfo = defTI
98− { termName = "hierarchy"
99− , version = showVersion Paths.version
100− , termDoc = "Creates a GraphViz directed graph of PureScript TypeClasses"
101− }
103+pscOptions :: Parser HierarchyOptions
104+pscOptions = HierarchyOptions <$> inputFile
105+ <*> outputFile
102106
103107main :: IO ()
104−main = run (term, termInfo)
108+main = execParser opts >>= compile
109+ where
110+ opts = info (helper <*> pscOptions) infoModList
111+ infoModList = fullDesc <> headerInfo <> footerInfo
112+ headerInfo = header "hierarchy - Creates a GraphViz directed graph of PureScript TypeClasses"
113+ footerInfo = footer $ "hierarchy " ++ showVersion Paths.version
114+
psc-docs/Main.hs+30−17
@@ -22,15 +22,24 @@ import Data.Function (on)
2222import Data.List
2323import Data.Maybe (fromMaybe)
2424import Data.Version (showVersion)
25+
26+import Options.Applicative
27+
2528import qualified Language.PureScript as P
2629import qualified Paths_purescript as Paths
2730import qualified System.IO.UTF8 as U
28−import System.Console.CmdTheLine
2931import System.Exit (exitSuccess, exitFailure)
3032import System.IO (stderr)
3133
32−docgen :: Bool -> [FilePath] -> IO ()
33−docgen showHierarchy input = do
34+
35+data PSCDocsOptions = PSCDocsOptions
36+ { pscdIncludeHeir :: Bool
37+ , pscdInputFiles :: [FilePath]
38+ }
39+
40+
41+docgen :: PSCDocsOptions -> IO ()
42+docgen (PSCDocsOptions showHierarchy input) = do
3443 e <- P.parseModulesFromFiles (fromMaybe "") <$> mapM (fmap (first Just) . parseFile) (nub input)
3544 case e of
3645 Left err -> do
@@ -218,21 +227,25 @@ isTypeInstanceDeclaration P.TypeInstanceDeclaration{} = True
218227isTypeInstanceDeclaration (P.PositionedDeclaration _ d) = isTypeInstanceDeclaration d
219228isTypeInstanceDeclaration _ = False
220229
221−inputFiles :: Term [FilePath]
222−inputFiles = value $ posAny [] $ posInfo { posName = "file(s)", posDoc = "The input .purs file(s)" }
223−
224−includeHeirarcy :: Term Bool
225−includeHeirarcy = value $ flag $ (optInfo [ "h", "hierarchy-images" ]) { optDoc = "Include markdown for type class hierarchy images in the output." }
230+inputFile :: Parser FilePath
231+inputFile = strArgument $
232+ metavar "FILE"
233+ <> help "The input .ps file(s)"
226234
227−term :: Term (IO ())
228−term = docgen <$> includeHeirarcy <*> inputFiles
235+includeHeirarcy :: Parser Bool
236+includeHeirarcy = switch $
237+ long "hierarchy-images"
238+ <> help "Include markdown for type class hierarchy images in the output."
229239
230−termInfo :: TermInfo
231−termInfo = defTI
232− { termName = "psc-docs"
233− , version = showVersion Paths.version
234− , termDoc = "Generate Markdown documentation from PureScript extern files"
235− }
240+pscDocsOptions :: Parser PSCDocsOptions
241+pscDocsOptions = PSCDocsOptions <$> includeHeirarcy
242+ <*> many inputFile
236243
237244main :: IO ()
238−main = run (term, termInfo)
245+main = execParser opts >>= docgen
246+ where
247+ opts = info (helper <*> pscDocsOptions) infoModList
248+ infoModList = fullDesc <> headerInfo <> footerInfo
249+ headerInfo = header "psc-docs - Generate Markdown documentation from PureScript extern files"
250+ footerInfo = footer $ "psc-docs " ++ showVersion Paths.version
251+
psc-make/Main.hs+77−49
@@ -21,7 +21,8 @@ import Control.Monad.Error
2121
2222import Data.Version (showVersion)
2323
24−import System.Console.CmdTheLine
24+import Options.Applicative as Opts
25+
2526import System.Directory
2627 (doesFileExist, getModificationTime, createDirectoryIfMissing)
2728import System.FilePath (takeDirectory)
@@ -32,6 +33,14 @@ import qualified Language.PureScript as P
3233import qualified Paths_purescript as Paths
3334import qualified System.IO.UTF8 as U
3435
36+
37+data PSCMakeOptions = PSCMakeOptions
38+ { pscmInput :: [FilePath]
39+ , pscmOutputDir :: FilePath
40+ , pscmOpts :: P.Options P.Make
41+ , pscmUsePrefix :: Bool
42+ }
43+
3544data InputOptions = InputOptions
3645 { ioNoPrelude :: Bool
3746 , ioInputFiles :: [FilePath]
@@ -39,7 +48,7 @@ data InputOptions = InputOptions
3948
4049readInput :: InputOptions -> IO [(Either P.RebuildPolicy FilePath, String)]
4150readInput InputOptions{..} = do
42− content <- forM ioInputFiles $ \inputFile -> (Right inputFile, ) <$> U.readFile inputFile
51+ content <- forM ioInputFiles $ \inFile -> (Right inFile, ) <$> U.readFile inFile
4352 return (if ioNoPrelude then content else (Left P.RebuildNever, P.prelude) : content)
4453
4554newtype Make a = Make { unMake :: ErrorT String IO a } deriving (Functor, Applicative, Monad, MonadIO, MonadError String)
@@ -66,8 +75,8 @@ instance P.MonadMake Make where
6675 liftError = either throwError return
6776 progress = makeIO . U.putStrLn
6877
69−compile :: [FilePath] -> FilePath -> P.Options P.Make -> Bool -> IO ()
70−compile input outputDir opts usePrefix = do
78+compile :: PSCMakeOptions -> IO ()
79+compile (PSCMakeOptions input outputDir opts usePrefix) = do
7180 modules <- P.parseModulesFromFiles (either (const "") id) <$> readInput (InputOptions (P.optionsNoPrelude opts) input)
7281 case modules of
7382 Left err -> do
@@ -89,51 +98,70 @@ compile input outputDir opts usePrefix = do
8998mkdirp :: FilePath -> IO ()
9099mkdirp = createDirectoryIfMissing True . takeDirectory
91100
92−inputFiles :: Term [FilePath]
93−inputFiles = value $ posAny [] $ posInfo
94− { posDoc = "The input .ps files" }
95−
96−outputDirectory :: Term FilePath
97−outputDirectory = value $ opt "output" $ (optInfo [ "o", "output" ])
98− { optDoc = "The output directory" }
99−
100−noTco :: Term Bool
101−noTco = value $ flag $ (optInfo [ "no-tco" ])
102− { optDoc = "Disable tail call optimizations" }
103−
104−noPrelude :: Term Bool
105−noPrelude = value $ flag $ (optInfo [ "no-prelude" ])
106− { optDoc = "Omit the Prelude" }
107−
108−noMagicDo :: Term Bool
109−noMagicDo = value $ flag $ (optInfo [ "no-magic-do" ])
110− { optDoc = "Disable the optimization that overloads the do keyword to generate efficient code specifically for the Eff monad." }
111−
112−noOpts :: Term Bool
113−noOpts = value $ flag $ (optInfo [ "no-opts" ])
114− { optDoc = "Skip the optimization phase." }
115−
116−verboseErrors :: Term Bool
117−verboseErrors = value $ flag $ (optInfo [ "v", "verbose-errors" ])
118− { optDoc = "Display verbose error messages" }
119−
120−options :: Term (P.Options P.Make)
121−options = P.Options <$> noPrelude <*> noTco <*> noMagicDo <*> pure Nothing <*> noOpts <*> verboseErrors <*> pure P.MakeOptions
122−
123−noPrefix :: Term Bool
124−noPrefix = value $ flag $ (optInfo ["p", "no-prefix" ])
125− { optDoc = "Do not include comment header"}
126−
127−term :: Term (IO ())
128−term = compile <$> inputFiles <*> outputDirectory <*> options <*> (not <$> noPrefix)
129−
130−termInfo :: TermInfo
131−termInfo = defTI
132− { termName = "psc-make"
133− , version = showVersion Paths.version
134− , termDoc = "Compiles PureScript to Javascript"
135− }
101+inputFile :: Parser FilePath
102+inputFile = strArgument $
103+ metavar "FILE"
104+ <> help "The input .ps file(s)"
105+
106+outputDirectory :: Parser FilePath
107+outputDirectory = strOption $
108+ short 'o'
109+ <> long "output"
110+ <> help "The output directory"
111+
112+noTco :: Parser Bool
113+noTco = switch $
114+ long "no-tco"
115+ <> help "Disable tail call optimizations"
116+
117+noPrelude :: Parser Bool
118+noPrelude = switch $
119+ long "no-prelude"
120+ <> help "Omit the Prelude"
121+
122+noMagicDo :: Parser Bool
123+noMagicDo = switch $
124+ long "no-magic-do"
125+ <> help "Disable the optimization that overloads the do keyword to generate efficient code specifically for the Eff monad."
126+
127+noOpts :: Parser Bool
128+noOpts = switch $
129+ long "no-opts"
130+ <> help "Skip the optimization phase."
131+
132+verboseErrors :: Parser Bool
133+verboseErrors = switch $
134+ short 'v'
135+ <> long "no-opts"
136+ <> help "Display verbose error messages"
137+
138+noPrefix :: Parser Bool
139+noPrefix = switch $
140+ short 'p'
141+ <> long "no-prefix"
142+ <> help "Do not include comment header"
143+
144+
145+options :: Parser (P.Options P.Make)
146+options = P.Options <$> noPrelude
147+ <*> noTco
148+ <*> noMagicDo
149+ <*> pure Nothing
150+ <*> noOpts
151+ <*> verboseErrors
152+ <*> pure P.MakeOptions
153+
154+pscMakeOptions :: Parser PSCMakeOptions
155+pscMakeOptions = PSCMakeOptions <$> many inputFile
156+ <*> outputDirectory
157+ <*> options
158+ <*> (not <$> noPrefix)
136159
137160main :: IO ()
138−main = run (term, termInfo)
161+main = execParser opts >>= compile
162+ where
163+ opts = info (helper <*> pscMakeOptions) infoModList
164+ infoModList = fullDesc <> headerInfo <> footerInfo
165+ headerInfo = header "psc-make - Compiles PureScript to Javascript"
166+ footerInfo = footer $ "psc-make " ++ showVersion Paths.version
139167
psc/Main.hs+125−75
@@ -22,7 +22,7 @@ import Control.Monad.Error
2222import Data.Maybe (fromMaybe)
2323import Data.Version (showVersion)
2424
25−import System.Console.CmdTheLine
25+import Options.Applicative as Opts
2626import System.Directory (createDirectoryIfMissing)
2727import System.FilePath (takeDirectory)
2828import System.Exit (exitSuccess, exitFailure)
@@ -32,6 +32,16 @@ import qualified Language.PureScript as P
3232import qualified Paths_purescript as Paths
3333import qualified System.IO.UTF8 as U
3434
35+
36+data PSCOptions = PSCOptions
37+ { pscInput :: [FilePath]
38+ , pscOpts :: P.Options P.Compile
39+ , pscStdIn :: Bool
40+ , pscOutput :: Maybe FilePath
41+ , pscExterns :: Maybe FilePath
42+ , pscUsePrefix :: Bool
43+ }
44+
3545data InputOptions = InputOptions
3646 { ioNoPrelude :: Bool
3747 , ioUseStdIn :: Bool
@@ -41,11 +51,11 @@ data InputOptions = InputOptions
4151readInput :: InputOptions -> IO [(Maybe FilePath, String)]
4252readInput InputOptions{..}
4353 | ioUseStdIn = return . (Nothing ,) <$> getContents
44− | otherwise = do content <- forM ioInputFiles $ \inputFile -> (Just inputFile, ) <$> U.readFile inputFile
54+ | otherwise = do content <- forM ioInputFiles $ \inFile -> (Just inFile, ) <$> U.readFile inFile
4555 return (if ioNoPrelude then content else (Nothing, P.prelude) : content)
4656
47−compile :: P.Options P.Compile -> Bool -> [FilePath] -> Maybe FilePath -> Maybe FilePath -> Bool -> IO ()
48−compile opts stdin input output externs usePrefix = do
57+compile :: PSCOptions -> IO ()
58+compile (PSCOptions input opts stdin output externs usePrefix) = do
4959 modules <- P.parseModulesFromFiles (fromMaybe "") <$> readInput (InputOptions (P.optionsNoPrelude opts) stdin input)
5060 case modules of
5161 Left err -> do
@@ -72,78 +82,118 @@ compile opts stdin input output externs usePrefix = do
7282mkdirp :: FilePath -> IO ()
7383mkdirp = createDirectoryIfMissing True . takeDirectory
7484
75−useStdIn :: Term Bool
76−useStdIn = value . flag $ (optInfo [ "s", "stdin" ])
77− { optDoc = "Read from standard input" }
78−
79−inputFiles :: Term [FilePath]
80−inputFiles = value $ posAny [] $ posInfo
81− { posDoc = "The input .ps files" }
82−
83−outputFile :: Term (Maybe FilePath)
84−outputFile = value $ opt Nothing $ (optInfo [ "o", "output" ])
85− { optDoc = "The output .js file" }
86−
87−externsFile :: Term (Maybe FilePath)
88−externsFile = value $ opt Nothing $ (optInfo [ "e", "externs" ])
89− { optDoc = "The output .e.ps file" }
90−
91−noTco :: Term Bool
92−noTco = value $ flag $ (optInfo [ "no-tco" ])
93− { optDoc = "Disable tail call optimizations" }
94−
95−noPrelude :: Term Bool
96−noPrelude = value $ flag $ (optInfo [ "no-prelude" ])
97− { optDoc = "Omit the Prelude" }
98−
99−noMagicDo :: Term Bool
100−noMagicDo = value $ flag $ (optInfo [ "no-magic-do" ])
101− { optDoc = "Disable the optimization that overloads the do keyword to generate efficient code specifically for the Eff monad." }
102−
103−runMain :: Term (Maybe String)
104−runMain = value $ defaultOpt (Just "Main") Nothing $ (optInfo [ "main" ])
105− { optDoc = "Generate code to run the main method in the specified module." }
106−
107−noOpts :: Term Bool
108−noOpts = value $ flag $ (optInfo [ "no-opts" ])
109− { optDoc = "Skip the optimization phase." }
110−
111−browserNamespace :: Term String
112−browserNamespace = value $ opt "PS" $ (optInfo [ "browser-namespace" ])
113− { optDoc = "Specify the namespace that PureScript modules will be exported to when running in the browser." }
114−
115−dceModules :: Term [String]
116−dceModules = value $ optAll [] $ (optInfo [ "m", "module" ])
117− { optDoc = "Enables dead code elimination, all code which is not a transitive dependency of a specified module will be removed. This argument can be used multiple times." }
118−
119−codeGenModules :: Term [String]
120−codeGenModules = value $ optAll [] $ (optInfo [ "codegen" ])
121− { optDoc = "A list of modules for which Javascript and externs should be generated. This argument can be used multiple times." }
122−
123−verboseErrors :: Term Bool
124−verboseErrors = value $ flag $ (optInfo [ "v", "verbose-errors" ])
125− { optDoc = "Display verbose error messages" }
126−
127−noPrefix :: Term Bool
128−noPrefix = value $ flag $ (optInfo ["no-prefix" ])
129− { optDoc = "Do not include comment header"}
130−
131−options :: Term (P.Options P.Compile)
132−options = P.Options <$> noPrelude <*> noTco <*> noMagicDo <*> runMain <*> noOpts <*> verboseErrors <*> additionalOptions
85+codeGenModule :: Parser String
86+codeGenModule = strOption $
87+ long "codegen"
88+ <> help "A list of modules for which Javascript and externs should be generated. This argument can be used multiple times."
89+
90+dceModule :: Parser String
91+dceModule = strOption $
92+ short 'm'
93+ <> long "module"
94+ <> help "Enables dead code elimination, all code which is not a transitive dependency of a specified module will be removed. This argument can be used multiple times."
95+
96+browserNamespace :: Parser String
97+browserNamespace = strOption $
98+ long "browser-namespace"
99+ <> Opts.value "PS"
100+ <> showDefault
101+ <> help "Specify the namespace that PureScript modules will be exported to when running in the browser."
102+
103+verboseErrors :: Parser Bool
104+verboseErrors = switch $
105+ short 'v'
106+ <> long "no-opts"
107+ <> help "Display verbose error messages"
108+
109+noOpts :: Parser Bool
110+noOpts = switch $
111+ long "no-opts"
112+ <> help "Skip the optimization phase."
113+
114+runMain :: Parser (Maybe String)
115+runMain = optional $ noArgs <|> withArgs
133116 where
134− additionalOptions = P.CompileOptions <$> browserNamespace <*> dceModules <*> codeGenModules
135−
136−term :: Term (IO ())
137−term = compile <$> options <*> useStdIn <*> inputFiles <*> outputFile <*> externsFile <*> (not <$> noPrefix)
138−
139−termInfo :: TermInfo
140−termInfo = defTI
141− { termName = "psc"
142− , version = showVersion Paths.version
143− , termDoc = "Compiles PureScript to Javascript"
144− }
117+ defaultVal = "Main"
118+ noArgs = flag' defaultVal (long "main")
119+ withArgs = strOption $
120+ long "main"
121+ <> help (concat [
122+ "Generate code to run the main method in the specified module. ",
123+ "(no argument: \"", defaultVal, "\")"
124+ ])
125+
126+noMagicDo :: Parser Bool
127+noMagicDo = switch $
128+ long "no-magic-do"
129+ <> help "Disable the optimization that overloads the do keyword to generate efficient code specifically for the Eff monad."
130+
131+noTco :: Parser Bool
132+noTco = switch $
133+ long "no-tco"
134+ <> help "Disable tail call optimizations"
135+
136+noPrelude :: Parser Bool
137+noPrelude = switch $
138+ long "no-prelude"
139+ <> help "Omit the Prelude"
140+
141+useStdIn :: Parser Bool
142+useStdIn = switch $
143+ short 's'
144+ <> long "stdin"
145+ <> help "Read from standard input"
146+
147+inputFile :: Parser FilePath
148+inputFile = strArgument $
149+ metavar "FILE"
150+ <> help "The input .ps file(s)"
151+
152+outputFile :: Parser (Maybe FilePath)
153+outputFile = optional . strOption $
154+ short 'o'
155+ <> long "output"
156+ <> help "The output .js file"
157+
158+externsFile :: Parser (Maybe FilePath)
159+externsFile = optional . strOption $
160+ short 'e'
161+ <> long "externs"
162+ <> help "The output .e.ps file"
163+
164+noPrefix :: Parser Bool
165+noPrefix = switch $
166+ short 'p'
167+ <> long "no-prefix"
168+ <> help "Do not include comment header"
169+
170+options :: Parser (P.Options P.Compile)
171+options = P.Options <$> noPrelude
172+ <*> noTco
173+ <*> noMagicDo
174+ <*> runMain
175+ <*> noOpts
176+ <*> verboseErrors
177+ <*> additionalOptions
178+ where
179+ additionalOptions =
180+ P.CompileOptions <$> browserNamespace
181+ <*> many dceModule
182+ <*> many codeGenModule
183+
184+pscOptions :: Parser PSCOptions
185+pscOptions = PSCOptions <$> many inputFile
186+ <*> options
187+ <*> useStdIn
188+ <*> outputFile
189+ <*> externsFile
190+ <*> (not <$> noPrefix)
145191
146192main :: IO ()
147−main = run (term, termInfo)
148−
193+main = execParser opts >>= compile
194+ where
195+ opts = info (helper <*> pscOptions) infoModList
196+ infoModList = fullDesc <> headerInfo <> footerInfo
197+ headerInfo = header "psc - Compiles PureScript to Javascript"
198+ footerInfo = footer $ "psc " ++ showVersion Paths.version
149199
psci/Main.hs+43−37
@@ -33,25 +33,32 @@ import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
3333import Control.Monad.Trans.State.Strict
3434import qualified Control.Monad.Trans.State.Lazy as L
3535
36+import Options.Applicative as Opts
37+
3638import System.Console.Haskeline
3739import System.Directory (createDirectoryIfMissing, getModificationTime, doesFileExist, findExecutable, getHomeDirectory, getCurrentDirectory)
3840import System.Exit
3941import System.FilePath (pathSeparator, takeDirectory, (</>), isPathSeparator)
4042import System.IO.Error (tryIOError)
4143import System.Process (readProcessWithExitCode)
42−import qualified System.Console.CmdTheLine as Cmd
4344import qualified System.IO.UTF8 as U (writeFile, putStrLn, print, readFile)
4445
45−import Text.Parsec (ParseError)
46+import qualified Text.Parsec as Par (ParseError)
4647
4748import qualified Language.PureScript as P
4849import qualified Language.PureScript.AST as D
4950import qualified Language.PureScript.Names as N
5051import qualified Paths_purescript as Paths
5152
52−import Commands
53+import Commands as C
5354import Parser
5455
56+
57+data PSCiOptions = PSCiOptions
58+ { psciSingleLineFlag :: Bool
59+ , psciInputFile :: [FilePath]
60+ }
61+
5562-- |
5663-- The PSCI state.
5764-- Holds a list of imported modules, loaded files, and partial let bindings.
@@ -125,7 +132,7 @@ loadModule filename = either (Left . show) Right . P.runIndentParser filename P.
125132-- |
126133-- Load all modules, including the Prelude
127134--
128−loadAllModules :: [FilePath] -> IO (Either ParseError [(Either P.RebuildPolicy FilePath, P.Module)])
135+loadAllModules :: [FilePath] -> IO (Either Par.ParseError [(Either P.RebuildPolicy FilePath, P.Module)])
129136loadAllModules files = do
130137 filesAndContent <- forM files $ \filename -> do
131138 content <- U.readFile filename
@@ -146,7 +153,7 @@ expandTilde p = return p
146153--
147154helpMessage :: String
148155helpMessage = "The following commands are available:\n\n " ++
149− intercalate "\n " (map (intercalate " ") help)
156+ intercalate "\n " (map (intercalate " ") C.help)
150157
151158-- |
152159-- The welcome prologue.
@@ -180,10 +187,10 @@ completion :: CompletionFunc (StateT PSCiState IO)
180187completion = completeWord Nothing " \t\n\r" findCompletions
181188 where
182189 findCompletions :: String -> StateT PSCiState IO [Completion]
183− findCompletions str = do
190+ findCompletions st = do
184191 ms <- map snd . psciLoadedModules <$> get
185− files <- listFiles str
186− let matches = filter (isPrefixOf str) (names ms)
192+ files <- listFiles st
193+ let matches = filter (isPrefixOf st) (names ms)
187194 return $ sortBy sorter $ map simpleCompletion matches ++ files
188195 getDeclName :: Maybe [P.DeclarationRef] -> P.Declaration -> Maybe P.Ident
189196 getDeclName Nothing (P.ValueDeclaration ident _ _ _) = Just ident
@@ -248,13 +255,13 @@ mkdirp = createDirectoryIfMissing True . takeDirectory
248255-- Makes a volatile module to execute the current expression.
249256--
250257createTemporaryModule :: Bool -> PSCiState -> P.Expr -> P.Module
251−createTemporaryModule exec PSCiState{psciImportedModuleNames = imports, psciLetBindings = lets} value =
258+createTemporaryModule exec PSCiState{psciImportedModuleNames = imports, psciLetBindings = lets} val =
252259 let
253260 moduleName = P.ModuleName [P.ProperName "$PSCI"]
254261 importDecl m = P.ImportDeclaration m P.Unqualified Nothing
255262 traceModule = P.ModuleName [P.ProperName "Debug", P.ProperName "Trace"]
256263 trace = P.Var (P.Qualified (Just traceModule) (P.Ident "print"))
257− itValue = foldl (\x f -> f x) value lets
264+ itValue = foldl (\x f -> f x) val lets
258265 mainValue = P.App trace (P.Var (P.Qualified Nothing (P.Ident "it")))
259266 itDecl = P.ValueDeclaration (P.Ident "it") P.Value [] $ Right itValue
260267 mainDecl = P.ValueDeclaration (P.Ident "main") P.Value [] $ Right mainValue
@@ -295,9 +302,9 @@ indexFile = ".psci_modules" ++ pathSeparator : "index.js"
295302-- Takes a value declaration and evaluates it with the current state.
296303--
297304handleDeclaration :: P.Expr -> PSCI ()
298−handleDeclaration value = do
305+handleDeclaration val = do
299306 st <- PSCI $ lift get
300− let m = createTemporaryModule True st value
307+ let m = createTemporaryModule True st val
301308 e <- psciIO . runMake $ P.make modulesDir options (psciLoadedModules st ++ [(Left P.RebuildAlways, m)]) []
302309 case e of
303310 Left err -> PSCI $ outputStrLn err
@@ -363,9 +370,9 @@ handleImport moduleName = do
363370-- Takes a value and prints its type
364371--
365372handleTypeOf :: P.Expr -> PSCI ()
366−handleTypeOf value = do
373+handleTypeOf val = do
367374 st <- PSCI $ lift get
368− let m = createTemporaryModule False st value
375+ let m = createTemporaryModule False st val
369376 e <- psciIO . runMake $ P.make modulesDir options (psciLoadedModules st ++ [(Left P.RebuildAlways, m)]) []
370377 case e of
371378 Left err -> PSCI $ outputStrLn err
@@ -434,7 +441,7 @@ handleKindOf typ = do
434441-- |
435442-- Parses the input and returns either a Metacommand or an expression.
436443--
437−getCommand :: Bool -> InputT (StateT PSCiState IO) (Either ParseError (Maybe Command))
444+getCommand :: Bool -> InputT (StateT PSCiState IO) (Either Par.ParseError (Maybe Command))
438445getCommand singleLineMode = do
439446 firstLine <- getInputLine "> "
440447 case firstLine of
@@ -478,17 +485,6 @@ handleCommand (Show "loaded") = handleShowLoadedModules
478485handleCommand (Show "import") = handleShowImportedModules
479486handleCommand _ = PSCI $ outputStrLn "Unknown command"
480487
481−singleLineFlag :: Cmd.Term Bool
482−singleLineFlag = Cmd.value $ Cmd.flag $ (Cmd.optInfo ["single-line-mode"])
483− { Cmd.optName = "Single-line mode"
484− , Cmd.optDoc = "Run in single-line mode"
485− }
486−
487−inputFiles :: Cmd.Term [FilePath]
488−inputFiles = Cmd.value $ Cmd.posAny [] $ Cmd.posInfo { Cmd.posName = "file(s)"
489− , Cmd.posDoc = "Optional .purs files to load on start"
490− }
491−
492488loadUserConfig :: IO (Maybe [Command])
493489loadUserConfig = do
494490 configFile <- (</> ".psci") <$> getCurrentDirectory
@@ -505,8 +501,8 @@ loadUserConfig = do
505501-- |
506502-- The PSCI main loop.
507503--
508−loop :: Bool -> [FilePath] -> IO ()
509−loop singleLineMode files = do
504+loop :: PSCiOptions -> IO ()
505+loop (PSCiOptions singleLineMode files) = do
510506 config <- loadUserConfig
511507 modulesOrFirstError <- loadAllModules files
512508 case modulesOrFirstError of
@@ -528,15 +524,25 @@ loop singleLineMode files = do
528524 Right (Just Quit) -> outputStrLn quitMessage
529525 Right (Just c') -> runPSCI (handleCommand c') >> go
530526
531−term :: Cmd.Term (IO ())
532−term = loop <$> singleLineFlag <*> inputFiles
527+singleLineFlag :: Parser Bool
528+singleLineFlag = switch $
529+ long "single-line-mode"
530+ <> Opts.help "Run in single-line mode"
533531
534−termInfo :: Cmd.TermInfo
535−termInfo = Cmd.defTI
536− { Cmd.termName = "psci"
537− , Cmd.version = showVersion Paths.version
538− , Cmd.termDoc = "Interactive mode for PureScript"
539− }
532+inputFile :: Parser FilePath
533+inputFile = strArgument $
534+ metavar "FILE"
535+ <> Opts.help "Optional .purs files to load on start"
536+
537+psciOptions :: Parser PSCiOptions
538+psciOptions = PSCiOptions <$> singleLineFlag
539+ <*> many inputFile
540540
541541main :: IO ()
542−main = Cmd.run (term, termInfo)
542+main = execParser opts >>= loop
543+ where
544+ opts = info (helper <*> psciOptions) infoModList
545+ infoModList = fullDesc <> headerInfo <> footerInfo
546+ headerInfo = header "psci - Interactive mode for PureScript"
547+ footerInfo = footer $ "psci " ++ showVersion Paths.version
548+
purescript.cabal+13−13
@@ -25,7 +25,6 @@ source-repository head
2525
2626library
2727 build-depends: base >=4.6 && <5,
28− cmdtheline == 0.2.*,
2928 containers -any,
3029 unordered-containers -any,
3130 directory >= 1.2,
@@ -107,9 +106,9 @@ library
107106 ghc-options: -Wall -O2
108107
109108executable psc
110− build-depends: base >=4 && <5, cmdtheline -any, containers -any,
111− directory -any, filepath -any, mtl -any, parsec -any,
112− purescript -any, transformers -any, utf8-string -any
109+ build-depends: base >=4 && <5, containers -any, directory -any, filepath -any,
110+ mtl -any, optparse-applicative -any, parsec -any, purescript -any,
111+ transformers -any, utf8-string -any
113112 main-is: Main.hs
114113 buildable: True
115114 hs-source-dirs: psc
@@ -117,9 +116,9 @@ executable psc
117116 ghc-options: -Wall -O2 -fno-warn-unused-do-bind
118117
119118executable psc-make
120− build-depends: base >=4 && <5, cmdtheline -any, containers -any,
121− directory -any, filepath -any, mtl -any, parsec -any,
122− purescript -any, transformers -any, utf8-string -any
119+ build-depends: base >=4 && <5, containers -any, directory -any, filepath -any,
120+ mtl -any, optparse-applicative -any, parsec -any, purescript -any,
121+ transformers -any, utf8-string -any
123122 main-is: Main.hs
124123 buildable: True
125124 hs-source-dirs: psc-make
@@ -128,9 +127,10 @@ executable psc-make
128127
129128executable psci
130129 build-depends: base >=4 && <5, containers -any, directory -any, filepath -any,
131− mtl -any, parsec -any, haskeline >= 0.7.0.0, purescript -any,
132− transformers -any, utf8-string -any, process -any,
133− cmdtheline -any
130+ mtl -any, optparse-applicative -any, parsec -any,
131+ haskeline >= 0.7.0.0, purescript -any, transformers -any,
132+ utf8-string -any, process -any
133+
134134 main-is: Main.hs
135135 buildable: True
136136 hs-source-dirs: psci
@@ -139,8 +139,8 @@ executable psci
139139 ghc-options: -Wall -O2
140140
141141executable psc-docs
142− build-depends: base >=4 && <5, cmdtheline -any, purescript -any, utf8-string -any,
143− process -any, mtl -any
142+ build-depends: base >=4 && <5, purescript -any, utf8-string -any,
143+ optparse-applicative -any, process -any, mtl -any
144144 main-is: Main.hs
145145 buildable: True
146146 hs-source-dirs: psc-docs
@@ -148,7 +148,7 @@ executable psc-docs
148148 ghc-options: -Wall -O2
149149
150150executable hierarchy
151− build-depends: base >=4 && <5, cmdtheline -any, purescript -any, utf8-string -any,
151+ build-depends: base >=4 && <5, purescript -any, utf8-string -any, optparse-applicative -any,
152152 process -any, mtl -any, parsec -any, filepath -any, directory -any
153153 main-is: Main.hs
154154 buildable: True