@@ -94,6 +94,10 @@ import Data.Word (Word)
94import Data.Either (partitionEithers)
94import Data.Either (partitionEithers)
95import Control.DeepSeq
95import Control.DeepSeq
97+import Control.Concurrent.Async (race)
98+import System.FSNotify (withManager, watchDir)
99+import System.FSNotify.Devel (allEvents, doAllEvents)
97import Numeric ( readHex )
101import Numeric ( readHex )
99import Debug.Trace
103import Debug.Trace
@@ -126,10 +130,8 @@ repl orig mods efile
126 do ms <- H.catch (lift $ processInput input orig mods efile)
130 do ms <- H.catch (lift $ processInput input orig mods efile)
127 (ctrlC (return (Just mods)))
131 (ctrlC (return (Just mods)))
128 case ms of
132 case ms of
129− Just mods -> let efile' = case mods of
133+ Just mods -> let efile' = fromMaybe efile (listToMaybe mods)
132− repl orig mods efile'
134+ in repl orig mods efile'
133 Nothing -> return ()
135 Nothing -> return ()
@@ -154,15 +156,13 @@ repl orig mods efile
155-- | Run the REPL server
157-- | Run the REPL server
156startServer :: PortID -> IState -> [FilePath] -> Idris ()
158startServer :: PortID -> IState -> [FilePath] -> Idris ()
157−startServer port orig fn_in = do tid <- runIO $ forkOS (serverLoop port)
159+startServer port orig fn_in = do tid <- runIO $ forkIO (serverLoop port)
158 return ()
160 return ()
159 where serverLoop port = withSocketsDo $
161 where serverLoop port = withSocketsDo $
160 do sock <- listenOnLocalhost port
162 do sock <- listenOnLocalhost port
161 loop fn orig { idris_colourRepl = False } sock
163 loop fn orig { idris_colourRepl = False } sock
163− fn = case fn_in of
165+ fn = fromMaybe "" (listToMaybe fn_in)
167 loop fn ist sock
167 loop fn ist sock
168 = do (h,_,_) <- accept sock
168 = do (h,_,_) <- accept sock
@@ -276,9 +276,7 @@ idemode h orig mods
276 i <- getIState
276 i <- getIState
277 putIState $ i { idris_outputmode = (IdeMode id h) }
277 putIState $ i { idris_outputmode = (IdeMode id h) }
278 idrisCatch -- to report correct id back!
278 idrisCatch -- to report correct id back!
279− (do let fn = case mods of
279+ (do let fn = fromMaybe "" (listToMaybe mods)
282 case IdeMode.sexpToCommand sexp of
280 case IdeMode.sexpToCommand sexp of
283 Just cmd -> runIdeModeCommand h id orig fn mods cmd
281 Just cmd -> runIdeModeCommand h id orig fn mods cmd
284 Nothing -> iPrintError "did not understand" )
282 Nothing -> iPrintError "did not understand" )
@@ -677,30 +675,54 @@ lit f = case splitExtension f of
677 (_, ".lidr") -> True
675 (_, ".lidr") -> True
678 _ -> False
676 _ -> False
678+reload :: IState -> [FilePath] -> Idris (Maybe [FilePath])
679+reload orig inputs = do
681+ -- The $!! here prevents a space leak on reloading.
682+ -- This isn't a solution - but it's a temporary stopgap.
684+ putIState $!! orig { idris_options = idris_options i
685+ , idris_colourTheme = idris_colourTheme i
686+ , imported = imported i
689+ fmap Just $ loadInputs inputs Nothing
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
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)
702+ Left _ -> return (Just inputs) -- canceled, so nop
703+ Right _ -> reload orig inputs >> watch orig inputs
680processInput :: String ->
705processInput :: String ->
681 IState -> [FilePath] -> FilePath -> Idris (Maybe [FilePath])
706 IState -> [FilePath] -> FilePath -> Idris (Maybe [FilePath])
682processInput cmd orig inputs efile
707processInput cmd orig inputs efile
683 = do i <- getIState
708 = do i <- getIState
684 let opts = idris_options i
709 let opts = idris_options i
685 let quiet = opt_quiet opts
710 let quiet = opt_quiet opts
686− let fn = case inputs of
711+ let fn = fromMaybe "" (listToMaybe inputs)
689 c <- colourise
712 c <- colourise
690 case parseCmd i "(input)" cmd of
713 case parseCmd i "(input)" cmd of
691 Failure err -> do iputStrLn $ show (fixColour c err)
714 Failure err -> do iputStrLn $ show (fixColour c err)
692 return (Just inputs)
715 return (Just inputs)
693 Success (Right Reload) ->
716 Success (Right Reload) ->
694− -- The $!! here prevents a space leak on reloading.
717+ reload orig inputs
695− -- This isn't a solution - but it's a temporary stopgap.
718+ Success (Right Watch) ->
696− -- See issue #2386
719+ if null inputs then
697− do putIState $!! orig { idris_options = idris_options i
720+ do iputStrLn "No loaded files to watch."
698− , idris_colourTheme = idris_colourTheme i
699− , imported = imported i
702− mods <- loadInputs inputs Nothing
703− return (Just mods)
721+ return (Just inputs)
724+ iputStrLn $ "Watching for .idr changes in " ++ show inputs ++ ", press enter to cancel."
704 Success (Right (Load f toline)) ->
726 Success (Right (Load f toline)) ->
705 -- The $!! here prevents a space leak on reloading.
727 -- The $!! here prevents a space leak on reloading.
706 -- This isn't a solution - but it's a temporary stopgap.
728 -- This isn't a solution - but it's a temporary stopgap.