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
What does this library provide¶
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": "..."
}
}
References¶
some Chinese blogs about how I write these language servers