packages feed

lsp-1.0.0.0: README.md

[![CircleCI](https://circleci.com/gh/alanz/lsp/tree/master.svg?style=svg)](https://circleci.com/gh/alanz/lsp/tree/master)
[![Hackage](https://img.shields.io/hackage/v/lsp.svg)](https://hackage.haskell.org/package/lsp)

# lsp
Haskell library for the Microsoft Language Server Protocol.
It currently implements all of the [3.15 specification](https://microsoft.github.io/language-server-protocol/specifications/specification-3-15/).

It is split into two separate packages, `lsp` and `lsp-types`
- `lsp-types` provides *type-safe* definitions that match up with the
typescript definitions laid out in the specification
- `lsp` is a library for building language servers, handling:
  - JSON-RPC transport
  - Keeping track of the document state in memory with the Virtual File System (VFS)
  - Responding to notifications and requests via handlers
  - Setting the server capabilities in the initialize request based on registered handlers
  - Dynamic registration of capabilities
  - Cancellable requests and progress notifications
  - Publishing and flushing of diagnostics

## Language servers built on lsp
- [ghcide](https://github.com/haskell/ghcide)
- [haskell-language-server](https://github.com/haskell/haskell-language-server)
- [dhall-lsp-server](https://github.com/dhall-lang/dhall-haskell/tree/master/dhall-lsp-server#readme)

## Example language servers
There are two example language servers in the `example/` folder. `Simple.hs` provides a minimal example:

```haskell
{-# LANGUAGE OverloadedStrings #-}

import Language.LSP.Server
import Language.LSP.Types
import Control.Monad.IO.Class
import qualified Data.Text as T

handlers :: Handlers (LspM ())
handlers = mconcat
  [ notificationHandler SInitialized $ \_not -> do
      let params = ShowMessageRequestParams MtInfo "Turn on code lenses?"
            (Just [MessageActionItem "Turn on", MessageActionItem "Don't"])
      _ <- sendRequest SWindowShowMessageRequest params $ \res ->
        case res of
          Right (Just (MessageActionItem "Turn on")) -> do
            let regOpts = CodeLensRegistrationOptions Nothing Nothing (Just False)
              
            _ <- registerCapability STextDocumentCodeLens regOpts $ \_req responder -> do
              let cmd = Command "Say hello" "lsp-hello-command" Nothing
                  rsp = List [CodeLens (mkRange 0 0 0 100) (Just cmd) Nothing]
              responder (Right rsp)
            pure ()
          Right _ ->
            sendNotification SWindowShowMessage (ShowMessageParams MtInfo "Not turning on code lenses")
          Left err ->
            sendNotification SWindowShowMessage (ShowMessageParams MtError $ "Something went wrong!\n" <> T.pack (show err))
      pure ()
  , requestHandler STextDocumentHover $ \req responder -> do
      let RequestMessage _ _ _ (HoverParams _doc pos _workDone) = req
          Position _l _c' = pos
          rsp = Hover ms (Just range)
          ms = HoverContents $ markedUpContent "lsp-demo-simple-server" "Hello world"
          range = Range pos pos
      responder (Right $ Just rsp)
  ]

main :: IO Int
main = runServer $ ServerDefinition
  { onConfigurationChange = const $ pure $ Right ()
  , doInitialize = \env _req -> pure $ Right env
  , staticHandlers = handlers
  , interpretHandler = \env -> Iso (runLspT env) liftIO
  , options = defaultOptions
  }
```

Whilst `Reactor.hs` shows how a reactor design can be used to handle all
requests on a separate thread, such in a way that we could then execute them on
multiple threads without blocking server communication. They can be installed
from source with

    cabal install lsp-demo-simple-server lsp-demo-reactor-server
    stack install :lsp-demo-simple-server :lsp-demo-reactor-server --flag haskell-lsp:demo

## Useful links

- https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md

## Other resources

See #haskell-ide-engine on IRC freenode