github saberzero1/motions 0.137.0

latest releases: 1.4.0, 1.3.1, 1.3.0...
one month ago

Added

  • vim.treesitter API — full treesitter integration backed by web-tree-sitter (WASM), running as a parallel parser alongside CM6's Lezer. Markdown and HTML grammars are bundled; the subsystem activates on-demand when Lua code calls get_parser(). Provides the complete Neovim vim.treesitter API surface:
    • Core: get_parser, get_string_parser, get_node, get_node_text, get_range, get_node_range, is_in_node_range, is_ancestor, node_contains, get_captures_at_pos, get_captures_at_cursor
    • TSNode: 31 methods (type, parent, child, named_child, field, start, end_, range, sexpr, equal, iter_children, named_children, descendant_for_range, and more)
    • TSTree: root, copy, included_ranges
    • LanguageTree: 18 methods (parse, trees, lang, children, parent, root, for_each_tree, register_cbs, node_for_range, tree_for_range, language_for_range, invalidate, destroy, and more)
    • Query engine: query.parse, query.get, query.set, Query:iter_captures, Query:iter_matches, Query:disable_capture, Query:disable_pattern
    • 8 built-in predicates: #eq?, #match?, #vim-match?, #lua-match?, #contains?, #any-of?, #has-ancestor?, #has-parent? with generic #not-*/#any-* prefix handling
    • 4 built-in directives: #set!, #offset!, #gsub!, #trim!
    • Custom predicates/directives: query.add_predicate, query.add_directive, query.list_predicates, query.list_directives
    • Language management: language.register, language.get_lang, language.get_filetypes, language.add (async via coroutine bridge), language.inspect (ABI version, fields, symbols, supertypes)
    • Stubs (present, won't error): start, stop, foldexpr, select, inspect_tree
    • Plugin: src/treesitter/runtime.ts, src/treesitter/bridge.ts, src/treesitter/query.ts, src/treesitter/predicates.ts, src/treesitter/directives.ts, src/treesitter/language-tree.ts, src/treesitter/injection.ts, src/treesitter/types.ts, src/treesitter/wasm.d.ts
    • Plugin: src/lua/treesitter/api.ts, src/lua/treesitter/node.ts, src/lua/treesitter/tree.ts, src/lua/treesitter/language.ts, src/lua/treesitter/query-api.ts, src/lua/treesitter/language-tree-api.ts, src/lua/treesitter/range.ts
    • Grammars: src/treesitter/grammars/tree-sitter-markdown.wasm, src/treesitter/grammars/tree-sitter-html.wasm
  • Treesitter-enhanced Markdown features — core plugin features now use treesitter for structural parsing when available, with regex fallback:
    • Fold provider: treesitter section node hierarchy for heading fold boundaries (replaces heading-level regex)
    • Fold placeholder: treesitter-based heading text and code language extraction
    • Heading navigation (]h/[h): getAllNodesOfType(view, 'atx_heading') replaces line-by-line regex scan; automatically skips headings inside fenced code blocks
    • Code block text objects (iC/aC): findContainingNodeOfType(view, row, col, 'fenced_code_block') replaces full-document fence scan
    • Blockquote text objects (iB/aB): findContainingNodeOfType(view, row, col, 'block_quote') with correct nesting depth (fixes nested diB scoping)
    • Delimiter text objects (i*/a*, i_/a_, i`/a`, i$/a$, i~/a~): inline grammar nodes (emphasis, strong_emphasis, code_span, latex_block, strikethrough) for correct nested delimiter boundaries
    • Snippet context detection: treesitter-based code/prose/frontmatter detection (O(1) vs O(n) document scan)
    • Plugin: src/text-objects/code-block.ts, src/text-objects/blockquote.ts, src/text-objects/delimiter.ts, src/motions/headings.ts, src/snippets/context.ts, src/fold/provider.ts, src/fold/placeholder.ts
  • Markdown inline grammar — bundled tree-sitter-markdown-inline.wasm (416KB) for inline content parsing. Provides structural nodes for emphasis, strong emphasis, code spans, inline links, strikethrough, LaTeX, HTML tags, and backslash escapes.
    • Plugin: src/treesitter/grammars/tree-sitter-markdown-inline.wasm
    • Plugin: src/treesitter/runtime.ts (parseInlineContent, getInlineNodeAtPosition)
  • JS-side treesitter API — TypeScript helper functions for querying treesitter trees from plugin code (not Lua):
    • Position lookup: getNodeAtPosition, getNamedNodeAtPosition, getInlineNodeAtPosition
    • Ancestor queries: hasAncestorOfType, findAncestorOfType, isInsideNodeType, findContainingNodeOfType
    • Inline nodes: findContainingInlineNodeOfType, isInsideInlineNodeType
    • Navigation: findNextNodeOfType, getAllNodesOfType
    • Full queries: queryCaptures
    • Plugin: src/treesitter/js-api.ts, src/treesitter/tree-state.ts
  • Fork: setTokenClassifier hook — codemirror-vim fork now exposes Vim.setTokenClassifier(fn) for host-provided token classification. The % bracket matcher uses the classifier to skip brackets inside inline code spans, improving Markdown bracket matching accuracy.
    • Fork: ~/Repos/codemirror-vim/src/vim.js (setTokenClassifier, moveToMatchedSymbol, surround match path)
    • Plugin: src/main.ts (installTokenClassifier)

Changed

  • Fold golden tests re-recorded — fold-motions golden data re-recorded with vim.treesitter.foldexpr() active and luaSetup forcing synchronous treesitter parse + fold recomputation before each test case. Corrected 2zk golden value that was affected by nvim_feedkeys async timing (verified against normal! behavior). All 12 fold motion golden cases now have correct Neovim reference values.

Fixed

  • Note Composer extract fails in visual-line mode — editor.replaceSelection() now works when called after visual-line mode has been exited between getSelection() and replaceSelection(). Root cause: commands that open a modal (Note Composer, Note Refactor) return immediately from checkCallback(false), causing the withExpandedSelection wrapper's finally block to restore cursor-only CM6 selection. The modal's async completion callback then calls getSelection() (works — patched) followed by replaceSelection(), but by that time the modal interaction has exited visual-line mode, so getVisualLineSel() returns null and the patched replaceSelection falls through to the unpatched original which sees no CM6 selection. Fixed by snapshotting the visual-line selection range when getSelection() is called; replaceSelection() uses the snapshot as fallback when vim visual-line state is no longer active, clearing it after use. (#157, regression of #137/#138)
    • Plugin: src/vim/visual-line-command-fix.ts (lastVisualLineSel snapshot in getSelection(), fallback in replaceSelection())
  • zj/zk skip nested heading folds — zj now visits all foldable lines including nested headings (e.g., ## Heading inside a # Heading section), matching Neovim behavior. Previously findNextFoldable/findPrevFoldable had a parentRange filter that excluded child folds contained within a parent fold's range. Closes 6 fold motion Neovim deviations (zj, 2zj, zk, 2zk, [z, ]z).
    • Plugin: src/fold/motions.ts (removed parentRange filter from foldNext/foldPrev, fixed foldPrev count search to use fold start instead of fold end)

Tests

  • 1 regression test in test/specs/visual-line-command.e2e.ts (#157): reads getSelection() in V-LINE, exits visual mode via <Esc>, calls replaceSelection() — verifies snapshotted range is used for replacement
  • 97 unit tests for treesitter subsystem: test/unit/treesitter/runtime.test.ts (12), test/unit/treesitter/api.test.ts (36), test/unit/treesitter/query.test.ts (19), test/unit/treesitter/language-tree.test.ts (16), test/unit/treesitter/js-api.test.ts (22 — including 8 inline node detection tests)
  • 12 e2e tests for treesitter Lua API: test/specs/treesitter.e2e.ts
  • Re-recorded golden data: test/neovim/golden-data/fold-motions.json (with luaSetup forcing treesitter parse before fold motions)
  • 6 fold motion Neovim deviations removed from test/neovim/deviations.ts

Documentation

  • CHANGELOG.md
  • KNOWN_LIMITATIONS.md: updated visual-line selection section with snapshot behavior for modal-based commands (#157)
  • AGENTS.md: treesitter architecture, new file descriptions, Lua API surface update, fork setTokenClassifier hook
  • CONTRIBUTING.md: treesitter file tree in src/ structure, tree-state.ts added
  • KNOWN_LIMITATIONS.md: treesitter integration section with 7 known limitations
  • README.md: treesitter feature in Lua configuration description
  • docs/configuration/lua-config.md: updated API availability note

Full Changelog: 0.136.0...0.137.0

Don't miss a new motions release

NewReleases is sending notifications on new releases.