Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

108 lsp #109

Merged
merged 9 commits into from
Nov 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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