@@ -9,11 +9,11 @@ import System.Exit (exitSuccess)
99import System.IO (Handle , hClose , hFlush , hGetLine ,
1010 hPutStrLn , stderr , stdout )
1111
12- import Control.Applicative ((<$>) )
12+ import Control.Applicative ((<$>) , (<*>) )
1313
1414import Data.Aeson (FromJSON (.. ), ToJSON (.. ),
1515 Value (.. ), eitherDecode , encode ,
16- object , (.:) , (.=) )
16+ object , (.:) , (.:?) , (.=) , (.! =) )
1717import qualified Data.ByteString.Lazy.Char8 as BS
1818
1919import GHC.Generics (Generic )
@@ -22,29 +22,32 @@ import Language.Haskell.GhcMod (check, defaultOptions, findCradle,
2222
2323import Language.Haskell.Stylish
2424
25+ import Data.Char (isSpace )
26+ import ReplSession
27+
2528main :: IO ()
2629main = withSocketsDo $ do
27- [portStr, clientIdStr] <- getArgs
30+ [portStr, clientIdStr, projectDir ] <- getArgs
2831 let port = fromIntegral (read portStr :: Int )
2932 clientId = read clientIdStr
3033 handle <- connectTo " localhost" (PortNumber port)
31- cwd <- getCurrentDirectory
34+ client <- startSession projectDir
3235
33- putStrLn $ " Connected: " ++ cwd
36+ putStrLn $ " Connected: " ++ projectDir
3437 hFlush stdout
3538
36- sendResponse handle $ LTConnection " Haskell" " haskell" clientId cwd [" haskell.api.reformat" , " haskell.api.syntax" ]
37- processCommands handle
39+ sendResponse handle $ LTConnection " Haskell" " haskell" clientId projectDir [" haskell.api.reformat" , " haskell.api.syntax" ]
3840
41+ processCommands $ LTClientState handle client
3942
40- processCommands :: Handle -> IO ()
41- processCommands handle = do
43+ processCommands :: LTClientState -> IO ()
44+ processCommands state @ ( LTClientState handle _) = do
4245 line <- hGetLine handle
4346 case parseCommand line of
4447 Left e -> hPutStrLn stderr (" Error processing command: " ++ e)
45- Right ltCommand -> execCommand handle ltCommand
48+ Right ltCommand -> execCommand state ltCommand
4649
47- processCommands handle
50+ processCommands state
4851
4952 where
5053 parseCommand :: String -> Either String (LTCommand (Maybe LTPayload ))
@@ -55,19 +58,22 @@ sendResponse handle = hPutStrLn handle . BS.unpack . encode
5558
5659-- API
5760
58- execCommand :: Handle -> LTCommand (Maybe LTPayload ) -> IO ()
61+ data LTClientState = LTClientState { ltHandle :: Handle , ltReplSession :: ReplSession }
62+
63+ execCommand :: LTClientState -> LTCommand (Maybe LTPayload ) -> IO ()
5964
60- execCommand handle (LTCommand (_, " client.close" , Nothing )) = do
61- hClose handle
65+ execCommand state (LTCommand (_, " client.close" , Nothing )) = do
66+ hClose $ ltHandle state
67+ endSession $ ltReplSession state
6268 exitSuccess
6369
64- execCommand handle (LTCommand (cId, command, Just ltPayload)) =
70+ execCommand state (LTCommand (cId, command, Just ltPayload)) =
6571 go command $ ltData ltPayload
6672
6773 where
6874 go " haskell.api.reformat" payloadData = do
6975 reformattedCode <- format payloadData
70- respond " editor.haskell.reformat.result" $ LTPayload reformattedCode
76+ respond " editor.haskell.reformat.result" $ LTPayload reformattedCode 0
7177
7278 go " haskell.api.syntax" payloadData = do
7379 syntaxIssues <- getSyntaxIssues payloadData
@@ -77,8 +83,26 @@ execCommand handle (LTCommand (cId, command, Just ltPayload)) =
7783 lintIssues <- getLintIssues payloadData
7884 respond " editor.haskell.lint.result" $ LTArrayPayload lintIssues
7985
86+ go " haskell.api.eval" payloadData = do
87+ result <- evalInSession payloadData $ ltReplSession state
88+ let line = ltLine ltPayload
89+ case result of
90+ Left msg -> respond " editor.eval.haskell.exception" $ LTPayload msg line
91+ Right msg | isBlank msg -> respond " editor.eval.haskell.success" $ LTPayload " " line
92+ Right msg -> respond " editor.eval.haskell.result" $ LTPayload msg line
93+
94+ go " haskell.api.type" payloadData = do
95+ result <- evalInSession (" :type " ++ payloadData) $ ltReplSession state
96+ let line = ltLine ltPayload
97+ case result of
98+ Left msg -> respond " editor.eval.haskell.exception" $ LTPayload msg line
99+ Right msg -> respond " editor.eval.haskell.result" $ LTPayload msg line
100+
80101 respond :: (ToJSON a ) => Command -> a -> IO ()
81- respond respCommand respPayload = sendResponse handle $ LTCommand (cId, respCommand, respPayload)
102+ respond respCommand respPayload = sendResponse (ltHandle state) $ LTCommand (cId, respCommand, respPayload)
103+
104+ isBlank :: String -> Bool
105+ isBlank = all isSpace
82106
83107-- API types
84108
@@ -89,12 +113,12 @@ data LTCommand a = LTCommand (Client, Command, a) deriving (Show, Generic)
89113instance (FromJSON a ) => FromJSON (LTCommand a )
90114instance (ToJSON a ) => ToJSON (LTCommand a )
91115
92- data LTPayload = LTPayload { ltData :: String } deriving (Show )
116+ data LTPayload = LTPayload { ltData :: String , ltLine :: Int } deriving (Show )
93117instance FromJSON LTPayload where
94- parseJSON (Object v) = LTPayload <$> v .: " data"
118+ parseJSON (Object v) = LTPayload <$> v .: " data" <*> (v .:? " line " .!= 0 )
95119
96120instance ToJSON LTPayload where
97- toJSON payload = object [ " data" .= ltData payload ]
121+ toJSON payload = object [ " data" .= ltData payload, " line " .= ltLine payload ]
98122
99123data LTArrayPayload = LTArrayPayload { ltDataArray :: [String ] } deriving (Show )
100124instance FromJSON LTArrayPayload where
0 commit comments