# lsp-tree-sitter
[![readthedocs](https://shields.io/readthedocs/lsp-tree-sitter)](https://lsp-tree-sitter.readthedocs.io)
[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/neomutt/lsp-tree-sitter/main.svg)](https://results.pre-commit.ci/latest/github/neomutt/lsp-tree-sitter/main)
[![github/workflow](https://github.com/neomutt/lsp-tree-sitter/actions/workflows/main.yml/badge.svg)](https://github.com/neomutt/lsp-tree-sitter/actions)
[![codecov](https://codecov.io/gh/neomutt/lsp-tree-sitter/branch/main/graph/badge.svg)](https://codecov.io/gh/neomutt/lsp-tree-sitter)
[![DeepSource](https://deepsource.io/gh/neomutt/lsp-tree-sitter.svg/?show_trend=true)](https://deepsource.io/gh/neomutt/lsp-tree-sitter)
[![github/downloads](https://shields.io/github/downloads/neomutt/lsp-tree-sitter/total)](https://github.com/neomutt/lsp-tree-sitter/releases)
[![github/downloads/latest](https://shields.io/github/downloads/neomutt/lsp-tree-sitter/latest/total)](https://github.com/neomutt/lsp-tree-sitter/releases/latest)
[![github/issues](https://shields.io/github/issues/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/issues)
[![github/issues-closed](https://shields.io/github/issues-closed/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/issues?q=is%3Aissue+is%3Aclosed)
[![github/issues-pr](https://shields.io/github/issues-pr/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/pulls)
[![github/issues-pr-closed](https://shields.io/github/issues-pr-closed/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/pulls?q=is%3Apr+is%3Aclosed)
[![github/discussions](https://shields.io/github/discussions/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/discussions)
[![github/milestones](https://shields.io/github/milestones/all/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/milestones)
[![github/forks](https://shields.io/github/forks/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/network/members)
[![github/stars](https://shields.io/github/stars/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/stargazers)
[![github/watchers](https://shields.io/github/watchers/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/watchers)
[![github/contributors](https://shields.io/github/contributors/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/graphs/contributors)
[![github/commit-activity](https://shields.io/github/commit-activity/w/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/graphs/commit-activity)
[![github/last-commit](https://shields.io/github/last-commit/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/commits)
[![github/release-date](https://shields.io/github/release-date/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/releases/latest)
[![github/license](https://shields.io/github/license/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/blob/main/LICENSE)
[![github/languages](https://shields.io/github/languages/count/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter)
[![github/languages/top](https://shields.io/github/languages/top/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter)
[![github/directory-file-count](https://shields.io/github/directory-file-count/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter)
[![github/code-size](https://shields.io/github/languages/code-size/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter)
[![github/repo-size](https://shields.io/github/repo-size/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter)
[![github/v](https://shields.io/github/v/release/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter)
[![pypi/status](https://shields.io/pypi/status/lsp-tree-sitter)](https://pypi.org/project/lsp-tree-sitter/#description)
[![pypi/v](https://shields.io/pypi/v/lsp-tree-sitter)](https://pypi.org/project/lsp-tree-sitter/#history)
[![pypi/downloads](https://shields.io/pypi/dd/lsp-tree-sitter)](https://pypi.org/project/lsp-tree-sitter/#files)
[![pypi/format](https://shields.io/pypi/format/lsp-tree-sitter)](https://pypi.org/project/lsp-tree-sitter/#files)
[![pypi/implementation](https://shields.io/pypi/implementation/lsp-tree-sitter)](https://pypi.org/project/lsp-tree-sitter/#files)
[![pypi/pyversions](https://shields.io/pypi/pyversions/lsp-tree-sitter)](https://pypi.org/project/lsp-tree-sitter/#files)
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](https://github.com/termux/termux-language-server/):
for some specific bash scripts:
- [`build.sh`](https://github.com/termux/termux-packages/wiki/Creating-new-package)
- [`PKGBUILD`](https://wiki.archlinux.org/title/PKGBUILD)
- [`*.ebuild`](https://dev.gentoo.org/~zmedico/portage/doc/man/ebuild.5.html)
- ...
- [mutt-language-server](https://github.com/neomutt/mutt-language-server):
for [(neo)mutt](https://github.com/neomutt/neomutt)'s (neo)muttrc
- [More](https://github.com/Freed-Wu?tab=repositories&q=lsp-server)
## 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](https://github.com/termux/termux-language-server/) as
an example.
`PKGBUILD`:
```sh
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
}
```
```sh
termux-language-server --convert PKGBUILD
```
```json
{
"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](https://github.com/termux/termux-language-server/tree/main/src/termux_language_server/assets/json):
<!-- markdownlint-disable MD013 -->
```sh
$ 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']
```
<!-- markdownlint-enable MD013 -->
![PKGBUILD](https://github.com/neomutt/lsp-tree-sitter/assets/32936898/58614996-bd8a-4e27-b573-87346c82ea2a)
Sometimes it will be more complicated:
`neomuttrc`:
```neomuttrc
set allow_ansi=yes sleep_time = no ispell = aspell
set query_command = 'mutt_ldap_query.pl %s'
```
```sh
mutt-language-server --convert neomuttrc
```
```json
{
"set": {
"allow_ansi": "yes",
"sleep_time": "no",
"ispell": "aspell",
"query_command": "mutt_ldap_query.pl %s"
}
}
```
```sh
$ mutt-language-server --check neomuttrc
neomuttrc:1:33-1:35:error: 'no' is not of type 'number'
```
![neomuttrc](https://github.com/neomutt/lsp-tree-sitter/assets/32936898/75ebf0c1-784a-43db-ae11-59783af57b4f)
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:
```python
@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.
```sh
mutt-language-server --generate-schema neomuttrc
```
<!-- markdownlint-disable MD013 -->
````json
{
"$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": "..."
}
}
````
<!-- markdownlint-enable MD013 -->
![hover](https://github.com/neomutt/lsp-tree-sitter/assets/32936898/22a0347e-3d4f-45c5-833b-e89225ce3b74)
## Template
This project provides a template for
[copier](https://github.com/copier-org/copier).
For example, you want to create a language server for a filetype named
[`zathurarc`](https://pwmt.org/projects/zathura/documentation/). Please follow
the following steps:
### Create a tree-sitter parser
1. Create a tree-sitter-parser from [template](https://github.com/tree-sitter-grammars/template).
2. Publish it to PYPI
You can see if
[py-tree-sitter-languages](https://github.com/grantjenks/py-tree-sitter-languages)
supports the language where you want to create a language server.
### Copy a template
```sh
$ 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
```
1. Edit `schema.py` to convert a tree-sitter's tree to a json, which is the
core function of `XXX-langauge-server --convert`
2. Edit a `misc/XXX.py` to generate json schemas, which is the core function of
`XXX-languageserver --generate-schema`
3. Edit `server.py` to make sure the LSP features can work for specific
tree-sitter parsers.
4. Edit `queries/XXX.scm` to make sure the LSP features can work for specific
tree-sitter parsers if you use them.
5. Edit `finders.py` to add the language specific finders for
`XXX-languageserver --check` and `XXX-languageserver --format`
### Test if it can work
```sh
$ git init
$ pip install -e .
$ which zathura-language-server
~/.local/bin/zathura-language-server
```
1. Refer `docs/resources/configure.md` to configure your language server for
your editor.
2. Refer `README.md` to see the LSP features provided by your language server.
```sh
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](https://github.com/Freed-Wu/zathura-language-server)
`zathurarc`'s syntax only has 4 directives:
- `set option value`
- `include /the/path`
- `map key function`
- `unmap key`
Very few directives make creating
[tree-sitter-zathurarc](https://github.com/Freed-Wu/tree-sitter-zathurarc) and
editing `schema.py` very easy. So I am highly recommended starting from it.
### [tmux-language-server](https://github.com/Freed-Wu/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](https://github.com/neomutt/mutt-language-server)
`muttrc` or `neomuttrc` has the following directives:
- `set option = value`
- `source /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 for `set option = yes`
- `set nooption`: a shortcut for `set option = no`
- `set invoption`
- `set nooption1 invoption2 option3 ...`
- ...
So, in fact it is harder than `tmux.conf`, IMO.
### [termux-language-server](https://github.com/termux/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](https://freed-wu.github.io/tag/lsp/) about how I write
these language servers
- [tree-sitter](https://tree-sitter.github.io/tree-sitter/)
- [language server protocol](https://microsoft.github.io/language-server-protocol/specifications/specification-current)
- [json schema](https://json-schema.org/specification)
Raw data
{
"_id": null,
"home_page": null,
"name": "lsp-tree-sitter",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "language server, tree sitter, json schema",
"author": null,
"author_email": "\"Wu, Zhenyu\" <wuzhenyu@ustc.edu>",
"download_url": "https://files.pythonhosted.org/packages/59/f2/d5c9001f09dbfb21bc28287b377ad0d02f7e8800666001fb761b37976ca4/lsp_tree_sitter-0.0.16.tar.gz",
"platform": null,
"description": "# lsp-tree-sitter\n\n[![readthedocs](https://shields.io/readthedocs/lsp-tree-sitter)](https://lsp-tree-sitter.readthedocs.io)\n[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/neomutt/lsp-tree-sitter/main.svg)](https://results.pre-commit.ci/latest/github/neomutt/lsp-tree-sitter/main)\n[![github/workflow](https://github.com/neomutt/lsp-tree-sitter/actions/workflows/main.yml/badge.svg)](https://github.com/neomutt/lsp-tree-sitter/actions)\n[![codecov](https://codecov.io/gh/neomutt/lsp-tree-sitter/branch/main/graph/badge.svg)](https://codecov.io/gh/neomutt/lsp-tree-sitter)\n[![DeepSource](https://deepsource.io/gh/neomutt/lsp-tree-sitter.svg/?show_trend=true)](https://deepsource.io/gh/neomutt/lsp-tree-sitter)\n\n[![github/downloads](https://shields.io/github/downloads/neomutt/lsp-tree-sitter/total)](https://github.com/neomutt/lsp-tree-sitter/releases)\n[![github/downloads/latest](https://shields.io/github/downloads/neomutt/lsp-tree-sitter/latest/total)](https://github.com/neomutt/lsp-tree-sitter/releases/latest)\n[![github/issues](https://shields.io/github/issues/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/issues)\n[![github/issues-closed](https://shields.io/github/issues-closed/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/issues?q=is%3Aissue+is%3Aclosed)\n[![github/issues-pr](https://shields.io/github/issues-pr/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/pulls)\n[![github/issues-pr-closed](https://shields.io/github/issues-pr-closed/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/pulls?q=is%3Apr+is%3Aclosed)\n[![github/discussions](https://shields.io/github/discussions/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/discussions)\n[![github/milestones](https://shields.io/github/milestones/all/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/milestones)\n[![github/forks](https://shields.io/github/forks/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/network/members)\n[![github/stars](https://shields.io/github/stars/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/stargazers)\n[![github/watchers](https://shields.io/github/watchers/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/watchers)\n[![github/contributors](https://shields.io/github/contributors/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/graphs/contributors)\n[![github/commit-activity](https://shields.io/github/commit-activity/w/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/graphs/commit-activity)\n[![github/last-commit](https://shields.io/github/last-commit/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/commits)\n[![github/release-date](https://shields.io/github/release-date/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/releases/latest)\n\n[![github/license](https://shields.io/github/license/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter/blob/main/LICENSE)\n[![github/languages](https://shields.io/github/languages/count/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter)\n[![github/languages/top](https://shields.io/github/languages/top/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter)\n[![github/directory-file-count](https://shields.io/github/directory-file-count/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter)\n[![github/code-size](https://shields.io/github/languages/code-size/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter)\n[![github/repo-size](https://shields.io/github/repo-size/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter)\n[![github/v](https://shields.io/github/v/release/neomutt/lsp-tree-sitter)](https://github.com/neomutt/lsp-tree-sitter)\n\n[![pypi/status](https://shields.io/pypi/status/lsp-tree-sitter)](https://pypi.org/project/lsp-tree-sitter/#description)\n[![pypi/v](https://shields.io/pypi/v/lsp-tree-sitter)](https://pypi.org/project/lsp-tree-sitter/#history)\n[![pypi/downloads](https://shields.io/pypi/dd/lsp-tree-sitter)](https://pypi.org/project/lsp-tree-sitter/#files)\n[![pypi/format](https://shields.io/pypi/format/lsp-tree-sitter)](https://pypi.org/project/lsp-tree-sitter/#files)\n[![pypi/implementation](https://shields.io/pypi/implementation/lsp-tree-sitter)](https://pypi.org/project/lsp-tree-sitter/#files)\n[![pypi/pyversions](https://shields.io/pypi/pyversions/lsp-tree-sitter)](https://pypi.org/project/lsp-tree-sitter/#files)\n\nA core library to support language servers.\n\nI write many language servers and they share some same code so I extract the\nshared code to this library.\n\nI've had enough of writing many DSLs in my editor without any LSP support\n(completion, hover, ...). So I decide to sacrifice my time to do this work.\n\n## Language servers\n\n- [termux-language-server](https://github.com/termux/termux-language-server/):\n for some specific bash scripts:\n - [`build.sh`](https://github.com/termux/termux-packages/wiki/Creating-new-package)\n - [`PKGBUILD`](https://wiki.archlinux.org/title/PKGBUILD)\n - [`*.ebuild`](https://dev.gentoo.org/~zmedico/portage/doc/man/ebuild.5.html)\n - ...\n- [mutt-language-server](https://github.com/neomutt/mutt-language-server):\n for [(neo)mutt](https://github.com/neomutt/neomutt)'s (neo)muttrc\n- [More](https://github.com/Freed-Wu?tab=repositories&q=lsp-server)\n\n## Usage\n\n### Schema\n\nA `Trie` to convert a file to a json, then you can use json schema to validate\nit to get diagnostics.\n\nTake\n[termux-language-server](https://github.com/termux/termux-language-server/) as\nan example.\n\n`PKGBUILD`:\n\n```sh\npkgname=hello\npkgver=0.0.1\npkgrel=1\npkgdesc=\"hello\"\narch=(wrong_arch)\nlicense=(GPL3)\n\nbuild() {\n cat <<EOF > hello\n#!/usr/bin/env sh\necho hello\nEOF\n}\n\npackage() {\n install -D hello -t $pkgdir/usr/bin\n}\n```\n\n```sh\ntermux-language-server --convert PKGBUILD\n```\n\n```json\n{\n \"pkgname\": \"hello\",\n \"pkgver\": \"0.0.1\",\n \"pkgrel\": \"1\",\n \"pkgdesc\": \"hello\",\n \"arch\": [\n \"wrong_arch\"\n ],\n \"license\": [\n \"GPL3\"\n ],\n \"build\": 0,\n \"package\": 0\n}\n```\n\nSo, we can validate the json by [a json schema](https://github.com/termux/termux-language-server/tree/main/src/termux_language_server/assets/json):\n\n<!-- markdownlint-disable MD013 -->\n\n```sh\n$ termux-language-server --check PKGBUILD\nPKGBUILD: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']\n```\n\n<!-- markdownlint-enable MD013 -->\n\n![PKGBUILD](https://github.com/neomutt/lsp-tree-sitter/assets/32936898/58614996-bd8a-4e27-b573-87346c82ea2a)\n\nSometimes it will be more complicated:\n\n`neomuttrc`:\n\n```neomuttrc\nset allow_ansi=yes sleep_time = no ispell = aspell\nset query_command = 'mutt_ldap_query.pl %s'\n```\n\n```sh\nmutt-language-server --convert neomuttrc\n```\n\n```json\n{\n \"set\": {\n \"allow_ansi\": \"yes\",\n \"sleep_time\": \"no\",\n \"ispell\": \"aspell\",\n \"query_command\": \"mutt_ldap_query.pl %s\"\n }\n}\n```\n\n```sh\n$ mutt-language-server --check neomuttrc\nneomuttrc:1:33-1:35:error: 'no' is not of type 'number'\n```\n\n![neomuttrc](https://github.com/neomutt/lsp-tree-sitter/assets/32936898/75ebf0c1-784a-43db-ae11-59783af57b4f)\n\nWe put the result to the json's `.set` not `.` just in order to reserve the\nother keys for other usages.\n\n### Finders\n\nSome finders to find the required node in tree-sitter's AST.\nSuch as, if you want to get the node under the cursor:\n\n```python\n@self.feature(TEXT_DOCUMENT_COMPLETION)\ndef completions(params: CompletionParams) -> CompletionList:\n document = self.workspace.get_document(params.text_document.uri)\n uni = PositionFinder(params.position, right_equal=True).find(\n document.uri, self.trees[document.uri]\n )\n # ...\n```\n\nUNI (Universal Node Identifier) is URI + node.\n\n### Utilities\n\nThis library also provides many utility functions. Such as converting man page to\nmarkdown and tokenizing it in order to generate the json schema.\n\n```sh\nmutt-language-server --generate-schema neomuttrc\n```\n\n<!-- markdownlint-disable MD013 -->\n\n````json\n{\n \"$id\": \"https://github.com/neomutt/mutt-language-server/blob/main/src/termux_language_server/assets/json/neomuttrc.json\",\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$comment\": \"Don't edit this file directly! It is generated by `mutt-language-server --generate-schema=neomuttrc`.\",\n \"type\": \"object\",\n \"properties\": {\n \"account-hook\": {\n \"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.\"\n },\n \"$comment\": \"...\"\n }\n}\n````\n\n<!-- markdownlint-enable MD013 -->\n\n![hover](https://github.com/neomutt/lsp-tree-sitter/assets/32936898/22a0347e-3d4f-45c5-833b-e89225ce3b74)\n\n## Template\n\nThis project provides a template for\n[copier](https://github.com/copier-org/copier).\n\nFor example, you want to create a language server for a filetype named\n[`zathurarc`](https://pwmt.org/projects/zathura/documentation/). Please follow\nthe following steps:\n\n### Create a tree-sitter parser\n\n1. Create a tree-sitter-parser from [template](https://github.com/tree-sitter-grammars/template).\n2. Publish it to PYPI\n\nYou can see if\n[py-tree-sitter-languages](https://github.com/grantjenks/py-tree-sitter-languages)\nsupports the language where you want to create a language server.\n\n### Copy a template\n\n```sh\n$ copier copy -rHEAD gh:neomutt/lsp-tree-sitter /path/to/your/XXX-language-server\n\ud83c\udfa4 What is your language name?\nzathurarc\n\ud83c\udfa4 What is your file patterns? split by \" \"\n*.zathurarc zathurarc\n\ud83c\udfa4 What is your project name?\nzathura-language-server\n\ud83c\udfa4 What is your Python module name?\nzathura_language_server\n\ud83c\udfa4 What is your Python class name?\nZathuraLanguageServer\n\ud83c\udfa4 What is your tree-sitter parser name?\ntree-sitter-zathurarc\n\ud83c\udfa4 What is your user name?\nwzy\n\ud83c\udfa4 What is your email?\n32936898+Freed-Wu@users.noreply.github.com\n\nCopying from template version None\ncreate .\n...\n$ cd /path/to/your/XXX-language-server\n$ tree .\n\ue5ff .\n\u251c\u2500\u2500 \ue5ff docs # documents\n\u2502 \u251c\u2500\u2500 \ue5ff api\n\u2502 \u2502 \u2514\u2500\u2500 \uf48a zathura-language-server.md\n\u2502 \u251c\u2500\u2500 \ue606 conf.py\n\u2502 \u251c\u2500\u2500 \uf48a index.md\n\u2502 \u251c\u2500\u2500 \ue606 requirements.txt\n\u2502 \u2514\u2500\u2500 \ue5ff resources\n\u2502 \u251c\u2500\u2500 \uf48a configure.md\n\u2502 \u251c\u2500\u2500 \uf48a install.md\n\u2502 \u2514\u2500\u2500 \uf48a requirements.md\n\u251c\u2500\u2500 \uf02d LICENSE\n\u251c\u2500\u2500 \ue606 pyproject.toml\n\u251c\u2500\u2500 \uf48a README.md\n\u251c\u2500\u2500 \ue5ff requirements # optional dependencies\n\u2502 \u251c\u2500\u2500 \uf15c colorize.txt\n\u2502 \u251c\u2500\u2500 \uf15c dev.txt\n\u2502 \u2514\u2500\u2500 \uf15c misc.txt\n\u251c\u2500\u2500 \ue606 requirements.txt\n\u251c\u2500\u2500 \ue5ff src\n\u2502 \u2514\u2500\u2500 \ue5ff zathura_language_server\n\u2502 \u251c\u2500\u2500 \ue606 __init__.py\n\u2502 \u251c\u2500\u2500 \ue606 __main__.py\n\u2502 \u251c\u2500\u2500 \ue606 _shtab.py\n\u2502 \u251c\u2500\u2500 \ue5ff assets\n\u2502 \u2502 \u251c\u2500\u2500 \ue5ff json # json schemas generated by misc/XXX.py\n\u2502 \u2502 \u2502 \u2514\u2500\u2500 \ue60b zathurarc.json\n\u2502 \u2502 \u2514\u2500\u2500 \ue5ff queries # tree-sitter queries\n\u2502 \u2502 \u2514\u2500\u2500 \uf15b import.scm\n\u2502 \u251c\u2500\u2500 \ue606 finders.py # project specific finders\n\u2502 \u251c\u2500\u2500 \ue5ff misc\n\u2502 \u2502 \u251c\u2500\u2500 \ue606 __init__.py\n\u2502 \u2502 \u2514\u2500\u2500 \ue606 zathurarc.py\n\u2502 \u251c\u2500\u2500 \uf15b py.typed\n\u2502 \u251c\u2500\u2500 \ue606 schema.py # project specific schemas\n\u2502 \u251c\u2500\u2500 \ue606 server.py # main file for server\n\u2502 \u2514\u2500\u2500 \ue606 utils.py\n\u251c\u2500\u2500 \ue5ff templates\n\u2502 \u251c\u2500\u2500 \uf15c class.txt\n\u2502 \u251c\u2500\u2500 \uf15c def.txt\n\u2502 \u251c\u2500\u2500 \uf15b metainfo.py.j2\n\u2502 \u2514\u2500\u2500 \uf15c noarg.txt\n\u2514\u2500\u2500 \ue5ff tests\n\u2514\u2500\u2500 \ue606 test_utils.py\n```\n\n1. Edit `schema.py` to convert a tree-sitter's tree to a json, which is the\n core function of `XXX-langauge-server --convert`\n2. Edit a `misc/XXX.py` to generate json schemas, which is the core function of\n `XXX-languageserver --generate-schema`\n3. Edit `server.py` to make sure the LSP features can work for specific\n tree-sitter parsers.\n4. Edit `queries/XXX.scm` to make sure the LSP features can work for specific\n tree-sitter parsers if you use them.\n5. Edit `finders.py` to add the language specific finders for\n `XXX-languageserver --check` and `XXX-languageserver --format`\n\n### Test if it can work\n\n```sh\n$ git init\n$ pip install -e .\n$ which zathura-language-server\n~/.local/bin/zathura-language-server\n```\n\n1. Refer `docs/resources/configure.md` to configure your language server for\n your editor.\n2. Refer `README.md` to see the LSP features provided by your language server.\n\n```sh\nvi /path/to/zathurarc\n```\n\nYou can test the LSP features.\n\nRefer <https://docs.readthedocs.io> to see how to publish the documents.\n\n## References\n\nThese following language servers can be a good example for beginners:\n\n### [zathura-language-server](https://github.com/Freed-Wu/zathura-language-server)\n\n`zathurarc`'s syntax only has 4 directives:\n\n- `set option value`\n- `include /the/path`\n- `map key function`\n- `unmap key`\n\nVery few directives make creating\n[tree-sitter-zathurarc](https://github.com/Freed-Wu/tree-sitter-zathurarc) and\nediting `schema.py` very easy. So I am highly recommended starting from it.\n\n### [tmux-language-server](https://github.com/Freed-Wu/tmux-language-server)\n\n`tmux.conf` is more complex than `zathurarc`. It has not only\n`set option = value` and `source /the/path`, but also 170+ other directives.\n\n### [mutt-language-server](https://github.com/neomutt/mutt-language-server)\n\n`muttrc` or `neomuttrc` has the following directives:\n\n- `set option = value`\n- `source /the/path`\n- 80+ other directives\n\nHowever, its `set` syntax is very flexible. The following syntaxes are legal:\n\n- `set option2 = value1 option2 = value2 ...`\n- `set option`: a shortcut for `set option = yes`\n- `set nooption`: a shortcut for `set option = no`\n- `set invoption`\n- `set nooption1 invoption2 option3 ...`\n- ...\n\nSo, in fact it is harder than `tmux.conf`, IMO.\n\n### [termux-language-server](https://github.com/termux/termux-language-server)\n\n`build.sh`, `PKGBUILD`, `*.ebuild` use same syntax of bash. However, they use\ndifferent json schemas. If the language where you want to create a language\nserver, you can refer it to know how to handle this situation.\n\n### Other references\n\nSome useful URLs for beginners who want to develop language servers:\n\n- some [Chinese blogs](https://freed-wu.github.io/tag/lsp/) about how I write\n these language servers\n- [tree-sitter](https://tree-sitter.github.io/tree-sitter/)\n- [language server protocol](https://microsoft.github.io/language-server-protocol/specifications/specification-current)\n- [json schema](https://json-schema.org/specification)\n",
"bugtrack_url": null,
"license": "GPL v3",
"summary": "a library to create language servers",
"version": "0.0.16",
"project_urls": {
"Bug Report": "https://github.com/neomutt/lsp-tree-sitter/issues",
"Download": "https://github.com/neomutt/lsp-tree-sitter/releases",
"Homepage": "https://lsp-tree-sitter.readthedocs.io",
"Source": "https://github.com/neomutt/lsp-tree-sitter"
},
"split_keywords": [
"language server",
" tree sitter",
" json schema"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "63376fcb1683dc3d8d99846211458e79a4cd772f2e43205d8262efdbdc6a8335",
"md5": "59cc60764f710cee047bd81527eb18ba",
"sha256": "45724b45b786cabf2d17ee8135fa6caacb9a5631f5c41d51980229cfa589fcf6"
},
"downloads": -1,
"filename": "lsp_tree_sitter-0.0.16-py3-none-any.whl",
"has_sig": false,
"md5_digest": "59cc60764f710cee047bd81527eb18ba",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 32210,
"upload_time": "2024-06-30T04:31:34",
"upload_time_iso_8601": "2024-06-30T04:31:34.694376Z",
"url": "https://files.pythonhosted.org/packages/63/37/6fcb1683dc3d8d99846211458e79a4cd772f2e43205d8262efdbdc6a8335/lsp_tree_sitter-0.0.16-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "59f2d5c9001f09dbfb21bc28287b377ad0d02f7e8800666001fb761b37976ca4",
"md5": "9fc2e27d1066e9bfc03d11db99692bb0",
"sha256": "6e11d66629ed31b4c829ee87a6669468a6a952b9e84b56e5898234e6a599cf62"
},
"downloads": -1,
"filename": "lsp_tree_sitter-0.0.16.tar.gz",
"has_sig": false,
"md5_digest": "9fc2e27d1066e9bfc03d11db99692bb0",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 66711,
"upload_time": "2024-06-30T04:31:36",
"upload_time_iso_8601": "2024-06-30T04:31:36.201373Z",
"url": "https://files.pythonhosted.org/packages/59/f2/d5c9001f09dbfb21bc28287b377ad0d02f7e8800666001fb761b37976ca4/lsp_tree_sitter-0.0.16.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-06-30 04:31:36",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "neomutt",
"github_project": "lsp-tree-sitter",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "colorama",
"specs": []
},
{
"name": "jinja2",
"specs": []
},
{
"name": "jsonschema",
"specs": [
[
">=",
"4.0.0"
]
]
},
{
"name": "pygls",
"specs": []
},
{
"name": "tree-sitter",
"specs": [
[
">=",
"0.22.0"
]
]
}
],
"lcname": "lsp-tree-sitter"
}