Skip to content

Commit

Permalink
Merge pull request #109 from skx/108-lsp
Browse files Browse the repository at this point in the history
108 lsp
  • Loading branch information
skx authored Nov 28, 2022
2 parents caf59f7 + 041ec04 commit d76580f
Show file tree
Hide file tree
Showing 13 changed files with 494 additions and 4 deletions.
2 changes: 2 additions & 0 deletions INTRODUCTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ That concludes the brief overview, note that `lambda` can be used as a synonym f

## See Also

* [LSP.md](LSP.md)
* LSP support.
* [README.md](README.md)
* More details of the project.
* [PRIMITIVES.md](PRIMITIVES.md)
Expand Down
98 changes: 98 additions & 0 deletions LSP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@

* [Language Server Provider](#language-server-provider)
* [Our LSP Features](#our-lsp-features)
* [Configuration](#configuration)
* [Emacs](#configuration-emacs)
* [NeoVim](#configuration-neovim)
* [Screenshots](#screenshots)
* [Notes](#notes)
* [See Also](#see-also)


# Language Server Provider

Adding features like auto complete, go to definition, or documentation
on hover for a programming language takes significant effort. Traditionally
this work had to be repeated for each development tool, as each tool
provides different APIs for implementing the same feature.

A Language Server is meant to provide the language-specific smarts and
communicate with development tools over a protocol that enables
inter-process communication.

The idea behind the Language Server Protocol (LSP) is to standardize
the protocol for how such servers and development tools communicate.
This way, a single Language Server can be re-used in multiple
development tools, which in turn can support multiple languages with
minimal effort.


## Our LSP Features

We only support the bare minimum LSP features:

* Provide completion for the names of all standard-library functions.
* Shows information on standard-library functions, on hover.




# Configuration

To use our LSP implementation you'll need to configure your editor, IDE, or environment appropriately. Configuration will vary depending on what you're using.

Typically configuration will involve at least:

* Specifying the type of files that hould use LSP (i.e. a filename suffixes).
* Specifying the name/arguments to use for the LSP server.

For our implementation you'll need to launch "`yal -lsp`" to startup the LSP-process.


## Configuration: Emacs

For GNU Emacs the following file should provide all the help you need:

* [_misc/yal.el](_misc/yal.el)


## Configuration: neovim

Create the file `~/.config/nvim/init.lua` with contents as below:

* [_misc/init.lua](_misc/init.lua)



# Screenshots

Here we see what completion might look like:

![Completion](_misc/complete.png?raw=true "Completion")

Here's our help-text being displayed on-hover:

![Help](_misc/help.png?raw=true "Help")



# Notes

As stated above we only support hover-text, and completion, from the
standard library. Supporting the users' own code is harder because that
would involve evaluating it - and that might cause side-effects.

It should be noted that our completion-support is very naive - it literally
returns the names of __all__ available methods, and relies upon the editor
to narrow down the selection - that seems to work though.



# See Also

* [README.md](README.md)
* More details of the project.
* [PRIMITIVES.md](PRIMITIVES.md)
* The list of built-in functions, whether implemented in Golang or YAL.
* [INTRODUCTION.md](INTRODUCTION.md)
* Getting started setting variables, defining functions, etc.
2 changes: 2 additions & 0 deletions PRIMITIVES.md
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,8 @@ Adding new tests is easy enough that this file should be updated over time with

# See Also

* [LSP.md](LSP.md)
* LSP support.
* [README.md](README.md)
* More details of the project.
* [INTRODUCTION.md](INTRODUCTION.md)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* [A list of primitives we have implemented](PRIMITIVES.md).
* This describes the functions we support, whether implemented in lisp or golang.
* For example `(car)`, `(cdr)`, `(file:lines)`, `(shell)`, etc.

* Notes on our [LSP](LSP.md) support.


## Building / Installing
Expand Down
Binary file added _misc/complete.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _misc/help.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
95 changes: 95 additions & 0 deletions _misc/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
--
-- ~/.config/nvim/init.lua
--
----

--
-- I used two references to build up this "solution":
--
-- https://vonheikemen.github.io/devlog/tools/manage-neovim-lsp-client-without-plugins/
--
-- Then for the completion I added the "config.on_attach" section, via this comment:
--
-- https://www.reddit.com/r/neovim/comments/rs47cx/tsserver_and_vimlspomnifunc/
--
-- I'm sure there are other approaches, but neovim is new to me.
--


--
-- Define a helper function which will associate our LSP
-- magic with the appropriate filenames.
--
local launch_yal_server = function()
local autocmd
local filetypes = {
'lisp',
'yal',
'*.lisp',
'*.yal',
}

local config = {
cmd = {'yal', '-lsp'},
name = 'yal',
root_dir = vim.fn.getcwd(),
capabilities = vim.lsp.protocol.make_client_capabilities(),
}

-- This gives completion.
config.on_attach = function(client, bufnr)
vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
end

config.on_init = function(client, results)
local buf_attach = function()
vim.lsp.buf_attach_client(0, client.id)
end

autocmd = vim.api.nvim_create_autocmd('FileType', {
desc = string.format('Attach LSP: %s', client.name),
pattern = filetypes,
callback = buf_attach
})

if vim.v.vim_did_enter == 1 and
vim.tbl_contains(filetypes, vim.bo.filetype)
then
buf_attach()
end
end

config.on_exit = vim.schedule_wrap(function(code, signal, client_id)
vim.api.nvim_del_autocmd(autocmd)
end)

vim.lsp.start_client(config)
end


--
-- When an LSP attachment happens then ensure we bind
-- a key for hover-information
--
vim.api.nvim_create_autocmd('LspAttach', {
desc = 'LSP actions',
callback = function()
local bufmap = function(mode, lhs, rhs)
local opts = {buffer = true}
vim.keymap.set(mode, lhs, rhs, opts)
end

-- Displays hover information about the symbol
-- under the cursor when you press "K".
bufmap('n', 'K', '<cmd>lua vim.lsp.buf.hover()<cr>')

end })


--
-- Invoke our helper function to start the server.
--
-- NOTE: This runs every time you launch neovim, even if you're not opening
-- a yal/lisp file.
--
launch_yal_server()
32 changes: 32 additions & 0 deletions _misc/yal.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
;;; yal.el -- Sample configuration for using Emacs LSP-mode with YAL


;; Create a keyboard-map for use within YAL files
(defvar yal-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-c TAB") 'completion-at-point)
map))

;; Define a hook which will run when entering YAL mode.
(add-hook 'yal-mode-hook 'lsp-deferred)

;; Now create a trivial "yal-mode"
(define-derived-mode yal-mode
lisp-mode "YAL"
"Major mode for working with yet another lisp, YAL.")

;; yal-mode will be invoked for *.yal files
(add-to-list 'auto-mode-alist '("\\.yal\\'" . yal-mode))

;; Load the library
(require 'lsp-mode)

;; Register an LSP helper
(lsp-register-client
(make-lsp-client :new-connection (lsp-stdio-connection '("yal" "-lsp"))
:major-modes '(yal-mode)
:priority -1
:server-id 'yal-ls))

;; Not sure what this does, but it seems to be necessary
(add-to-list 'lsp-language-id-configuration '(yal-mode . "yal"))
2 changes: 1 addition & 1 deletion examples/lisp-tests.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ If the name of the test is not unique then that will cause an error to be printe

;; structures
(deftest struct:1 (list (do (struct person name) (type (person "me")))
"struct-person"))
"person"))
(deftest struct:2 (list (do (struct person name) (person? (person "me")))
true))
(deftest struct:3 (list (do (struct person name) (person.name (person "me")))
Expand Down
25 changes: 25 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
module github.com/skx/yal

go 1.18

require (
github.com/tliron/glsp v0.1.1
github.com/tliron/kutil v0.1.63
go.lsp.dev/uri v0.3.0
)

require (
github.com/gorilla/websocket v1.5.0 // indirect
github.com/iancoleman/strcase v0.2.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/muesli/termenv v0.12.0 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/sasha-s/go-deadlock v0.3.1 // indirect
github.com/sourcegraph/jsonrpc2 v0.1.0 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect
)
49 changes: 49 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/muesli/termenv v0.12.0 h1:KuQRUE3PgxRFWhq4gHvZtPSLCGDqM5q/cYr1pZ39ytc=
github.com/muesli/termenv v0.12.0/go.mod h1:WCCv32tusQ/EEZ5S8oUIIrC/nIuBcxCVqlN4Xfkv+7A=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0=
github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM=
github.com/sourcegraph/jsonrpc2 v0.1.0 h1:ohJHjZ+PcaLxDUjqk2NC3tIGsVa5bXThe1ZheSXOjuk=
github.com/sourcegraph/jsonrpc2 v0.1.0/go.mod h1:ZafdZgk/axhT1cvZAPOhw+95nz2I/Ra5qMlU4gTRwIo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tliron/glsp v0.1.1 h1:GNNgUX9p1Q9MoPQooJoZ0+WaLL03EkhcKZUYJAtiNqs=
github.com/tliron/glsp v0.1.1/go.mod h1:RVyVKeY3U+Nlc3DRklUiaegNsQyjzNTEool6YWh1v7g=
github.com/tliron/kutil v0.1.63 h1:/xOqEShxPymwhcVcPFAks8zj43HU+NljbmzYjNXIO+Y=
github.com/tliron/kutil v0.1.63/go.mod h1:Mo1pAtg/9yG3ClnUv32Hrl+t0BFFCg49RpCjHG3sY7c=
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
go.lsp.dev/uri v0.3.0 h1:KcZJmh6nFIBeJzTugn5JTU6OOyG0lDOo3R9KwTxTYbo=
go.lsp.dev/uri v0.3.0/go.mod h1:P5sbO1IQR+qySTWOCnhnK7phBx+W3zbLqSMDJNTw88I=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc=
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading

0 comments on commit d76580f

Please sign in to comment.