module Language.Haskell.LSP.Test.Session
( Session
, SessionConfig(..)
+ , defaultConfig
, SessionMessage(..)
, SessionContext(..)
, SessionState(..)
, sendMessage
, updateState
, withTimeout
+ , logMsg
+ , LogMsgType(..)
)
where
import qualified Control.Monad.Trans.State as State (get, put)
import qualified Data.ByteString.Lazy.Char8 as B
import Data.Aeson
+import Data.Aeson.Encode.Pretty
import Data.Conduit as Conduit
import Data.Conduit.Parser as Parser
import Data.Default
-- You can send and receive messages to the server within 'Session' via 'getMessage',
-- 'sendRequest' and 'sendNotification'.
--
--- @
--- runSession \"path\/to\/root\/dir\" $ do
--- docItem <- getDocItem "Desktop/simple.hs" "haskell"
--- sendNotification TextDocumentDidOpen (DidOpenTextDocumentParams docItem)
--- diagnostics <- getMessage :: Session PublishDiagnosticsNotification
--- @
+
type Session = ParserStateReader FromServerMessage SessionState SessionContext IO
-- | Stuff you can configure for a 'Session'.
data SessionConfig = SessionConfig
- {
- messageTimeout :: Int -- ^ Maximum time to wait for a message in seconds. Defaults to 60.
- , logStdErr :: Bool -- ^ When True redirects the servers stderr output to haskell-lsp-test's stdout. Defaults to False.
- , logMessages :: Bool -- ^ When True traces the communication between client and server to stdout. Defaults to True.
+ { messageTimeout :: Int -- ^ Maximum time to wait for a message in seconds, defaults to 60.
+ , logStdErr :: Bool -- ^ Redirect the server's stderr to this stdout, defaults to False.
+ , logMessages :: Bool -- ^ Trace the messages sent and received to stdout, defaults to True.
+ , logColor :: Bool -- ^ Add ANSI color to the logged messages, defaults to True.
}
+-- | The configuration used in 'Language.Haskell.LSP.Test.runSession'.
+defaultConfig :: SessionConfig
+defaultConfig = SessionConfig 60 False True True
+
instance Default SessionConfig where
- def = SessionConfig 60 False True
+ def = defaultConfig
data SessionMessage = ServerMessage FromServerMessage
| TimeoutMessage Int
yield msg
chanSource
-
watchdog :: ConduitM SessionMessage FromServerMessage (StateT SessionState (ReaderT SessionContext IO)) ()
watchdog = Conduit.awaitForever $ \msg -> do
curId <- curTimeoutId <$> get
sendMessage :: (MonadIO m, HasReader SessionContext m, ToJSON a) => a -> m ()
sendMessage msg = do
h <- serverIn <$> ask
- let encoded = encode msg
- liftIO $ do
-
- setSGR [SetColor Foreground Vivid Cyan]
- putStrLn $ "--> " ++ B.unpack encoded
- setSGR [Reset]
-
- B.hPut h (addHeader encoded)
+ logMsg LogClient msg
+ liftIO $ B.hPut h (addHeader $ encode msg)
-- | Execute a block f that will throw a 'TimeoutException'
-- after duration seconds. This will override the global timeout
overridingTimeout = False
}
return res
+
+data LogMsgType = LogServer | LogClient
+ deriving Eq
+
+-- | Logs the message if the config specified it
+logMsg :: (ToJSON a, MonadIO m, HasReader SessionContext m)
+ => LogMsgType -> a -> m ()
+logMsg t msg = do
+ shouldLog <- asks $ logMessages . config
+ shouldColor <- asks $ logColor . config
+ liftIO $ when shouldLog $ do
+ when shouldColor $ setSGR [SetColor Foreground Dull color]
+ putStrLn $ arrow ++ showPretty msg
+ when shouldColor $ setSGR [Reset]
+
+ where arrow
+ | t == LogServer = "<-- "
+ | otherwise = "--> "
+ color
+ | t == LogServer = Magenta
+ | otherwise = Cyan
+
+ showPretty = B.unpack . encodePretty