on master help sign in
Added a :watch command to the repl to watch for file changes

* Uses a new dep: fsnotify, plus a transitive dep of that, async * Watches the currently loaded files for changes, runs :reload on changes. * Took the :w command away from "warranty" and gave it to "watch" (you can still use :warranty)

commit51e6a296285509c22b2ec9e6447787b34d8fc418 authorLeif Warner <abimelech@gmail.com> dateFri 11 Dec 2015, 21:53 (11 years ago) parentacbcadb
4 files changed+45−11
idris.cabal+2 src/Idris/AbsSyntaxTree.hs+1 src/Idris/REPL.hs+40−10 src/Idris/REPLParser.hs+2−1
idris.cabal+2
@@ -979,6 +979,8 @@ Library
979979 , vector-binary-instances < 0.3
980980 , zip-archive > 0.2.3.5 && < 0.2.4
981981 , safe
982+ , fsnotify < 2.2
983+ , async < 2.1
982984 -- zlib >= 0.6.1 is broken with GHC < 7.10.3
983985 if impl(ghc < 7.10.3)
984986 build-depends: zlib < 0.6.1
src/Idris/AbsSyntaxTree.hs+1
@@ -391,6 +391,7 @@ data Command = Quit
391391 | DocStr (Either Name Const) HowMuchDocs
392392 | TotCheck Name
393393 | Reload
394+ | Watch
394395 | Load FilePath (Maybe Int) -- up to maximum line number
395396 | ChangeDirectory FilePath
396397 | ModImport String
src/Idris/REPL.hs+40−10
@@ -94,6 +94,10 @@ import Data.Word (Word)
9494import Data.Either (partitionEithers)
9595import Control.DeepSeq
9696
97+import Control.Concurrent.Async (race)
98+import System.FSNotify (withManager, watchDir)
99+import System.FSNotify.Devel (allEvents, doAllEvents)
100+
97101import Numeric ( readHex )
98102
99103import Debug.Trace
@@ -671,6 +675,33 @@ lit f = case splitExtension f of
671675 (_, ".lidr") -> True
672676 _ -> False
673677
678+reload :: IState -> [FilePath] -> Idris (Maybe [FilePath])
679+reload orig inputs = do
680+ i <- getIState
681+ -- The $!! here prevents a space leak on reloading.
682+ -- This isn't a solution - but it's a temporary stopgap.
683+ -- See issue #2386
684+ putIState $!! orig { idris_options = idris_options i
685+ , idris_colourTheme = idris_colourTheme i
686+ , imported = imported i
687+ }
688+ clearErr
689+ fmap Just $ loadInputs inputs Nothing
690+
691+watch :: IState -> [FilePath] -> Idris (Maybe [FilePath])
692+watch orig inputs = do
693+ let inputSet = S.fromList inputs
694+ let dirs = nub $ map takeDirectory inputs
695+ resp <- runIO $ do
696+ signal <- newEmptyMVar
697+ withManager $ \mgr -> do
698+ forM_ dirs $ \dir ->
699+ watchDir mgr dir (allEvents $ flip S.member inputSet) (doAllEvents $ putMVar signal)
700+ race getLine (takeMVar signal)
701+ case resp of
702+ Left _ -> return (Just inputs) -- canceled, so nop
703+ Right _ -> reload orig inputs >> watch orig inputs
704+
674705processInput :: String ->
675706 IState -> [FilePath] -> FilePath -> Idris (Maybe [FilePath])
676707processInput cmd orig inputs efile
@@ -683,16 +714,15 @@ processInput cmd orig inputs efile
683714 Failure err -> do iputStrLn $ show (fixColour c err)
684715 return (Just inputs)
685716 Success (Right Reload) ->
686− -- The $!! here prevents a space leak on reloading.
687− -- This isn't a solution - but it's a temporary stopgap.
688− -- See issue #2386
689− do putIState $!! orig { idris_options = idris_options i
690− , idris_colourTheme = idris_colourTheme i
691− , imported = imported i
692− }
693− clearErr
694− mods <- loadInputs inputs Nothing
695− return (Just mods)
717+ reload orig inputs
718+ Success (Right Watch) ->
719+ if null inputs then
720+ do iputStrLn "No loaded files to watch."
721+ return (Just inputs)
722+ else
723+ do iputStrLn efile
724+ iputStrLn $ "Watching for .idr changes in " ++ show inputs ++ ", press enter to cancel."
725+ watch orig inputs
696726 Success (Right (Load f toline)) ->
697727 -- The $!! here prevents a space leak on reloading.
698728 -- This isn't a solution - but it's a temporary stopgap.
src/Idris/REPLParser.hs+2−1
@@ -67,6 +67,7 @@ parserCommandsForHelp =
6767 , namespaceArgCmd ["browse"] Browse "List the contents of some namespace"
6868 , nameArgCmd ["total"] TotCheck "Check the totality of a name"
6969 , noArgCmd ["r", "reload"] Reload "Reload current file"
70+ , noArgCmd ["w", "watch"] Watch "Watch the current file for changes"
7071 , (["l", "load"], FileArg, "Load a new file"
7172 , strArg (\f -> Load f Nothing))
7273 , (["cd"], FileArg, "Change working directory"
@@ -98,7 +99,7 @@ parserCommandsForHelp =
9899 , (["consolewidth"], ConsoleWidthArg, "Set the width of the console", cmd_consolewidth)
99100 , (["printerdepth"], OptionalArg NumberArg, "Set the maximum pretty-printer depth (no arg for infinite)", cmd_printdepth)
100101 , noArgCmd ["q", "quit"] Quit "Exit the Idris system"
101− , noArgCmd ["w", "warranty"] Warranty "Displays warranty information"
102+ , noArgCmd ["warranty"] Warranty "Displays warranty information"
102103 , (["let"], ManyArgs DeclArg
103104 , "Evaluate a declaration, such as a function definition, instance implementation, or fixity declaration"
104105 , cmd_let)