@@ -36,6 +36,8 @@ import Data.Map (Map)
3636import qualified Data.Map as Map
3737import Data.Maybe (mapMaybe )
3838import System.FilePath
39+ import UnliftIO.STM
40+ import UnliftIO.Exception (SomeException (.. ), catch )
3941
4042
4143-- | Simple data type containing a few information on how to start ghcid.
@@ -56,28 +58,32 @@ instance ToJSON ProjectSettings
5658instance FromJSON ProjectSettings
5759
5860
59- data GhcidState r = GhcidState
60- { startedSessions :: Map FilePath (Ghci , Neovim r ( GhcidState r ) ( ) )
61+ data GhcidEnv = GhcidEnv
62+ { startedSessions :: TVar ( Map FilePath (Ghci , Neovim GhcidEnv () ))
6163 -- ^ A map from the root directory (see 'rootDir') to a 'Ghci' session and a
6264 -- release function which unregisters some autocmds and stops the ghci
6365 -- session.
6466
65- , quickfixItems :: [QuickfixListItem String ]
67+ , quickfixItems :: TVar [QuickfixListItem String ]
6668 }
6769
6870
69- modifyStartedSessions :: (Map FilePath (Ghci , Neovim r (GhcidState r ) () )
70- -> Map FilePath (Ghci , Neovim r (GhcidState r ) () ))
71- -> Neovim r (GhcidState r ) ()
72- modifyStartedSessions f = modify $ \ s -> s { startedSessions = f (startedSessions s) }
71+ initGhcidEnv :: MonadIO m => m GhcidEnv
72+ initGhcidEnv = GhcidEnv <$> newTVarIO mempty <*> newTVarIO mempty
73+
74+ modifyStartedSessions :: (Map FilePath (Ghci , Neovim GhcidEnv () )
75+ -> Map FilePath (Ghci , Neovim GhcidEnv () ))
76+ -> Neovim GhcidEnv ()
77+ modifyStartedSessions f = do
78+ atomically . flip modifyTVar' f =<< asks startedSessions
7379
7480
7581-- | Start or update a ghcid session.
7682--
7783-- This will call 'determineProjectSettings' and ask you to confirm or overwrite
7884-- its proposed settings. If you prepend a bang, it acts as if you have
7985-- confirmed all settings.
80- ghcidStart :: CommandArguments -> Neovim r ( GhcidState r ) ()
86+ ghcidStart :: CommandArguments -> Neovim GhcidEnv ()
8187ghcidStart copts = do
8288 currentBufferPath <- errOnInvalidResult $ vim_call_function " expand" [ObjectBinary " %:p:h" ]
8389 liftIO (determineProjectSettings' currentBufferPath) >>= \ case
@@ -103,41 +109,45 @@ ghcidStart copts = do
103109
104110-- | Start a new ghcid session or reload the modules to update the quickfix
105111-- list.
106- startOrReload :: ProjectSettings -> Neovim r (GhcidState r ) ()
107- startOrReload s@ (ProjectSettings d c) = Map. lookup d <$> gets startedSessions >>= \ case
108- Nothing -> do
109- (g, ls) <- liftIO $ startGhci c (Just d) (\ _ _ -> return () )
110- applyQuickfixActions $ loadToQuickfix ls
111- void $ vim_command " cwindow"
112- ra <- addAutocmd " BufWritePost" def (startOrReload s) >>= \ case
113- Nothing ->
114- return $ return ()
112+ startOrReload :: ProjectSettings -> Neovim GhcidEnv ()
113+ startOrReload s@ (ProjectSettings d c) = do
114+ sessions <- atomically . readTVar =<< asks startedSessions
115+ case Map. lookup d sessions of
116+ Nothing -> do
117+ (g, ls) <- liftIO (startGhci c (Just d) (\ _ _ -> return () ))
118+ `catch` \ (SomeException e) -> err . pretty $ " Failed to start ghcid session: " <> show e
119+ applyQuickfixActions $ loadToQuickfix ls
120+ void $ vim_command " cwindow"
121+ ra <- addAutocmd " BufWritePost" def (startOrReload s) >>= \ case
122+ Nothing ->
123+ return $ return ()
115124
116- Just (Left a) ->
117- return a
125+ Just (Left a) ->
126+ return a
118127
119- Just (Right rk) ->
120- return $ Resource. release rk
128+ Just (Right rk) ->
129+ return $ Resource. release rk
121130
122- modifyStartedSessions $ Map. insert d (g,ra >> liftIO (stopGhci g))
131+ modifyStartedSessions $ Map. insert d (g,ra >> liftIO (stopGhci g))
123132
124- Just (ghci, _) -> do
125- applyQuickfixActions =<< loadToQuickfix <$> liftIO (reload ghci)
126- void $ vim_command " cwindow"
133+ Just (ghci, _) -> do
134+ applyQuickfixActions =<< loadToQuickfix <$> liftIO (reload ghci)
135+ void $ vim_command " cwindow"
127136
128137
129- applyQuickfixActions :: [QuickfixListItem String ] -> Neovim r ( GhcidState r ) ()
138+ applyQuickfixActions :: [QuickfixListItem String ] -> Neovim GhcidEnv ()
130139applyQuickfixActions qs = do
131- fqs <- (nub' . rights . map bufOrFile) <$> gets quickfixItems
132- modify $ \ s -> s { quickfixItems = qs }
140+ qfItems <- asks quickfixItems
141+ fqs <- (nub' . rights . map bufOrFile) <$> atomically (readTVar qfItems)
142+ atomically $ modifyTVar' qfItems (const qs)
133143 forM_ fqs $ \ f -> void . vim_command $ " sign unplace * file=" <> f
134144 setqflist qs Replace
135145 placeSigns qs
136146 where
137147 nub' = map head . groupBy (==) . sort
138148
139149
140- placeSigns :: [QuickfixListItem String ] -> Neovim r st ()
150+ placeSigns :: [QuickfixListItem String ] -> Neovim env ()
141151placeSigns qs = forM_ (zip [(1 :: Integer ).. ] qs) $ \ (i, q) -> case (lnumOrPattern q, bufOrFile q) of
142152 (Right _, _) ->
143153 -- Patterns not handled as they are not produced
@@ -160,10 +170,11 @@ placeSigns qs = forM_ (zip [(1::Integer)..] qs) $ \(i, q) -> case (lnumOrPattern
160170 ]
161171
162172-- | Stop a ghcid session associated to the currently active buffer.
163- ghcidStop :: CommandArguments -> Neovim r ( GhcidState r ) ()
173+ ghcidStop :: CommandArguments -> Neovim GhcidEnv ()
164174ghcidStop _ = do
165175 d <- errOnInvalidResult $ vim_call_function " expand" [ObjectBinary " %:p:h" ]
166- Map. lookupLE d <$> gets startedSessions >>= \ case
176+ sessions <- atomically . readTVar =<< asks startedSessions
177+ case Map. lookupLE d sessions of
167178 Nothing ->
168179 return ()
169180 Just (p,(_, releaseAction)) -> do
@@ -172,7 +183,7 @@ ghcidStop _ = do
172183
173184
174185-- | Same as @:GhcidStop@ followed by @:GhcidStart!@. Note the bang!
175- ghcidRestart :: CommandArguments -> Neovim r ( GhcidState r ) ()
186+ ghcidRestart :: CommandArguments -> Neovim GhcidEnv ()
176187ghcidRestart _ = do
177188 ghcidStop def
178189 ghcidStart def { bang = Just True }
0 commit comments