Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/neovim/tree-sitter-vimdoc

Tree-sitter parser for Vim help files
https://github.com/neovim/tree-sitter-vimdoc

tree-sitter tree-sitter-parser

Last synced: about 1 month ago
JSON representation

Tree-sitter parser for Vim help files

Awesome Lists containing this project

README

        

tree-sitter-vimdoc
==================

This grammar implements the vimdoc "spec"
([ref1](https://neovim.io/doc/user/helphelp.html#help-writing),
[ref2](https://github.com/nanotee/vimdoc-notes)).
Predictable results are the primary goal, so that _output_ formats (e.g. HTML)
are well-formed; the _input_ (vimdoc) is secondary. The first step should
always be to try to fix the input rather than insist on a grammar that handles
vimdoc's endless quirks.

Overview
--------

- `block` is the main top-level node, delimited by blank line(s) or any line
starting with `<` (codeblock terminator).
- contains `line` and `line_li` nodes.
- `line`:
- contains atoms (words, tags, taglinks, …)
- contains headings (`h1`, `h2`, `h3`, `column_heading`) because `codeblock`
terminated by "implicit stop" (no terminating `<`) consumes blank lines, so
`block` has no way to end.
- `line_li` ("listitem")
- lines starting with `-`/`•` (_not_ `+`/`*`) are listitems.
- consumes lines until blank line, codeblock, or next listitem.
- nesting is ignored: indented listitems are parsed as siblings.
- `codeblock`:
- contained by `line` or `line_li`, because ">" can start a codeblock at the
end of any line.
- contains `line` nodes without `word` nodes: it's just the full raw text
line including whitespace. This is somewhat dictated by its "preformatted"
nature; parsing the contents would require loading a "child" language
(injection). See [#2](https://github.com/neovim/tree-sitter-vimdoc/issues/2).
- the terminating `<` (and any following whitespace) is discarded (anonymous).
- `h1` = "Heading 1": `======` followed by text and optional `*tags*`.
- `h2` = "Heading 2": `------` followed by text and optional `*tags*`.
- `h3` = "Heading 3": UPPERCASE WORDS, followed by optional `*tags*`, followed
by atoms.

Known issues
------------

- Input must end with newline/EOL (`\n`). Grammar does not support files without EOL.
- Input must end with a blank line. Though this doesn't seem to matter in practice.
- Spec requires that `codeblock` delimiter ">" must be preceded by a space
(" >"), not a tab. But currently the grammar doesn't enforce this. Example:
`:help lcs-tab`.
- `url` doesn't handle _surrounding_ parens. E.g. `(https://example.com/#yay)` yields `word`
- `url` doesn't handle _nested_ parens. E.g. `(https://example.com/(foo)#yay)`
- `column_heading` currently only recognizes tilde `~` preceded by space (i.e.
`foo ~` not `foo~`). This covers 99% of :help files.
- `column_heading` children should be plaintext, but currently are parsed as `$._atom`.
- `modeline` must be preceded by a blank line.

TODO
----

- `tag_heading` : line(s) containing only tags, typically implies a "heading"
before a block.

Release
-------

Steps to perform a release:

1. Bump and tag the version:

**First** bump `Cargo.toml`, `pyproject.toml`, and `Makefile` to the new version. **Then** bump the package:
```bash
npm version patch -m "release %s"
```

Choose `patch`/`minor`/`major` to indicate query compatibility:
- `patch` for bugfixes (no changes to queries needed)
- `minor` for added nodes (queries may need changes to use new nodes but will not error)
- `major` for removed or renamed nodes (queries will error if not adapted), other breaking changes

2. Bump to prerelease, without creating a tag:
```bash
npm version --no-git-tag-version prerelease --preid dev
git add package*.json Cargo.toml pyproject.toml Makefile
git commit -m bump
```
3. Push:
```bash
git push && git push --tags
```
4. Release the tagged commit: https://github.com/neovim/tree-sitter-vimdoc/releases/new