a library to create language servers
Project description
lsp-tree-sitter
A core library to support language servers.
I write many language servers and they share some same code so I extract the shared code to this library.
I've had enough of writing many DSLs in my editor without any LSP support (completion, hover, ...). So I decide to sacrifice my time to do this work.
Language servers
- termux-language-server: for some specific bash scripts:
- mutt-language-server: for (neo)mutt's (neo)muttrc
- More
Usage
Schema
A Trie to convert a file to a json, then you can use json schema to validate
it to get diagnostics.
Take termux-language-server as an example.
PKGBUILD:
pkgname=hello
pkgver=0.0.1
pkgrel=1
pkgdesc="hello"
arch=(wrong_arch)
license=(GPL3)
build() {
cat <<EOF > hello
#!/usr/bin/env sh
echo hello
EOF
}
package() {
install -D hello -t $pkgdir/usr/bin
}
termux-language-server --convert PKGBUILD
{
"pkgname": "hello",
"pkgver": "0.0.1",
"pkgrel": "1",
"pkgdesc": "hello",
"arch": [
"wrong_arch"
],
"license": [
"GPL3"
],
"build": 0,
"package": 0
}
So, we can validate the json by a json schema:
$ termux-language-server --check PKGBUILD
PKGBUILD:5:7-5:17:error: 'wrong_arch' is not one of ['any', 'pentium4', 'i486', 'i686', 'x86_64', 'x86_64_v3', 'arm', 'armv6h', 'armv7h', 'armv8', 'aarch64']
Sometimes it will be more complicated:
neomuttrc:
set allow_ansi=yes sleep_time = no ispell = aspell
set query_command = 'mutt_ldap_query.pl %s'
mutt-language-server --convert neomuttrc
{
"set": {
"allow_ansi": "yes",
"sleep_time": "no",
"ispell": "aspell",
"query_command": "mutt_ldap_query.pl %s"
}
}
$ mutt-language-server --check neomuttrc
neomuttrc:1:33-1:35:error: 'no' is not of type 'number'
We put the result to the json's .set not . just in order to reserve the
other keys for other usages.
Finders
Some finders to find the required node in tree-sitter's AST. Such as, if you want to get the node under the cursor:
@self.feature(TEXT_DOCUMENT_COMPLETION)
def completions(params: CompletionParams) -> CompletionList:
document = self.workspace.get_document(params.text_document.uri)
uni = PositionFinder(params.position, right_equal=True).find(
document.uri, self.trees[document.uri]
)
# ...
UNI (Universal Node Identifier) is URI + node.
Utilities
This library also provides many utility functions. Such as converting man page to markdown and tokenizing it in order to generate the json schema.
mutt-language-server --generate-schema neomuttrc
{
"$id": "https://github.com/neomutt/mutt-language-server/blob/main/src/termux_language_server/assets/json/neomuttrc.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"$comment": "Don't edit this file directly! It is generated by `mutt-language-server --generate-schema=neomuttrc`.",
"type": "object",
"properties": {
"account-hook": {
"description": "```neomuttrc\naccount-hook regex command\n```\nThis hook is executed whenever you access a remote mailbox. Useful to adjust configuration settings to different IMAP or POP servers."
},
"$comment": "..."
}
}
Template
This project provides a template for copier.
For example, you want to create a language server for a filetype named
zathurarc. Please follow
the following steps:
Create a tree-sitter parser
- Create a tree-sitter-parser from template.
- Publish it to PYPI
You can see if py-tree-sitter-languages supports the language where you want to create a language server.
Copy a template
$ copier copy -rHEAD gh:neomutt/lsp-tree-sitter /path/to/your/XXX-language-server
๐ค What is your language name?
zathurarc
๐ค What is your file patterns? split by " "
*.zathurarc zathurarc
๐ค What is your project name?
zathura-language-server
๐ค What is your Python module name?
zathura_language_server
๐ค What is your Python class name?
ZathuraLanguageServer
๐ค What is your tree-sitter parser name?
tree-sitter-zathurarc
๐ค What is your user name?
wzy
๐ค What is your email?
32936898+Freed-Wu@users.noreply.github.com
Copying from template version None
create .
...
$ cd /path/to/your/XXX-language-server
$ tree .
๎ฟ .
โโโ ๎ฟ docs # documents
โ โโโ ๎ฟ api
โ โ โโโ ๏ zathura-language-server.md
โ โโโ ๎ conf.py
โ โโโ ๏ index.md
โ โโโ ๎ requirements.txt
โ โโโ ๎ฟ resources
โ โโโ ๏ configure.md
โ โโโ ๏ install.md
โ โโโ ๏ requirements.md
โโโ ๏ญ LICENSE
โโโ ๎ pyproject.toml
โโโ ๏ README.md
โโโ ๎ฟ requirements # optional dependencies
โ โโโ ๏
colorize.txt
โ โโโ ๏
dev.txt
โ โโโ ๏
misc.txt
โโโ ๎ requirements.txt
โโโ ๎ฟ src
โ โโโ ๎ฟ zathura_language_server
โ โโโ ๎ __init__.py
โ โโโ ๎ __main__.py
โ โโโ ๎ _shtab.py
โ โโโ ๎ฟ assets
โ โ โโโ ๎ฟ json # json schemas generated by misc/XXX.py
โ โ โ โโโ ๎ zathurarc.json
โ โ โโโ ๎ฟ queries # tree-sitter queries
โ โ โโโ ๏
import.scm
โ โโโ ๎ finders.py # project specific finders
โ โโโ ๎ฟ misc
โ โ โโโ ๎ __init__.py
โ โ โโโ ๎ zathurarc.py
โ โโโ ๏
py.typed
โ โโโ ๎ schema.py # project specific schemas
โ โโโ ๎ server.py # main file for server
โ โโโ ๎ utils.py
โโโ ๎ฟ templates
โ โโโ ๏
class.txt
โ โโโ ๏
def.txt
โ โโโ ๏
metainfo.py.j2
โ โโโ ๏
noarg.txt
โโโ ๎ฟ tests
โโโ ๎ test_utils.py
- Edit
schema.pyto convert a tree-sitter's tree to a json, which is the core function ofXXX-langauge-server --convert - Edit a
misc/XXX.pyto generate json schemas, which is the core function ofXXX-languageserver --generate-schema - Edit
server.pyto make sure the LSP features can work for specific tree-sitter parsers. - Edit
queries/XXX.scmto make sure the LSP features can work for specific tree-sitter parsers if you use them. - Edit
finders.pyto add the language specific finders forXXX-languageserver --checkandXXX-languageserver --format
Test if it can work
$ git init
$ pip install -e .
$ which zathura-language-server
~/.local/bin/zathura-language-server
- Refer
docs/resources/configure.mdto configure your language server for your editor. - Refer
README.mdto see the LSP features provided by your language server.
vi /path/to/zathurarc
You can test the LSP features.
Refer https://docs.readthedocs.io to see how to publish the documents.
References
These following language servers can be a good example for beginners:
zathura-language-server
zathurarc's syntax only has 4 directives:
set option valueinclude /the/pathmap key functionunmap key
Very few directives make creating
tree-sitter-zathurarc and
editing schema.py very easy. So I am highly recommended starting from it.
tmux-language-server
tmux.conf is more complex than zathurarc. It has not only
set option = value and source /the/path, but also 170+ other directives.
mutt-language-server
muttrc or neomuttrc has the following directives:
set option = valuesource /the/path- 80+ other directives
However, its set syntax is very flexible. The following syntaxes are legal:
set option2 = value1 option2 = value2 ...set option: a shortcut forset option = yesset nooption: a shortcut forset option = noset invoptionset nooption1 invoption2 option3 ...- ...
So, in fact it is harder than tmux.conf, IMO.
termux-language-server
build.sh, PKGBUILD, *.ebuild use same syntax of bash. However, they use
different json schemas. If the language where you want to create a language
server, you can refer it to know how to handle this situation.
Other references
Some useful URLs for beginners who want to develop language servers:
- some Chinese blogs about how I write these language servers
- tree-sitter
- language server protocol
- json schema
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lsp_tree_sitter-0.1.1.tar.gz.
File metadata
- Download URL: lsp_tree_sitter-0.1.1.tar.gz
- Upload date:
- Size: 66.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1668dd456e5669e9d6e102b2dd46952fd39d19573c19b8c985446e272d59128c
|
|
| MD5 |
f28f1cd59cbba3000fdf820c9e674942
|
|
| BLAKE2b-256 |
0438b539693b8222ceae26ef532f229d9ca57f294ed4dcb64dc771e082eec9a7
|
File details
Details for the file lsp_tree_sitter-0.1.1-py3-none-any.whl.
File metadata
- Download URL: lsp_tree_sitter-0.1.1-py3-none-any.whl
- Upload date:
- Size: 32.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eef148b333c95ae1cd58dbf6685029a4e58a806bbffe02367c4bb90d50b0519c
|
|
| MD5 |
1737bf8adc8a6e037f2df2154d8c807f
|
|
| BLAKE2b-256 |
b5c8b8b772a8c686c912cd5747a2345be7f4fabeab6ddc8d1b8c554162379c59
|