@@ -21,15 +21,21 @@ import qualified Control.Concurrent.MVar as M
21import qualified Control.Concurrent.Chan as C
21import qualified Control.Concurrent.Chan as C
22import System.Directory (getModificationTime)
22import System.Directory (getModificationTime)
23import Network.Wai.Handler.SimpleServer (parseRequest, sendResponse)
23import Network.Wai.Handler.SimpleServer (parseRequest, sendResponse)
24+import Control.Monad (filterM)
26+import Control.Arrow ((&&&))
27+import System.Directory (doesDirectoryExist,
28+ doesFileExist, getDirectoryContents)
29+import Control.Applicative ((<$>))
25type FunctionName = String
31type FunctionName = String
27−run :: Port -> ModuleName -> FunctionName -> IO ()
33+run :: Port -> ModuleName -> FunctionName -> [FilePath] -> IO ()
28−run port modu func = do
34+run port modu func dirs = do
29 queue <- C.newChan
35 queue <- C.newChan
30 mqueue <- M.newMVar queue
36 mqueue <- M.newMVar queue
31 startApp queue $ loadingApp Nothing
37 startApp queue $ loadingApp Nothing
32− _ <- forkIO $ fillApp modu func mqueue
38+ _ <- forkIO $ fillApp modu func mqueue dirs
33 run' port mqueue
39 run' port mqueue
35startApp :: Queue -> Handler -> IO ()
41startApp :: Queue -> Handler -> IO ()
@@ -41,7 +47,7 @@ startApp queue withApp = do
41 case msession of
47 case msession of
42 Nothing -> return ()
48 Nothing -> return ()
43 Just (req, onRes) -> do
49 Just (req, onRes) -> do
44− void $ forkIO $ (handle onErr $ app req) >>= onRes
50+ void $ forkIO $ (E.handle onErr $ app req) >>= onRes
46 onErr :: SomeException -> IO Response
52 onErr :: SomeException -> IO Response
47 onErr e = return
53 onErr e = return
@@ -50,13 +56,13 @@ startApp queue withApp = do
50 $ "Exception thrown while running application\n\n" ++ show e
56 $ "Exception thrown while running application\n\n" ++ show e
51 void x = x >> return ()
57 void x = x >> return ()
53−fillApp :: String -> String -> M.MVar Queue -> IO ()
59+fillApp :: String -> String -> M.MVar Queue -> [FilePath] -> IO ()
54−fillApp modu func mqueue =
60+fillApp modu func mqueue dirs =
55 go Nothing []
61 go Nothing []
57 constSE :: x -> SomeException -> x
63 constSE :: x -> SomeException -> x
58 constSE = const
64 constSE = const
59− getTimes = handle (constSE $ return []) . mapM getModificationTime
65+ getTimes = E.handle (constSE $ return []) . mapM getModificationTime
60 go prevError prevFiles = do
66 go prevError prevFiles = do
61 toReload <-
67 toReload <-
62 if null prevFiles
68 if null prevFiles
@@ -79,7 +85,9 @@ fillApp modu func mqueue =
79 putStrLn $ "Compile failed: " ++ show err
85 putStrLn $ "Compile failed: " ++ show err
80 loadingApp' (Just $ toException err) mqueue
86 loadingApp' (Just $ toException err) mqueue
81 return (Just $ toException err, [])
87 return (Just $ toException err, [])
82− Right (app, files) -> do
88+ Right (app, files') -> E.handle onInitErr $ do
89+ files'' <- mapM fileList dirs
90+ let files = concat $ files' : files''
83 putStrLn "Interpreting success, new app loaded"
91 putStrLn "Interpreting success, new app loaded"
84 E.handle onInitErr $ do
92 E.handle onInitErr $ do
85 swapApp app mqueue
93 swapApp app mqueue
@@ -90,6 +98,26 @@ fillApp modu func mqueue =
90 loadingApp' (Just e) mqueue
98 loadingApp' (Just e) mqueue
91 return (Just e, [])
99 return (Just e, [])
101+fileList :: FilePath -> IO [FilePath]
103+ ex <- doesDirectoryExist top
104+ if ex then fileList' top "" else return []
106+fileList' :: FilePath -> FilePath -> IO [FilePath]
107+fileList' realTop top = do
108+ let prefix1 = top ++ "/"
109+ prefix2 = realTop ++ prefix1
110+ allContents <- filter notHidden <$> getDirectoryContents prefix2
111+ let all' = map ((++) prefix1 &&& (++) prefix2) allContents
112+ files <- map snd <$> filterM (doesFileExist . snd) all'
113+ dirs <- filterM (doesDirectoryExist . snd) all' >>=
114+ mapM (fileList' realTop . fst)
115+ return $ concat $ files : dirs
117+notHidden :: FilePath -> Bool
118+notHidden ('.':_) = False
93loadingApp' :: Maybe SomeException -> M.MVar Queue -> IO ()
121loadingApp' :: Maybe SomeException -> M.MVar Queue -> IO ()
94loadingApp' err mqueue = swapApp (loadingApp err) mqueue
122loadingApp' err mqueue = swapApp (loadingApp err) mqueue