Skip to content

Commit

Permalink
Merge pull request #385 from swyddfa/develop
Browse files Browse the repository at this point in the history
New Release
  • Loading branch information
alcarney authored May 9, 2022
2 parents a8c0ac1 + 4e449c1 commit fcf90f4
Show file tree
Hide file tree
Showing 19 changed files with 189 additions and 79 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ repos:
args: [--config=lib/esbonio/setup.cfg]

- repo: https://github.com/asottile/reorder_python_imports
rev: v3.0.1
rev: v3.1.0
hooks:
- id: reorder-python-imports
args: [--application-directories=lib:esbonio]
1 change: 0 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
},
"files.associations": {
"setup.cfg": "ini",
"pyproject.toml": "ini"
},
"files.exclude": {
"**/.git": true,
Expand Down
16 changes: 14 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,27 @@ def lsp_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
def setup(app: Sphinx):
app.add_role("lsp", lsp_role)

# So that it's possible to use intersphinx to link to configuration options
# in sphinx.
app.add_object_type(
"confval",
"confval",
objname="configuration value",
indextemplate="pair: %s; configuration value",
)

app.add_object_type(
"startmod",
"startmod",
objname="startup module",
indextemplate="pair: %s; startup module",
)

app.add_object_type(
"extmod",
"extmod",
objname="extension module",
indextemplate="pair: %s; startup module",
)

# So that it's possible to use intersphinx to link to IPython magics
app.add_object_type(
"magic",
Expand Down
11 changes: 6 additions & 5 deletions docs/ext/cli_help.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import argparse
import importlib

from docutils import nodes
Expand All @@ -13,13 +14,13 @@ def run(self):
name = self.arguments[0]
mod = importlib.import_module(name)

if not hasattr(mod, "cli"):
return []

cli = mod.cli
if not hasattr(cli, "format_help"):
candidates = [
v for v in mod.__dict__.values() if isinstance(v, argparse.ArgumentParser)
]
if len(candidates) == 0:
return []

cli = candidates[0]
return [nodes.literal_block("", cli.format_help(), language="none")]


Expand Down
Binary file modified docs/images/vscode-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Here is a quick summary of the features implemented by the language server.
lsp/getting-started
lsp/advanced-usage
lsp/extending
lsp/how-to
changelog

Sphinx Extensions
Expand Down
37 changes: 17 additions & 20 deletions docs/lsp/advanced-usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,46 +16,40 @@ the section on :doc:`/lsp/extending` if you want to know more)

However, all that we need to know for the moment is the concept of startup modules.

.. _lsp-startup-mods:

Startup Modules
---------------

A startup module is any python module (or script) that results in a running language server.
The following startup modules are included with the ``esbonio`` python package.

.. relevant-to:: esbonio
:category: Startup Module
.. startmod:: esbonio

The default startup module you are probably already familiar with.
It is in fact just an alias for the ``esbonio.lsp.sphinx`` startup module.
It is in fact just an alias for the :startmod:`esbonio.lsp.sphinx` startup module.

.. cli-help:: esbonio.__main__
.. .. cli-help:: esbonio.__main__
.. relevant-to:: esbonio.lsp.rst
:category: Startup Module
.. startmod:: esbonio.lsp.rst

A "vanilla" reStructuedText language server for use with docutils projects.

.. cli-help:: esbonio.lsp.rst
.. .. cli-help:: esbonio.lsp.rst
.. relevant-to:: esbonio.lsp.sphinx
:category: Startup Module
.. startmod:: esbonio.lsp.sphinx

A language server tailored for use with Sphinx projects.

.. cli-help:: esbonio.lsp.sphinx
.. .. cli-help:: esbonio.lsp.sphinx
Note that, the command line interfaces for these servers is identical and the only difference
between them is the module name passed to ``python -m``.
Modules
-------
Extension Modules
-----------------

Inspired by the way Sphinx extensions work, functionality is added to ``esbonio`` servers through
lists of python modules with each module contributing some features. The ``--include`` and
``--exclude`` arguments command line arguments allow you to add additional modules or remove any
that you don't need or find problematic.
Inspired by the way Sphinx extensions work, functionality is added to a language server through a list of python modules with each module contributing some features.

Below is the list of modules included by default for each of the provided startup modules.
Below is the list of modules loaded by default for each of the provided servers.

.. relevant-to:: esbonio
:category: Startup Module
Expand Down Expand Up @@ -84,7 +78,10 @@ Below is the list of modules included by default for each of the provided startu
In addition to the modules enabled by default, the following modules are provided and can be
enabled if you wish.

``esbonio.lsp.spelling`` (Experimental)
.. extmod:: esbonio.lsp.spelling

**Experimental**

Basic spell checking, with errors reported as diagnostics and corrections suggested as code actions.
Currently only available for English and can be confused by reStructuredText syntax.

Expand Down
4 changes: 2 additions & 2 deletions docs/lsp/extending.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Architecture

Language Feature
Language features are subclasses of :class:`~esbonio.lsp.rst.LanguageFeature`.
They are typically based on a single aspect of reStructuredText (e.g. :class:`~esbonio.lsp.roles.Roles`) or Sphinx (e.g. :class:`` responsible for providing
They are typically based on a single aspect of reStructuredText (e.g. :class:`~esbonio.lsp.roles.Roles`).

Language Features (where it makes sense) should be server agnostic, that way the same features can be reused across different envrionments.

Expand All @@ -52,7 +52,7 @@ Architecture

There is nothing in Esbonio that would prevent you from writing your own if you so desired.

Module
Extension Module
Ordinary Python modules are used to group related functionality together.
Taking inspiration from how Sphinx is architected, language servers are assembled by passing the list of modules to load to the :func:`~esbonio.lsp.create_language_server`.
This assembly process calls any functions with the name ``esbonio_setup`` allowing for ``LanguageFeatures`` to be configured and loaded into the server.
Expand Down
46 changes: 20 additions & 26 deletions docs/lsp/getting-started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ Getting Started
This section contains notes on how to use the Language Server with your text
editor of choice.


.. relevant-to:: VSCode
.. relevant-to:: VSCode (Esbonio)
:category: Editor

.. figure:: /images/vscode-screenshot.png
:align: center
:target: /_images/vscode-screenshot.png

The VSCode extension in action.
The Esbonio VSCode extension.

.. relevant-to:: Emacs (eglot)
:category: Editor
Expand Down Expand Up @@ -101,7 +100,7 @@ building your documentation e.g.
Otherwise the language server will fail to properly understand your project.


.. relevant-to:: VSCode
.. relevant-to:: VSCode (Esbonio)
:category: Editor

Integration with `VSCode`_ is provided by the `Esbonio`_ extension.
Expand Down Expand Up @@ -139,7 +138,7 @@ Otherwise the language server will fail to properly understand your project.
Configuration
-------------

.. relevant-to:: VSCode
.. relevant-to:: VSCode (Esbonio)
:category: Editor

.. include:: ./editors/vscode/_configuration.rst
Expand Down Expand Up @@ -171,10 +170,8 @@ Configuration

.. confval:: sphinx.buildDir (string)

By default the language server will choose a cache directory (as determined by
`appdirs <https://pypi.org/project/appdirs>`_) to put Sphinx's build output.
This option can be used to force the language server to use a location
of your choosing, currently accepted values include:
By default the language server will choose a cache directory (as determined by `appdirs <https://pypi.org/project/appdirs>`_) to put Sphinx's build output.
This option can be used to force the language server to use a location of your choosing, currently accepted values include:

- ``/path/to/src/`` - An absolute path
- ``${workspaceRoot}/docs/src`` - A path relative to the root of your workspace
Expand All @@ -183,21 +180,19 @@ Configuration

.. confval:: sphinx.confDir (string)

The language server attempts to automatically find the folder which contains your
project's ``conf.py``. If necessary this can be used to override the default discovery
mechanism and force the server to use a folder of your choosing. Currently accepted
values include:
The language server attempts to automatically find the folder which contains your project's ``conf.py``.
If necessary this can be used to override the default discovery mechanism and force the server to use a folder of your choosing.
Currently accepted values include:

- ``/path/to/docs`` - An absolute path
- ``${workspaceRoot}/docs`` - A path relative to the root of your workspace.
- ``${workspaceFolder}/docs`` - Same as ``${workspaceRoot}``, placeholder for true multi-root workspace support.

.. confval:: sphinx.srcDir (string)

The language server assumes that your project's ``srcDir`` (the folder containing your
rst files) is the same as your projects's ``confDir``. If this assumption is not true,
you can use this setting to tell the server where to look. Currently accepted values
include:
The language server assumes that your project's ``srcDir`` (the folder containing your rst files) is the same as your projects's ``confDir``.
If this assumption is not true, you can use this setting to tell the server where to look.
Currently accepted values include:

- ``/path/to/src/`` - An absolute path
- ``${workspaceRoot}/docs/src`` - A path relative to the root of your workspace
Expand All @@ -212,21 +207,22 @@ Configuration

Controls the number of parallel jobs used during a Sphinx build.

The default value of ``"auto"`` will behave the same as passing ``-j auto`` to a ``sphinx-build`` command. Setting this value to ``1`` effectively disables parallel builds.
The default value of ``"auto"`` will behave the same as passing ``-j auto`` to a ``sphinx-build`` command.
Setting this value to ``1`` effectively disables parallel builds.

.. confval:: server.logLevel (string)

This can be used to set the level of log messages emitted by the server. This can be set
to one of the following values.
This can be used to set the level of log messages emitted by the server.
This can be set to one of the following values.

- ``error`` (default)
- ``info``
- ``debug``

.. confval:: server.logFilter (string[])

The language server will typically include log output from all of its components. This
option can be used to restrict the log output to be only those named.
The language server will typically include log output from all of its components.
This option can be used to restrict the log output to be only those named.

.. confval:: server.hideSphinxOutput (boolean)

Expand Down Expand Up @@ -267,9 +263,7 @@ to help get you started.
Debugging
---------

In the event that something does not work as expected, you can increase the
logging level of the server by setting the ``server.logLevel`` initialization option
to ``debug``.
In the event that something does not work as expected, you can increase the logging level of the server by setting the :confval:`server.logLevel (string)` option to ``debug``.

.. relevant-to:: Neovim (lspconfig)
:category: Editor
Expand All @@ -289,7 +283,7 @@ to ``debug``.
Additional Details
------------------

.. relevant-to:: VSCode
.. relevant-to:: VSCode (Esbonio)
:category: Editor


Expand Down
7 changes: 7 additions & 0 deletions docs/lsp/how-to.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
How To
======

.. toctree::
:glob:

how-to/*
38 changes: 38 additions & 0 deletions docs/lsp/how-to/get-debug-info.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
How To: Get Debug Information
=============================

In its default configuration the language server doesn't give you much information, you get Sphinx's build output and not much else.
Depending on your needs you may find one of the following options useful.

Enable Debug Logging
--------------------

The simplest way to get more information is to set the :confval:`server.logLevel (string)` option to ``debug``.
Additional messages from the language server will be sent to your language client as :lsp:`window/logMessage` messages.

Capture All Messages
--------------------

If you are using one of the VSCode extensions you can set the ``esbonio.trace.server`` option to ``verbose``.
This will print all LSP message bodies sent to/from the client in the ``Output`` window.

**Note:** This will generate a *lot* of output.

Capture All Output
------------------

.. important::

This option requires the ``lsp-devtools`` package be installed in the same Python environment as the ``esbonio`` language server::

$ pip install lsp-devtools

Alternatively you can capture **everything** sent to/from the language server in a text file ``lsp.log`` by using one of the following debug :ref:`lsp-startup-mods`

.. startmod:: esbonio.lsp.rst._record

Exactly the same as :startmod:`esbonio.lsp.rst`, but with output capture enabled.

.. startmod:: esbonio.lsp.sphinx._record

Exaclty the same as :startmod:`esbonio.lsp.sphinx` but with output capture enabled.
5 changes: 5 additions & 0 deletions lib/esbonio/CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ Features

The server also supports resolving links for directive arguments with initial support for ``.. image::``, ``.. figure::``, ``.. include::`` and ``.. literalinclude::`` directives. (`#294 <https://github.com/swyddfa/esbonio/issues/294>`_)

Enhancements
^^^^^^^^^^^^

- Language clients can now control if the server forces a full build of a Sphinx project on startup by providing a ``sphinx.forceFullBuild`` initialization option, which defaults to ``true`` (`#358 <https://github.com/swyddfa/esbonio/issues/358>`_)
- Language clients can now control the number of parallel jobs by providing a ``sphinx.numJobs`` initialization option, which defaults to ``auto``. Clients can disable parallel builds by setting this option to ``1`` (`#359 <https://github.com/swyddfa/esbonio/issues/359>`_)

Fixes
^^^^^
Expand Down
2 changes: 2 additions & 0 deletions lib/esbonio/changes/380.enhancement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add ``esbonio.lsp.rst._record`` and ``esbonio.lsp.sphinx._record`` startup modules.
These can be used to record all LSP client-sever communication to a text file.
1 change: 1 addition & 0 deletions lib/esbonio/changes/381.fix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The language server now detects functionality bundled with standard Sphinx extensions
17 changes: 17 additions & 0 deletions lib/esbonio/esbonio/lsp/rst/_record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""Startup module that launches the real server in a sub process and dumps all messages
to a file."""
import sys
from argparse import Namespace

from lsp_devtools.cmds.record import record


def main():
args = Namespace(file="lsp.log", format="%(message)s", raw=True)
cmd = [sys.executable, "-m", "esbonio.lsp.rst"] + sys.argv[1:]

record(args, cmd)


if __name__ == "__main__":
main()
4 changes: 2 additions & 2 deletions lib/esbonio/esbonio/lsp/sphinx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ def _load_sphinx_extensions(self, app: Sphinx):
if name in self._loaded_modules:
self.logger.debug("Skipping previously loaded module '%s'", name)

if not hasattr(ext, "esbonio_setup"):
if not hasattr(mod, "esbonio_setup"):
continue

self.logger.debug("Loading sphinx module '%s'", name)
Expand Down Expand Up @@ -1013,7 +1013,7 @@ def exception_to_diagnostic(exc: BaseException):
tb = exc.__traceback__
frame = traceback.extract_tb(tb)[-1]
path = pathlib.Path(frame.filename)
line = frame.lineno - 1
line = (frame.lineno or 1) - 1

message = type(exc).__name__ if exc.args.count == 0 else exc.args[0]

Expand Down
Loading

0 comments on commit fcf90f4

Please sign in to comment.