.. highlight:: shell
*********************
Dylan Language Server
*********************
This is an implementation of the `Language Server Protocol
`_ for Dylan.
.. toctree::
:hidden:
Current Status
==============
As of 2024-04-19, the server implements
* Jump to declaration
* Jump to definition
* Diagnostics (i.e., compiler warnings)
* Hover (i.e., argument lists)
When applied to a symbol which is bound to a generic function, "jump to
definition" will show a list containing the generic function and its specific
methods, whereas "jump to declaration" will jump straight to the generic
function.
Installation
============
1. First install `Open Dylan `_ 2023.1 or newer.
2. Clone the `lsp-dylan repository `_::
$ git clone --recursive https://github.com/dylan-lang/lsp-dylan
3. Update the workspace so that dependencies are installed and the registry is
created::
$ cd lsp-dylan
$ dylan update
4. Build the ``dylan-lsp-server`` binary. This will install the binary in
``${DYLAN}/bin``. If :envvar:`DYLAN` is not defined it defaults to
``${HOME}/dylan``.
::
$ make install
or just run these commands::
$ dylan build --unify dylan-lsp-server
$ cp _build/sbin/dylan-lsp-server /usr/local/bin/
5. Make sure ``dylan-lsp-server`` is on your :envvar:`PATH`.
Usage
=====
The LSP server needs to be able to open a project (that is, a Dylan library)
associated with the file you're editing when you turn on LSP in your editor. It
assumes you are using a `deft `_ workspace
and searches for a project to open as follows:
1. If there is a :file:`workspace.json` file and that file has a
`"default-library"` property, the specified library is opened.
2. It uses :program:`deft` to choose a library defined in the workspace. This
is `generally
`_
the test suite library, if one exists; otherwise it chooses a project
arbitrarily.
Normally you shouldn't need to set any environment variables; everything is
derived from the full pathname to the :program:`dylan-compiler` executable,
which must be on your :envvar:`PATH`.
When you open each new file in your editor the LSP client may try to start a
new project if the file isn't part of the same :program:`dylan` workspace
directory. If you want the client to use just one project, use a `multi-package
workspace `_.
.. note:: Always run ``dylan update`` and ``dylan build -a`` in your workspace
**before** starting the LSP server, or :program:`dylan-lsp-server`
may not be able to open your project. (This requirement will be
removed in a future release.)
Emacs Usage
-----------
1. Make sure the :program:`dylan-lsp-server` executable is on your
:envvar:`PATH`, or customize the ``lsp-dylan-exe-pathname`` elisp variable. See
below for more on customization.
2. Install `lsp-mode `_ and `dylan-mode
`_. Both of these are
available from MELPA.
3. When you jump to another :file:`.dylan` file, that file does not
automatically have LSP enabled so you must use ``M-x lsp`` again. To make
this automatic, add this to your emacs init file:
.. code-block:: elisp
(add-hook 'dylan-mode-hook 'lsp)
4. Start emacs and make sure that :file:`lsp-dylan.el` is loaded. For example::
emacs --load=/path/to/lsp-dylan/lsp-dylan.el
You will probably want to modify your Emacs init file to load the file with
.. code-block:: elisp
(load "/path/to/lsp-dylan/lsp-dylan.el")
5. Open a Dylan source file and type ``M-x lsp`` to start the client (unless
you added the hook above, in which case it started automatically).
The client starts the LSP server (the `dylan-lsp-server` executable) and
connects to it. You should see a message telling you what Dylan project was
opened.
The emacs client has a customization group "lsp-dylan" which is a member of the
"Language Server (lsp-mode)" group, and has the following variables:
* ``lsp-dylan-exe-pathname``
* ``lsp-dylan-extra-command-line-options``
* ``lsp-dylan-log-pathname``
* ``lsp-dylan-open-dylan-release``
These are documented in the customization interface within emacs. Use ``M-x
customize-group`` ``lsp-dylan`` to customize these variables.
.. note:: Emacs lsp-mode saves state in :file:`~/.emacs.d/.lsp-session-v1`. If
you have a problem with Dylan's LSP support it's a good idea to
delete this file and try again.
Visual Studio Code Usage
------------------------
These instructions were tested on Linux and macOS.
1. Install Visual Studio Code and ``npm``.
2. The VS Code extension is in the folder ``vscode-dylan``. It is necessary to
run ``npm install`` in this folder before starting the extension for the
first time, and any time a ``git pull`` updates the dependencies.
3. Open the ``vscode-dylan`` folder in VS Code.
4. In the debug viewlet, click the green play arrow (Launch Extension) or
press ``F5``.
5. A build process will begin in 'watch mode'; whenever the source is changed,
the extension will be rebuilt. It is possible to debug the VS Code
extension in this window, set breakpoints, watch variables and so on.
6. A new VS Code window will open with the extension running.
7. Open a folder with a Dylan project in it.
8. If :program:`dylan-lsp-server` is on the system path, it will be
found. Otherwise, open the Settings *in the new extension window*, find the
Dylan section under Extensions, and edit the path to the LSP server. The
full, absolute pathname to the executable needs to be specified. It is
usually better to set this in the 'User' scope, otherwise it will only
apply to that particular project.
9. It should now be possible to use the extension window to edit Dylan code
using LSP.
10. If the VS Code extension is changed, it is necessary to restart the
extension host, or just close and re-open the extension window.
LSP Server Development
======================
This section contains notes for people interested in helping to improve LSP
support for Dylan.
Open Dylan
----------
Unless you're an Open Dylan expert already, you'll probably find that you want
to add debug statements in the Open Dylan IDE code to figure out what's going
on....
1. Turn on the ``--debug-opendylan`` by customizing
``lsp-dylan-extra-command-line-options``. This causes extra in the
``*lsp-dylan::stderr*`` buffer from calls to the ``debug-out`` macro.
2. Create a multi-package workspace with both the ``lsp-dylan`` repo and the
``opendylan`` repo::
$ mkdir lsp; cd lsp
$ git clone --recursive https://github.com/dylan-lang/lsp-dylan
$ git clone --recursive https://github.com/dylan-lang/opendylan
$ echo '{ "default-library": "dylan-lsp-server" }' > workspace.json
3. Sprinkle calls like ``debug-out(#"lsp", "your message here", ...)`` around
in the Open Dylan code as needed.
4. Remember to delete :file:`~/.emacs.d/.lsp-session-v1` as needed. I (cgay)
usually start a new emacs after rebuilding :program:`dylan-lsp-server`,
like this::
$ rm -f ~/.emacs.d/.lsp-session-v1; emacs &
If you don't start a new emacs, you probably want to at least kill the old
:program:`dylan-lsp-server` process. I (cgay) usually rebuild like this::
$ pkill -f bin/dylan-lsp-server; make install
References
==========
* `Intro to LSP from Microsoft
`_ -
Besides being a quick introduction, this has links to some other tools that
would help in developing VS Code integration for Dylan.
* `LSP v3.15 Specification
`_ -
This is the version we are currently coding to.
* `langserver.org `_ lists LSP implementations that
support at least one of the six major LSP features.
Index and Search
================
* :ref:`genindex`
* :ref:`search`