purescript 0.15.14 → 0.15.15
raw patch · 11 files changed
+153/−82 lines, 11 files
Files
- app/Command/Compile.hs +14/−31
- app/Command/Docs.hs +19/−9
- app/Command/Graph.hs +14/−28
- app/Command/Ide.hs +9/−2
- app/Command/REPL.hs +13/−8
- app/SharedCLI.hs +24/−0
- purescript.cabal +3/−1
- src/Language/PureScript/Glob.hs +44/−0
- src/Language/PureScript/Ide.hs +9/−3
- src/Language/PureScript/Ide/Types.hs +2/−0
- tests/Language/PureScript/Ide/Test.hs +2/−0
app/Command/Compile.hs view
@@ -7,7 +7,7 @@ import Data.Aeson qualified as A import Data.Bool (bool) import Data.ByteString.Lazy.UTF8 qualified as LBU8-import Data.List (intercalate, (\\))+import Data.List (intercalate) import Data.Map qualified as M import Data.Set qualified as S import Data.Text qualified as T@@ -15,17 +15,19 @@ import Language.PureScript qualified as P import Language.PureScript.CST qualified as CST import Language.PureScript.Errors.JSON (JSONResult(..), toJSONErrors)+import Language.PureScript.Glob (toInputGlobs, PSCGlobs(..), warnFileTypeNotFound) import Language.PureScript.Make (buildMakeActions, inferForeignModules, runMake) import Options.Applicative qualified as Opts+import SharedCLI qualified import System.Console.ANSI qualified as ANSI import System.Exit (exitSuccess, exitFailure) import System.Directory (getCurrentDirectory)-import System.FilePath.Glob (glob)-import System.IO (hPutStr, hPutStrLn, stderr, stdout)+import System.IO (hPutStr, stderr, stdout) import System.IO.UTF8 (readUTF8FilesT) data PSCMakeOptions = PSCMakeOptions { pscmInput :: [FilePath]+ , pscmInputFromFile :: Maybe FilePath , pscmExclude :: [FilePath] , pscmOutputDir :: FilePath , pscmOpts :: P.Options@@ -54,9 +56,12 @@ compile :: PSCMakeOptions -> IO () compile PSCMakeOptions{..} = do- included <- globWarningOnMisses warnFileTypeNotFound pscmInput- excluded <- globWarningOnMisses warnFileTypeNotFound pscmExclude- let input = included \\ excluded+ input <- toInputGlobs $ PSCGlobs+ { pscInputGlobs = pscmInput+ , pscInputGlobsFromFile = pscmInputFromFile+ , pscExcludeGlobs = pscmExclude+ , pscWarnFileTypeNotFound = warnFileTypeNotFound "compile"+ } when (null input) $ do hPutStr stderr $ unlines [ "purs compile: No input files." , "Usage: For basic information, try the `--help' option."@@ -72,29 +77,6 @@ printWarningsAndErrors (P.optionsVerboseErrors pscmOpts) pscmJSONErrors moduleFiles makeWarnings makeErrors exitSuccess -warnFileTypeNotFound :: String -> IO ()-warnFileTypeNotFound = hPutStrLn stderr . ("purs compile: No files found using pattern: " ++)--globWarningOnMisses :: (String -> IO ()) -> [FilePath] -> IO [FilePath]-globWarningOnMisses warn = concatMapM globWithWarning- where- globWithWarning pattern' = do- paths <- glob pattern'- when (null paths) $ warn pattern'- return paths- concatMapM f = fmap concat . mapM f--inputFile :: Opts.Parser FilePath-inputFile = Opts.strArgument $- Opts.metavar "FILE"- <> Opts.help "The input .purs file(s)."--excludedFiles :: Opts.Parser FilePath-excludedFiles = Opts.strOption $- Opts.short 'x'- <> Opts.long "exclude-files"- <> Opts.help "Glob of .purs files to exclude from the supplied files."- outputDirectory :: Opts.Parser FilePath outputDirectory = Opts.strOption $ Opts.short 'o'@@ -161,8 +143,9 @@ handleTargets ts = S.fromList (if P.JSSourceMap `elem` ts then P.JS : ts else ts) pscMakeOptions :: Opts.Parser PSCMakeOptions-pscMakeOptions = PSCMakeOptions <$> many inputFile- <*> many excludedFiles+pscMakeOptions = PSCMakeOptions <$> many SharedCLI.inputFile+ <*> SharedCLI.globInputFile+ <*> many SharedCLI.excludeFiles <*> outputDirectory <*> options <*> (not <$> noPrefix)
app/Command/Docs.hs view
@@ -13,12 +13,14 @@ import Language.PureScript qualified as P import Language.PureScript.Docs qualified as D import Language.PureScript.Docs.Tags (dumpCtags, dumpEtags)+import Language.PureScript.Glob (PSCGlobs(..), toInputGlobs, warnFileTypeNotFound) import Options.Applicative qualified as Opts import Text.PrettyPrint.ANSI.Leijen qualified as PP+import SharedCLI qualified import System.Directory (getCurrentDirectory, createDirectoryIfMissing, removeFile) import System.Exit (exitFailure) import System.FilePath ((</>))-import System.FilePath.Glob (compile, glob, globDir1)+import System.FilePath.Glob (compile, globDir1) import System.IO (hPutStrLn, stderr) import System.IO.UTF8 (writeUTF8FileT) @@ -35,12 +37,19 @@ , _pscdOutput :: Maybe FilePath , _pscdCompileOutputDir :: FilePath , _pscdInputFiles :: [FilePath]+ , _pscdInputFromFile :: Maybe FilePath+ , _pscdExcludeFiles :: [FilePath] } deriving (Show) docgen :: PSCDocsOptions -> IO ()-docgen (PSCDocsOptions fmt moutput compileOutput inputGlob) = do- input <- concat <$> mapM glob inputGlob+docgen (PSCDocsOptions fmt moutput compileOutput inputGlob inputGlobFromFile excludeGlob) = do+ input <- toInputGlobs $ PSCGlobs+ { pscInputGlobs = inputGlob+ , pscInputGlobsFromFile = inputGlobFromFile+ , pscExcludeGlobs = excludeGlob+ , pscWarnFileTypeNotFound = warnFileTypeNotFound "docs"+ } when (null input) $ do hPutStrLn stderr "purs docs: no input files." exitFailure@@ -104,7 +113,13 @@ Ctags -> "tags" pscDocsOptions :: Opts.Parser PSCDocsOptions-pscDocsOptions = PSCDocsOptions <$> format <*> output <*> compileOutputDir <*> many inputFile+pscDocsOptions = + PSCDocsOptions <$> format + <*> output + <*> compileOutputDir + <*> many SharedCLI.inputFile+ <*> SharedCLI.globInputFile+ <*> many SharedCLI.excludeFiles where format :: Opts.Parser Format format = Opts.option Opts.auto $@@ -127,11 +142,6 @@ <> Opts.long "compile-output" <> Opts.metavar "DIR" <> Opts.help "Compiler output directory"-- inputFile :: Opts.Parser FilePath- inputFile = Opts.strArgument $- Opts.metavar "FILE"- <> Opts.help "The input .purs file(s)" command :: Opts.Parser (IO ()) command = docgen <$> (Opts.helper <*> pscDocsOptions)
app/Command/Graph.hs view
@@ -10,21 +10,30 @@ import Data.ByteString.Lazy.UTF8 qualified as LBU8 import Language.PureScript qualified as P import Language.PureScript.Errors.JSON (JSONResult(..), toJSONErrors)+import Language.PureScript.Glob (PSCGlobs(..), toInputGlobs, warnFileTypeNotFound) import Options.Applicative qualified as Opts+import SharedCLI qualified import System.Console.ANSI qualified as ANSI import System.Exit (exitFailure) import System.Directory (getCurrentDirectory)-import System.FilePath.Glob (glob) import System.IO (hPutStr, hPutStrLn, stderr) data GraphOptions = GraphOptions { graphInput :: [FilePath]+ , graphInputFromFile :: Maybe FilePath+ , graphExclude :: [FilePath] , graphJSONErrors :: Bool } graph :: GraphOptions -> IO () graph GraphOptions{..} = do- input <- globWarningOnMisses (unless graphJSONErrors . warnFileTypeNotFound) graphInput+ input <- toInputGlobs $ PSCGlobs+ { pscInputGlobs = graphInput+ , pscInputGlobsFromFile = graphInputFromFile+ , pscExcludeGlobs = graphExclude+ , pscWarnFileTypeNotFound = unless graphJSONErrors . warnFileTypeNotFound "graph"+ }+ when (null input && not graphJSONErrors) $ do hPutStr stderr $ unlines [ "purs graph: No input files."@@ -37,26 +46,16 @@ printWarningsAndErrors graphJSONErrors makeWarnings makeResult >>= (LB.putStr . Json.encode) - where- warnFileTypeNotFound :: String -> IO ()- warnFileTypeNotFound =- hPutStrLn stderr . ("purs graph: No files found using pattern: " <>)-- command :: Opts.Parser (IO ()) command = graph <$> (Opts.helper <*> graphOptions) where graphOptions :: Opts.Parser GraphOptions graphOptions =- GraphOptions <$> many inputFile+ GraphOptions <$> many SharedCLI.inputFile+ <*> SharedCLI.globInputFile+ <*> many SharedCLI.excludeFiles <*> jsonErrors - inputFile :: Opts.Parser FilePath- inputFile =- Opts.strArgument $- Opts.metavar "FILE" <>- Opts.help "The input .purs file(s)."- jsonErrors :: Opts.Parser Bool jsonErrors = Opts.switch $@@ -84,16 +83,3 @@ case errors of Left _errs -> exitFailure Right res -> pure res---globWarningOnMisses :: (String -> IO ()) -> [FilePath] -> IO [FilePath]-globWarningOnMisses warn = concatMapM globWithWarning- where- globWithWarning :: String -> IO [FilePath]- globWithWarning pattern' = do- paths <- glob pattern'- when (null paths) $ warn pattern'- return paths-- concatMapM :: (a -> IO [b]) -> [a] -> IO [b]- concatMapM f = fmap concat . mapM f
app/Command/Ide.hs view
@@ -35,6 +35,7 @@ import Language.PureScript.Ide.Types (Ide, IdeConfiguration(..), IdeEnvironment(..), IdeLogLevel(..), emptyIdeState) import Network.Socket qualified as Network import Options.Applicative qualified as Opts+import SharedCLI qualified import System.Directory (doesDirectoryExist, getCurrentDirectory, setCurrentDirectory) import System.FilePath ((</>)) import System.IO (BufferMode(..), hClose, hFlush, hSetBuffering, hSetEncoding, utf8)@@ -59,6 +60,8 @@ data ServerOptions = ServerOptions { _serverDirectory :: Maybe FilePath , _serverGlobs :: [FilePath]+ , _serverGlobsFromFile :: Maybe FilePath+ , _serverGlobsExcluded :: [FilePath] , _serverOutputPath :: FilePath , _serverPort :: Network.PortNumber , _serverLoglevel :: IdeLogLevel@@ -110,7 +113,7 @@ Opts.option Opts.auto (Opts.long "port" `mappend` Opts.short 'p' `mappend` Opts.value (4242 :: Integer)) server :: ServerOptions -> IO ()- server opts'@(ServerOptions dir globs outputPath port logLevel editorMode polling noWatch) = do+ server opts'@(ServerOptions dir globs globsFromFile globsExcluded outputPath port logLevel editorMode polling noWatch) = do when (logLevel == LogDebug || logLevel == LogAll) (putText "Parsed Options:" *> print opts') maybe (pure ()) setCurrentDirectory dir@@ -136,6 +139,8 @@ { confLogLevel = logLevel , confOutputPath = outputPath , confGlobs = globs+ , confGlobsFromFile = globsFromFile+ , confGlobsExclude = globsExcluded } ts <- newIORef Nothing let@@ -150,7 +155,9 @@ serverOptions = ServerOptions <$> optional (Opts.strOption (Opts.long "directory" `mappend` Opts.short 'd'))- <*> many (Opts.argument Opts.str (Opts.metavar "Source GLOBS..."))+ <*> many SharedCLI.inputFile+ <*> SharedCLI.globInputFile+ <*> many SharedCLI.excludeFiles <*> Opts.strOption (Opts.long "output-directory" `mappend` Opts.value "output/") <*> (fromIntegral <$> Opts.option Opts.auto (Opts.long "port" `mappend` Opts.short 'p' `mappend` Opts.value (4242 :: Integer)))
app/Command/REPL.hs view
@@ -15,27 +15,25 @@ import Data.Foldable (for_) import Language.PureScript qualified as P import Language.PureScript.CST qualified as CST+import Language.PureScript.Glob (PSCGlobs(..), toInputGlobs, warnFileTypeNotFound) import Language.PureScript.Interactive import Options.Applicative qualified as Opts+import SharedCLI qualified import System.Console.Haskeline (InputT, Settings(..), defaultSettings, getInputLine, handleInterrupt, outputStrLn, runInputT, setComplete, withInterrupt) import System.IO.UTF8 (readUTF8File) import System.Exit (ExitCode(..), exitFailure) import System.Directory (doesFileExist, getCurrentDirectory) import System.FilePath ((</>))-import System.FilePath.Glob qualified as Glob import System.IO (hPutStrLn, stderr) -- | Command line options data PSCiOptions = PSCiOptions { psciInputGlob :: [String]+ , psciInputFromFile :: Maybe String+ , psciExclude :: [String] , psciBackend :: Backend } -inputFile :: Opts.Parser FilePath-inputFile = Opts.strArgument $- Opts.metavar "FILES"- <> Opts.help "Optional .purs files to load on start"- nodePathOption :: Opts.Parser (Maybe FilePath) nodePathOption = Opts.optional . Opts.strOption $ Opts.metavar "FILE"@@ -63,7 +61,9 @@ <|> (nodeBackend <$> nodePathOption <*> nodeFlagsOption) psciOptions :: Opts.Parser PSCiOptions-psciOptions = PSCiOptions <$> many inputFile+psciOptions = PSCiOptions <$> many SharedCLI.inputFile+ <*> SharedCLI.globInputFile+ <*> many SharedCLI.excludeFiles <*> backend -- | Parses the input and returns either a command, or an error as a 'String'.@@ -132,7 +132,12 @@ where loop :: PSCiOptions -> IO () loop PSCiOptions{..} = do- inputFiles <- concat <$> traverse Glob.glob psciInputGlob+ inputFiles <- toInputGlobs $ PSCGlobs+ { pscInputGlobs = psciInputGlob+ , pscInputGlobsFromFile = psciInputFromFile+ , pscExcludeGlobs = psciExclude+ , pscWarnFileTypeNotFound = warnFileTypeNotFound "repl"+ } e <- runExceptT $ do modules <- ExceptT (loadAllModules inputFiles) when (null modules) . liftIO $ do
@@ -0,0 +1,24 @@+module SharedCLI where++import Prelude++import Options.Applicative qualified as Opts++inputFile :: Opts.Parser FilePath+inputFile = Opts.strArgument $+ Opts.metavar "GLOB"+ <> Opts.help "A glob for input .purs file(s)."++globInputFile :: Opts.Parser (Maybe FilePath)+globInputFile = Opts.optional $ Opts.strOption $+ Opts.long "source-globs-file"+ <> Opts.metavar "FILE"+ <> Opts.help "A file containing a line-separated list of input .purs globs."++excludeFiles :: Opts.Parser FilePath+excludeFiles = Opts.strOption $+ Opts.short 'x'+ <> Opts.long "exclude-files"+ <> Opts.metavar "GLOB"+ <> Opts.help "A glob of .purs files to exclude from the input .purs files."+
purescript.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: purescript-version: 0.15.14+version: 0.15.15 license: BSD-3-Clause license-file: LICENSE copyright:@@ -137,6 +137,7 @@ Language.PureScript.Errors Language.PureScript.Errors.JSON Language.PureScript.Externs+ Language.PureScript.Glob Language.PureScript.Graph Language.PureScript.Hierarchy Language.PureScript.Ide@@ -335,6 +336,7 @@ Command.Ide Command.Publish Command.REPL+ SharedCLI Version Paths_purescript
+ src/Language/PureScript/Glob.hs view
@@ -0,0 +1,44 @@+module Language.PureScript.Glob where++import Prelude++import Control.Monad (when)+import Data.List (nub, (\\))+import Data.Text qualified as T+import System.FilePath.Glob (glob)+import System.IO (hPutStrLn, stderr)+import System.IO.UTF8 (readUTF8FileT)++data PSCGlobs = PSCGlobs+ { pscInputGlobs :: [FilePath]+ , pscInputGlobsFromFile :: Maybe FilePath+ , pscExcludeGlobs :: [FilePath]+ , pscWarnFileTypeNotFound :: FilePath -> IO ()+ }++toInputGlobs :: PSCGlobs -> IO [FilePath]+toInputGlobs (PSCGlobs {..}) = do+ globsFromFile <- inputGlobsFromFile pscInputGlobsFromFile+ included <- globWarningOnMisses pscWarnFileTypeNotFound $ nub $ pscInputGlobs <> globsFromFile+ excluded <- globWarningOnMisses pscWarnFileTypeNotFound pscExcludeGlobs+ pure $ included \\ excluded++inputGlobsFromFile :: Maybe FilePath -> IO [FilePath]+inputGlobsFromFile globsFromFile = do+ mbInputsFromFile <- traverse readUTF8FileT globsFromFile+ let+ excludeBlankLines = not . T.null . T.strip+ excludeComments = not . T.isPrefixOf "#"+ toInputs = map (T.unpack . T.strip) . filter (\x -> excludeBlankLines x && excludeComments x) . T.lines+ pure $ foldMap toInputs mbInputsFromFile++globWarningOnMisses :: (String -> IO ()) -> [FilePath] -> IO [FilePath]+globWarningOnMisses warn = foldMap globWithWarning+ where+ globWithWarning pattern' = do+ paths <- glob pattern'+ when (null paths) $ warn pattern'+ return paths++warnFileTypeNotFound :: String -> String -> IO ()+warnFileTypeNotFound pursCmd = hPutStrLn stderr . ("purs " <> pursCmd <> ": No files found using pattern: " ++)
src/Language/PureScript/Ide.hs view
@@ -24,6 +24,7 @@ import Data.Map qualified as Map import Data.Text qualified as T import Language.PureScript qualified as P+import Language.PureScript.Glob (toInputGlobs, PSCGlobs(..)) import Language.PureScript.Ide.CaseSplit qualified as CS import Language.PureScript.Ide.Command (Command(..), ImportCommand(..), ListType(..)) import Language.PureScript.Ide.Completion (CompletionOptions, completionFromMatch, getCompletions, getExactCompletions, simpleExport)@@ -42,7 +43,6 @@ import Language.PureScript.Ide.Usage (findUsages) import System.Directory (getCurrentDirectory, getDirectoryContents, doesDirectoryExist, doesFileExist) import System.FilePath ((</>), normalise)-import System.FilePath.Glob (glob) -- | Accepts a Command and runs it against psc-ide's State. This is the main -- entry point for the server.@@ -179,8 +179,14 @@ -- | Finds all matches for the globs specified at the commandline findAllSourceFiles :: Ide m => m [FilePath] findAllSourceFiles = do- globs <- confGlobs . ideConfiguration <$> ask- liftIO (concatMapM glob globs)+ IdeConfiguration{..} <- ideConfiguration <$> ask+ liftIO $ toInputGlobs $ PSCGlobs+ { pscInputGlobs = confGlobs+ , pscInputGlobsFromFile = confGlobsFromFile+ , pscExcludeGlobs = confGlobsExclude+ , pscWarnFileTypeNotFound = const $ pure ()+ }+ -- | Looks up the ExternsFiles for the given Modulenames and loads them into the -- server state. Then proceeds to parse all the specified sourcefiles and
src/Language/PureScript/Ide/Types.hs view
@@ -162,6 +162,8 @@ { confOutputPath :: FilePath , confLogLevel :: IdeLogLevel , confGlobs :: [FilePath]+ , confGlobsFromFile :: Maybe FilePath+ , confGlobsExclude :: [FilePath] } data IdeEnvironment =
tests/Language/PureScript/Ide/Test.hs view
@@ -22,6 +22,8 @@ { confLogLevel = LogNone , confOutputPath = "output/" , confGlobs = ["src/**/*.purs"]+ , confGlobsFromFile = Nothing+ , confGlobsExclude = [] } runIde' :: IdeConfiguration -> IdeState -> [Command] -> IO ([Either IdeError Success], IdeState)