Showing preview only (311K chars total). Download the full file or copy to clipboard to get everything.
Repository: meain/evil-textobj-tree-sitter
Branch: master
Commit: 7f58008a82c7
Files: 257
Total size: 254.1 KB
Directory structure:
gitextract_1hjhbj7p/
├── .github/
│ └── workflows/
│ ├── test.yaml
│ └── update-queries.yaml
├── .gitignore
├── AGENTS.md
├── Cask
├── Eask
├── LICENSE
├── Makefile
├── README.md
├── additional-queries/
│ ├── README.md
│ ├── c/
│ │ └── textobjects.scm
│ ├── go/
│ │ └── textobjects.scm
│ ├── python/
│ │ └── textobjects.scm
│ └── rust/
│ └── textobjects.scm
├── converter/
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ └── main_test.go
├── docs/
│ └── updating-neovim-queries.md
├── evil-textobj-tree-sitter-core.el
├── evil-textobj-tree-sitter-query-test.el
├── evil-textobj-tree-sitter-test.el
├── evil-textobj-tree-sitter-thing-at-point.el
├── evil-textobj-tree-sitter.el
├── fixtures/
│ ├── bash/
│ │ └── textobjects.scm
│ ├── javascript/
│ │ └── textobjects.scm
│ ├── tsx/
│ │ └── textobjects.scm
│ ├── typescript/
│ │ └── textobjects.scm
│ └── zig/
│ └── textobjects.scm
├── flake.nix
├── queries/
│ ├── apex/
│ │ └── textobjects.scm
│ ├── astro/
│ │ └── textobjects.scm
│ ├── bash/
│ │ └── textobjects.scm
│ ├── bibtex/
│ │ └── textobjects.scm
│ ├── c/
│ │ └── textobjects.scm
│ ├── c_sharp/
│ │ └── textobjects.scm
│ ├── cmake/
│ │ └── textobjects.scm
│ ├── cpp/
│ │ └── textobjects.scm
│ ├── css/
│ │ └── textobjects.scm
│ ├── cuda/
│ │ └── textobjects.scm
│ ├── dart/
│ │ └── textobjects.scm
│ ├── dockerfile/
│ │ └── textobjects.scm
│ ├── ecma/
│ │ └── textobjects.scm
│ ├── elixir/
│ │ └── textobjects.scm
│ ├── elm/
│ │ └── textobjects.scm
│ ├── enforce/
│ │ └── textobjects.scm
│ ├── fennel/
│ │ └── textobjects.scm
│ ├── fish/
│ │ └── textobjects.scm
│ ├── foam/
│ │ └── textobjects.scm
│ ├── gdscript/
│ │ └── textobjects.scm
│ ├── git_config/
│ │ └── textobjects.scm
│ ├── gleam/
│ │ └── textobjects.scm
│ ├── glimmer/
│ │ └── textobjects.scm
│ ├── glsl/
│ │ └── textobjects.scm
│ ├── go/
│ │ └── textobjects.scm
│ ├── hack/
│ │ └── textobjects.scm
│ ├── haskell/
│ │ └── textobjects.scm
│ ├── hcl/
│ │ └── textobjects.scm
│ ├── heex/
│ │ └── textobjects.scm
│ ├── hlsl/
│ │ └── textobjects.scm
│ ├── html/
│ │ └── textobjects.scm
│ ├── inko/
│ │ └── textobjects.scm
│ ├── java/
│ │ └── textobjects.scm
│ ├── javascript/
│ │ └── textobjects.scm
│ ├── json/
│ │ └── textobjects.scm
│ ├── jsx/
│ │ └── textobjects.scm
│ ├── julia/
│ │ └── textobjects.scm
│ ├── kotlin/
│ │ └── textobjects.scm
│ ├── latex/
│ │ └── textobjects.scm
│ ├── lua/
│ │ └── textobjects.scm
│ ├── markdown/
│ │ └── textobjects.scm
│ ├── matlab/
│ │ └── textobjects.scm
│ ├── nasm/
│ │ └── textobjects.scm
│ ├── nim/
│ │ └── textobjects.scm
│ ├── nix/
│ │ └── textobjects.scm
│ ├── ocaml/
│ │ └── textobjects.scm
│ ├── odin/
│ │ └── textobjects.scm
│ ├── perl/
│ │ └── textobjects.scm
│ ├── php/
│ │ └── textobjects.scm
│ ├── php_only/
│ │ └── textobjects.scm
│ ├── python/
│ │ └── textobjects.scm
│ ├── ql/
│ │ └── textobjects.scm
│ ├── query/
│ │ └── textobjects.scm
│ ├── r/
│ │ └── textobjects.scm
│ ├── readline/
│ │ └── textobjects.scm
│ ├── rst/
│ │ └── textobjects.scm
│ ├── ruby/
│ │ └── textobjects.scm
│ ├── rust/
│ │ └── textobjects.scm
│ ├── scala/
│ │ └── textobjects.scm
│ ├── scss/
│ │ └── textobjects.scm
│ ├── slang/
│ │ └── textobjects.scm
│ ├── supercollider/
│ │ └── textobjects.scm
│ ├── svelte/
│ │ └── textobjects.scm
│ ├── swift/
│ │ └── textobjects.scm
│ ├── systemverilog/
│ │ └── textobjects.scm
│ ├── tact/
│ │ └── textobjects.scm
│ ├── terraform/
│ │ └── textobjects.scm
│ ├── toml/
│ │ └── textobjects.scm
│ ├── tsx/
│ │ └── textobjects.scm
│ ├── twig/
│ │ └── textobjects.scm
│ ├── typescript/
│ │ └── textobjects.scm
│ ├── v/
│ │ └── textobjects.scm
│ ├── verilog/
│ │ └── textobjects.scm
│ ├── vim/
│ │ └── textobjects.scm
│ ├── vue/
│ │ └── textobjects.scm
│ ├── wgsl/
│ │ └── textobjects.scm
│ ├── wgsl_bevy/
│ │ └── textobjects.scm
│ ├── yaml/
│ │ └── textobjects.scm
│ ├── zig/
│ │ └── textobjects.scm
│ └── zsh/
│ └── textobjects.scm
├── scripts/
│ ├── append-additional-helix-queries
│ ├── check-available
│ ├── fix-queries
│ ├── get-helix-queries
│ └── get-neovim-queries
└── treesit-queries/
├── _jsx/
│ └── textobjects.scm
├── _typescript/
│ └── textobjects.scm
├── ada/
│ └── textobjects.scm
├── adl/
│ └── textobjects.scm
├── amber/
│ └── textobjects.scm
├── awk/
│ └── textobjects.scm
├── bash/
│ └── textobjects.scm
├── basic/
│ └── textobjects.scm
├── blade/
│ └── textobjects.scm
├── c/
│ └── textobjects.scm
├── c-sharp/
│ └── textobjects.scm
├── caddyfile/
│ └── textobjects.scm
├── cairo/
│ └── textobjects.scm
├── clojure/
│ └── textobjects.scm
├── cmake/
│ └── textobjects.scm
├── codeql/
│ └── textobjects.scm
├── cpp/
│ └── textobjects.scm
├── cross-config/
│ └── textobjects.scm
├── crystal/
│ └── textobjects.scm
├── cylc/
│ └── textobjects.scm
├── d/
│ └── textobjects.scm
├── dart/
│ └── textobjects.scm
├── dhall/
│ └── textobjects.scm
├── docker-bake/
│ └── textobjects.scm
├── docker-compose/
│ └── textobjects.scm
├── dockerfile/
│ └── textobjects.scm
├── doxyfile/
│ └── textobjects.scm
├── earthfile/
│ └── textobjects.scm
├── ecma/
│ └── textobjects.scm
├── eiffel/
│ └── textobjects.scm
├── elixir/
│ └── textobjects.scm
├── elm/
│ └── textobjects.scm
├── env/
│ └── textobjects.scm
├── erlang/
│ └── textobjects.scm
├── fga/
│ └── textobjects.scm
├── fish/
│ └── textobjects.scm
├── freebasic/
│ └── textobjects.scm
├── gas/
│ └── textobjects.scm
├── gdscript/
│ └── textobjects.scm
├── git-cliff-config/
│ └── textobjects.scm
├── git-commit/
│ └── textobjects.scm
├── git-config/
│ └── textobjects.scm
├── github-action/
│ └── textobjects.scm
├── gitlab-ci/
│ └── textobjects.scm
├── gjs/
│ └── textobjects.scm
├── gleam/
│ └── textobjects.scm
├── glsl/
│ └── textobjects.scm
├── go/
│ └── textobjects.scm
├── godot-resource/
│ └── textobjects.scm
├── graphql/
│ └── textobjects.scm
├── gren/
│ └── textobjects.scm
├── gts/
│ └── textobjects.scm
├── haskell/
│ └── textobjects.scm
├── hcl/
│ └── textobjects.scm
├── heex/
│ └── textobjects.scm
├── hocon/
│ └── textobjects.scm
├── html/
│ └── textobjects.scm
├── hurl/
│ └── textobjects.scm
├── inko/
│ └── textobjects.scm
├── java/
│ └── textobjects.scm
├── javascript/
│ └── textobjects.scm
├── jjconfig/
│ └── textobjects.scm
├── jq/
│ └── textobjects.scm
├── json/
│ └── textobjects.scm
├── json-ld/
│ └── textobjects.scm
├── json5/
│ └── textobjects.scm
├── jsonc/
│ └── textobjects.scm
├── jsx/
│ └── textobjects.scm
├── julia/
│ └── textobjects.scm
├── just/
│ └── textobjects.scm
├── kdl/
│ └── textobjects.scm
├── kotlin/
│ └── textobjects.scm
├── koto/
│ └── textobjects.scm
├── latex/
│ └── textobjects.scm
├── llvm/
│ └── textobjects.scm
├── llvm-mir/
│ └── textobjects.scm
├── lua/
│ └── textobjects.scm
├── luau/
│ └── textobjects.scm
├── mail/
│ └── textobjects.scm
├── matlab/
│ └── textobjects.scm
├── miseconfig/
│ └── textobjects.scm
├── mojo/
│ └── textobjects.scm
├── nasm/
│ └── textobjects.scm
├── nestedtext/
│ └── textobjects.scm
├── nim/
│ └── textobjects.scm
├── nix/
│ └── textobjects.scm
├── nu/
│ └── textobjects.scm
├── odin/
│ └── textobjects.scm
├── ohm/
│ └── textobjects.scm
├── opencl/
│ └── textobjects.scm
├── pascal/
│ └── textobjects.scm
├── penrose/
│ └── textobjects.scm
├── perl/
│ └── textobjects.scm
├── pest/
│ └── textobjects.scm
├── php/
│ └── textobjects.scm
├── picat/
│ └── textobjects.scm
├── pkgbuild/
│ └── textobjects.scm
├── po/
│ └── textobjects.scm
├── ponylang/
│ └── textobjects.scm
├── prisma/
│ └── textobjects.scm
├── properties/
│ └── textobjects.scm
├── protobuf/
│ └── textobjects.scm
├── purescript/
│ └── textobjects.scm
├── python/
│ └── textobjects.scm
├── qml/
│ └── textobjects.scm
├── rescript/
│ └── textobjects.scm
├── robots.txt/
│ └── textobjects.scm
├── rshtml/
│ └── textobjects.scm
├── ruby/
│ └── textobjects.scm
├── rust/
│ └── textobjects.scm
├── rust-format-args-macro/
│ └── textobjects.scm
├── sage/
│ └── textobjects.scm
├── scala/
│ └── textobjects.scm
├── scheme/
│ └── textobjects.scm
├── shellcheckrc/
│ └── textobjects.scm
├── slang/
│ └── textobjects.scm
├── slint/
│ └── textobjects.scm
├── solidity/
│ └── textobjects.scm
├── sourcepawn/
│ └── textobjects.scm
├── sql/
│ └── textobjects.scm
├── starlark/
│ └── textobjects.scm
├── sway/
│ └── textobjects.scm
├── swift/
│ └── textobjects.scm
├── tablegen/
│ └── textobjects.scm
├── tact/
│ └── textobjects.scm
├── textproto/
│ └── textobjects.scm
├── tilt/
│ └── textobjects.scm
├── toml/
│ └── textobjects.scm
├── tsx/
│ └── textobjects.scm
├── typescript/
│ └── textobjects.scm
├── typespec/
│ └── textobjects.scm
├── unison/
│ └── textobjects.scm
├── v/
│ └── textobjects.scm
├── vala/
│ └── textobjects.scm
├── verilog/
│ └── textobjects.scm
├── wesl/
│ └── textobjects.scm
├── wgsl/
│ └── textobjects.scm
├── woodpecker-ci/
│ └── textobjects.scm
├── wren/
│ └── textobjects.scm
├── xml/
│ └── textobjects.scm
├── yaml/
│ └── textobjects.scm
└── zig/
└── textobjects.scm
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/test.yaml
================================================
name: Run tests
on:
workflow_dispatch:
pull_request:
push:
jobs:
check:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
emacs_version:
- 30.1
# - snapshot # causing issues with compat
steps:
- uses: actions/checkout@v4
- uses: purcell/setup-emacs@master
with:
version: ${{ matrix.emacs_version }}
- uses: emacs-eask/setup-eask@master
with:
version: 'snapshot'
- run: make install-deps
- run: make compile
- run: make lint
- run: make checkdoc
- run: make test
- run: make test-queries
- run: cd converter && go test -v
================================================
FILE: .github/workflows/update-queries.yaml
================================================
name: Update tree-siter queries
on:
schedule:
- cron: '0 13 * * 5'
workflow_dispatch:
jobs:
update-queries:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Update repos
run: |
git clone --depth 1 https://github.com/nvim-treesitter/nvim-treesitter-textobjects /tmp/nts
rm -r queries && cp -r /tmp/nts/queries .
./scripts/fix-queries
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
commit-message: Update tree-sitter queries to latest
title: Update tree-sitter queries
body: Update tree-sitter queries to latest from nvim-treesitter/nvim-treesitter-textobjects
branch: auto-update-queries
base: master
token: ${{ secrets.REPO_SCOPED_PAT }} # need this to trigger CI
================================================
FILE: .gitignore
================================================
__debug_bin
.cask/
.eask/
*.elc
================================================
FILE: AGENTS.md
================================================
## Project Overview
An Emacs package providing tree-sitter powered text objects for `evil-mode` and `thing-at-point`. Works with both `elisp-tree-sitter` and the builtin `treesit` library (Emacs 29+).
## Build & Test Commands
Dependencies are managed via Cask (`Cask` file). Install with `cask install`.
- **Compile:** `make compile`
- **Lint:** `make lint` (package-lint on the main .el file)
- **Checkdoc:** `make checkdoc`
- **Run tests:** `make test` (core functionality tests using ert)
- **Run query tests:** `make test-queries` (per-language query loading tests)
- **Converter tests:** `cd converter && go test -v`
All make targets use `cask exec emacs` under the hood. The `elpa` target runs `cask install` automatically when needed.
## Architecture
### Elisp Modules
- `evil-textobj-tree-sitter.el` — Entry point; requires core and thing-at-point modules
- `evil-textobj-tree-sitter-core.el` — All core logic: query loading, node filtering, range computation, textobj/goto functions. Supports dual backends (`elisp-tree-sitter` vs builtin `treesit`) detected at runtime
- `evil-textobj-tree-sitter-thing-at-point.el` — Registers tree-sitter things (function, loop, conditional, etc.) with Emacs `thing-at-point`
### Query System (Two Separate Sets)
- `queries/` — For `elisp-tree-sitter`, sourced from [nvim-treesitter-textobjects](https://github.com/nvim-treesitter/nvim-treesitter-textobjects). Uses `#make-range!` directives
- `treesit-queries/` — For builtin `treesit`, sourced from [Helix editor](https://github.com/helix-editor/helix). Updated via `scripts/get-helix-queries`
- `additional-queries/` — Extra queries appended to treesit-queries during the build step for cases helix doesn't cover
- `fixtures/` — Test query files for unit tests
The correct query directory is selected at runtime based on whether the current buffer uses a `-ts-mode` (treesit) or regular mode (elisp-tree-sitter).
### Converter (Go)
`converter/` contains a Go program that transforms nvim-treesitter query format (with `#make-range!` directives) into the `_start`/`_end` capture format used by `elisp-tree-sitter`. Used by `scripts/get-neovim-queries`.
### Scripts
- `scripts/get-neovim-queries` — Pulls queries from nvim-treesitter-textobjects into `queries/`. See [docs/updating-neovim-queries.md](docs/updating-neovim-queries.md) for the manual fixup process required after pulling.
- `scripts/get-helix-queries` — Pulls queries from Helix into `treesit-queries/`, appending `additional-queries/`
- `scripts/fix-queries` — Post-processing fixups on query files
### Key Design Details
- `evil-textobj-tree-sitter-major-mode-language-alist` maps Emacs major modes to tree-sitter language names (including both regular and `-ts-mode` variants)
- Query files support `;; inherits:` directives for language inheritance (e.g., typescript inherits javascript)
- Node selection priority: nodes containing point (innermost first), then nodes after point
- `evil-textobj-tree-sitter-use-next-if-not-within` controls whether to fall through to next match when not inside one
- Tests run against both `elisp-tree-sitter` and `treesit` backends (e.g., `c-mode` and `c-ts-mode`)
### Notes
- This repo is maintained using jj and not git (do not try to run any jj commands).
================================================
FILE: Cask
================================================
(source gnu)
(source melpa)
(package-file "evil-textobj-tree-sitter.el")
(development
(depends-on "ert")
(depends-on "package-lint")
(depends-on "evil")
(depends-on "tree-sitter")
(depends-on "go-mode")
(depends-on "tree-sitter-langs")
(depends-on "treesit-auto"))
================================================
FILE: Eask
================================================
;; -*- mode: eask; lexical-binding: t -*-
(package "evil-textobj-tree-sitter"
"0.5"
"Provides evil textobjects using tree-sitter")
(website-url "https://github.com/meain/evil-textobj-tree-sitter")
(keywords "evil" "tree-sitter" "text-object" "convenience")
(package-file "evil-textobj-tree-sitter.el")
(source "gnu")
(source "melpa")
(depends-on "emacs" "25.1")
(development
(depends-on "ert")
(depends-on "package-lint")
(depends-on "evil")
(depends-on "tree-sitter")
(depends-on "go-mode")
(depends-on "tree-sitter-langs")
(depends-on "treesit-auto"))
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2021 Abin Simon
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: Makefile
================================================
compile:
eask compile
lint:
eask lint package evil-textobj-tree-sitter.el
checkdoc:
eask lint checkdoc
test: install-deps
eask test ert evil-textobj-tree-sitter-test.el
test-queries: install-deps
eask test ert evil-textobj-tree-sitter-query-test.el
install-deps:
eask install-deps --dev
.PHONY: compile lint checkdoc test test-queries install-deps
================================================
FILE: README.md
================================================
# evil-textobj-tree-sitter
[](https://melpa.org/#/evil-textobj-tree-sitter)
[](https://github.com/meain/evil-textobj-tree-sitter/actions/workflows/test.yaml)
Tree-sitter powered textobjects for Emacs. You can use them with `evil-mode` or with `thing-at-point`.

This package will let you create evil textobjects using tree-sitter
grammars. You can easily create function,class,comment etc textobjects
in multiple languages. It also make additional `things` available in
`thing-at-point` like `function`, `class`, `loop`, `comment` etc.
> It can work with either elisp-tree-sitter or the builtin treesit library.
# Installation
You can install `evil-textobj-tree-sitter` from melpa. Here is how you would do it using `use-package` and `package.el`:
```emacs-lisp
(use-package evil-textobj-tree-sitter :ensure t)
```
Or you can use `straight.el`:
```emacs-lisp
(use-package evil-textobj-tree-sitter :straight t)
```
Or using `straight.el` and `el-get` to pull from source:
```emacs-lisp
(use-package evil-textobj-tree-sitter
:straight (evil-textobj-tree-sitter :type git
:host github
:repo "meain/evil-textobj-tree-sitter"
:files (:defaults "queries" "treesit-queries")))
```
> You will also have to setup [`tree-sitter`](https://github.com/emacs-tree-sitter/elisp-tree-sitter).
# Usage
## `thing-at-point` additions
The package adds more "things" to `thing-at-point`. You can find all
the things that it adds in the
[source](https://github.com/meain/evil-textobj-tree-sitter/blob/master/evil-textobj-tree-sitter-thing-at-point.el).
You can use these like any other `thing-at-point` entries. For example
in case of functions, we make the following available:
- `(thing-at-point 'function)`
- `(function-at-point)`
## Mapping textobjects
By default, the library does not provide any keybindings, but it
should be relatively easy to add them.
```emacs-lisp
;; bind `function.outer`(entire function block) to `f` for use in things like `vaf`, `yaf`
(define-key evil-outer-text-objects-map "f" (evil-textobj-tree-sitter-get-textobj "function.outer"))
;; bind `function.inner`(function block without name and args) to `f` for use in things like `vif`, `yif`
(define-key evil-inner-text-objects-map "f" (evil-textobj-tree-sitter-get-textobj "function.inner"))
;; You can also bind multiple items and we will match the first one we can find
(define-key evil-outer-text-objects-map "a" (evil-textobj-tree-sitter-get-textobj ("conditional.outer" "loop.outer")))
```
## Custom textobjects
If you are not able to find the text object that you are looking for
in the builtin list, you can create custom text objects by passing the
a custom query with captures.
For example if you want to create text object to select `import`
statements, you can write something like below. _You will have to
provide the tree-sitter queries for all the languages that you want it
to work for_
```emacs-lisp
;; The first arguemnt to `evil-textobj-tree-sitter-get-textobj' will be the capture group to use
;; and the second arg will be an alist mapping major-mode to the corresponding query to use.
(define-key evil-outer-text-objects-map "m" (evil-textobj-tree-sitter-get-textobj "import"
'((python-mode . ((import_statement) @import)) ;; default modes (using tree-sitter)
(python-ts-mode . ((import_statement) @import)) ;; treesit modes
(rust-mode . ((use_declaration) @import)))))
```
## Goto
We have also added support for for a fancier version of
`goto-char`. You can use this to go to the next function, previous
class or do any motions like that.
You can use the `evil-textobj-tree-sitter-goto-textobj` function to
invoke goto. You can either use this in other function or just bound
to a key. The first argument is the textobj that you want to use, the
second one specifies if you want to search forward or backward and the
last one is for specifying weather to go to the start or end of the
textobj.
Below are some sample binding that you can do. You can use any textobj
that is available here.
```emacs-lisp
;; Goto start of next function
(define-key evil-normal-state-map
(kbd "]f")
(lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "function.outer")))
;; Goto start of previous function
(define-key evil-normal-state-map
(kbd "[f")
(lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "function.outer" t)))
;; Goto end of next function
(define-key evil-normal-state-map
(kbd "]F")
(lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "function.outer" nil t)))
;; Goto end of previous function
(define-key evil-normal-state-map
(kbd "[F")
(lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "function.outer" t t)))
```
# Development
A Nix flake is provided for development. Enter the dev shell with:
```sh
nix develop
```
This gives you `emacs`, `eask`, `go`, and `gcc`. Then run:
```sh
make install-deps # install Emacs package dependencies
make test # run core tests
make test-queries # run per-language query loading tests
make compile # byte-compile
make lint # package-lint
make checkdoc # checkdoc
cd converter && go test -v # converter tests
```
# Finding and contributing to textobjects
`evil-textobj-tree-sitter` work with both builtin `treesit` and
`elisp-tree-sitter`. The queries in use are a bit different in both
cases with the `elisp-tree-sitter` version currently being more feature
complete. In both cases we pull the queries from external sources. For
`elisp-tree-sitter`, we source them from
[nvim-treesitter/nvim-treesitter-textobjects](https://github.com/nvim-treesitter/nvim-treesitter-textobjects#built-in-textobjects)
and is places into
[queries](https://github.com/meain/evil-textobj-tree-sitter/tree/master/queries)
directory. And for `treesit` queries, it is sourced from
[helix](https://github.com/helix-editor/helix/tree/master/runtime/queries)
and placed in
[treesit-queries](https://github.com/meain/evil-textobj-tree-sitter/tree/master/treesit-queries).
You can check these files to see what all is available. If you are
interesting in contributing additional textobjects, you can do so by
submitting to the respective projects. If there is enough interest, I
don't mind starting to manage queries ourselves.
If you are adding a completely new language, there is two other things
that you will have to do to make sure everything will work well.
1. Make sure the lang is available in [emacs-tree-sitter/tree-sitter-langs](https://github.com/emacs-tree-sitter/tree-sitter-langs/tree/master/queries) or `treesit`.
2. Make sure we have a `major-mode` mapping in [evil-textobj-tree-sitter-major-mode-language-alist](https://github.com/meain/evil-textobj-tree-sitter/blob/d416b3ab8610f179defadd58f5c20fdc65bf21e5/evil-textobj-tree-sitter.el#L40)
*If you would like to test out new textobjects, I would suggest using
[custom textobjects](#custom-textobjects). If you want to edit the
query files, you can edit them in
`evil-textobj-tree-sitter--queries-dir` or by forking the repo, and
using the forked version with your edits.*
> For cases where upstream does not consider the queries (only in case
> of treesit queries, ie the ones from helix), you can add them to
> `additional-queries` directory. They will get appended with the
> treesit queries during the build step(`./scripts/get-helix-queries`).
# License
The primary codebase is licensed under `Apache-2.0`. The queries have
be taken from
[nvim-treesitter/nvim-treesitter-textobjects](https://github.com/nvim-treesitter/nvim-treesitter-textobjects)
which is also licensed under the same license.
================================================
FILE: additional-queries/README.md
================================================
These folder contains queries that will not be accepted to upstream helix (not neovim as we are no longer maintaining it for now), for example ones like loop and conditional.
Example: https://github.com/meain/evil-textobj-tree-sitter/pull/108
================================================
FILE: additional-queries/c/textobjects.scm
================================================
(for_statement
body: (_) @loop.inner) @loop.outer
(while_statement
body: (_) @loop.inner) @loop.outer
(do_statement
body: (_) @loop.inner) @loop.outer
(if_statement
consequence: (_) @conditional.inner) @conditional.outer
================================================
FILE: additional-queries/go/textobjects.scm
================================================
(if_statement
consequence: (block) @conditional.inner) @conditional.outer
(if_statement
alternative: (block) @conditional.inner)? @conditional.outer
(expression_switch_statement
(expression_case) @conditional.inner) @conditional.outer
(type_switch_statement
(type_case) @conditional.inner) @conditional.outer
(select_statement
(communication_case) @conditional.inner) @conditional.outer
(for_statement
body: (block) @loop.inner) @loop.outer
================================================
FILE: additional-queries/python/textobjects.scm
================================================
(for_statement
body: (_) @loop.inner) @loop.outer
(while_statement
body: (_) @loop.inner) @loop.outer
(if_statement
consequence: (_) @conditional.inner) @conditional.outer
================================================
FILE: additional-queries/rust/textobjects.scm
================================================
(loop_expression
body: (_) @loop.inner) @loop.outer
(while_expression
body: (_) @loop.inner) @loop.outer
(for_expression
body: (_) @loop.inner) @loop.outer
(if_expression
consequence: (_) @conditional.inner) @conditional.outer
================================================
FILE: converter/go.mod
================================================
module github.com/meain/evil-texobj-treesitter-converter
go 1.16
require (
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
github.com/sergi/go-diff v1.2.0 // indirect
github.com/stretchr/testify v1.5.1 // indirect
)
================================================
FILE: converter/go.sum
================================================
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
================================================
FILE: converter/main.go
================================================
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"regexp"
"strings"
)
func reprint(col []string, mr []string) []string {
if mr != nil {
ibc := 0
icol := []string{}
for _, ie := range col {
switch ie {
case "(":
ibc += 1
icol = append(icol, ie)
case ")":
icol = append(icol, ie)
ibc -= 1
case mr[1]:
if ie != "@_start" && ie != "@_end" {
icol = append(icol, ie)
}
icol = append(icol, " ", "@"+mr[0]+"._start")
case mr[2]:
if ie != "@_start" && ie != "@_end" {
icol = append(icol, ie)
}
icol = append(icol, " ", "@"+mr[0]+"._end")
default:
icol = append(icol, ie)
}
}
return icol
} else {
return col
}
}
func tokenize(input string) []string {
// I thought of writing a full tokenizer, but lets use a hacky one
reg := regexp.MustCompile("[^( )]+|[( )]")
lines := strings.Split(input, "\n")
split := []string{}
for _, l := range lines {
split = append(split, reg.FindAllString(l, -1)...)
split = append(split, "\n")
}
msplit := []string{}
ins := false
s := []string{}
for _, e := range split {
switch e {
case "\"":
if ins {
msplit = append(msplit, "\""+strings.Join(s, "")+"\"")
s = []string{}
}
ins = !ins
default:
if ins {
s = append(s, e)
} else {
msplit = append(msplit, e)
}
}
}
return msplit
}
func reformat(input string) string {
split := tokenize(input)
bc := 0
i := 0
var mr []string
var col []string
var out []string
for {
e := split[i]
switch e {
case "(":
bc += 1
col = append(col, e)
case ")":
bc -= 1
col = append(col, e)
if bc == 0 {
out = append(out, reprint(col, mr)...)
mr = nil
col = []string{}
}
case "#make-range!":
col = col[:len(col)-1]
bc -= 1
mr = []string{split[i+2][1 : len(split[i+2])-1], split[i+4], split[i+6]}
i += 7
default:
if bc == 0 {
out = append(out, e)
} else {
col = append(col, e)
}
}
i++
if i >= len(split) {
break
}
}
return strings.Join(out, "")
}
func main() {
// TODO: see what is with function.outer.start in the source
content, err := ioutil.ReadFile(os.Args[1]) // the file is inside the local directory
if err != nil {
log.Fatalf("unable to read file %s", os.Args[1])
}
fmt.Print(reformat(string(content)))
}
================================================
FILE: converter/main_test.go
================================================
package main
import (
"strings"
"testing"
"github.com/andreyvit/diff"
)
func TestReformatExact(t *testing.T) {
input := `(function_definition
body: (block)? @function.inner) @function.outer`
expected := `(function_definition
body: (block)? @function.inner) @function.outer`
actual := reformat(input)
if a, e := strings.TrimSpace(actual), strings.TrimSpace(expected); a != e {
t.Errorf("Result not as expected:\n%v", diff.LineDiff(e, a))
}
}
func TestReformatSimple(t *testing.T) {
input := `((tuple
"," @_start .
(_) @parameter.inner
)
(#make-range! "parameter.outer" @_start @parameter.inner)
)`
expected := `((tuple
"," @parameter.outer._start .
(_) @parameter.inner @parameter.outer._end
)
)`
actual := reformat(input)
// fmt.Println(strings.ReplaceAll(actual, " ", "."))
// fmt.Println(strings.ReplaceAll(expected, " ", "."))
if a, e := strings.TrimSpace(actual), strings.TrimSpace(expected); a != e {
t.Errorf("Result not as expected:\n%v", diff.LineDiff(e, a))
}
}
func TestReformatQuotedBracket(t *testing.T) {
input := `((tuple
"(" .
(_) @parameter.inner
. ","? @_end
)
(#make-range! "parameter.outer" @parameter.inner @_end)
)`
expected := `((tuple
"(" .
(_) @parameter.inner @parameter.outer._start
. ","? @parameter.outer._end
)
)`
actual := reformat(input)
if a, e := strings.TrimSpace(actual), strings.TrimSpace(expected); a != e {
t.Errorf("Result not as expected:\n%v", diff.LineDiff(e, a))
}
}
func TestReformatRoot(t *testing.T) {
input := `(parameter_list
"," @_start .
(parameter_declaration) @parameter.inner
(#make-range! "parameter.outer" @_start @parameter.inner))`
expected := `(parameter_list
"," @parameter.outer._start .
(parameter_declaration) @parameter.inner @parameter.outer._end
)`
actual := reformat(input)
if a, e := strings.TrimSpace(actual), strings.TrimSpace(expected); a != e {
t.Errorf("Result not as expected:\n%v", diff.LineDiff(e, a))
}
}
================================================
FILE: docs/updating-neovim-queries.md
================================================
# Doc for updating neovim queries
We need to manually edit the neovim queries after pulling it down as we currently do not support all query formats that are available within Neovim in Emacs.
1. Run the `./scripts/get-neovim-queries` command to pull down the latest update of neovim queries.
2. Fix things we don't support (see below). Use previous version of same query if they are available from the diff, but skip them otherwise.
3. Grep for unsupported predicates and make sure none remain: `grep -rn '#offset!\|#any-of?\|#not-any-of?\|#not-lua-match?\|#lua-match?' queries/`
4. Verify all parentheses are balanced (see "Ensuring balanced brackets" below).
5. Run tests: `make test && make test-queries`
## Things we do not support
These are Neovim-specific predicates/directives that `elisp-tree-sitter` does not handle.
Queries using these need to be manually removed or rewritten using the previous
version of the same query from the diff.
- `#offset!` — Neovim directive to adjust capture boundaries (e.g., trimming comment markers). Not a standard tree-sitter predicate.
- `#not-lua-match?` — Neovim-specific Lua pattern negation. Note: `#lua-match?` is auto-converted to `#match?` by `fix-queries`, and `#not-lua-match?` becomes `#not-match?` via the same sed rule. However, verify the conversion happened; if not, manually replace `#not-lua-match?` with `#not-match?`.
- `#any-of?` — Set membership check. May be silently ignored by older versions of the tree-sitter C library bundled in `elisp-tree-sitter`, leading to false-positive matches.
- `#not-any-of?` — Negated set membership. Same concern as `#any-of?`.
### How to fix each unsupported predicate
**`#offset!`**: Do NOT blindly delete the `(#offset! ...)` line — it is
often the last expression inside a surrounding `(...)` form, and removing
it without also fixing the closing parenthesis will leave unbalanced
brackets. Instead, remove the entire `(#offset! ...)` expression and
make sure the enclosing pattern still has balanced parentheses. For
example:
```scheme
;; Before (with #offset!):
(if_statement
condition: (_) @conditional.inner
(#offset! @conditional.inner 0 1 0 -1))
;; After (remove #offset! line, keep closing paren):
(if_statement
condition: (_) @conditional.inner)
```
**`#any-of?`**: Convert to `#match?` with regex alternation, or expand
into separate patterns each using `#eq?`.
```scheme
;; Before:
(#any-of? @name "foo" "bar" "baz")
;; Option 1 — #match? (preferred when there are many values):
(#match? @name "^(foo|bar|baz)$")
;; Option 2 — duplicate pattern with #eq? (preferred for few values):
;; Copy the entire enclosing pattern once per value, each with:
(#eq? @name "foo")
```
**`#not-any-of?`**: Convert to multiple `#not-eq?` predicates (AND
semantics — all must hold).
```scheme
;; Before:
(#not-any-of? @name "do" "while" "when")
;; After:
(#not-eq? @name "do")
(#not-eq? @name "while")
(#not-eq? @name "when")
```
**`#not-lua-match?`**: Replace with `#not-match?` (adjusting the pattern
from Lua pattern syntax to regex if needed).
## Ensuring balanced brackets
After making edits, verify that every query file has balanced
parentheses and square brackets. A quick check:
```sh
# Note: must strip string literals first since queries contain "(" and
# similar inside strings which would throw off a naive character count.
for f in queries/*/textobjects.scm; do
stripped=$(sed 's/"[^"]*"//g' "$f")
opens=$(echo "$stripped" | tr -cd '(' | wc -c)
closes=$(echo "$stripped" | tr -cd ')' | wc -c)
if [ "$opens" -ne "$closes" ]; then
echo "UNBALANCED parens in $f: (=$opens )=$closes"
fi
opens=$(echo "$stripped" | tr -cd '[' | wc -c)
closes=$(echo "$stripped" | tr -cd ']' | wc -c)
if [ "$opens" -ne "$closes" ]; then
echo "UNBALANCED brackets in $f: [=$opens ]=$closes"
fi
done
```
If any file is reported as unbalanced, open it and fix the issue before
running tests.
## Things that are supported
- `#eq?` — Standard tree-sitter equality predicate, works as-is.
- `#not-eq?` — Standard negated equality, works as-is.
- `#match?` — Standard regex matching, works as-is.
- `#not-match?` — Standard negated regex matching, works as-is.
- `#make-range!` — Neovim-specific, but handled by the Go converter in `converter/` which transforms it to `_start`/`_end` captures.
================================================
FILE: evil-textobj-tree-sitter-core.el
================================================
;;; evil-textobj-tree-sitter-core.el --- Provides evil textobjects using tree-sitter -*- lexical-binding: t; -*-
;; URL: https://github.com/meain/evil-textobj-tree-sitter
;; Keywords: evil, tree-sitter, text-object, convenience
;; SPDX-License-Identifier: Apache-2.0
;; Package-Requires: ((emacs "25.1"))
;; Version: 0.5
;;; Commentary:
;; This package is a port of nvim-treesitter/nvim-treesitter-textobjects.
;; This package will let you create evil textobjects using the power
;; of tree-sitter grammars. You can easily create
;; function,class,comment etc textobjects in multiple languages.
;;
;; You can do a sample map like below to create a function textobj.
;; (define-key evil-outer-text-objects-map "f"
;; (evil-textobj-tree-sitter-get-textobj "function.outer"))
;; `evil-textobj-tree-sitter-get-textobj' will return you a function
;; that you can use in a define-key map. You can pass in any of the
;; supported queries as an arg of that function. You can also pass in
;; multiple queries as a list and we will match on all of them, ranked
;; on which ones comes up first in the file.
;; You can find more info in the README.md file at
;; https://github.com/meain/evil-textobj-tree-sitter
;;; Code:
(require 'cl-lib)
(require 'map)
(defvar evil-textobj-tree-sitter--can-use-elisp-treesitter
(require 'tree-sitter nil t)
"If non-nil, we are can make use of elisp-tree-sitter instead of builtin.")
(defvar evil-textobj-tree-sitter--can-use-builtin-treesit
(require 'treesit nil t)
"If non-nil, we are can make use of builtin treesit instead of elisp-tree-sitter.")
(defvar evil-textobj-tree-sitter--evil-available (require 'evil nil t)
"Specifies if we have `evil-mode' available to use in package.")
(defgroup evil-textobj-tree-sitter nil "Text objects based on tree-sitter for Evil."
:group 'tools)
;; Ignore warnings from optionally requiring tree-sitter and treesit
(defvar tree-sitter-language)
(defvar tree-sitter-tree)
(declare-function tsc-node-byte-range "tsc" t t)
(declare-function tsc--buffer-substring-no-properties "tsc")
(declare-function tsc-query-matches "tsc")
(declare-function tsc-root-node "tsc" t t)
(declare-function tsc-make-query "tsc")
(declare-function treesit-node-end "treesit.c")
(declare-function treesit-node-start "treesit.c")
(declare-function treesit-query-capture "treesit.c")
(declare-function treesit-buffer-root-node "treesit")
(defconst evil-textobj-tree-sitter--dir (file-name-directory (locate-library "evil-textobj-tree-sitter.el"))
"The directory where the library `tree-sitter-langs' is located.")
(defun evil-textobj-tree-sitter--use-builtin-treesitter ()
"Return non-nil if we should use builtin treesitter."
(and evil-textobj-tree-sitter--can-use-builtin-treesit
(let ((major-mode-name (symbol-name major-mode)))
(or (string-suffix-p "-ts-mode" major-mode-name)
(and (bound-and-true-p rust-mode-treesitter-derive)
(derived-mode-p 'rust-mode))))))
(defun evil-textobj-tree-sitter--get-queries-dir ()
"Get the queries directory.
Currently treesit queries are different from queries for elisp-tree-sitter."
(if (evil-textobj-tree-sitter--use-builtin-treesitter)
(file-name-as-directory (concat evil-textobj-tree-sitter--dir "treesit-queries"))
(file-name-as-directory (concat evil-textobj-tree-sitter--dir "queries"))))
(defcustom evil-textobj-tree-sitter--get-queries-dir-func #'evil-textobj-tree-sitter--get-queries-dir
"Function to get location for the queries."
:group 'evil-textobj-tree-sitter
:type 'function)
(defcustom evil-textobj-tree-sitter-major-mode-language-alist nil
"Alist that maps major modes to tree-sitter language names."
:group 'evil-textobj-tree-sitter
:type '(alist :key-type symbol
:value-type string))
(pcase-dolist (`(,major-mode . ,lang-symbol)
(reverse '((c++-mode . "cpp")
(c++-ts-mode . "cpp")
(c-mode . "c")
(c-ts-mode . "c")
(csharp-mode . "c_sharp")
(csharp-ts-mode . "c-sharp")
(elixir-mode . "elixir")
(elixir-ts-mode . "elixir")
(elm-mode . "elm")
(elm-ts-mode . "elm")
(ess-r-mode . "r")
(go-mode . "go")
(go-ts-mode . "go")
(haskell-mode . "haskell")
(haskell-ts-mode . "haskell")
(html-mode . "html")
(html-ts-mode . "html")
(java-mode . "java")
(java-ts-mode . "java")
(javascript-mode . "javascript")
(javascript-ts-mode . "javascript")
(js-mode . "javascript")
(js-ts-mode . "javascript")
(js2-mode . "javascript")
(js3-mode . "javascript")
(julia-mode . "julia")
(julia-ts-mode . "julia")
(matlab-mode . "matlab")
(tuareg-mode . "ocaml")
(php-mode . "php")
(php-ts-mode . "php")
(prisma-mode . "prisma")
(prisma-ts-mode . "prisma")
(python-mode . "python")
(python-ts-mode . "python")
(rjsx-mode . "javascript")
(ruby-mode . "ruby")
(ruby-ts-mode . "ruby")
(rust-mode . "rust")
(rust-ts-mode . "rust")
(rustic-mode . "rust")
(sh-mode . "bash")
(bash-ts-mode . "sh")
(shell-script-mode . "bash")
(tsx-mode . "tsx")
(tsx-ts-mode . "tsx")
(typescript-mode . "typescript")
(typescript-ts-mode . "typescript")
(verilog-mode . "verilog")
(zig-mode . "zig"))))
(setf (map-elt evil-textobj-tree-sitter-major-mode-language-alist
major-mode) lang-symbol))
(defcustom evil-textobj-tree-sitter-use-next-if-not-within t
"When non-nil, use the next match if we are not within one."
:group 'evil-textobj-tree-sitter
:type 'boolean)
(defun evil-textobj-tree-sitter--nodes-filter-before (nodes)
"NODES which contain the current after them."
(sort (cl-remove-if-not (lambda (x)
(< (car (last x)) (point)))
nodes)
(lambda (x y) (< (car (last x)) (car (last y))))))
(defun evil-textobj-tree-sitter--nodes-filter-within (nodes)
"NODES which contain the current point inside them ordered inside out."
(let ((byte-pos (point)))
(sort (cl-remove-if-not (lambda (x)
(and (<= (nth 1 x) byte-pos)
(< byte-pos (car (last x)))))
nodes)
(lambda (x y)
(< (+ (abs (- byte-pos (nth 1 x)))
(abs (- byte-pos (car (last x)))))
(+ (abs (- byte-pos (nth 1 y)))
(abs (- byte-pos (car (last y))))))))))
(defun evil-textobj-tree-sitter--nodes-filter-after (nodes)
"NODES which contain the current point before them ordered top to bottom."
(sort (cl-remove-if-not (lambda (x)
(> (nth 1 x) (point)))
nodes)
(lambda (x y) (< (nth 1 x) (nth 1 y)))))
(defun evil-textobj-tree-sitter--get-inherits-line (filename)
"Get the inherits line from `FILENAME'.
It might not be on the fist line and so we cannot just get the first line."
(with-temp-buffer
(if (file-exists-p filename)
(progn
(insert-file-contents filename)
(goto-char (point-min))
(search-forward "; inherits: " nil t)
(let ((line (thing-at-point 'line t)))
(if (string-match "^; inherits: \\([a-z_,()]+\\)$" line)
(match-string 1 line)))))))
(defun evil-textobj-tree-sitter--get-query-from-dir (language queries-dir top-level)
"Get tree sitter query for `LANGUAGE' from `QUERIES-DIR'.
`TOP-LEVEL' is used to mention if we should load optional inherits.
https://github.com/nvim-treesitter/nvim-treesitter/pull/564"
(let ((filename (concat queries-dir language "/textobjects.scm")))
(with-temp-buffer
(if (file-exists-p filename)
(progn
(insert-file-contents filename)
(goto-char (point-min))
(let ((inherits-line (evil-textobj-tree-sitter--get-inherits-line filename)))
(if inherits-line
(insert (string-join (mapcar (lambda (x)
(if (string-prefix-p "(" x)
(if top-level
(evil-textobj-tree-sitter--get-query-from-dir (substring x 1 -1)
queries-dir nil))
(evil-textobj-tree-sitter--get-query-from-dir x queries-dir nil)))
(split-string inherits-line ","))
"\n"))))
(buffer-string))))))
(defun evil-textobj-tree-sitter--get-query (language)
"Get tree sitter query for `LANGUAGE'."
(evil-textobj-tree-sitter--get-query-from-dir language (funcall evil-textobj-tree-sitter--get-queries-dir-func) t))
(defun evil-textobj-tree-sitter--treesit-get-nodes (query)
"Get nodes for `QUERY' using builtin `treesit'."
(if (not (treesit-parser-list))
(progn
(message "evil-textobj-tree-sitter: treesit parser is not available in %s" major-mode)
nil)
(let* ((lang-name (alist-get major-mode evil-textobj-tree-sitter-major-mode-language-alist))
(user-query (alist-get major-mode query))
(f-query (if (eq user-query nil)
(evil-textobj-tree-sitter--get-query lang-name)
user-query))
(root-node (treesit-buffer-root-node))
(captures (treesit-query-capture root-node f-query)))
(seq-map (lambda (x)
(list (car x)
(treesit-node-start (cdr x))
(treesit-node-end (cdr x))))
captures))))
(defun evil-textobj-tree-sitter--elisp-tree-sitter-get-nodes (query)
"Get nodes for `QUERY' using `elisp-tree-sitter'."
(if (not (bound-and-true-p tree-sitter-tree))
(progn
(message "evil-textobj-tree-sitter: tree-sitter is not available in %s" major-mode)
nil)
(let* ((lang-name (alist-get major-mode evil-textobj-tree-sitter-major-mode-language-alist))
(user-query (alist-get major-mode query))
(f-query (if (eq user-query nil)
(evil-textobj-tree-sitter--get-query lang-name)
user-query))
(root-node (tsc-root-node tree-sitter-tree))
(query (tsc-make-query tree-sitter-language f-query))
(matches (tsc-query-matches query root-node #'tsc--buffer-substring-no-properties))
(all-captures '()))
(progn
(seq-map (lambda (x)
(let* ((match-captures (cdr x))
(capture-start nil)
(capture-end nil))
(seq-map (lambda (y)
(let ((csplits (split-string (symbol-name (car y)) "\\.")))
(pcase (car (last csplits))
("_end" (setq capture-end y))
("_start" (setq capture-start y))
(_ (push (list (car y)
(car (tsc-node-byte-range (cdr y)))
(cdr (tsc-node-byte-range (cdr y))))
all-captures)))))
match-captures)
(if (and capture-start capture-end)
(push (list (intern (string-join (butlast (split-string (symbol-name (car capture-start)) "\\.") 1) "."))
(car (tsc-node-byte-range (cdr capture-start)))
(cdr (tsc-node-byte-range (cdr capture-end))))
all-captures))))
matches)
(mapcar (lambda (c)
(list (car c)
(byte-to-position (cadr c))
(byte-to-position (caddr c))))
all-captures)))))
(defun evil-textobj-tree-sitter--get-nodes (group query)
"Get a list of viable nodes based on `GROUP' value.
They will be order with captures with point inside them first then the
ones that follow. If a `QUERY' alist is provided and
it contains a current `major-mode',
we make use of that instead of the builtin query set."
(cl-remove-duplicates (cl-remove-if-not (lambda (x)
(member (car x) group))
(if (evil-textobj-tree-sitter--use-builtin-treesitter)
(evil-textobj-tree-sitter--treesit-get-nodes query)
(evil-textobj-tree-sitter--elisp-tree-sitter-get-nodes query)))
:test (lambda (x y)
(and (eq (car x) (car y)) ;; names are equal
(= (nth 1 x) (nth 1 y))
(= (car (last x)) (car (last y)))))))
(defun evil-textobj-tree-sitter--get-within-and-after (group count query)
"Given a `GROUP' `QUERY' find `COUNT' number of nodes within in and after point."
(let* ((nodes (evil-textobj-tree-sitter--get-nodes group query))
(nodes-within (evil-textobj-tree-sitter--nodes-filter-within nodes))
(nodes-after (evil-textobj-tree-sitter--nodes-filter-after nodes))
(filtered-nodes (if (and (equal 1 count)
(not evil-textobj-tree-sitter-use-next-if-not-within))
nodes-within
(append nodes-within nodes-after))))
(if (> (length filtered-nodes) 0)
(cl-subseq filtered-nodes 0 count))))
(defun evil-textobj-tree-sitter--get-within (group count query)
"Given a `GROUP' `QUERY' find `COUNT' number of nodes within point."
(let* ((nodes (evil-textobj-tree-sitter--get-nodes group query))
(nodes-within (evil-textobj-tree-sitter--nodes-filter-within nodes)))
(if (> (length nodes-within) 0)
(cl-subseq nodes-within 0 count))))
(defun evil-textobj-tree-sitter--range (count ts-group &optional query)
"Get the range of the closeset item of type `TS-GROUP'.
`COUNT' is supported even thought it does not actually make sense in
most cases as if we do 3-in-func the selections will not be continues,
but we can only provide the start and end as of now which is what we
are doing. If a `QUERY' alist is provided, we make use of that
instead of the builtin query set."
(let ((nodes (evil-textobj-tree-sitter--get-within-and-after ts-group count query)))
(if (not (eq nodes nil))
(let ((range-min (apply #'min
(seq-map (lambda (x)
(nth 1 x))
nodes)))
(range-max (apply #'max
(seq-map (lambda (x)
(car (last x)))
nodes))))
;; Have to compute min and max like this as we might have nested functions
(cons range-min range-max)))))
(defun evil-textobj-tree-sitter--message-not-found (groups)
"Log a message that `GROUPS' are not found."
(let ((not-found (mapconcat (lambda (g)
(concat "'" g "'"))
groups
" or ")))
(error (concat "No " not-found " text object found"))))
;;;###autoload
(defmacro evil-textobj-tree-sitter-get-textobj (group &optional query)
"Macro to create a textobj function from `GROUP'.
You can pass in multiple groups as a list and in that case as long as
any one of them is available, it will be picked.
You can optionally pass in a alist mapping `major-mode' to their
respective tree-sitter query in `QUERY' with named captures to use
that instead of the default query list. If `QUERY' does not contain
current `major-mode', then the default queries are used.
Check the README file in the repo to see how to use it.
Check this url for builtin objects
https://github.com/nvim-treesitter/nvim-treesitter-textobjects#built-in-textobjects"
(declare (debug t) (indent defun))
(if evil-textobj-tree-sitter--evil-available
(let* ((groups (if (eq (type-of group) 'string)
(list group)
group))
(funsymbol (intern (concat "evil-textobj-tree-sitter-function--"
(mapconcat 'identity groups "-"))))
(interned-groups (mapcar #'intern groups)))
`(evil-define-text-object ,funsymbol
;; rest argument is named because of compiler warning `argument _ not left unused`
(count &rest unused)
(let ((range (evil-textobj-tree-sitter--range count ',interned-groups ,query)))
(if (not (eq range nil))
(evil-range (car range)
(cdr range))
(evil-textobj-tree-sitter--message-not-found ',groups)))))
(error "Cannot use `evil-textobj-tree-sitter-goto-textobj' without `evil-mode'")))
(defun evil-textobj-tree-sitter--get-goto-location (groups previous end query)
"Get the start/end of the textobj of type `GROUPS'.
By default it goes to the start of the textobj, but pass in `END' if
you want to go to the end of the textobj instead. You can pass in
`PREVIOUS' if you want to search backwards. `QUERY' for custom queries."
(let* ((nodes (evil-textobj-tree-sitter--get-nodes groups query))
(usable-nodes (if previous
(if end
(cl-remove-if-not (lambda (x)
(< (car (last x)) (point)))
nodes)
(cl-remove-if-not (lambda (x)
(< (nth 1 x) (point)))
nodes))
(if end
(cl-remove-if-not (lambda (x)
;; -1 is needed as evil cannot select till end
(> (- (car (last x)) 1) (point)))
nodes)
(cl-remove-if-not (lambda (x)
(> (nth 1 x) (point)))
nodes))))
(node (car (sort usable-nodes
(lambda (x y)
(if previous
(if end
(> (car(last x)) (car (last y)))
(> (nth 1 x) (nth 1 y)))
(if end
(< (car(last x)) (car (last y)))
(< (nth 1 x) (nth 1 y)))))))))
(if node
(let ((actual-position (if end
(car (last node))
(nth 1 node))))
(if end
;; tree sitter count + 1 kinda (probably have to look in other places as well)
;; This is a mess that evil creates (not really an issue in Emacs mode)
(- actual-position 1)
actual-position)))))
;;;###autoload
(defun evil-textobj-tree-sitter-goto-textobj (group &optional previous end query)
"Got to the start/end of the textobj of type `GROUP'.
By default it goes to the start of the textobj, but pass in `END' if
you want to go to the end of the textobj instead. You can pass in
`PREVIOUS' if you want to search backwards. Optionally pass in
`QUERY' if you want to define a custom query."
(let* ((groups (if (eq (type-of group) 'string)
(list group)
group))
(interned-groups (mapcar #'intern groups))
(goto-position (evil-textobj-tree-sitter--get-goto-location
interned-groups previous end query)))
(if goto-position
(goto-char goto-position)
(evil-textobj-tree-sitter--message-not-found groups))))
(provide 'evil-textobj-tree-sitter-core)
;;; evil-textobj-tree-sitter-core.el ends here
================================================
FILE: evil-textobj-tree-sitter-query-test.el
================================================
;;; Code:
(require 'tree-sitter-langs)
(require 'evil-textobj-tree-sitter)
(require 'ert)
(defun evil-textobj-tree-sitter--test-loading-with-comment-prefix (lang comment-prefix)
"Try loading grammar for `LANG' and test with comment using `COMMENT-PREFIX'."
(evil-textobj-tree-sitter--test-loading-with-comment
lang
(concat comment-prefix " howdy!")))
(defun evil-textobj-tree-sitter--test-loading-with-comment (lang text &optional region)
"Try loading grammar for `LANG'.
And test with comment provided in `TEXT' optionally passing in `REGION'."
(let* ((bufname (make-temp-name "evil-textobj-tree-sitter-test--"))
(filename (concat "/tmp/" bufname)))
(find-file filename)
(fundamental-mode)
(with-current-buffer bufname
(when (null tree-sitter-major-mode-language-table)
(setq tree-sitter-major-mode-language-table (make-hash-table :test 'eq)))
(puthash 'fundamental-mode lang tree-sitter-major-mode-language-table)
(setq-local evil-textobj-tree-sitter-major-mode-language-alist `((fundamental-mode . ,(symbol-name lang))))
(insert text)
(tree-sitter-mode)
(goto-char 0)
(should (equal
(evil-textobj-tree-sitter--range
1
(list (intern "comment.outer")))
(if region region (cons 1 (+ 1 (length text)))))))
(set-buffer-modified-p nil)
(kill-buffer bufname)))
;; TODO: Simplify code using macros and dolist
;; bash
(ert-deftest evil-textobj-tree-sitter-try-bash ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'bash "#"))
;; c
(ert-deftest evil-textobj-tree-sitter-try-c ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'c "//"))
;; cpp
(ert-deftest evil-textobj-tree-sitter-try-cpp ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'cpp "//"))
;; elixir
(ert-deftest evil-textobj-tree-sitter-try-elixir ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'elixir "#"))
;; elm
(ert-deftest evil-textobj-tree-sitter-try-elm ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'elm "--"))
;; go
(ert-deftest evil-textobj-tree-sitter-try-go ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'go "//"))
;; haskell
(ert-deftest evil-textobj-tree-sitter-try-haskell ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'haskell "--"))
;; hcl
(ert-deftest evil-textobj-tree-sitter-try-hcl ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'hcl "#"))
;; html <!--
(ert-deftest evil-textobj-tree-sitter-try-html ()
(evil-textobj-tree-sitter--test-loading-with-comment 'html "<!-- howdy -->"))
;; java
(ert-deftest evil-textobj-tree-sitter-try-java ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'java "//"))
;; javascript
(ert-deftest evil-textobj-tree-sitter-try-javascript ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'javascript "//"))
;; julia TODO: Needs grammar update
;; (ert-deftest evil-textobj-tree-sitter-try-julia ()
;; (evil-textobj-tree-sitter--test-loading-with-comment-prefix 'julia "#"))
;; php
(ert-deftest evil-textobj-tree-sitter-try-php ()
(evil-textobj-tree-sitter--test-loading-with-comment 'php "<?php\n// howdy\n?>" (cons 7 15)))
;; python
(ert-deftest evil-textobj-tree-sitter-try-python ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'python "#"))
;; r
(ert-deftest evil-textobj-tree-sitter-try-r ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'r "#"))
;; ruby
(ert-deftest evil-textobj-tree-sitter-try-ruby ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'ruby "#"))
;; rust
(ert-deftest evil-textobj-tree-sitter-try-rust ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'rust "//"))
;; typescript
(ert-deftest evil-textobj-tree-sitter-try-typescript ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'typescript "//"))
;; verilog
(ert-deftest evil-textobj-tree-sitter-try-verilog ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'verilog "//"))
;; zig
(ert-deftest evil-textobj-tree-sitter-try-zig ()
(evil-textobj-tree-sitter--test-loading-with-comment-prefix 'zig "//"))
;;; evil-textobj-tree-sitter-query-test.el ends here
================================================
FILE: evil-textobj-tree-sitter-test.el
================================================
;;; evil-textobj-tree-sitter-test.el --- Tests for evil-textobj-tree-sitter -*- lexical-binding: t -*-
;;; Commentary:
;; We can only use statically linked files here or libstdc++ screams at you.
;; C is an ideal candidate for this as it is builtin and is statically linked.
;;; Code:
(require 'tree-sitter-langs)
(require 'evil-textobj-tree-sitter)
(require 'go-mode)
(setq treesit-language-source-alist
'((c . ("https://github.com/tree-sitter/tree-sitter-c"))
(cpp . ("https://github.com/tree-sitter/tree-sitter-cpp"))
(python . ("https://github.com/tree-sitter/tree-sitter-python"))
(go . ("https://github.com/tree-sitter/tree-sitter-go"))
(gomod . ("https://github.com/camdencheek/tree-sitter-go-mod.git"))))
;; Unset GIT_DIR/GIT_WORK_TREE so treesit-install-language-grammar can git
;; clone into temp directories (these may be set for jj repo compatibility)
(setenv "GIT_DIR" nil)
(setenv "GIT_WORK_TREE" nil)
(treesit-install-language-grammar 'c)
(treesit-install-language-grammar 'cpp)
(treesit-install-language-grammar 'python)
(treesit-install-language-grammar 'go)
(treesit-install-language-grammar 'gomod)
(defvar evil-textobj-tree-sitter--test-file-content
'((c-simple . "// Lukasz
int main() {
printf(\"hello\")
}")
(c-multiple-funcs . "// mango
int main() {
printf(\"hello\")
}
int main2() {
printf(\"hello2\")
}
")
(c-unicode . "// Łukasz
int main() {
printf(\"hello\")
}")
(c-multibyte . "// Комментарий
int main(int temp, int temp2) {
printf(\"hello\");
}")
(go-multibyte-code . "// Комментарий
func main(int Комментарий, int temp2) {
printf(\"hello\");
}")
(go-nested . "// comment
func main() {
fmt.Println(\"howdy bruh!\")
func() {
fmt.Println(\"yo!\")
}
}")
(py-complex . "def func ():
var1
def func2(): pass
def nested():
var2
def inner():
var3
var4
var5
")))
(defun evil-textobj-tree-sitter--range-test (mode treesit start textobj range content)
"Check ranges of tree-sitter targets.
`MODE' is the `major-mode' to be used.
`TREESIT' non nil will use `treesit'.
`CONTENT' is the content to be used.
`START' is the starting position.
`TEXTOBJ' is the textobject to check.
`RANGE' is the range that should be returned."
(let* ((bufname (make-temp-name "evil-textobj-tree-sitter-test--"))
(buffer (get-buffer-create bufname)))
(with-current-buffer buffer
(insert (alist-get content evil-textobj-tree-sitter--test-file-content))
(funcall mode)
(if (not treesit) (tree-sitter-mode))
(message "%s" major-mode)
(goto-char start)
(should (equal
(evil-textobj-tree-sitter--range 1 (list (intern textobj)))
range)))
(kill-buffer buffer)))
(ert-deftest evil-textobj-tree-sitter-within-unicode-test ()
"Check inner range queries within unicode buffers."
;; function.inner selects brackets in treesit queries but not in tree-sitter ones
(evil-textobj-tree-sitter--range-test 'c-mode nil 31 "function.inner" (cons 28 43) 'c-unicode)
(evil-textobj-tree-sitter--range-test 'c-ts-mode t 31 "function.inner" (cons 22 45) 'c-unicode))
(ert-deftest evil-textobj-tree-sitter-within-unicode-test-outer ()
"Check outer range queries within unicode buffers."
(evil-textobj-tree-sitter--range-test 'c-mode nil 31 "function.outer" (cons 11 45) 'c-unicode)
(evil-textobj-tree-sitter--range-test 'c-ts-mode t 31 "function.outer" (cons 11 45) 'c-unicode))
(ert-deftest evil-textobj-tree-sitter-within-multibyte-buffers ()
"Check range in multibyte comment before."
(evil-textobj-tree-sitter--range-test 'c-mode nil 35 "parameter.inner" (cons 35 44) 'c-multibyte)
(evil-textobj-tree-sitter--range-test 'c-ts-mode t 35 "parameter.inner" (cons 35 44) 'c-multibyte))
(ert-deftest evil-textobj-tree-sitter-within-unicode-test3 ()
"Check range with multibyte code."
(evil-textobj-tree-sitter--range-test 'go-mode nil 31 "parameter.inner" (cons 26 41) 'go-multibyte-code)
(evil-textobj-tree-sitter--range-test 'go-ts-mode t 31 "parameter.inner" (cons 26 41) 'go-multibyte-code))
(ert-deftest evil-textobj-tree-sitter-within-test ()
"Check range when we are within the textobj with buffer having only ASCII chars."
(evil-textobj-tree-sitter--range-test 'c-mode nil 31 "function.outer" (cons 11 45) 'c-simple)
(evil-textobj-tree-sitter--range-test 'c-ts-mode t 31 "function.outer" (cons 11 45) 'c-simple))
(ert-deftest evil-textobj-tree-sitter-lookahed-test ()
"Check range when we are before the textobj with buffer having only ASCII chars."
(evil-textobj-tree-sitter--range-test 'c-mode nil 1 "function.outer" (cons 11 45) 'c-simple)
(evil-textobj-tree-sitter--range-test 'c-ts-mode t 1 "function.outer" (cons 11 45) 'c-simple))
(ert-deftest evil-textobj-tree-sitter-right-at-start-test ()
"Checking for off by one errors at start."
(evil-textobj-tree-sitter--range-test 'c-mode nil 11 "function.outer" (cons 11 45) 'c-simple)
(evil-textobj-tree-sitter--range-test 'c-ts-mode t 11 "function.outer" (cons 11 45) 'c-simple))
;;; Reading query files
(ert-deftest evil-textoj-tree-sitter-check-query-read-simple ()
"Simple query read check."
(let ((evil-textobj-tree-sitter--get-queries-dir-func (lambda () "fixtures/")))
(should (string-prefix-p ";; \"Classes\"" (evil-textobj-tree-sitter--get-query "zig")))))
(ert-deftest evil-textoj-tree-sitter-check-query-read-nocomment ()
"Check a query file with no comment."
(let ((evil-textobj-tree-sitter--get-queries-dir-func (lambda () "fixtures/")))
(should (string-prefix-p "(function_definition" (evil-textobj-tree-sitter--get-query "bash")))))
(ert-deftest evil-textoj-tree-sitter-check-query-read-nested ()
"Check a query with nested files to be loaded."
(let ((evil-textobj-tree-sitter--get-queries-dir-func (lambda () "fixtures/")))
(should (string-prefix-p "; inherits: (jsx)" (evil-textobj-tree-sitter--get-query "typescript")))))
(ert-deftest evil-textoj-tree-sitter-check-query-read-nested-nofile ()
"Check a file pointing to a non existent file."
(let ((evil-textobj-tree-sitter--get-queries-dir-func (lambda () "fixtures/")))
(should (string-prefix-p "; inherits: (jsx)" (evil-textobj-tree-sitter--get-query "javascript")))))
(ert-deftest evil-textoj-tree-sitter-check-query-read-nested-multi ()
"Check a query with multiple nesting items."
(let ((evil-textobj-tree-sitter--get-queries-dir-func (lambda () "fixtures/")))
(should (string-prefix-p "; inherits: (javascript)" (evil-textobj-tree-sitter--get-query "tsx")))))
(ert-deftest evil-textoj-tree-sitter-check-query-read-non-top-level ()
"Check a non top level direct query."
(should (string-prefix-p "; inherits: (javascript)" (evil-textobj-tree-sitter--get-query-from-dir "typescript" "fixtures/" nil))))
(defun evil-textobj-tree-sitter--goto-test (mode treesit start textobj pos prev end content)
"Check for location of goto actions.
`MODE' is the `major-mode' to be used.
`TREESIT' non nil will use `treesit'.
`CONTENT' is the content to be used.
`START' is the starting position.
`TEXTOBJ' is the textobject to check.
`PREV' goes to previous textobj.
`END' goes to end of textobj.
`POS' is the position that should be returned."
(let* ((bufname (make-temp-name "evil-textobj-tree-sitter-test--"))
(buffer (get-buffer-create bufname)))
(with-current-buffer buffer
(insert (alist-get content evil-textobj-tree-sitter--test-file-content))
(funcall mode)
(if (not treesit) (tree-sitter-mode))
(goto-char start)
(should (equal (evil-textobj-tree-sitter--get-goto-location
(list (intern textobj)) prev end nil)
pos)))
(kill-buffer bufname)))
(ert-deftest evil-textobj-tree-sitter-goto-next-start-simple ()
"Go to next start in ASCII buffers."
(evil-textobj-tree-sitter--goto-test 'c-mode nil 1 "function.outer" 11 nil nil 'c-simple)
(evil-textobj-tree-sitter--goto-test 'c-ts-mode t 1 "function.outer" 11 nil nil 'c-simple))
(ert-deftest evil-textobj-tree-sitter-goto-next-start-multiple-textobjects ()
"Check to see if we are able to find first one when we have multiple textobjects."
(evil-textobj-tree-sitter--goto-test 'c-mode nil 1 "parameter.outer" 25 nil nil 'c-multibyte)
(evil-textobj-tree-sitter--goto-test 'c-ts-mode t 1 "parameter.outer" 25 nil nil 'c-multibyte))
(ert-deftest evil-textobj-tree-sitter-goto-next-end-simple ()
"Check if we can navigate to end of a textobj."
(evil-textobj-tree-sitter--goto-test 'c-mode nil 1 "function.outer" 69 nil t 'c-multibyte)
(evil-textobj-tree-sitter--goto-test 'c-ts-mode t 1 "function.outer" 69 nil t 'c-multibyte))
(ert-deftest evil-textobj-tree-sitter-goto-next-end-multi ()
"Goto end when we have multiple functions."
(evil-textobj-tree-sitter--goto-test 'c-mode nil 1 "function.outer" 43 nil t 'c-multiple-funcs)
(evil-textobj-tree-sitter--goto-test 'c-ts-mode t 1 "function.outer" 43 nil t 'c-multiple-funcs))
(ert-deftest evil-textobj-tree-sitter-goto-previous-end-multi ()
"Goto end of previous textobj."
(evil-textobj-tree-sitter--goto-test 'c-mode nil 69 "function.outer" 43 t t 'c-multiple-funcs)
(evil-textobj-tree-sitter--goto-test 'c-ts-mode t 69 "function.outer" 43 t t 'c-multiple-funcs))
(ert-deftest evil-textobj-tree-sitter-goto-previous-end-multi-on-end ()
"Testing going to end of previous one while on end of current one."
(evil-textobj-tree-sitter--goto-test 'c-mode nil 82 "function.outer" 43 t t 'c-multiple-funcs)
(evil-textobj-tree-sitter--goto-test 'c-ts-mode t 82 "function.outer" 43 t t 'c-multiple-funcs))
(ert-deftest evil-textobj-tree-sitter-goto-previous-start-nested ()
"Goto the start of the previous textobj in a nested scenario."
(evil-textobj-tree-sitter--goto-test 'go-mode nil 66 "function.outer" 55 t nil 'go-nested)
(evil-textobj-tree-sitter--goto-test 'go-ts-mode t 66 "function.outer" 55 t nil 'go-nested))
(ert-deftest evil-textobj-tree-sitter-goto-previous-start-nested-3 ()
"Go to previous nested complex test."
(evil-textobj-tree-sitter--goto-test 'python-mode nil 71 "function.outer" 49 t nil 'py-complex)
(evil-textobj-tree-sitter--goto-test 'python-ts-mode t 71 "function.outer" 49 t nil 'py-complex))
;;; `thing-at-point' tests
(defun evil-textobj-tree-sitter--thing-at-point-test (mode treesit start thing content selection range)
"Check ranges of tree-sitter targets.
`MODE' is the `major-mode' to be used.
`TREESIT' non nil will use `treesit'.
`CONTENT' is the content to be used.
`START' is the starting position.
`THING' is the thing to select.
`SELECTION' is the selection that `thing-at-point' will return."
(let* ((bufname (make-temp-name "evil-textobj-tree-sitter-test--"))
(buffer (get-buffer-create bufname)))
(with-current-buffer buffer
(insert (alist-get content evil-textobj-tree-sitter--test-file-content))
(funcall mode)
(if (not treesit) (tree-sitter-mode))
(goto-char start)
(should (equal (thing-at-point thing t) selection))
(should (equal (bounds-of-thing-at-point thing) range)))
(kill-buffer bufname)))
(ert-deftest evil-textobj-tree-sitter-thing-at-point ()
"Check if `thing-at-point' returns correct result."
(let ((selection "int main() {
printf(\"hello\")
}"))
(evil-textobj-tree-sitter--thing-at-point-test 'c-mode nil 31 'function 'c-unicode selection (cons 11 45))
(evil-textobj-tree-sitter--thing-at-point-test 'c-ts-mode t 31 'function 'c-unicode selection (cons 11 45))))
(ert-deftest evil-textobj-tree-sitter-no-error-without-parser ()
"Check that operations gracefully return nil when tree-sitter is unavailable."
(let* ((bufname (make-temp-name "evil-textobj-tree-sitter-test--"))
(buffer (get-buffer-create bufname)))
(with-current-buffer buffer
(insert "some text without a tree-sitter parser")
(fundamental-mode)
;; Should not error, just return nil
(goto-char 1)
(should (equal (evil-textobj-tree-sitter--range 1 '(function.outer)) nil))
(should (equal (evil-textobj-tree-sitter--get-goto-location
'(function.outer) nil nil nil) nil)))
(kill-buffer buffer)))
(ert-deftest evil-textobj-tree-sitter-within-leaf-selects-smallest ()
"Check that leaf text object selects smallest node when multiple overlap.
Uses the treesit path where the bug manifests: treesit returns nodes
outermost-first, so the buggy comparator (which ignored end positions)
preserved the wrong order and selected the block (71,126) instead of
the identifier (71,75)."
(let* ((bufname (make-temp-name "evil-textobj-tree-sitter-test--"))
(buffer (get-buffer-create bufname))
(leaf-query '((python-ts-mode . "(_) @leaf"))))
(with-current-buffer buffer
(insert (alist-get 'py-complex evil-textobj-tree-sitter--test-file-content))
(python-ts-mode)
;; Position 71 is the start of `var2` inside `nested()`. Both the
;; identifier node (71,75) and the enclosing block node (71,126) share
;; the same start position, which exercises the sort comparator bug
;; where (car (last x)) was used for both operands. The expected
;; range (71 . 75) is the smallest node — the `var2` identifier.
(goto-char 71)
(should (equal (evil-textobj-tree-sitter--range 1 '(leaf) leaf-query)
(cons 71 75))))
(kill-buffer buffer)))
;;; evil-textobj-tree-sitter-test.el ends here
================================================
FILE: evil-textobj-tree-sitter-thing-at-point.el
================================================
;;; evil-textobj-tree-sitter-thing-at-point.el --- Provides thing-at-point integration for tree-sitter textobjects -*- lexical-binding: t; -*-
;; URL: https://github.com/meain/evil-textobj-tree-sitter
;; Keywords: evil, tree-sitter, text-object, convenience
;; SPDX-License-Identifier: Apache-2.0
;; Package-Requires: ((emacs "25.1"))
;; Version: 0.5
;;; Commentary:
;; This adds `thing-at-point' things powered by tree-sitter.
;; Suggestion for package which could help improve the use for this
;; https://github.com/plandes/mark-thing-at
;;; Code:
(require 'thingatpt)
(require 'evil-textobj-tree-sitter-core)
(defun evil-textobj-tree-sitter--thing-at-point-bounds (group)
"Return the bounds of the `GROUP' at point."
(when-let* ((entity (evil-textobj-tree-sitter--get-within (list (intern group)) 1 nil))
(pos (cdr (car entity))))
(cons (car pos) (cadr pos))))
(put 'function 'bounds-of-thing-at-point (lambda () (evil-textobj-tree-sitter--thing-at-point-bounds "function.outer")))
(put 'loop 'bounds-of-thing-at-point (lambda () (evil-textobj-tree-sitter--thing-at-point-bounds "loop.outer")))
(put 'conditional 'bounds-of-thing-at-point (lambda () (evil-textobj-tree-sitter--thing-at-point-bounds "conditional.outer")))
(put 'assignment 'bounds-of-thing-at-point (lambda () (evil-textobj-tree-sitter--thing-at-point-bounds "assignment.outer")))
(put 'class 'bounds-of-thing-at-point (lambda () (evil-textobj-tree-sitter--thing-at-point-bounds "class.outer")))
(put 'comment 'bounds-of-thing-at-point (lambda () (evil-textobj-tree-sitter--thing-at-point-bounds "comment.outer")))
(put 'parameter 'bounds-of-thing-at-point (lambda () (evil-textobj-tree-sitter--thing-at-point-bounds "parameter.outer")))
;;;###autoload
(defun function-at-point ()
"Return the function at point, or nil if none is found."
(thing-at-point 'function))
;;;###autoload
(defun loop-at-point ()
"Return the loop at point, or nil if none is found."
(thing-at-point 'loop))
;;;###autoload
(defun conditional-at-point ()
"Return the conditional at point, or nil if none is found."
(thing-at-point 'conditional))
;;;###autoload
(defun assignment-at-point ()
"Return the assignment at point, or nil if none is found."
(thing-at-point 'assignment))
;;;###autoload
(defun class-at-point ()
"Return the class at point, or nil if none is found."
(thing-at-point 'class))
;;;###autoload
(defun comment-at-point ()
"Return the comment at point, or nil if none is found."
(thing-at-point 'comment))
;;;###autoload
(defun parameter-at-point ()
"Return the parameter at point, or nil if none is found."
(thing-at-point 'parameter))
(provide 'evil-textobj-tree-sitter-thing-at-point)
;;; evil-textobj-tree-sitter-thing-at-point.el ends here
================================================
FILE: evil-textobj-tree-sitter.el
================================================
;;; evil-textobj-tree-sitter.el --- Provides evil textobjects using tree-sitter -*- lexical-binding: t; -*-
;; URL: https://github.com/meain/evil-textobj-tree-sitter
;; Keywords: evil, tree-sitter, text-object, convenience
;; SPDX-License-Identifier: Apache-2.0
;; Package-Requires: ((emacs "25.1"))
;; Version: 0.5
;;; Commentary:
;; This package is a port of nvim-treesitter/nvim-treesitter-textobjects.
;; This package will let you create evil textobjects using the power
;; of tree-sitter grammars. You can easily create
;; function,class,comment etc textobjects in multiple languages.
;;
;; You can do a sample map like below to create a function textobj.
;; (define-key evil-outer-text-objects-map "f"
;; (evil-textobj-tree-sitter-get-textobj "function.outer"))
;; `evil-textobj-tree-sitter-get-textobj' will return you a function
;; that you can use in a define-key map. You can pass in any of the
;; supported queries as an arg of that function. You can also pass in
;; multiple queries as a list and we will match on all of them, ranked
;; on which ones comes up first in the file.
;; You can find more info in the README.md file at
;; https://github.com/meain/evil-textobj-tree-sitter
;; This package also provides with thing-at-point functions for common
;; textobjects like functions, loops, conditionals etc.
;; You need to either have elisp-tree-sitter installed or have Emacs
;; version >=29 for this package to work.
;;; Code:
(require 'evil-textobj-tree-sitter-core)
(require 'evil-textobj-tree-sitter-thing-at-point)
(provide 'evil-textobj-tree-sitter)
;;; evil-textobj-tree-sitter.el ends here
================================================
FILE: fixtures/bash/textobjects.scm
================================================
(function_definition
(_) @function.inner ) @function.outer
(case_statement) @conditional.outer
(if_statement
(_) @conditional.inner ) @conditional.outer
(for_statement
(_) @loop.inner ) @loop.outer
(while_statement
(_) @loop.inner ) @loop.outer
(comment) @comment.outer
================================================
FILE: fixtures/javascript/textobjects.scm
================================================
; inherits: (jsx)
(function_declaration
body: (statement_block) @function.inner) @function.outer
(export_statement
(function_declaration) @function.outer) @function.outer.start
================================================
FILE: fixtures/tsx/textobjects.scm
================================================
; inherits: typescript,jsx
================================================
FILE: fixtures/typescript/textobjects.scm
================================================
; inherits: (javascript)
================================================
FILE: fixtures/zig/textobjects.scm
================================================
;; "Classes"
(VarDecl
(_ (_ (ContainerDecl (ContainerMembers)? @class.inner)))) @class.outer
;; functions
(_
(FnProto)
(Block) @function.inner) @function.outer
================================================
FILE: flake.nix
================================================
{
description = "evil-textobj-tree-sitter development environment";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
};
outputs = { self, nixpkgs }:
let
forAllSystems = nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
in
{
devShells = forAllSystems (system:
let
pkgs = nixpkgs.legacyPackages.${system};
# Wrapper that sets GIT_DIR/GIT_WORK_TREE for jj repos so
# tree-sitter-langs can find the git repo during eask install-deps
eask-jj = pkgs.writeShellScriptBin "eask" ''
if [ -z "''${GIT_DIR:-}" ] && command -v jj >/dev/null 2>&1 && jj root >/dev/null 2>&1; then
export GIT_DIR="$(jj root)/.jj/repo/store/git"
export GIT_WORK_TREE="$(jj root)"
fi
exec ${pkgs.eask-cli}/bin/eask "$@"
'';
in
{
default = pkgs.mkShell {
buildInputs = [
pkgs.emacs
eask-jj
pkgs.go
pkgs.gcc
];
};
});
};
}
================================================
FILE: queries/apex/textobjects.scm
================================================
(class_declaration
body: (class_body) @class.inner) @class.outer
(method_declaration) @function.outer
(method_declaration
body: (block
.
"{"
_+ @function.inner
"}"))
(constructor_declaration) @function.outer
(constructor_declaration
body: (constructor_body
.
"{"
_+ @function.inner
"}"))
(for_statement
body: (_)? @loop.inner) @loop.outer
(enhanced_for_statement
body: (_)? @loop.inner) @loop.outer
(while_statement
body: (_)? @loop.inner) @loop.outer
(do_statement
body: (_)? @loop.inner) @loop.outer
(if_statement
condition: (_
(parenthesized_expression) @conditional.inner) @conditional.outer)
(if_statement
consequence: (_)? @conditional.inner
alternative: (_)? @conditional.inner) @conditional.outer
(switch_expression
body: (_)? @conditional.inner) @conditional.outer
; blocks
(block) @block.outer
(method_invocation) @call.outer
(method_invocation
arguments: (argument_list
.
"("
_+ @call.inner
")"))
; parameters
(formal_parameters
"," @parameter.outer
.
(formal_parameter) @parameter.inner @parameter.outer)
(formal_parameters
.
(formal_parameter) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(argument_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(argument_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
[
(line_comment)
(block_comment)
] @comment.outer
; assignment
(variable_declarator
name: (identifier) @assignment.lhs
value: (_) @assignment.rhs) @assignment.inner @assignment.outer
================================================
FILE: queries/astro/textobjects.scm
================================================
; inherits: html
================================================
FILE: queries/bash/textobjects.scm
================================================
(function_definition) @function.outer
(function_definition
body: (compound_statement
.
"{"
_+ @function.inner
"}"))
(case_statement) @conditional.outer
(if_statement
(_) @conditional.inner) @conditional.outer
(for_statement
(_) @loop.inner) @loop.outer
(while_statement
(_) @loop.inner) @loop.outer
(comment) @comment.outer
(regex) @regex.inner
((word) @number.inner
(#match? @number.inner "^[0-9]+$"))
(variable_assignment) @assignment.outer
(variable_assignment
name: (_) @assignment.inner @assignment.lhs)
(variable_assignment
value: (_) @assignment.inner @assignment.rhs)
(command
argument: (word) @parameter.inner)
================================================
FILE: queries/bibtex/textobjects.scm
================================================
(entry) @block.outer
(field) @statement.outer
================================================
FILE: queries/c/textobjects.scm
================================================
(declaration
declarator: (function_declarator)) @function.outer
(function_definition
body: (compound_statement)) @function.outer
(function_definition
body: (compound_statement
.
"{"
_+ @function.inner
"}"))
(struct_specifier
body: (_) @class.inner) @class.outer
(enum_specifier
body: (_) @class.inner) @class.outer
; conditionals
(if_statement
consequence: (compound_statement
.
"{"
_+ @conditional.inner
"}")) @conditional.outer
(if_statement
alternative: (else_clause
(compound_statement
.
"{"
_+ @conditional.inner
"}"))) @conditional.outer
(if_statement) @conditional.outer
(if_statement
condition: (_) @conditional.inner)
(while_statement
condition: (_) @conditional.inner)
(do_statement
condition: (_) @conditional.inner)
(for_statement
condition: (_) @conditional.inner)
; loops
(while_statement) @loop.outer
(while_statement
body: (compound_statement
.
"{"
_+ @loop.inner
"}")) @loop.outer
(for_statement) @loop.outer
(for_statement
body: (compound_statement
.
"{"
_+ @loop.inner
"}")) @loop.outer
(do_statement) @loop.outer
(do_statement
body: (compound_statement
.
"{"
_+ @loop.inner
"}")) @loop.outer
(compound_statement) @block.outer
(comment) @comment.outer
(call_expression) @call.outer
(call_expression
arguments: (argument_list
.
"("
_+ @call.inner
")"))
(return_statement
(_)? @return.inner) @return.outer
; Statements
;(expression_statement ;; this is what we actually want to capture in most cases (";" is missing) probably
;(_) @statement.inner) ;; the other statement like node type is declaration but declaration has a ";"
(compound_statement
(_) @statement.outer)
(field_declaration_list
(_) @statement.outer)
(preproc_if
(_) @statement.outer)
(preproc_elif
(_) @statement.outer)
(preproc_else
(_) @statement.outer)
(parameter_list
"," @parameter.outer
.
(parameter_declaration) @parameter.inner @parameter.outer)
(parameter_list
.
(parameter_declaration) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(argument_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(argument_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(number_literal) @number.inner
(declaration
declarator: (init_declarator
declarator: (_) @assignment.lhs
value: (_) @assignment.rhs) @assignment.inner) @assignment.outer
(declaration
type: (primitive_type)
declarator: (_) @assignment.inner)
(expression_statement
(assignment_expression
left: (_) @assignment.lhs
right: (_) @assignment.rhs) @assignment.inner) @assignment.outer
================================================
FILE: queries/c_sharp/textobjects.scm
================================================
(class_declaration
body: (declaration_list
.
"{"
_* @class.inner
"}")) @class.outer
(struct_declaration
body: (declaration_list
.
"{"
_* @class.inner
"}")) @class.outer
(record_declaration
body: (declaration_list
.
"{"
_* @class.inner
"}")) @class.outer
(interface_declaration
body: (declaration_list
.
"{"
_+ @class.inner
"}")) @class.outer
(enum_declaration
body: (enum_member_declaration_list
.
"{"
_* @class.inner
"}")) @class.outer
(method_declaration
body: (block
.
"{"
_* @function.inner
"}")) @function.outer
(method_declaration
body: (arrow_expression_clause
"=>"
_+ @function.inner)) @function.outer
; method without body(abstract method/decompiled metadata)
(method_declaration
_+
";") @function.outer
(property_declaration
accessors: (accessor_list
(accessor_declaration
body: (block
.
"{"
_* @function.inner
"}")) @function.outer))
(property_declaration
accessors: (accessor_list
(accessor_declaration
body: (arrow_expression_clause
"=>"
_* @function.inner)) @function.outer))
(indexer_declaration
accessors: (accessor_list
(accessor_declaration
body: (arrow_expression_clause
"=>"
_+ @function.inner)) @function.outer))
(indexer_declaration
accessors: (accessor_list
(accessor_declaration
body: (block
.
"{"
_* @function.inner
"}")) @function.outer))
(conversion_operator_declaration
body: (block
.
"{"
_* @function.inner
"}")) @function.outer
(conversion_operator_declaration
body: (arrow_expression_clause
"=>"
_+ @function.inner)) @function.outer
(operator_declaration
body: (block
.
"{"
_* @function.inner
"}")) @function.outer
; operator without body(abstract/decompiled metadata)
(operator_declaration
_+
";") @function.outer
(operator_declaration
body: (arrow_expression_clause
"=>"
_+ @function.inner)) @function.outer
(constructor_declaration
body: (block
.
"{"
_* @function.inner
"}")) @function.outer
; constructor without body(metadata)
(constructor_declaration
_+
";") @function.outer
(local_function_statement
body: (block
.
"{"
_* @function.inner
"}")) @function.outer
(local_function_statement
body: (arrow_expression_clause
"=>"
_+ @function.inner)) @function.outer
(anonymous_method_expression
(block
.
"{"
_* @function.inner
"}")) @function.outer
(lambda_expression
body: (block
.
"{"
_+ @function.inner
"}")) @function.outer
; loops
(for_statement
body: (_) @loop.inner) @loop.outer
(foreach_statement
body: (_) @loop.inner) @loop.outer
(do_statement
(block) @loop.inner) @loop.outer
(while_statement
(block) @loop.inner) @loop.outer
; conditionals
(if_statement
consequence: (_)? @conditional.inner
alternative: (_)? @conditional.inner) @conditional.outer
(switch_statement
body: (switch_body) @conditional.inner) @conditional.outer
; calls
(invocation_expression) @call.outer
(invocation_expression
arguments: (argument_list
.
"("
_+ @call.inner
")"))
; blocks
(_
(block) @block.inner) @block.outer
; parameters
(parameter_list
"," @parameter.outer
.
(parameter) @parameter.inner @parameter.outer)
(parameter_list
.
(parameter) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(argument_list
"," @parameter.outer
.
(argument) @parameter.inner @parameter.outer)
(argument_list
.
(argument) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; comments
(comment) @comment.outer
================================================
FILE: queries/cmake/textobjects.scm
================================================
(function_def) @function.outer
(function_def
.
(function_command)
_+ @function.inner
(endfunction_command) .)
(if_condition) @conditional.outer
(if_condition
.
(if_command)
_+ @conditional.inner
(endif_command) .)
(foreach_loop) @loop.outer
(foreach_loop
.
(foreach_command)
_+ @loop.inner
(endforeach_command) .)
(normal_command) @call.outer
(normal_command
"("
_+ @call.inner
")")
(line_comment) @comment.outer
================================================
FILE: queries/cpp/textobjects.scm
================================================
; inherits: c
(class_specifier
body: (_) @class.inner) @class.outer
(field_declaration
type: (enum_specifier)
default_value: (initializer_list) @class.inner) @class.outer
(for_range_loop) @loop.outer
(for_range_loop
body: (compound_statement
.
"{"
_+ @loop.inner
"}"))
(template_declaration
(function_definition)) @function.outer
(template_declaration
(struct_specifier)) @class.outer
(template_declaration
(class_specifier)) @class.outer
(lambda_capture_specifier
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(lambda_capture_specifier
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(template_argument_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(template_argument_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(template_parameter_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(template_parameter_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(parameter_list
"," @parameter.outer
.
(optional_parameter_declaration) @parameter.inner @parameter.outer)
(parameter_list
.
(optional_parameter_declaration) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(initializer_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(initializer_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(new_expression
(argument_list) @call.inner) @call.outer
================================================
FILE: queries/css/textobjects.scm
================================================
[
(integer_value)
(float_value)
(color_value)
] @number.inner
(declaration
(property_name) @assignment.lhs
.
":"
_+ @assignment.inner @assignment.rhs
";") @assignment.outer
(declaration
(property_name) @assignment.inner)
(comment) @comment.outer
================================================
FILE: queries/cuda/textobjects.scm
================================================
; inherits: cpp
================================================
FILE: queries/dart/textobjects.scm
================================================
; class
((annotation)? @class.outer
.
(class_definition
body: (class_body) @class.inner) @class.outer)
(mixin_declaration
(class_body) @class.inner) @class.outer
(enum_declaration
body: (enum_body) @class.inner) @class.outer
(extension_declaration
body: (extension_body) @class.inner) @class.outer
; function/method
((annotation)? @function.outer
.
[
(method_signature)
(function_signature)
] @function.outer
.
(function_body) @function.outer)
(function_body
(block
.
"{"
_+ @function.inner
"}"))
(type_alias
(function_type)? @function.inner) @function.outer
; parameter
[
(formal_parameter)
(normal_parameter_type)
(type_parameter)
] @parameter.inner
("," @parameter.outer
.
[
(formal_parameter)
(normal_parameter_type)
(type_parameter)
] @parameter.outer)
([
(formal_parameter)
(normal_parameter_type)
(type_parameter)
] @parameter.outer
.
"," @parameter.outer)
; TODO: (_)* not supported yet -> for now this works correctly only with simple arguments
(arguments
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(arguments
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
; call
((identifier) @call.outer
.
(selector
(argument_part) @call.outer))
((identifier)
.
(selector
(argument_part
(arguments
.
"("
_+ @call.inner
")"))))
; block
(block) @block.outer
; conditional
(if_statement
[
condition: (_)
consequence: (_)
alternative: (_)?
] @conditional.inner) @conditional.outer
(switch_statement
body: (switch_block) @conditional.inner) @conditional.outer
(conditional_expression
[
consequence: (_)
alternative: (_)
] @conditional.inner) @conditional.outer
; loop
(for_statement
body: (block) @loop.inner) @loop.outer
(while_statement
body: (block) @loop.inner) @loop.outer
(do_statement
body: (block) @loop.inner) @loop.outer
; comment
[
(comment)
(documentation_comment)
] @comment.outer
; statement
[
(break_statement)
(do_statement)
(expression_statement)
(for_statement)
(if_statement)
(return_statement)
(switch_statement)
(while_statement)
(assert_statement)
;(labeled_statement)
(yield_statement)
(yield_each_statement)
(continue_statement)
(try_statement)
] @statement.outer
================================================
FILE: queries/dockerfile/textobjects.scm
================================================
(expose_instruction
(expose_port) @number.inner)
================================================
FILE: queries/ecma/textobjects.scm
================================================
(function_declaration
body: (statement_block)) @function.outer
(generator_function_declaration
body: (statement_block)) @function.outer
(function_expression
body: (statement_block)) @function.outer
(function_declaration
body: (statement_block
.
"{"
_+ @function.inner
"}"))
(generator_function_declaration
body: (statement_block
.
"{"
_+ @function.inner
"}"))
(function_expression
body: (statement_block
.
"{"
_+ @function.inner
"}"))
(export_statement
(function_declaration)) @function.outer
(arrow_function
body: (_) @function.inner) @function.outer
(arrow_function
body: (statement_block
.
"{"
_+ @function.inner
"}"))
(method_definition
body: (statement_block)) @function.outer
(method_definition
body: (statement_block
.
"{"
_+ @function.inner
"}"))
(class_declaration
body: (class_body)) @class.outer
(class_declaration
body: (class_body
.
"{"
_+ @class.inner
"}"))
(export_statement
(class_declaration)) @class.outer
(for_in_statement
body: (statement_block
.
"{"
_+ @loop.inner
"}")) @loop.outer
(for_statement
body: (statement_block
.
"{"
_+ @loop.inner
"}")) @loop.outer
(while_statement
body: (statement_block
.
"{"
_+ @loop.inner
"}")) @loop.outer
(do_statement
body: (statement_block
.
"{"
_+ @loop.inner
"}")) @loop.outer
(if_statement
consequence: (statement_block
.
"{"
_+ @conditional.inner
"}")) @conditional.outer
(if_statement
alternative: (else_clause
(statement_block
.
"{"
_+ @conditional.inner
"}"))) @conditional.outer
(if_statement) @conditional.outer
(switch_statement
body: (_)? @conditional.inner) @conditional.outer
(call_expression) @call.outer
(call_expression
arguments: (arguments
.
"("
_+ @call.inner
")"))
(new_expression
constructor: (identifier) @call.outer
arguments: (arguments
.
"("
_+ @call.inner
")") @call.outer)
; blocks
(statement_block
(_)* @block.inner) @block.outer
; parameters
; function ({ x }) ...
; function ([ x ]) ...
; function (v = default_value)
(formal_parameters
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(formal_parameters
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; last element with trailing comma
(formal_parameters
(_) @parameter.outer
.
"," @parameter.outer .)
; If the array/object pattern is the first parameter, treat its elements as the argument list
(formal_parameters
.
(_
[
(object_pattern
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(array_pattern
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
]))
(formal_parameters
.
(_
[
(object_pattern
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(array_pattern
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
]))
; last element with trailing comma
(formal_parameters
.
(_
[
(object_pattern
(_) @parameter.outer
.
"," @parameter.outer .)
(array_pattern
(_) @parameter.outer
.
"," @parameter.outer .)
]))
; arguments
(arguments
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(arguments
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; last element with trailing comma
(arguments
(_) @parameter.outer
.
"," @parameter.outer .)
; comment
(comment) @comment.outer
; regex
(regex
(regex_pattern) @regex.inner) @regex.outer
; number
(number) @number.inner
(lexical_declaration
(variable_declarator
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs)) @assignment.outer
(variable_declarator
name: (_) @assignment.inner)
(object
(pair
key: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer)
(return_statement
(_) @return.inner) @return.outer
(return_statement) @statement.outer
[
(if_statement)
(expression_statement)
(for_statement)
(while_statement)
(do_statement)
(for_in_statement)
(export_statement)
(lexical_declaration)
] @statement.outer
; 1. default import
(import_statement
(import_clause
(identifier) @parameter.inner @parameter.outer))
; 2. namespace import e.g. `* as React`
(import_statement
(import_clause
(namespace_import
(identifier) @parameter.inner) @parameter.outer))
; 3. named import e.g. `import { Bar, Baz } from ...`
(import_statement
(import_clause
(named_imports
(import_specifier) @parameter.inner)))
; 3‑A. named import followed by a comma
(import_statement
(import_clause
(named_imports
(import_specifier) @parameter.outer
.
"," @parameter.outer)))
; 3‑B. comma followed by named import
(import_statement
(import_clause
(named_imports
"," @parameter.outer
.
(import_specifier) @parameter.outer)))
; 3-C. only one named import without a comma
(import_statement
(import_clause
(named_imports
.
(import_specifier) @parameter.outer .)))
; Treat list or object elements as @parameter
; 1. parameter.inner
(object
(_) @parameter.inner)
(array
(_) @parameter.inner)
(object_pattern
(_) @parameter.inner)
(array_pattern
(_) @parameter.inner)
; 2. parameter.outer: Only one element, no comma
(object
.
(_) @parameter.outer .)
(array
.
(_) @parameter.outer .)
(object_pattern
.
(_) @parameter.outer .)
(array_pattern
.
(_) @parameter.outer .)
; 3. parameter.outer: Comma before or after
[
(object
"," @parameter.outer
.
(_) @parameter.outer)
(array
"," @parameter.outer
.
(_) @parameter.outer)
(object_pattern
"," @parameter.outer
.
(_) @parameter.outer)
(array_pattern
"," @parameter.outer
.
(_) @parameter.outer)
]
[
(object
.
(_) @parameter.outer
.
"," @parameter.outer)
(array
.
(_) @parameter.outer
.
"," @parameter.outer)
(object_pattern
.
(_) @parameter.outer
.
"," @parameter.outer)
(array_pattern
.
(_) @parameter.outer
.
"," @parameter.outer)
]
================================================
FILE: queries/elixir/textobjects.scm
================================================
; Block Objects
([
(do_block
"do"
_+ @block.inner
"end")
(do_block
"do"
.
((_) @block.inner) @block.inner
.
"end")
]) @block.outer
; Class Objects (Modules, Protocols)
; multiple children
(call
target: ((identifier) @_identifier
(#match? @_identifier "^(defmodule|defprotocol|defimpl)$"))
(arguments
(alias))
(do_block
"do"
_+ @class.inner
"end")) @class.outer
; single child match
(call
target: ((identifier) @_identifier
(#match? @_identifier "^(defmodule|defprotocol|defimpl)$"))
(arguments
(alias))
(do_block
"do"
.
(_) @class.inner
.
"end")) @class.outer
; Function, Parameter, and Call Objects
(anonymous_function
(stab_clause
right: (body) @function.inner)) @function.outer
(call
target: ((identifier) @_identifier
(#match? @_identifier "^(def|defmacro|defmacrop|defn|defnp|defp)$"))
(arguments
[
(call
[
(arguments
(_) @parameter.inner @parameter.outer
.
"," @parameter.outer)
(arguments
((_) @parameter.inner @parameter.outer) @parameter.outer .)
])
(binary_operator
left: (call
[
(arguments
(_) @parameter.inner @parameter.outer
.
"," @parameter.outer)
(arguments
((_) @parameter.inner @parameter.outer) @parameter.outer .)
]))
])
[
(do_block
"do"
_+ @function.inner
"end")
(do_block
"do"
.
((_) @function.inner) @function.inner
.
"end")
]) @function.outer
(call
target: ((identifier) @_identifier
(#match? @_identifier "^(def|defmacro|defmacrop|defn|defnp|defp)$"))
(arguments
[
(identifier)
(binary_operator
(identifier))
])
[
(do_block
"do"
_+ @function.inner
"end")
(do_block
"do"
.
((_) @function.inner) @function.inner
.
"end")
]) @function.outer
(call
target: ((identifier) @_identifier
(#match? @_identifier "^(def|defmacro|defmacrop|defn|defnp|defp)$"))
(arguments
[
(call
[
(arguments
(_) @parameter.inner @parameter.outer
.
"," @parameter.outer)
(arguments
((_) @parameter.inner @parameter.outer) @parameter.outer .)
])
(binary_operator
left: (call
[
(arguments
(_) @parameter.inner @parameter.outer
.
"," @parameter.outer)
(arguments
((_) @parameter.inner @parameter.outer) @parameter.outer .)
]))
]
(keywords
(pair
value: (_) @function.inner)))) @function.outer
(call
target: ((identifier) @_identifier
(#match? @_identifier "^(def|defmacro|defmacrop|defn|defnp|defp)$"))
(arguments
[
(identifier)
(binary_operator
(identifier))
]
(keywords
(pair
value: (_) @function.inner)))) @function.outer
; Comment Objects
(comment) @comment.outer
; Documentation Objects
(unary_operator
operator: "@"
operand: (call
target: ((identifier) @_identifier
(#match? @_identifier "^(moduledoc|typedoc|shortdoc|doc)$"))
(arguments
[
; attributes style documentation
; @doc deprecated: "...."
(keywords) @comment.inner
; heredoc style documentation
; @moduledoc """"""
(string
(quoted_content) @comment.inner)
]))) @comment.outer
; Regex Objects
(sigil
(quoted_content) @regex.inner) @regex.outer
================================================
FILE: queries/elm/textobjects.scm
================================================
; Functions
; top level function with type annotation and doc comment
((module_declaration)
(block_comment) @function.outer
.
(type_annotation)
.
(value_declaration
body: (_)? @function.inner) @function.outer)
; top level function with type annotation
((module_declaration)
(type_annotation) @function.outer
.
(value_declaration
body: (_)? @function.inner) @function.outer)
; top level function without type annotation
((module_declaration)
(value_declaration
body: (_)? @function.inner) @function.outer)
; Comments
[
(block_comment)
(line_comment)
] @comment.outer
; Conditionals
(if_else_expr
exprList: (_)
exprList: (_) @conditional.inner) @conditional.outer
(case_of_expr
branch: (case_of_branch) @conditional.inner) @conditional.outer
; Parameters
; type annotations
(type_expression
(arrow) @parameter.outer
.
(type_ref) @parameter.inner @parameter.outer)
(type_expression
.
(type_ref) @parameter.inner @parameter.outer
.
(arrow)? @parameter.outer)
; list items
(list_expr
"," @parameter.outer
.
exprList: (_) @parameter.inner @parameter.outer)
(list_expr
.
exprList: (_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; tuple items
(tuple_expr
"," @parameter.outer
.
expr: (_) @parameter.inner @parameter.outer)
(tuple_expr
.
expr: (_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
================================================
FILE: queries/enforce/textobjects.scm
================================================
[
(comment_line)
(comment_block)
(doc_line)
(doc_block)
] @comment.outer
[
(literal_int)
(literal_float)
] @number.inner
; TODO: capture inside braces
(decl_class
body: (_) @class.inner) @class.outer
(decl_method
body: (_) @function.inner) @function.outer
(for
body: (_) @loop.inner) @loop.outer
(while
body: (_) @loop.inner) @loop.outer
(return
(_)? @return.inner) @return.outer
; blocks
(block) @block.outer
(invokation) @call.outer
(formal_parameters
"," @parameter.outer
.
(formal_parameter) @parameter.inner @parameter.outer)
(formal_parameters
.
(formal_parameter) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(actual_parameters
"," @parameter.outer
.
(actual_parameter) @parameter.inner @parameter.outer)
(actual_parameters
.
(actual_parameter) @parameter.inner @parameter.outer
.
","? @parameter.outer)
================================================
FILE: queries/fennel/textobjects.scm
================================================
; https://fennel-lang.org/reference
(comment
body: (comment_body) @comment.inner) @comment.outer
(_
.
"("
")" .) @statement.outer
; functions
; NOTE: Doesn't capture the comments before the first `item` field
(fn_form
[
(table_metadata)
(docstring)
]
.
item: (_) @function.inner
(_)? @function.inner
.
close: _ .)
(fn_form
args: (_)
.
item: (_) @function.inner
(_)? @function.inner
.
close: _ .)
(lambda_form
[
(table_metadata)
(docstring)
]
.
item: (_) @function.inner
(_)? @function.inner
.
close: _ .)
(lambda_form
args: (_)
.
item: (_) @function.inner
(_)? @function.inner
.
close: _ .)
(macro_form
[
(table_metadata)
(docstring)
]
.
item: (_) @function.inner
(_)? @function.inner
.
close: _ .)
(macro_form
args: (_)
.
item: (_) @function.inner
(_)? @function.inner
.
close: _ .)
[
(fn_form)
(lambda_form)
(macro_form)
] @function.outer
; function arguments
(sequence_arguments
item: (_) @parameter.inner) @parameter.outer
; call
(list
call: (symbol) @_fn_name
item: (_) @call.inner
(_) @call.inner
.
close: _
(#not-eq? @_fn_name "do")
(#not-eq? @_fn_name "while")
(#not-eq? @_fn_name "when")) @call.outer
; assignment
(local_form
(binding_pair
lhs: (_) @assignment.lhs
rhs: (_) @assignment.rhs) @assignment.inner) @assignment.outer
(var_form
(binding_pair
lhs: (_) @assignment.lhs
rhs: (_) @assignment.rhs) @assignment.inner) @assignment.outer
(global_form
(binding_pair
lhs: (_) @assignment.lhs
rhs: (_) @assignment.rhs) @assignment.inner) @assignment.outer
(set_form
lhs: (_) @assignment.lhs @assignment.inner
rhs: (_) @assignment.rhs @assignment.inner) @assignment.outer
(let_vars
(binding_pair
lhs: (_) @assignment.lhs
rhs: (_) @assignment.rhs) @assignment.inner) @assignment.outer
; conditionals
(if_form
(if_pair
expression: (_) @conditional.inner)) @conditional.outer
(if_form
else: (_) @conditional.inner) @conditional.outer
(list
call: (symbol) @_cond
.
item: (_)
item: (_)* @conditional.inner
(#eq? @_cond "when")) @conditional.outer
; loops
(each_form
iter_body: (_)
_+ @loop.inner
close: _)
(each_form) @loop.outer
(collect_form
iter_body: (_)
_+ @loop.inner
close: _)
(collect_form) @loop.outer
(icollect_form
iter_body: (_)
_+ @loop.inner
close: _)
(icollect_form) @loop.outer
(accumulate_form
iter_body: (_)
_+ @loop.inner
close: _)
(accumulate_form) @loop.outer
(for_form
iter_body: (_)
_+ @loop.inner
close: _)
(for_form) @loop.outer
(fcollect_form
iter_body: (_)
_+ @loop.inner
close: _)
(fcollect_form) @loop.outer
(faccumulate_form
iter_body: (_)
_+ @loop.inner
close: _)
(faccumulate_form) @loop.outer
(list
call: (symbol) @_sym
.
item: (_)
item: (_)* @loop.inner
(#eq? @_sym "while"))
(list
call: (symbol) @_sym
(#eq? @_sym "while")) @loop.outer
================================================
FILE: queries/fish/textobjects.scm
================================================
; assignment
(command
name: (word) @_command
argument: (word) @_varname @assignment.lhs @assignment.inner
argument: (_)* @assignment.rhs
(#not-match? @_varname "^[-].*")
(#eq? @_command "set")) @assignment.outer
(command
name: (word) @_name
argument: (_)* @assignment.inner
(#eq? @_name "set"))
; block
([
(case_clause)
(if_statement)
(switch_statement)
(else_clause)
(for_statement)
(while_statement)
]) @block.outer
; call
; call.inner doesn't work because it can't select *all* arguments
(command) @call.outer
; comment
; leave space after comment marker if there is one
((comment) @comment.inner @comment.outer
(#match? @comment.outer "# .*"))
; else remove everything accept comment marker
((comment) @comment.inner @comment.outer)
; conditional
(if_statement
(command) @conditional.inner) @conditional.outer
(switch_statement
(_) @conditional.inner) @conditional.outer
; function
((function_definition) @function.inner @function.outer)
; loop
(for_statement
(_) @loop.inner) @loop.outer
(while_statement
condition: (command)
(command) @loop.inner) @loop.outer
; number
[
(integer)
(float)
] @number.inner
; parameter
(command
argument: (_) @parameter.outer)
; return
(return
(_) @return.inner) @return.outer
; statement
(command) @statement.outer
================================================
FILE: queries/foam/textobjects.scm
================================================
(dict) @class.outer
(dict_core) @class.inner
(key_value
value: _? @function.inner
(_)* @function.inner
_? @parameter.inner @function.inner) @function.outer
(code
(_)* @class.inner) @class.outer
(comment)+ @comment.outer
(comment) @comment.inner
================================================
FILE: queries/gdscript/textobjects.scm
================================================
(function_definition
body: (_) @function.inner) @function.outer
(constructor_definition
body: (_) @function.inner) @function.outer
(class_definition
body: (_) @class.inner) @class.outer
(if_statement
body: (_) @conditional.inner) @conditional.outer
(if_statement
alternative: (_
(_) @conditional.inner)?) @conditional.outer
(if_statement
condition: (_) @conditional.inner)
[
(for_statement)
(while_statement)
] @loop.outer
(while_statement
body: (_) @loop.inner)
(for_statement
body: (_) @loop.inner)
(comment) @comment.outer
(parameters
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(parameters
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(arguments
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(arguments
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(array
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(array
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
================================================
FILE: queries/git_config/textobjects.scm
================================================
; assignments
(variable
(_) @assignment.lhs @assignment.inner
value: (_) @assignment.rhs) @assignment.outer
(variable
value: (_) @assignment.inner)
; blocks
(section
(section_header)
(_)+ @block.inner) @block.outer
; comments
(comment) @comment.outer
; statements
(section
(section_header)
(_) @statement.outer)
================================================
FILE: queries/gleam/textobjects.scm
================================================
; assignments
(let
pattern: (_) @assignment.lhs @assignment.inner
value: (_) @assignment.rhs) @assignment.outer
(let
value: (_) @assignment.inner)
(let_assert
pattern: (_) @assignment.lhs @assignment.inner
value: (_) @assignment.rhs) @assignment.outer
(let_assert
value: (_) @assignment.inner)
(use
assignments: (use_assignments) @assignment.lhs @assignment.inner
value: (_) @assignment.rhs) @assignment.outer
(use
value: (_) @assignment.inner)
; block
(block
"{"
.
_+ @block.inner
.
"}") @block.outer
; calls
(function_call
arguments: (arguments
.
"("
_+ @call.inner
")")) @call.outer
(record
arguments: (arguments
.
"("
_+ @call.inner
")")) @call.outer
(record_update
".." @call.inner
.
spread: (_) @call.inner
.
"," @call.inner
arguments: (record_update_arguments) @call.inner) @call.outer
; class
(type_definition
(data_constructors) @class.inner) @class.outer
; comment
(comment) @comment.outer
; conditionals
(case
clauses: (case_clauses
(case_clause) @conditional.inner)) @conditional.outer
; numbers
[
(integer)
(float)
] @number.inner
; parameters in functions declarations
(function_parameters
"," @parameter.outer
.
(function_parameter) @parameter.inner @parameter.outer)
(function_parameters
.
; first parameter
(function_parameter) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(function_parameters
(function_parameter) @parameter.inner @parameter.outer
.
; trailing comma
"," @parameter.outer .)
; parameters in calls
(arguments
"," @parameter.outer
.
(argument) @parameter.inner @parameter.outer)
(arguments
.
; first parameter
(argument) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(arguments
(argument) @parameter.inner @parameter.outer
.
; trailing comma
"," @parameter.outer .)
; parameters for types and records
(data_constructor_arguments
"," @parameter.outer
.
(data_constructor_argument) @parameter.inner @parameter.outer)
(data_constructor_arguments
.
; first parameter
(data_constructor_argument) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(data_constructor_arguments
(data_constructor_argument) @parameter.inner @parameter.outer
.
; trailing comma
"," @parameter.outer .)
(type_parameters
"," @parameter.outer
.
(type_parameter) @parameter.inner @parameter.outer)
(type_parameters
.
; first parameter
(type_parameter) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(type_parameters
(type_parameter) @parameter.inner @parameter.outer
.
; trailing comma
"," @parameter.outer .)
(type_arguments
"," @parameter.outer
.
(type_argument) @parameter.inner @parameter.outer)
(type_arguments
.
; first parameter
(type_argument) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(type_arguments
(type_argument) @parameter.inner @parameter.outer
.
; trailing comma
"," @parameter.outer .)
(record_pattern_arguments
"," @parameter.outer
.
(record_pattern_argument) @parameter.inner @parameter.outer)
(record_pattern_arguments
.
; first parameter
(record_pattern_argument) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(record_pattern_arguments
(record_pattern_argument) @parameter.inner @parameter.outer
.
; trailing comma
"," @parameter.outer .)
(record_update
".." @parameter.inner @parameter.outer
.
spread: (_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(record_update
"," @parameter.outer
arguments: (record_update_arguments
.
; first parameter after spread
(record_update_argument) @parameter.inner @parameter.outer))
(record_update
arguments: (record_update_arguments
"," @parameter.outer
.
(record_update_argument) @parameter.inner @parameter.outer))
(record_update
arguments: (record_update_arguments
(record_update_argument) @parameter.inner @parameter.outer
. ; trailing comma
"," @parameter.outer .))
; parameters in lists
(list
"," @parameter.outer
(_) @parameter.inner @parameter.outer)
(list
.
; first parameter
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(list
(_) @parameter.inner @parameter.outer
.
;trailing comma
"," @parameter.outer .)
(list_pattern
"," @parameter.outer
(_) @parameter.inner @parameter.outer)
(list_pattern
.
; first parameter
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(list_pattern
(_) @parameter.inner @parameter.outer
.
;trailing comma
"," @parameter.outer .)
; parameters in tuples
(tuple
"," @parameter.outer
(_) @parameter.inner @parameter.outer)
(tuple
.
; first parameter
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(tuple
(_) @parameter.inner @parameter.outer
.
;trailing comma
"," @parameter.outer .)
; parameters in bit arrays
(bit_array
"," @parameter.outer
(_) @parameter.inner @parameter.outer)
(bit_array
.
; first parameter
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(bit_array
(_) @parameter.inner @parameter.outer
.
;trailing comma
"," @parameter.outer .)
; functions
(function
body: (block
"{"
.
_+ @function.inner
.
"}")) @function.outer
(anonymous_function
body: (block
"{"
.
_+ @function.inner
.
"}")) @function.outer
; returns
(function
body: (block
(_) @return.inner @return.outer .))
(anonymous_function
body: (block
(_) @return.inner @return.outer .))
; statements
(block
(_) @statement.outer)
================================================
FILE: queries/glimmer/textobjects.scm
================================================
[
(element_node)
(block_statement)
] @function.outer
[
(mustache_statement)
(block_statement_start)
] @block.outer
(attribute_node) @attribute.outer
(attribute_node
[
(concat_statement)
(mustache_statement)
] @attribute.inner)
(element_node
(element_node_start)
.
(_) @function.inner
.
(element_node_end))
(block_statement
(block_statement_start)
.
(_) @function.inner
.
(block_statement_end))
(element_node
(element_node_start)
_+ @function.inner
(element_node_end))
(block_statement
(block_statement_start)
_+ @function.inner
(block_statement_end))
(mustache_statement
.
"{{"
(_) @block.inner
.
"}}")
(block_statement_start
.
"{{#"
(_) @block.inner
.
"}}")
(comment_statement) @comment.outer
================================================
FILE: queries/glsl/textobjects.scm
================================================
; inherits: c
================================================
FILE: queries/go/textobjects.scm
================================================
; inner function textobject
(function_declaration
body: (block
.
"{"
_+ @function.inner
"}"))
; inner function literals
(func_literal
body: (block
.
"{"
_+ @function.inner
"}"))
; method as inner function textobject
(method_declaration
body: (block
.
"{"
_+ @function.inner
"}"))
; outer function textobject
(function_declaration) @function.outer
; outer function literals
(func_literal
(_)?) @function.outer
; method as outer function textobject
(method_declaration
body: (block)?) @function.outer
; struct and interface declaration as class textobject?
(type_declaration
(type_spec
(type_identifier)
(struct_type
(field_declaration_list
(_)?) @class.inner))) @class.outer
(type_declaration
(type_spec
(type_identifier)
(interface_type) @class.inner)) @class.outer
; struct literals as class textobject
(composite_literal
(type_identifier)?
(struct_type
(_))?
(literal_value
(_)) @class.inner) @class.outer
; conditionals
(if_statement
alternative: (_
(_) @conditional.inner)?) @conditional.outer
(if_statement
consequence: (block)? @conditional.inner)
(if_statement
condition: (_) @conditional.inner)
; loops
(for_statement
body: (block)? @loop.inner) @loop.outer
; blocks
(_
(block) @block.inner) @block.outer
; statements
(block
(_) @statement.outer)
; comments
(comment) @comment.outer
; calls
(call_expression) @call.outer
(call_expression
arguments: (argument_list
.
"("
_+ @call.inner
")"))
; parameters
(parameter_list
"," @parameter.outer
.
(parameter_declaration) @parameter.inner @parameter.outer)
(parameter_list
.
(parameter_declaration) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(parameter_declaration
name: (identifier)
type: (_)) @parameter.inner
(parameter_declaration
name: (identifier)
type: (_)) @parameter.inner
(parameter_list
"," @parameter.outer
.
(variadic_parameter_declaration) @parameter.inner @parameter.outer)
; arguments
(argument_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(argument_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; assignments
(short_var_declaration
left: (_) @assignment.lhs
right: (_) @assignment.rhs @assignment.inner) @assignment.outer
(assignment_statement
left: (_) @assignment.lhs
right: (_) @assignment.rhs @assignment.inner) @assignment.outer
(var_spec
name: (_) @assignment.lhs
value: (_) @assignment.rhs @assignment.inner) @assignment.outer
(var_spec
name: (_) @assignment.inner
type: (_)) @assignment.outer
(const_spec
name: (_) @assignment.lhs
value: (_) @assignment.rhs @assignment.inner) @assignment.outer
(const_spec
name: (_) @assignment.inner
type: (_)) @assignment.outer
================================================
FILE: queries/hack/textobjects.scm
================================================
(method_declaration) @function.outer
================================================
FILE: queries/haskell/textobjects.scm
================================================
(apply
.
function: (_)
_+ @call.inner) @call.outer
(infix
(_)
[
(infix_id
(variable)) ; x `plus` y
(operator) ; x + y
]
(_)) @call.outer
(decl/function) @function.outer
(decl/function
patterns: (_)
match: _+ @function.inner)
; also treat function signature as @function.outer
(signature) @function.outer
; treat signature with function as @function.outer
(((decl/signature
name: (_) @_sig_name) @function.outer
.
(decl/function
name: (_) @_func_name) @function.outer)
(#eq? @_sig_name @_func_name))
(class) @class.outer
(class
"where"
_ @class.inner)
(instance
"where"?
.
_ @class.inner) @class.outer
(comment) @comment.outer
(haddock) @comment.outer
(expression/conditional) @conditional.outer
(expression/conditional
(_) @conditional.inner)
; e.g. forM [1..10] $ \i -> do...
(infix
(apply
(name) @_name
(#eq? @_name "for"))
(operator) @_op
(#eq? @_op "$")
(lambda
(_)
(_) @loop.inner)) @loop.outer
(infix
(apply
(name) @_name
(#eq? @_name "for_"))
(operator) @_op
(#eq? @_op "$")
(lambda
(_)
(_) @loop.inner)) @loop.outer
(infix
(apply
(name) @_name
(#eq? @_name "forM"))
(operator) @_op
(#eq? @_op "$")
(lambda
(_)
(_) @loop.inner)) @loop.outer
(infix
(apply
(name) @_name
(#eq? @_name "forM_"))
(operator) @_op
(#eq? @_op "$")
(lambda
(_)
(_) @loop.inner)) @loop.outer
; e.g. forM [1..10] print
(apply
(name) @_name
(#eq? @_name "for")
(_)
(_) @loop.inner) @loop.outer
(apply
(name) @_name
(#eq? @_name "for_")
(_)
(_) @loop.inner) @loop.outer
(apply
(name) @_name
(#eq? @_name "forM")
(_)
(_) @loop.inner) @loop.outer
(apply
(name) @_name
(#eq? @_name "forM_")
(_)
(_) @loop.inner) @loop.outer
; e.g. func x
(function
(patterns
(_) @parameter.outer))
; e.g. func mb@(Just x)
(function
(patterns
(parens
(_) @parameter.inner)))
(function
(patterns
(as
(parens
(_) @parameter.inner))))
(signature
(context
(function
(type/apply) @parameter.inner)))
(signature
(context
(function
(type/name) @parameter.inner)))
(signature
(function
(type/apply) @parameter.inner))
(signature
(function
(type/name) @parameter.inner))
(signature
(type/apply) @parameter.inner)
(signature
(type/name) @parameter.inner)
================================================
FILE: queries/hcl/textobjects.scm
================================================
(attribute
(identifier) @assignment.lhs
(expression) @assignment.inner @assignment.rhs) @assignment.outer
(attribute
(identifier) @assignment.inner)
(block
(body)? @block.inner) @block.outer
(block
(body
(_) @statement.outer))
(function_call
(function_arguments) @call.inner) @call.outer
(comment) @comment.outer
(conditional
(expression) @conditional.inner) @conditional.outer
(for_cond
(expression) @conditional.inner) @conditional.outer
(for_expr
(for_object_expr
(for_intro) @loop.inner
(expression) @loop.inner
(expression) @loop.inner
(for_cond)? @loop.inner)) @loop.outer
(for_expr
(for_object_expr
(for_intro) @loop.inner))
(for_expr
(for_object_expr
(expression) @loop.inner))
(for_expr
(for_tuple_expr
(for_intro) @loop.inner
(expression) @loop.inner
(for_cond)? @loop.inner)) @loop.outer
(for_expr
(for_tuple_expr
(for_intro) @loop.inner))
(for_expr
(for_tuple_expr
(expression) @loop.inner))
(numeric_lit) @number.inner
(function_arguments
"," @parameter.outer
.
(expression) @parameter.inner @parameter.outer)
(function_arguments
.
(expression) @parameter.inner @parameter.outer
.
","? @parameter.outer)
================================================
FILE: queries/heex/textobjects.scm
================================================
(tag) @function.outer
(tag
(start_tag)
.
(_) @function.inner
.
(end_tag))
(attribute_value) @attribute.inner
(attribute) @attribute.outer
(tag
(start_tag)
_+ @function.inner
(end_tag))
================================================
FILE: queries/hlsl/textobjects.scm
================================================
; inherits: cpp
================================================
FILE: queries/html/textobjects.scm
================================================
(element) @function.outer
(element
(start_tag)
.
(_) @function.inner
.
(end_tag))
(attribute_value) @attribute.inner
(attribute) @attribute.outer
(element
(start_tag)
_+ @function.inner
(end_tag))
(script_element) @function.outer
(script_element
(start_tag)
.
(_) @function.inner
.
(end_tag))
(style_element) @function.outer
(style_element
(start_tag)
.
(_) @function.inner
.
(end_tag))
((element
(start_tag
(tag_name) @_tag)) @class.outer
(#match? @_tag "^(html|section|h[0-9]|header|title|head|body)$"))
((element
(start_tag
(tag_name) @_tag)
.
(_) @class.inner
.
(end_tag))
(#match? @_tag "^(html|section|h[0-9]|header|title|head|body)$"))
((element
(start_tag
(tag_name) @_tag)
_+ @class.inner
(end_tag))
(#match? @_tag "^(html|section|h[0-9]|header|title|head|body)$"))
(comment) @comment.outer
================================================
FILE: queries/inko/textobjects.scm
================================================
; Classes
(class) @class.outer
(class
body: (class_body
.
"{"
_+ @class.inner
"}"))
; Traits
(trait) @class.outer
(trait
body: (trait_body
.
"{"
_+ @class.inner
"}"))
; Implementations
(implement_trait) @class.outer
(implement_trait
body: (implement_trait_body
.
"{"
_+ @class.inner
"}"))
(reopen_class) @class.outer
(reopen_class
body: (reopen_class_body
.
"{"
_+ @class.inner
"}"))
; Methods and closures
(method) @function.outer
(method
body: (block
.
"{"
_+ @function.inner
"}"))
(closure) @function.outer
(closure
body: (block
.
"{"
_+ @function.inner
"}"))
; Loops
(while
body: (block
.
"{"
_+ @loop.inner
"}")) @loop.outer
(while
condition: (_) @conditional.inner)
(loop
body: (block
.
"{"
_+ @loop.inner
"}")) @loop.outer
; Conditionals
(if
alternative: (_
(_) @conditional.inner)?) @conditional.outer
(if
consequence: (block) @conditional.inner)
(if
condition: (_) @conditional.inner)
(case) @conditional.inner
(match) @conditional.outer
; Method calls
(call) @call.outer
(call
arguments: (arguments
.
"("
_+ @call.inner
")"))
(return
(_)? @return.inner) @return.outer
; Call and type arguments
(arguments
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(arguments
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(type_arguments
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(type_arguments
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; Patterns
(class_pattern
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(class_pattern
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(tuple_pattern
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(tuple_pattern
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; Sequence types
(tuple
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(tuple
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(array
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(array
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; Blocks
(block
(_)? @block.inner) @block.outer
; Comments
(line_comment) @comment.outer
; Numbers
[
(integer)
(float)
] @number.inner
; Variable definitions and assignments
(identifier_pattern
name: (_) @assignment.lhs
type: (_) @assignment.inner @assignment.rhs) @assignment.outer
(define_constant
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(assign_local
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(assign_field
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(assign_receiver_field
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(replace_local
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(replace_field
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(compound_assign_local
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(compound_assign_field
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(compound_assign_receiver_field
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
================================================
FILE: queries/java/textobjects.scm
================================================
(class_declaration
body: (class_body) @class.inner) @class.outer
(method_declaration) @function.outer
(method_declaration
body: (block
.
"{"
_+ @function.inner
"}"))
(constructor_declaration) @function.outer
(constructor_declaration
body: (constructor_body
.
"{"
_+ @function.inner
"}"))
(return_statement
(_)? @return.inner) @return.outer
(for_statement
body: (_)? @loop.inner) @loop.outer
(enhanced_for_statement
body: (_)? @loop.inner) @loop.outer
(while_statement
body: (_)? @loop.inner) @loop.outer
(do_statement
body: (_)? @loop.inner) @loop.outer
(if_statement
condition: (_
(parenthesized_expression) @conditional.inner) @conditional.outer)
(if_statement
consequence: (_)? @conditional.inner
alternative: (_)? @conditional.inner) @conditional.outer
(switch_expression
body: (_)? @conditional.inner) @conditional.outer
; blocks
(block) @block.outer
(method_invocation) @call.outer
(method_invocation
arguments: (argument_list
.
"("
_+ @call.inner
")"))
; parameters
(formal_parameters
"," @parameter.outer
.
(formal_parameter) @parameter.inner @parameter.outer)
(formal_parameters
.
(formal_parameter) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(argument_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(argument_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
[
(line_comment)
(block_comment)
] @comment.outer
[
(decimal_integer_literal)
(decimal_floating_point_literal)
(hex_integer_literal)
(binary_integer_literal)
(octal_integer_literal)
] @number.inner
; scopename
; statement
(statement) @statement.outer
(return_statement) @statement.outer
================================================
FILE: queries/javascript/textobjects.scm
================================================
; inherits: ecma,jsx
================================================
FILE: queries/json/textobjects.scm
================================================
(comment) @comment.outer
================================================
FILE: queries/jsx/textobjects.scm
================================================
; inherits: ecma
(jsx_attribute) @attribute.outer
(jsx_attribute
(property_identifier)
(_
(_) @attribute.inner))
================================================
FILE: queries/julia/textobjects.scm
================================================
; Blocks
(compound_statement) @block.outer
(compound_statement
.
(_) @block.inner
(_)? @block.inner .)
(quote_statement) @block.outer
(quote_statement
.
(_) @block.inner
(_)? @block.inner .)
(let_statement) @block.outer
(let_statement
.
(_) @block.inner
(_)? @block.inner .)
; Conditionals
(if_statement
condition: (_) @conditional.inner) @conditional.outer
(if_statement
alternative: (elseif_clause
condition: (_) @conditional.inner))
((if_statement
condition: (_)
.
(_) @conditional.inner
(_)? @conditional.inner
.
[
"end"
(elseif_clause)
(else_clause)
]) @conditional.outer
(elseif_clause
condition: (_)
.
(_) @conditional.inner
(_)? @conditional.inner .))
(else_clause
.
(_) @conditional.inner
(_)? @conditional.inner .)
; Loops
(for_statement) @loop.outer
(for_statement
.
(_) @loop.inner
(_)? @loop.inner .)
(while_statement
condition: (_) @loop.inner) @loop.outer
(while_statement
condition: (_)
.
(_) @loop.inner
(_)? @loop.inner .)
; Type definitions
(struct_definition) @class.outer
(struct_definition
(type_head)
.
(_) @class.inner
(_)? @class.inner .)
; Function definitions
(function_definition) @function.outer
(function_definition
(signature)
.
(_) @function.inner
(_)? @function.inner .)
(assignment
(call_expression)
(operator)
(_) @function.inner) @function.outer
(arrow_function_expression
[
(identifier)
(argument_list)
]
"->"
(_) @function.inner) @function.outer
(macro_definition) @function.outer
(macro_definition
(signature)
.
(_) @function.inner
(_)? @function.inner .)
; Calls
(call_expression) @call.outer
(call_expression
(argument_list
.
"("
.
(_) @call.inner
(_)? @call.inner
.
")"))
(macrocall_expression) @call.outer
(macrocall_expression
(argument_list
.
"("
.
(_) @call.inner
(_)? @call.inner
.
")"))
(broadcast_call_expression) @call.outer
(broadcast_call_expression
(argument_list
.
"("
.
(_) @call.inner
(_)? @call.inner
.
")"))
; Parameters
((argument_list
[
","
";"
] @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(argument_list
(_) @parameter.inner @parameter.outer
.
[
","
";"
] @parameter.outer))
(tuple_expression
[
","
";"
] @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(tuple_expression
"("
.
(_) @parameter.inner @parameter.outer
.
[
","
";"
]? @parameter.outer)
(vector_expression
[
","
";"
] @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(vector_expression
.
(_) @parameter.inner @parameter.outer
.
[
","
";"
]? @parameter.outer)
; Assignment
(assignment
.
(_) @assignment.lhs
(_) @assignment.inner @assignment.rhs .) @assignment.outer
(assignment
.
(_) @assignment.inner)
(compound_assignment_expression
.
(_) @assignment.lhs
(_) @assignment.inner @assignment.rhs .) @assignment.outer
(compound_assignment_expression
.
(_) @assignment.inner)
; Comments
[
(line_comment)
(block_comment)
] @comment.outer
; Regex
((prefixed_string_literal
prefix: (identifier) @_prefix) @regex.inner @regex.outer
(#eq? @_prefix "r"))
================================================
FILE: queries/kotlin/textobjects.scm
================================================
(class_declaration
[
(class_body)
(enum_class_body)
]? @class.inner) @class.outer
[
(function_declaration
(function_body) @function.inner)
(getter
(function_body) @function.inner)
(setter
(function_body) @function.inner)
(primary_constructor)
] @function.outer
(primary_constructor) @function.inner
[
(parameter
(simple_identifier) @parameter.inner)
(class_parameter
(simple_identifier) @parameter.inner)
] @parameter.outer
(value_arguments
"," @parameter.outer
.
(value_argument) @parameter.inner @parameter.outer)
(value_arguments
.
(value_argument) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; last element, with trailing comma
(value_arguments
(value_argument) @parameter.outer
.
"," @parameter.outer .)
[
(line_comment)
(multiline_comment)
] @comment.outer
(if_expression
(control_structure_body) @conditional.inner) @conditional.outer
(when_expression
(when_entry) @conditional.inner) @conditional.outer
[
(for_statement
(control_structure_body) @loop.inner)
(while_statement
(control_structure_body) @loop.inner)
] @loop.outer
[
(integer_literal)
(real_literal)
] @number.inner
================================================
FILE: queries/latex/textobjects.scm
================================================
(generic_environment
.
(_)
_+ @block.inner
(_) .) @block.outer
((generic_environment
(begin
name: (curly_group_text
(text) @_frame))
_+ @frame.inner
(_) .) @frame.outer
(#eq? @_frame "frame"))
[
(generic_command)
(text_mode)
] @call.outer
(text_mode
(curly_group
"{"
_+ @call.inner
"}"))
(generic_command
(curly_group
"{"
_+ @call.inner
"}"))
(part
text: (_)
_+ @class.inner)
(part
text: (_)) @class.outer
(chapter
text: (_)
_+ @class.inner)
(chapter
text: (_)) @class.outer
(section
text: (_)
_+ @class.inner)
(section
text: (_)) @class.outer
(subsection
text: (_)
_+ @class.inner)
(subsection
text: (_)) @class.outer
(subsubsection
text: (_)
_+ @class.inner)
(subsubsection
text: (_)) @class.outer
(paragraph
text: (_)
_+ @class.inner)
(paragraph
text: (_)) @class.outer
(subparagraph
text: (_)
_+ @class.inner)
(subparagraph
text: (_)) @class.outer
================================================
FILE: queries/lua/textobjects.scm
================================================
; block
(_
(block) @block.inner) @block.outer
; call
(function_call) @call.outer
================================================
FILE: queries/markdown/textobjects.scm
================================================
(atx_heading
heading_content: (_) @class.inner) @class.outer
(setext_heading
heading_content: (_) @class.inner) @class.outer
(thematic_break) @class.outer
(fenced_code_block
(code_fence_content) @block.inner) @block.outer
[
(paragraph)
(list)
] @block.outer
================================================
FILE: queries/matlab/textobjects.scm
================================================
(_
(block) @block.inner) @block.outer
(block
(_) @statement.outer)
(source_file
(_) @statement.outer)
(function_call
(arguments)? @call.inner) @call.outer
(arguments
","? @parameter.outer
.
(_) @parameter.inner @parameter.outer .)
(arguments
(_) @parameter.inner @parameter.outer
.
"," @parameter.outer)
(command) @call.outer
(command
(command_argument) @parameter.inner @parameter.outer)
(command
(command_argument)+ @call.inner)
(if_statement
(block) @conditional.inner) @conditional.outer
(if_statement
(elseif_clause
(block) @conditional.inner))
(if_statement
(else_clause
(block) @conditional.inner))
(switch_statement
(case_clause
(block) @conditional.inner)) @conditional.outer
(switch_statement
(otherwise_clause
(block) @conditional.inner))
(for_statement
(block) @loop.inner) @loop.outer
(while_statement
(block) @loop.inner) @loop.outer
(lambda
expression: (_) @function.inner) @function.outer
(global_operator
(identifier) @parameter.inner)
(persistent_operator
(identifier) @parameter.inner)
(function_definition
(block) @function.inner) @function.outer
(function_output
(identifier) @parameter.inner @parameter.outer)
(function_arguments
","? @parameter.outer
.
(_) @parameter.inner @parameter.outer .)
(function_arguments
(_) @parameter.inner @parameter.outer
.
"," @parameter.outer)
(multioutput_variable
","? @parameter.outer
.
(_) @parameter.inner @parameter.outer .)
(multioutput_variable
(_) @parameter.inner @parameter.outer
.
"," @parameter.outer)
(try_statement
(block) @conditional.inner) @conditional.outer
(catch_clause
(identifier) @parameter.inner @parameter.outer)
(catch_clause
(block) @conditional.inner)
(class_definition) @class.outer
(number) @number.inner
(_
(return_statement) @return.inner @return.outer)
(comment) @comment.outer
(matrix
(row) @parameter.outer)
(cell
(row) @parameter.outer)
(row
(_) @parameter.inner)
(assignment
left: (_) @assignment.lhs
(_) @assignment.rhs) @assignment.outer
(superclasses
"&"? @parameter.outer
.
(_) @parameter.inner @parameter.outer .)
(superclasses
(_) @parameter.inner @parameter.outer
.
"&" @parameter.outer)
(enum
(identifier) @parameter.inner @parameter.outer)
(property
name: (_) @parameter.outer @parameter.inner)
(enum
","? @parameter.outer
.
(_) @parameter.inner @parameter.outer .)
(enum
(_) @parameter.inner @parameter.outer
.
"," @parameter.outer)
(validation_functions
","? @parameter.outer
.
(_) @parameter.inner @parameter.outer .)
(validation_functions
(_) @parameter.inner @parameter.outer
.
"," @parameter.outer)
(dimensions
","? @parameter.outer
.
(_) @parameter.inner @parameter.outer .)
(dimensions
(_) @parameter.inner @parameter.outer
.
"," @parameter.outer)
(attributes
","? @parameter.outer
.
(_) @parameter.inner @parameter.outer .)
(attributes
(_) @parameter.inner @parameter.outer
.
"," @parameter.outer)
================================================
FILE: queries/nasm/textobjects.scm
================================================
; adapted from https://github.com/naclsn/tree-sitter-nasm/blob/main/queries/textobjects.scm
(preproc_multiline_macro
body: (body) @function.inner) @function.outer
(struc_declaration
body: (struc_declaration_body) @class.inner) @class.outer
(struc_instance
body: (struc_instance_body) @class.inner) @class.outer
(preproc_function_def_parameters
(word) @parameter.inner)
(call_syntax_arguments
(_) @parameter.inner)
(operand) @parameter.inner
(comment) @comment.outer
================================================
FILE: queries/nim/textobjects.scm
================================================
; ==============================================================================
; @attribute.inner
; @attribute.outer
; ==============================================================================
; @function.inner
; @function.outer
(proc_declaration
body: (statement_list) @function.inner) @function.outer
(func_declaration
body: (statement_list) @function.inner) @function.outer
(method_declaration
body: (statement_list) @function.inner) @function.outer
(iterator_declaration
body: (statement_list) @function.inner) @function.outer
(converter_declaration
body: (statement_list) @function.inner) @function.outer
(template_declaration
body: (statement_list) @function.inner) @function.outer
(macro_declaration
body: (statement_list) @function.inner) @function.outer
(proc_expression
body: (statement_list) @function.inner) @function.outer
(func_expression
body: (statement_list) @function.inner) @function.outer
(iterator_expression
body: (statement_list) @function.inner) @function.outer
; ==============================================================================
; @class.inner
; @class.outer
; NOTE: seems pointless to handle just object declarations differently
; ==============================================================================
; @conditional.inner
; @conditional.outer
[
(if)
(when)
(conditional_declaration)
(case)
(variant_declaration)
(elif_branch)
(else_branch)
(of_branch)
] @conditional.outer
(if
condition: (_) @conditional.inner)
(if
consequence: (statement_list) @conditional.inner)
(when
condition: (_) @conditional.inner)
(when
consequence: (statement_list) @conditional.inner)
(conditional_declaration
condition: (_) @conditional.inner)
(conditional_declaration
consequence: (field_declaration_list) @conditional.inner)
(elif_branch
condition: (_) @conditional.inner)
(elif_branch
consequence: [
(statement_list)
(field_declaration_list)
] @conditional.inner)
(else_branch
consequence: [
(statement_list)
(field_declaration_list)
] @conditional.inner)
(case
value: (_) @conditional.inner)
(variant_declaration
(variant_discriminator_declaration) @conditional.inner)
(of_branch
values: (expression_list) @conditional.inner)
(of_branch
consequence: [
(statement_list)
(field_declaration_list)
] @conditional.inner)
; ==============================================================================
; @loop.inner
; @loop.outer
[
(for)
(while)
] @loop.outer
(for
left: (_) @loop.inner
right: (_) @loop.inner)
(for
body: (statement_list) @loop.inner)
(while
condition: (_) @loop.inner)
(while
body: (statement_list) @loop.inner)
; ==============================================================================
; @call.inner
; @call.outer
(call
(argument_list) @call.inner) @call.outer
; NOTE: parenthesis are included in @call.inner
; ==============================================================================
; @block.inner
; @block.outer
(case
":"
_+ @block.inner) @block.outer
(object_declaration
(field_declaration_list) @block.inner) @block.outer
(tuple_type
(field_declaration_list
.
"["
_+ @block.inner
"]" .)) @block.outer
(enum_declaration
.
"enum"
_+ @block.inner) @block.outer
(using_section
.
"using"
_+ @block.inner) @block.outer
(const_section
.
"const"
_+ @block.inner) @block.outer
(let_section
.
"let"
_+ @block.inner) @block.outer
(var_section
.
"var"
_+ @block.inner) @block.outer
(type_section
.
"type"
_+ @block.inner)
(_
(statement_list) @block.inner) @block.outer
; ==============================================================================
; @parameter.inner
; @parameter.outer
; parameters when declaring
(parameter_declaration_list
[
","
";"
] @parameter.outer
.
(parameter_declaration) @parameter.inner @parameter.outer)
(parameter_declaration_list
.
(parameter_declaration) @parameter.inner @parameter.outer
.
[
","
";"
]? @parameter.outer)
; generic parameters when declaring
(generic_parameter_list
"," @parameter.outer
.
(parameter_declaration) @parameter.inner @parameter.outer)
(generic_parameter_list
.
(parameter_declaration) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; arguments when calling
(argument_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(argument_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; containers
(array_construction
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(array_construction
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(tuple_construction
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(tuple_construction
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(curly_construction
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(curly_construction
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; generic arguments when calling
; subscript operator
; generic types
(bracket_expression
right: (argument_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer))
(bracket_expression
right: (argument_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer))
; import x,x
; import except x,x
; include x,x
; from import x,x
; bind x,x
; mixin x,x
; case of x,x
; try except x,x
(expression_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(expression_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; pragmas
(pragma_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(pragma_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; variable_declaration
; for
; identifier_declaration `x,y: type = value`
(symbol_declaration_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(symbol_declaration_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; infix_expression
(infix_expression
operator: (_) @parameter.outer
right: (_) @parameter.inner @parameter.outer)
(infix_expression
left: (_) @parameter.inner @parameter.outer
operator: (_) @parameter.outer)
; tuple_type inline
(field_declaration_list
[
","
";"
] @parameter.outer
.
(field_declaration) @parameter.inner @parameter.outer)
(field_declaration_list
.
(field_declaration) @parameter.inner @parameter.outer
.
[
","
";"
]? @parameter.outer)
; enum
(enum_declaration
"," @parameter.outer
.
(enum_field_declaration) @parameter.inner @parameter.outer)
(enum_declaration
.
(enum_field_declaration) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; tuple_deconstruct_declaration
(tuple_deconstruct_declaration
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(tuple_deconstruct_declaration
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; concept parameter list
; concept refinement list
(parameter_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(parameter_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(refinement_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(refinement_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; dot_generic_call `v.call[:type, type]()
(generic_argument_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(generic_argument_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; ==============================================================================
; @regex.inner
; @regex.outer
; ==============================================================================
; @comment.inner
; @comment.outer
(comment
(comment_content) @comment.inner) @comment.outer
(block_comment
(comment_content) @comment.inner) @comment.outer
(documentation_comment
(comment_content) @comment.inner) @comment.outer
(block_documentation_comment
(comment_content) @comment.inner) @comment.outer
; ==============================================================================
; @assignment.inner
; @assignment.outer
; @assignment.lhs
; @assignment.rhs
(variable_declaration
(symbol_declaration_list) @assignment.lhs
type: (type_expression)? @assignment.lhs
value: (_) @assignment.rhs @assignment.inner) @assignment.outer
(type_declaration
(type_symbol_declaration) @assignment.lhs
.
"="
.
(_) @assignment.rhs @assignment.inner) @assignment.outer
(assignment
left: (_) @assignment.lhs
right: (_) @assignment.rhs @assignment.inner) @assignment.outer
; default parameter in proc decl
; keyword argument in call
; array construction
(colon_expression
left: (_) @assignment.lhs
right: (_) @assignment.rhs @assignment.inner) @assignment.outer
; object construction
; tuple construction
; table construction
(equal_expression
left: (_) @assignment.lhs
right: (_) @assignment.rhs @assignment.inner) @assignment.outer
; object declaration fields
; tuple declaration fields
(field_declaration
(symbol_declaration_list) @assignment.lhs
type: (type_expression)? @assignment.lhs
value: (_)? @assignment.rhs @assignment.inner) @assignment.outer
; enum types
(enum_field_declaration
(symbol_declaration) @assignment.lhs
"="?
value: (_)? @assignment.rhs @assignment.inner) @assignment.outer
; ==============================================================================
; @return.inner
; @return.outer
(return_statement
(_) @return.inner) @return.outer
; ==============================================================================
; @statement.outer
[
; simple
(import_statement)
(import_from_statement)
(export_statement)
(include_statement)
(discard_statement)
(return_statement)
(raise_statement)
(yield_statement)
(break_statement)
(continue_statement)
(assembly_statement)
(bind_statement)
(mixin_statement)
(pragma_statement)
; complex
(while)
(static_statement)
(defer)
; declarations
(proc_declaration)
(func_declaration)
(method_declaration)
(iterator_declaration)
(macro_declaration)
(template_declaration)
(converter_declaration)
(using_section)
(const_section)
(let_section)
(var_section)
(type_section)
; expression statements
(block)
(if)
(when)
(case)
(try)
(for)
(assignment)
; NOTE: not including
; simple_expression, call, infix_expression, prefix_expression
; because it would confusing
] @statement.outer
; ==============================================================================
; @scopename.inner
; ==============================================================================
; @number.inner
[
(integer_literal)
(float_literal)
] @number.inner
================================================
FILE: queries/nix/textobjects.scm
================================================
; named function
(binding
(function_expression)) @function.outer
; anonymous function
(function_expression
(_) ; argument
(_) @function.inner) @function.outer
(function_expression
(formals
(formal) @parameter.inner))
(function_expression
(_) @parameter.outer
(_))
(comment) @comment.outer
(if_expression
(_) @conditional.inner) @conditional.outer
[
(integer_expression)
(float_expression)
] @number.inner
================================================
FILE: queries/ocaml/textobjects.scm
================================================
(value_definition
(let_binding
; let f x = 1 but not let x = 1
(parameter)+
body: (_) @function.inner)) @function.outer
(value_definition
(let_binding
; let f = function | A | B -> body
body: (function_expression) @function.inner)) @function.outer
(value_definition
(let_binding
; let f = fun x -> body
body: (fun_expression) @function.inner)) @function.outer
; standalone function expression, e.g. List.iter ~f:(function | A | B -> body)
(parenthesized_expression
(function_expression) @function.inner) @function.outer
; standalone function expression, e.g. List.iter ~f:(fun x -> body)
(parenthesized_expression
(fun_expression) @function.inner) @function.outer
(method_definition
body: (_) @function.inner) @function.outer
; let pattern = body (also matches let f x = expr due to grammar limits)
; Since we want @assignment.inner to match both pattern and body we have to split it into two:
(value_definition
(let_binding
pattern: (_) @assignment.lhs @assignment.inner)) @assignment.outer
(value_definition
(let_binding
body: (_) @assignment.rhs @assignment.inner))
; module M = struct ... end
(module_definition
(module_binding
body: (structure) @class.inner)) @class.outer
; struct ... end
(structure
(_structure_item)+ @block.inner) @block.outer
(class_definition
(class_binding
body: (_) @class.inner)) @class.outer
(for_expression
(do_clause
(_) @loop.inner)) @loop.outer
(while_expression
(do_clause
(_) @loop.inner)) @loop.outer
(if_expression
condition: (_)
(then_clause
(_) @conditional.inner)
(else_clause
(_) @conditional.inner)) @conditional.outer
(if_expression
condition: (_)
(then_clause
(_) @conditional.inner)) @conditional.outer
(function_expression
(match_case)+ @conditional.inner) @conditional.outer
(match_expression
(match_case)+ @conditional.inner) @conditional.outer
(comment) @comment.outer
(parameter) @parameter.outer
(application_expression
argument: (_) @parameter.outer) @call.outer
(application_expression
argument: (_)+ @call.inner)
; parenthesized selections are handled well by vi
================================================
FILE: queries/odin/textobjects.scm
================================================
; procedures
(procedure_declaration
(_
(block
.
"{"
_+ @function.inner
"}"))) @function.outer
; returns
(return_statement
(_)? @return.inner) @return.outer
; call function in module
(member_expression
(call_expression)) @call.outer
; call arguments
(call_expression
function: (_)
.
argument: (_) @call.inner
argument: (_) @call.inner .)
; block
(block
.
"{"
_+ @block.inner
"}") @block.outer
; classes
(struct_declaration
"{"
_+ @class.inner
"}") @class.outer
(union_declaration
"{"
_+ @class.inner
"}") @class.outer
(enum_declaration
"{"
_+ @class.inner
"}") @class.outer
; comments
(comment) @comment.outer
(block_comment) @comment.outer
; assignment
; works also for multiple targets in lhs. ex. 'res, ok := get_res()'
(assignment_statement
.
(_) @assignment.lhs
(_) @assignment.lhs
.
(_) @assignment.rhs @assignment.inner .) @assignment.outer
; attribute
(attribute
(_) @attribute.inner) @attribute.outer
; number
(number) @number.inner
; parameters
(parameters
"," @parameter.outer
.
(parameter) @parameter.inner @parameter.outer)
(parameters
.
(parameter) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(call_expression
function: (_)
"," @parameter.outer
.
argument: (_) @parameter.inner @parameter.outer)
(call_expression
function: (_)
.
argument: (_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
================================================
FILE: queries/perl/textobjects.scm
================================================
(comment) @comment.outer
(quoted_regexp) @regex.outer
(match_regexp) @regex.outer
================================================
FILE: queries/php/textobjects.scm
================================================
; functions
(function_definition
body: (compound_statement
.
"{"
_+ @function.inner
"}"))
(function_definition) @function.outer
(anonymous_function
body: (compound_statement
.
"{"
_+ @function.inner
"}"))
(anonymous_function) @function.outer
; methods
(method_declaration
body: (compound_statement
.
"{"
_+ @function.inner
"}"))
(method_declaration) @function.outer
; traits
(trait_declaration
body: (declaration_list
.
"{"
_+ @class.inner
"}"))
(trait_declaration) @class.outer
; interfaces
(interface_declaration
body: (declaration_list
.
"{"
_+ @class.inner
"}"))
(interface_declaration) @class.outer
; enums
(enum_declaration
body: (enum_declaration_list
.
"{"
_+ @class.inner
"}"))
(enum_declaration) @class.outer
; classes
(class_declaration
body: (declaration_list
.
"{"
_+ @class.inner
"}"))
(class_declaration) @class.outer
; loops
(for_statement
(compound_statement
.
"{"
_+ @loop.inner
"}"))
(for_statement) @loop.outer
(foreach_statement
body: (compound_statement
.
"{"
_+ @loop.inner
"}"))
(foreach_statement) @loop.outer
(while_statement
body: (compound_statement
.
"{"
_+ @loop.inner
"}"))
(while_statement) @loop.outer
(do_statement
body: (compound_statement
.
"{"
_+ @loop.inner
"}"))
(do_statement) @loop.outer
; conditionals
(switch_statement
body: (switch_block
.
"{"
_+ @conditional.inner
"}"))
(switch_statement) @conditional.outer
(if_statement
body: (compound_statement
.
"{"
_+ @conditional.inner
"}"))
(if_statement) @conditional.outer
(else_clause
body: (compound_statement
.
"{"
_+ @conditional.inner
"}"))
(else_if_clause
body: (compound_statement
.
"{"
_+ @conditional.inner
"}"))
; blocks
(_
(switch_block) @block.inner) @block.outer
; parameters
(arguments
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(arguments
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(formal_parameters
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(formal_parameters
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; comments
(comment) @comment.outer
; call
(function_call_expression) @call.outer
(member_call_expression) @call.outer
(nullsafe_member_call_expression) @call.outer
(scoped_call_expression) @call.outer
(function_call_expression
arguments: (arguments
.
"("
_+ @call.inner
")"))
(member_call_expression
arguments: (arguments
.
"("
_+ @call.inner
")"))
(nullsafe_member_call_expression
arguments: (arguments
.
"("
_+ @call.inner
")"))
(scoped_call_expression
arguments: (arguments
.
"("
_+ @call.inner
")"))
; statement
[
(expression_statement)
(declare_statement)
(return_statement)
(namespace_use_declaration)
(namespace_definition)
(if_statement)
(empty_statement)
(switch_statement)
(while_statement)
(do_statement)
(for_statement)
(foreach_statement)
(goto_statement)
(continue_statement)
(break_statement)
(try_statement)
(echo_statement)
(unset_statement)
(const_declaration)
(function_definition)
(class_declaration)
(interface_declaration)
(trait_declaration)
(enum_declaration)
(global_declaration)
(function_static_declaration)
] @statement.outer
================================================
FILE: queries/php_only/textobjects.scm
================================================
; inherits php
================================================
FILE: queries/python/textobjects.scm
================================================
(decorated_definition
(function_definition)) @function.outer
(function_definition
body: (block)? @function.inner) @function.outer
(decorated_definition
(class_definition)) @class.outer
(class_definition
body: (block)? @class.inner) @class.outer
(while_statement
body: (block)? @loop.inner) @loop.outer
(for_statement
body: (block)? @loop.inner) @loop.outer
(if_statement
alternative: (_
(_) @conditional.inner)?) @conditional.outer
(if_statement
consequence: (block)? @conditional.inner)
(if_statement
condition: (_) @conditional.inner)
(_
(block) @block.inner) @block.outer
; leave space after comment marker if there is one
((comment) @comment.inner @comment.outer
(#match? @comment.outer "# .*"))
; else remove everything accept comment marker
((comment) @comment.inner @comment.outer)
(block
(_) @statement.outer)
(module
(_) @statement.outer)
(call) @call.outer
(call
arguments: (argument_list
.
"("
_+ @call.inner
")"))
(return_statement
(_)? @return.inner) @return.outer
; Parameters
(parameters
"," @parameter.outer
.
[
(identifier)
(tuple)
(typed_parameter)
(default_parameter)
(typed_default_parameter)
(dictionary_splat_pattern)
(list_splat_pattern)
] @parameter.inner @parameter.outer)
(parameters
.
[
(identifier)
(tuple)
(typed_parameter)
(default_parameter)
(typed_default_parameter)
(dictionary_splat_pattern)
(list_splat_pattern)
] @parameter.inner @parameter.outer
.
","? @parameter.outer)
(lambda_parameters
"," @parameter.outer
.
[
(identifier)
(tuple)
(typed_parameter)
(default_parameter)
(typed_default_parameter)
(dictionary_splat_pattern)
(list_splat_pattern)
] @parameter.inner @parameter.outer)
(lambda_parameters
.
[
(identifier)
(tuple)
(typed_parameter)
(default_parameter)
(typed_default_parameter)
(dictionary_splat_pattern)
(list_splat_pattern)
] @parameter.inner @parameter.outer
.
","? @parameter.outer)
(tuple
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(tuple
"("
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(dictionary
.
(pair) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(dictionary
"," @parameter.outer
.
(pair) @parameter.inner @parameter.outer)
(argument_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(argument_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(subscript
"["
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(subscript
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(import_statement
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(import_statement
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(import_from_statement
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(import_from_statement
"import"
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
[
(integer)
(float)
] @number.inner
(assignment
left: (_) @assignment.lhs
right: (_) @assignment.inner @assignment.rhs) @assignment.outer
(assignment
left: (_) @assignment.inner)
(augmented_assignment
left: (_) @assignment.lhs
right: (_) @assignment.inner @assignment.rhs) @assignment.outer
(augmented_assignment
left: (_) @assignment.inner)
; TODO: exclude comments using the future negate syntax from tree-sitter
================================================
FILE: queries/ql/textobjects.scm
================================================
; class textobject
(dataclass
(typeExpr)
(_) @class.inner) @class.outer
; function textobject
(charpred
(className)
(_) @function.inner) @function.outer
(memberPredicate
(body) @function.inner) @function.outer
(classlessPredicate
(body) @function.inner) @function.outer
; scope name textobject
(dataclass
name: (className) @scopename.inner)
(classlessPredicate
name: (predicateName) @scopename.inner)
(memberPredicate
name: (predicateName) @scopename.inner)
(charpred
(className) @scopename.inner)
================================================
FILE: queries/query/textobjects.scm
================================================
(comment) @comment.outer
[
(named_node)
(grouping)
(list)
] @block.outer
(program
[
(named_node)
(grouping)
(list)
] @statement.outer)
(parameters
(_) @parameter.inner)
================================================
FILE: queries/r/textobjects.scm
================================================
; block
; call
(call) @call.outer
(arguments) @call.inner
; class
; comment
(comment) @comment.outer
; conditional
(if_statement
condition: (_)? @conditional.inner) @conditional.outer
; function
(function_definition
[
(call)
(binary_operator)
(braced_expression)
] @function.inner) @function.outer
; loop
[
(while_statement)
(repeat_statement)
(for_statement)
] @loop.outer
(while_statement
body: (_) @loop.inner)
(repeat_statement
body: (_) @loop.inner)
(for_statement
body: (_) @loop.inner)
; statement
(braced_expression
(_) @statement.outer)
(program
(_) @statement.outer)
; parameter
(parameters
(comma) @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(parameters
.
(_) @parameter.inner @parameter.outer
.
(comma)? @parameter.outer)
(arguments
(comma)? @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(arguments
.
(_) @parameter.inner @parameter.outer
.
(comma)? @parameter.outer)
; number
(float) @number.inner
; assignment
(binary_operator
lhs: (_) @assignment.inner @assignment.lhs
rhs: (_) @assignment.rhs) @assignment.outer
================================================
FILE: queries/readline/textobjects.scm
================================================
(variable_setting) @statement.outer
(comment) @comment.outer
((comment) @comment.inner)
[
(alternative)
(consequence)
(test)
] @conditional.inner
(conditional_construct) @conditional.outer
[
(number_value)
(version_number)
] @number.inner
================================================
FILE: queries/rst/textobjects.scm
================================================
(directive
body: (body) @function.inner) @function.outer
(section
(title) @class.inner) @class.outer
(transition) @class.outer
[
(bullet_list)
(enumerated_list)
(definition_list)
(field_list)
(literal_block)
(line_block)
(block_quote)
(doctest_block)
] @block.outer
(footnote
body: (body) @block.inner) @block.outer
(citation
body: (body) @block.inner) @block.outer
(target
link: (link) @block.inner) @block.outer
(substitution_definition
body: (directive) @block.inner) @block.outer
(comment) @comment.outer
================================================
FILE: queries/ruby/textobjects.scm
================================================
; @functions
(method
body: (body_statement) @function.inner)
(method) @function.outer
(singleton_method
body: (body_statement) @function.inner)
(singleton_method) @function.outer
; @blocks
(block
body: (block_body) @block.inner)
(block) @block.outer
(do_block
body: (body_statement) @block.inner)
(do_block) @block.outer
; @classes
(class
body: (body_statement) @class.inner)
(class) @class.outer
(module
body: (body_statement) @class.inner)
(module) @class.outer
(singleton_class
body: (body_statement) @class.inner)
(singleton_class) @class.outer
; @parameters
(block_parameters
(_) @parameter.inner)
(method_parameters
(_) @parameter.inner)
(lambda_parameters
(_) @parameter.inner)
(argument_list
(_) @parameter.inner)
[
(block_parameters)
(method_parameters)
(lambda_parameters)
(argument_list)
] @parameter.outer
; @comment
(comment) @comment.outer
; @regex
(regex
(string_content) @regex.inner) @regex.outer
================================================
FILE: queries/rust/textobjects.scm
================================================
; functions
(function_signature_item) @function.outer
(function_item) @function.outer
(function_item
body: (block
.
"{"
_+ @function.inner
"}"))
; quantifies as class(es)
(struct_item) @class.outer
(struct_item
body: (field_declaration_list
.
"{"
_+ @class.inner
"}"))
(enum_item) @class.outer
(enum_item
body: (enum_variant_list
.
"{"
_+ @class.inner
"}"))
(union_item) @class.outer
(union_item
body: (field_declaration_list
.
"{"
_+ @class.inner
"}"))
(trait_item) @class.outer
(trait_item
body: (declaration_list
.
"{"
_+ @class.inner
"}"))
(impl_item) @class.outer
(impl_item
body: (declaration_list
.
"{"
_+ @class.inner
"}"))
(mod_item) @class.outer
(mod_item
body: (declaration_list
.
"{"
_+ @class.inner
"}"))
; conditionals
(if_expression
alternative: (_
(_) @conditional.inner)?) @conditional.outer
(if_expression
alternative: (else_clause
(block) @conditional.inner))
(if_expression
condition: (_) @conditional.inner)
(if_expression
consequence: (block) @conditional.inner)
(match_arm
(_)) @conditional.inner
(match_expression) @conditional.outer
; loops
(loop_expression
body: (block
.
"{"
_+ @loop.inner
"}")) @loop.outer
(while_expression
body: (block
.
"{"
_+ @loop.inner
"}")) @loop.outer
(for_expression
body: (block
.
"{"
_+ @loop.inner
"}")) @loop.outer
; blocks
(block
(_)* @block.inner) @block.outer
(unsafe_block
(_)* @block.inner) @block.outer
; calls
(macro_invocation) @call.outer
(macro_invocation
(token_tree
.
"("
_+ @call.inner
")"))
(call_expression) @call.outer
(call_expression
arguments: (arguments
.
"("
_+ @call.inner
")"))
; returns
(return_expression
(_)? @return.inner) @return.outer
; statements
(block
(_) @statement.outer)
; comments
(line_comment) @comment.outer
(block_comment) @comment.outer
; parameter
(parameters
"," @parameter.outer
.
[
(self_parameter)
(parameter)
(type_identifier)
] @parameter.inner @parameter.outer)
(parameters
.
[
(self_parameter)
(parameter)
(type_identifier)
] @parameter.inner @parameter.outer
.
","? @parameter.outer)
; last element, with trailing comma
(parameters
[
(self_parameter)
(parameter)
(type_identifier)
] @parameter.outer
.
"," @parameter.outer .)
(type_parameters
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(type_parameters
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; last element, with trailing comma
(type_parameters
(_) @parameter.outer
.
"," @parameter.outer .)
(tuple_pattern
"," @parameter.outer
.
(identifier) @parameter.inner @parameter.outer)
(tuple_pattern
.
(identifier) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; last element, with trailing comma
(tuple_pattern
(identifier) @parameter.outer
.
"," @parameter.outer .)
(tuple_struct_pattern
"," @parameter.outer
.
(identifier) @parameter.inner @parameter.outer)
(tuple_struct_pattern
.
(identifier) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; last element, with trailing comma
(tuple_struct_pattern
(identifier) @parameter.outer
.
"," @parameter.outer .)
(tuple_expression
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(tuple_expression
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; last element, with trailing comma
(tuple_expression
(_) @parameter.outer
.
"," @parameter.outer .)
(tuple_type
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(tuple_type
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; last element, with trailing comma
(tuple_type
(_) @parameter.outer
.
"," @parameter.outer .)
(struct_item
body: (field_declaration_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer))
(struct_item
body: (field_declaration_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer))
; last element, with trailing comma
(struct_item
body: (field_declaration_list
(_) @parameter.outer
.
"," @parameter.outer .))
(struct_expression
body: (field_initializer_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer))
(struct_expression
body: (field_initializer_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer))
; last element, with trailing comma
(struct_expression
body: (field_initializer_list
(_) @parameter.outer
.
"," @parameter.outer .))
(closure_parameters
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(closure_parameters
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; last element, with trailing comma
(closure_parameters
(_) @parameter.outer
.
"," @parameter.outer .)
(arguments
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(arguments
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; last element, with trailing comma
(arguments
(_) @parameter.outer
.
"," @parameter.outer .)
(type_arguments
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(type_arguments
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; last element, with trailing comma
(type_arguments
(_) @parameter.outer
.
"," @parameter.outer .)
(token_tree
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(token_tree
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; last element, with trailing comma
(token_tree
(_) @parameter.outer
.
"," @parameter.outer .)
(scoped_use_list
list: (use_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer))
(scoped_use_list
list: (use_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer))
; last element, with trailing comma
(scoped_use_list
list: (use_list
(_) @parameter.outer
.
"," @parameter.outer .))
[
(integer_literal)
(float_literal)
] @number.inner
(let_declaration
pattern: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(let_declaration
pattern: (_) @assignment.inner)
(assignment_expression
left: (_) @assignment.lhs
right: (_) @assignment.inner @assignment.rhs) @assignment.outer
(assignment_expression
left: (_) @assignment.inner)
================================================
FILE: queries/scala/textobjects.scm
================================================
(class_definition
body: (template_body)? @class.inner) @class.outer
(object_definition
body: (template_body)? @class.inner) @class.outer
(function_definition
body: [
(indented_block)
(expression)
(indented_cases)
(block)
] @function.inner) @function.outer
(parameter
name: (identifier) @parameter.inner) @parameter.outer
(class_parameter
name: (identifier) @parameter.inner) @parameter.outer
(case_clause
body: (_) @conditional.inner) @conditional.outer
(comment) @comment.outer
================================================
FILE: queries/scss/textobjects.scm
================================================
; inherits: css
================================================
FILE: queries/slang/textobjects.scm
================================================
; inherits: hlsl
(template_declaration
(interface_specifier)) @class.outer
(template_declaration
(extension_specifier)) @class.outer
(extension_specifier
body: (_) @class.inner) @class.outer
(interface_specifier
body: (_) @class.inner) @class.outer
================================================
FILE: queries/supercollider/textobjects.scm
================================================
; assignment
(variable_definition
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(function_definition
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
; block
(code_block
(_)* @block.inner) @block.outer
; class
(class_def
(class_def_body) @class.inner) @class.outer
; call
(function_call
arguments: (_
.
"("
_+ @call.inner
")")?) @call.outer
; comment
(line_comment) @comment.outer
(block_comment) @comment.outer
; conditional:
(function_call
name: (_) @_name
(#eq? @_name "if")
arguments: (parameter_call_list
(_) @conditional.inner)?) @conditional.outer
; function
((function_block) @function.inner @function.outer)
; loop
(function_call
name: (identifier) @_fname
(#eq? @_fname "while")
arguments: (parameter_call_list
(_) @loop.inner)?) @loop.outer
(function_call
name: (identifier) @_fname
(#eq? @_fname "for")
arguments: (parameter_call_list
(_) @loop.inner .)?) @loop.outer
(function_call
name: (identifier) @_fname
(#eq? @_fname "forBy")
arguments: (parameter_call_list
(_) @loop.inner .)?) @loop.outer
; number
(number) @number.inner
;parameters
(parameter_call_list
(_) @parameter.inner @parameter.outer
.
(",")? @parameter.outer)
(parameter_call_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer .)
(parameter_list
(_) @parameter.inner @parameter.outer
.
(",")? @parameter.outer)
(parameter_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer .)
(collection
(_) @parameter.inner @parameter.outer
.
(",")? @parameter.outer)
(collection
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer .)
; return
(return_statement
(_) @return.inner) @return.outer
================================================
FILE: queries/svelte/textobjects.scm
================================================
; inherits: html
; Svelte-specific text objects
; based on grammar defined at
; https://github.com/tree-sitter-grammars/tree-sitter-svelte
; if block
(if_statement) @block.outer @conditional.outer
(if_statement
(if_start)
.
_+ @block.inner @conditional.inner
.
(if_end))
; each block
(each_statement) @block.outer @loop.outer
(each_statement
(each_start)
.
_+ @block.inner @loop.inner
.
(each_end))
; key block
(key_statement) @block.outer
(key_statement
(key_start)
.
_+ @block.inner
.
(key_end))
; await block
(await_statement) @block.outer
(await_statement
(await_start)
.
_+ @block.inner
.
(await_end))
; snippet block
(snippet_statement) @block.outer
(snippet_statement
(snippet_start)
.
_+ @block.inner
.
(snippet_end))
================================================
FILE: queries/swift/textobjects.scm
================================================
(class_declaration
body: (class_body
.
"{"
_+ @class.inner
"}")) @class.outer
(class_declaration
body: (enum_class_body
.
"{"
_+ @class.inner
"}")) @class.outer
(function_declaration
body: (function_body
.
"{"
_+ @function.inner
"}")) @function.outer
(lambda_literal
("{"
_+ @function.inner
"}")) @function.outer
(call_suffix
(value_arguments
.
"("
_+ @call.inner
")")) @call.outer
(value_argument
value: (_) @parameter.inner) @parameter.outer
(comment) @comment.outer
(multiline_comment) @comment.outer
================================================
FILE: queries/systemverilog/textobjects.scm
================================================
(function_declaration
(function_body_declaration
(tf_port_list)
.
_+ @function.inner
.
"endfunction")) @function.outer
(task_declaration
(task_body_declaration
(tf_port_list)
.
_+ @function.inner
.
"endtask")) @function.outer
[
(seq_block)
(generate_block)
] @block.outer
(seq_block
"begin"
(simple_identifier)?
.
_+ @block.inner
.
"end")
(generate_block
"begin"
(simple_identifier)?
.
_+ @block.inner
.
"end")
[
(one_line_comment)
(block_comment)
] @comment.outer
================================================
FILE: queries/tact/textobjects.scm
================================================
; See: https://github.com/nvim-treesitter/nvim-treesitter-textobjects#built-in-textobjects
; function.inner & outer
; ----------------------
; global
(global_function
body: (_)) @function.outer
(global_function
body: (function_body
.
"{"
_+ @function.inner
"}"))
; init
(init_function
body: (_)) @function.outer
(init_function
body: (function_body
.
"{"
_+ @function.inner
"}"))
; bounced
(bounced_function
body: (_)) @function.outer
(bounced_function
body: (function_body
.
"{"
_+ @function.inner
"}"))
; receive
(receive_function
body: (_)) @function.outer
(receive_function
body: (function_body
.
"{"
_+ @function.inner
"}"))
; external
(external_function
body: (_)) @function.outer
(external_function
body: (function_body
.
"{"
_+ @function.inner
"}"))
; contract/trait function
(storage_function
body: (_)) @function.outer
(storage_function
body: (function_body
.
"{"
_+ @function.inner
"}"))
; class.inner & outer
; -------------------
(struct) @class.outer
(struct
body: (struct_body
.
"{"
_+ @class.inner
"}"))
(message) @class.outer
(message
body: (message_body
.
"{"
_+ @class.inner
"}"))
(contract) @class.outer
(contract
body: (contract_body
.
"{"
_+ @class.inner
"}"))
(trait) @class.outer
(trait
body: (trait_body
.
"{"
_+ @class.inner
"}"))
; attribute.inner & outer
; -----------------------
("@name"
"("
func_name: (func_identifier) @attribute.inner
")") @attribute.outer
(contract_attributes
("@interface"
"("
(string) @attribute.inner
")") @attribute.outer)
(trait_attributes
("@interface"
"("
(string) @attribute.inner
")") @attribute.outer)
(trait_attributes
("@interface"
"("
(string) @attribute.inner
")") @attribute.outer)
; loop.inner & outer
; ------------------
(while_statement) @loop.outer
(while_statement
body: (block_statement
.
"{"
_+ @loop.inner
"}"))
(repeat_statement) @loop.outer
(repeat_statement
body: (block_statement
.
"{"
_+ @loop.inner
"}"))
(do_until_statement) @loop.outer
(do_until_statement
body: (block_statement
.
"{"
_+ @loop.inner
"}"))
(foreach_statement) @loop.outer
(foreach_statement
body: (block_statement
.
"{"
_+ @loop.inner
"}"))
; conditional.inner & outer
; -------------------------
(if_statement) @conditional.outer
(if_statement
consequence: (block_statement
.
"{"
_+ @conditional.inner
"}"))
(if_statement
alternative: (else_clause
(block_statement
.
"{"
_+ @conditional.inner
"}")))
; block.inner & outer
; -------------------
(_
(block_statement) @block.inner) @block.outer
; call.inner & outer
; ------------------
(method_call_expression) @call.outer
(method_call_expression
arguments: (argument_list
.
"("
_+ @call.inner
")"))
(static_call_expression) @call.outer
(static_call_expression
arguments: (argument_list
.
"("
_+ @call.inner
")"))
(instance_expression) @call.outer
(instance_expression
arguments: (instance_argument_list
.
"{"
_+ @call.inner
"}"))
(initOf
name: (identifier) @call.outer
arguments: (argument_list
.
"("
_+ @call.inner
")") @call.outer)
; return.inner & outer
; --------------------
(return_statement
(_) @return.inner) @return.outer
; number.inner
; ------------
(integer) @number.inner
; parameter.inner & outer
; -----------------------
; second and following
(parameter_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
; first
(parameter_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; second and following
(argument_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
; first
(argument_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; second and following
(instance_argument_list
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
; first
(instance_argument_list
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
; single parameter
(receive_function
parameter: (_) @parameter.inner @parameter.outer)
(bounced_function
parameter: (_) @parameter.inner @parameter.outer)
(external_function
parameter: (_) @parameter.inner @parameter.outer)
; assignment.inner & outer w/ lhs & rhs
; -------------------------------------
(let_statement
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(storage_variable
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(global_constant
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(storage_constant
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
(field
name: (_) @assignment.lhs
value: (_) @assignment.inner @assignment.rhs) @assignment.outer
; comment.inner & outer
; ---------------------
(comment) @comment.inner @comment.outer
; quantified captures aren't supported yet:
; (comment)+ @comment.outer
================================================
FILE: queries/terraform/textobjects.scm
================================================
; inherits: hcl
================================================
FILE: queries/toml/textobjects.scm
================================================
[
(integer)
(float)
] @number.inner
(table
(pair) @parameter.inner @parameter.outer)
(inline_table
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(inline_table
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(array
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
(array
.
(_) @parameter.inner @parameter.outer
.
","? @parameter.outer)
(comment) @comment.outer
================================================
FILE: queries/tsx/
gitextract_1hjhbj7p/
├── .github/
│ └── workflows/
│ ├── test.yaml
│ └── update-queries.yaml
├── .gitignore
├── AGENTS.md
├── Cask
├── Eask
├── LICENSE
├── Makefile
├── README.md
├── additional-queries/
│ ├── README.md
│ ├── c/
│ │ └── textobjects.scm
│ ├── go/
│ │ └── textobjects.scm
│ ├── python/
│ │ └── textobjects.scm
│ └── rust/
│ └── textobjects.scm
├── converter/
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ └── main_test.go
├── docs/
│ └── updating-neovim-queries.md
├── evil-textobj-tree-sitter-core.el
├── evil-textobj-tree-sitter-query-test.el
├── evil-textobj-tree-sitter-test.el
├── evil-textobj-tree-sitter-thing-at-point.el
├── evil-textobj-tree-sitter.el
├── fixtures/
│ ├── bash/
│ │ └── textobjects.scm
│ ├── javascript/
│ │ └── textobjects.scm
│ ├── tsx/
│ │ └── textobjects.scm
│ ├── typescript/
│ │ └── textobjects.scm
│ └── zig/
│ └── textobjects.scm
├── flake.nix
├── queries/
│ ├── apex/
│ │ └── textobjects.scm
│ ├── astro/
│ │ └── textobjects.scm
│ ├── bash/
│ │ └── textobjects.scm
│ ├── bibtex/
│ │ └── textobjects.scm
│ ├── c/
│ │ └── textobjects.scm
│ ├── c_sharp/
│ │ └── textobjects.scm
│ ├── cmake/
│ │ └── textobjects.scm
│ ├── cpp/
│ │ └── textobjects.scm
│ ├── css/
│ │ └── textobjects.scm
│ ├── cuda/
│ │ └── textobjects.scm
│ ├── dart/
│ │ └── textobjects.scm
│ ├── dockerfile/
│ │ └── textobjects.scm
│ ├── ecma/
│ │ └── textobjects.scm
│ ├── elixir/
│ │ └── textobjects.scm
│ ├── elm/
│ │ └── textobjects.scm
│ ├── enforce/
│ │ └── textobjects.scm
│ ├── fennel/
│ │ └── textobjects.scm
│ ├── fish/
│ │ └── textobjects.scm
│ ├── foam/
│ │ └── textobjects.scm
│ ├── gdscript/
│ │ └── textobjects.scm
│ ├── git_config/
│ │ └── textobjects.scm
│ ├── gleam/
│ │ └── textobjects.scm
│ ├── glimmer/
│ │ └── textobjects.scm
│ ├── glsl/
│ │ └── textobjects.scm
│ ├── go/
│ │ └── textobjects.scm
│ ├── hack/
│ │ └── textobjects.scm
│ ├── haskell/
│ │ └── textobjects.scm
│ ├── hcl/
│ │ └── textobjects.scm
│ ├── heex/
│ │ └── textobjects.scm
│ ├── hlsl/
│ │ └── textobjects.scm
│ ├── html/
│ │ └── textobjects.scm
│ ├── inko/
│ │ └── textobjects.scm
│ ├── java/
│ │ └── textobjects.scm
│ ├── javascript/
│ │ └── textobjects.scm
│ ├── json/
│ │ └── textobjects.scm
│ ├── jsx/
│ │ └── textobjects.scm
│ ├── julia/
│ │ └── textobjects.scm
│ ├── kotlin/
│ │ └── textobjects.scm
│ ├── latex/
│ │ └── textobjects.scm
│ ├── lua/
│ │ └── textobjects.scm
│ ├── markdown/
│ │ └── textobjects.scm
│ ├── matlab/
│ │ └── textobjects.scm
│ ├── nasm/
│ │ └── textobjects.scm
│ ├── nim/
│ │ └── textobjects.scm
│ ├── nix/
│ │ └── textobjects.scm
│ ├── ocaml/
│ │ └── textobjects.scm
│ ├── odin/
│ │ └── textobjects.scm
│ ├── perl/
│ │ └── textobjects.scm
│ ├── php/
│ │ └── textobjects.scm
│ ├── php_only/
│ │ └── textobjects.scm
│ ├── python/
│ │ └── textobjects.scm
│ ├── ql/
│ │ └── textobjects.scm
│ ├── query/
│ │ └── textobjects.scm
│ ├── r/
│ │ └── textobjects.scm
│ ├── readline/
│ │ └── textobjects.scm
│ ├── rst/
│ │ └── textobjects.scm
│ ├── ruby/
│ │ └── textobjects.scm
│ ├── rust/
│ │ └── textobjects.scm
│ ├── scala/
│ │ └── textobjects.scm
│ ├── scss/
│ │ └── textobjects.scm
│ ├── slang/
│ │ └── textobjects.scm
│ ├── supercollider/
│ │ └── textobjects.scm
│ ├── svelte/
│ │ └── textobjects.scm
│ ├── swift/
│ │ └── textobjects.scm
│ ├── systemverilog/
│ │ └── textobjects.scm
│ ├── tact/
│ │ └── textobjects.scm
│ ├── terraform/
│ │ └── textobjects.scm
│ ├── toml/
│ │ └── textobjects.scm
│ ├── tsx/
│ │ └── textobjects.scm
│ ├── twig/
│ │ └── textobjects.scm
│ ├── typescript/
│ │ └── textobjects.scm
│ ├── v/
│ │ └── textobjects.scm
│ ├── verilog/
│ │ └── textobjects.scm
│ ├── vim/
│ │ └── textobjects.scm
│ ├── vue/
│ │ └── textobjects.scm
│ ├── wgsl/
│ │ └── textobjects.scm
│ ├── wgsl_bevy/
│ │ └── textobjects.scm
│ ├── yaml/
│ │ └── textobjects.scm
│ ├── zig/
│ │ └── textobjects.scm
│ └── zsh/
│ └── textobjects.scm
├── scripts/
│ ├── append-additional-helix-queries
│ ├── check-available
│ ├── fix-queries
│ ├── get-helix-queries
│ └── get-neovim-queries
└── treesit-queries/
├── _jsx/
│ └── textobjects.scm
├── _typescript/
│ └── textobjects.scm
├── ada/
│ └── textobjects.scm
├── adl/
│ └── textobjects.scm
├── amber/
│ └── textobjects.scm
├── awk/
│ └── textobjects.scm
├── bash/
│ └── textobjects.scm
├── basic/
│ └── textobjects.scm
├── blade/
│ └── textobjects.scm
├── c/
│ └── textobjects.scm
├── c-sharp/
│ └── textobjects.scm
├── caddyfile/
│ └── textobjects.scm
├── cairo/
│ └── textobjects.scm
├── clojure/
│ └── textobjects.scm
├── cmake/
│ └── textobjects.scm
├── codeql/
│ └── textobjects.scm
├── cpp/
│ └── textobjects.scm
├── cross-config/
│ └── textobjects.scm
├── crystal/
│ └── textobjects.scm
├── cylc/
│ └── textobjects.scm
├── d/
│ └── textobjects.scm
├── dart/
│ └── textobjects.scm
├── dhall/
│ └── textobjects.scm
├── docker-bake/
│ └── textobjects.scm
├── docker-compose/
│ └── textobjects.scm
├── dockerfile/
│ └── textobjects.scm
├── doxyfile/
│ └── textobjects.scm
├── earthfile/
│ └── textobjects.scm
├── ecma/
│ └── textobjects.scm
├── eiffel/
│ └── textobjects.scm
├── elixir/
│ └── textobjects.scm
├── elm/
│ └── textobjects.scm
├── env/
│ └── textobjects.scm
├── erlang/
│ └── textobjects.scm
├── fga/
│ └── textobjects.scm
├── fish/
│ └── textobjects.scm
├── freebasic/
│ └── textobjects.scm
├── gas/
│ └── textobjects.scm
├── gdscript/
│ └── textobjects.scm
├── git-cliff-config/
│ └── textobjects.scm
├── git-commit/
│ └── textobjects.scm
├── git-config/
│ └── textobjects.scm
├── github-action/
│ └── textobjects.scm
├── gitlab-ci/
│ └── textobjects.scm
├── gjs/
│ └── textobjects.scm
├── gleam/
│ └── textobjects.scm
├── glsl/
│ └── textobjects.scm
├── go/
│ └── textobjects.scm
├── godot-resource/
│ └── textobjects.scm
├── graphql/
│ └── textobjects.scm
├── gren/
│ └── textobjects.scm
├── gts/
│ └── textobjects.scm
├── haskell/
│ └── textobjects.scm
├── hcl/
│ └── textobjects.scm
├── heex/
│ └── textobjects.scm
├── hocon/
│ └── textobjects.scm
├── html/
│ └── textobjects.scm
├── hurl/
│ └── textobjects.scm
├── inko/
│ └── textobjects.scm
├── java/
│ └── textobjects.scm
├── javascript/
│ └── textobjects.scm
├── jjconfig/
│ └── textobjects.scm
├── jq/
│ └── textobjects.scm
├── json/
│ └── textobjects.scm
├── json-ld/
│ └── textobjects.scm
├── json5/
│ └── textobjects.scm
├── jsonc/
│ └── textobjects.scm
├── jsx/
│ └── textobjects.scm
├── julia/
│ └── textobjects.scm
├── just/
│ └── textobjects.scm
├── kdl/
│ └── textobjects.scm
├── kotlin/
│ └── textobjects.scm
├── koto/
│ └── textobjects.scm
├── latex/
│ └── textobjects.scm
├── llvm/
│ └── textobjects.scm
├── llvm-mir/
│ └── textobjects.scm
├── lua/
│ └── textobjects.scm
├── luau/
│ └── textobjects.scm
├── mail/
│ └── textobjects.scm
├── matlab/
│ └── textobjects.scm
├── miseconfig/
│ └── textobjects.scm
├── mojo/
│ └── textobjects.scm
├── nasm/
│ └── textobjects.scm
├── nestedtext/
│ └── textobjects.scm
├── nim/
│ └── textobjects.scm
├── nix/
│ └── textobjects.scm
├── nu/
│ └── textobjects.scm
├── odin/
│ └── textobjects.scm
├── ohm/
│ └── textobjects.scm
├── opencl/
│ └── textobjects.scm
├── pascal/
│ └── textobjects.scm
├── penrose/
│ └── textobjects.scm
├── perl/
│ └── textobjects.scm
├── pest/
│ └── textobjects.scm
├── php/
│ └── textobjects.scm
├── picat/
│ └── textobjects.scm
├── pkgbuild/
│ └── textobjects.scm
├── po/
│ └── textobjects.scm
├── ponylang/
│ └── textobjects.scm
├── prisma/
│ └── textobjects.scm
├── properties/
│ └── textobjects.scm
├── protobuf/
│ └── textobjects.scm
├── purescript/
│ └── textobjects.scm
├── python/
│ └── textobjects.scm
├── qml/
│ └── textobjects.scm
├── rescript/
│ └── textobjects.scm
├── robots.txt/
│ └── textobjects.scm
├── rshtml/
│ └── textobjects.scm
├── ruby/
│ └── textobjects.scm
├── rust/
│ └── textobjects.scm
├── rust-format-args-macro/
│ └── textobjects.scm
├── sage/
│ └── textobjects.scm
├── scala/
│ └── textobjects.scm
├── scheme/
│ └── textobjects.scm
├── shellcheckrc/
│ └── textobjects.scm
├── slang/
│ └── textobjects.scm
├── slint/
│ └── textobjects.scm
├── solidity/
│ └── textobjects.scm
├── sourcepawn/
│ └── textobjects.scm
├── sql/
│ └── textobjects.scm
├── starlark/
│ └── textobjects.scm
├── sway/
│ └── textobjects.scm
├── swift/
│ └── textobjects.scm
├── tablegen/
│ └── textobjects.scm
├── tact/
│ └── textobjects.scm
├── textproto/
│ └── textobjects.scm
├── tilt/
│ └── textobjects.scm
├── toml/
│ └── textobjects.scm
├── tsx/
│ └── textobjects.scm
├── typescript/
│ └── textobjects.scm
├── typespec/
│ └── textobjects.scm
├── unison/
│ └── textobjects.scm
├── v/
│ └── textobjects.scm
├── vala/
│ └── textobjects.scm
├── verilog/
│ └── textobjects.scm
├── wesl/
│ └── textobjects.scm
├── wgsl/
│ └── textobjects.scm
├── woodpecker-ci/
│ └── textobjects.scm
├── wren/
│ └── textobjects.scm
├── xml/
│ └── textobjects.scm
├── yaml/
│ └── textobjects.scm
└── zig/
└── textobjects.scm
SYMBOL INDEX (8 symbols across 2 files)
FILE: converter/main.go
function reprint (line 12) | func reprint(col []string, mr []string) []string {
function tokenize (line 44) | func tokenize(input string) []string {
function reformat (line 76) | func reformat(input string) string {
function main (line 119) | func main() {
FILE: converter/main_test.go
function TestReformatExact (line 10) | func TestReformatExact(t *testing.T) {
function TestReformatSimple (line 22) | func TestReformatSimple(t *testing.T) {
function TestReformatQuotedBracket (line 44) | func TestReformatQuotedBracket(t *testing.T) {
function TestReformatRoot (line 66) | func TestReformatRoot(t *testing.T) {
Condensed preview — 257 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (291K chars).
[
{
"path": ".github/workflows/test.yaml",
"chars": 659,
"preview": "name: Run tests\n\non:\n workflow_dispatch:\n pull_request:\n push:\n\njobs:\n check:\n runs-on: ubuntu-latest\n strateg"
},
{
"path": ".github/workflows/update-queries.yaml",
"chars": 898,
"preview": "name: Update tree-siter queries\non:\n schedule:\n - cron: '0 13 * * 5'\n workflow_dispatch:\njobs:\n update-queries:\n "
},
{
"path": ".gitignore",
"chars": 32,
"preview": "__debug_bin\n.cask/\n.eask/\n*.elc\n"
},
{
"path": "AGENTS.md",
"chars": 3277,
"preview": "## Project Overview\n\nAn Emacs package providing tree-sitter powered text objects for `evil-mode` and `thing-at-point`. W"
},
{
"path": "Cask",
"chars": 273,
"preview": "(source gnu)\n(source melpa)\n\n(package-file \"evil-textobj-tree-sitter.el\")\n\n(development\n (depends-on \"ert\")\n (depends-on"
},
{
"path": "Eask",
"chars": 585,
"preview": ";; -*- mode: eask; lexical-binding: t -*-\n\n(package \"evil-textobj-tree-sitter\"\n \"0.5\"\n \"Provides evil te"
},
{
"path": "LICENSE",
"chars": 11340,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "Makefile",
"chars": 360,
"preview": "compile:\n\teask compile\n\nlint:\n\teask lint package evil-textobj-tree-sitter.el\n\ncheckdoc:\n\teask lint checkdoc\n\ntest: insta"
},
{
"path": "README.md",
"chars": 8240,
"preview": "# evil-textobj-tree-sitter\n\n[](https://melpa.org/"
},
{
"path": "additional-queries/README.md",
"chars": 243,
"preview": "These folder contains queries that will not be accepted to upstream helix (not neovim as we are no longer maintaining it"
},
{
"path": "additional-queries/c/textobjects.scm",
"chars": 227,
"preview": "(for_statement\n body: (_) @loop.inner) @loop.outer\n\n(while_statement\n body: (_) @loop.inner) @loop.outer\n\n(do_statement\n"
},
{
"path": "additional-queries/go/textobjects.scm",
"chars": 457,
"preview": "(if_statement\n consequence: (block) @conditional.inner) @conditional.outer\n\n(if_statement\n alternative: (block) @condi"
},
{
"path": "additional-queries/python/textobjects.scm",
"chars": 176,
"preview": "(for_statement\n body: (_) @loop.inner) @loop.outer\n\n(while_statement\n body: (_) @loop.inner) @loop.outer\n\n(if_statement\n"
},
{
"path": "additional-queries/rust/textobjects.scm",
"chars": 237,
"preview": "(loop_expression\n body: (_) @loop.inner) @loop.outer\n\n(while_expression\n body: (_) @loop.inner) @loop.outer\n\n(for_expr"
},
{
"path": "converter/go.mod",
"chars": 234,
"preview": "module github.com/meain/evil-texobj-treesitter-converter\n\ngo 1.16\n\nrequire (\n\tgithub.com/andreyvit/diff v0.0.0-201704060"
},
{
"path": "converter/go.sum",
"chars": 1869,
"preview": "github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=\ngithub.com/"
},
{
"path": "converter/main.go",
"chars": 2317,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n\t\"regexp\"\n\t\"strings\"\n)\n\nfunc reprint(col []string, mr []string) "
},
{
"path": "converter/main_test.go",
"chars": 1931,
"preview": "package main\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/andreyvit/diff\"\n)\n\nfunc TestReformatExact(t *testing.T) {\n\tin"
},
{
"path": "docs/updating-neovim-queries.md",
"chars": 4327,
"preview": "# Doc for updating neovim queries\n\nWe need to manually edit the neovim queries after pulling it down as we currently do "
},
{
"path": "evil-textobj-tree-sitter-core.el",
"chars": 21468,
"preview": ";;; evil-textobj-tree-sitter-core.el --- Provides evil textobjects using tree-sitter -*- lexical-binding: t; -*-\n\n;; URL"
},
{
"path": "evil-textobj-tree-sitter-query-test.el",
"chars": 4288,
"preview": ";;; Code:\n\n(require 'tree-sitter-langs)\n(require 'evil-textobj-tree-sitter)\n(require 'ert)\n\n(defun evil-textobj-tree-sit"
},
{
"path": "evil-textobj-tree-sitter-test.el",
"chars": 13526,
"preview": ";;; evil-textobj-tree-sitter-test.el --- Tests for evil-textobj-tree-sitter -*- lexical-binding: t -*-\n\n;;; Commentary:\n"
},
{
"path": "evil-textobj-tree-sitter-thing-at-point.el",
"chars": 2769,
"preview": ";;; evil-textobj-tree-sitter-thing-at-point.el --- Provides thing-at-point integration for tree-sitter textobjects -*- l"
},
{
"path": "evil-textobj-tree-sitter.el",
"chars": 1635,
"preview": ";;; evil-textobj-tree-sitter.el --- Provides evil textobjects using tree-sitter -*- lexical-binding: t; -*-\n\n;; URL: htt"
},
{
"path": "fixtures/bash/textobjects.scm",
"chars": 281,
"preview": "(function_definition\n (_) @function.inner ) @function.outer\n\n(case_statement) @conditional.outer\n\n(if_statement\n (_) @"
},
{
"path": "fixtures/javascript/textobjects.scm",
"chars": 182,
"preview": "; inherits: (jsx)\n(function_declaration\n body: (statement_block) @function.inner) @function.outer\n\n(export_statement\n "
},
{
"path": "fixtures/tsx/textobjects.scm",
"chars": 27,
"preview": "; inherits: typescript,jsx\n"
},
{
"path": "fixtures/typescript/textobjects.scm",
"chars": 25,
"preview": "; inherits: (javascript)\n"
},
{
"path": "fixtures/zig/textobjects.scm",
"chars": 169,
"preview": ";; \"Classes\"\n(VarDecl \n (_ (_ (ContainerDecl (ContainerMembers)? @class.inner)))) @class.outer\n\n;; functions\n(_ \n (FnP"
},
{
"path": "flake.nix",
"chars": 1134,
"preview": "{\n description = \"evil-textobj-tree-sitter development environment\";\n\n inputs = {\n nixpkgs.url = \"github:NixOS/nixp"
},
{
"path": "queries/apex/textobjects.scm",
"chars": 1589,
"preview": "(class_declaration\n body: (class_body) @class.inner) @class.outer\n\n(method_declaration) @function.outer\n\n(method_declar"
},
{
"path": "queries/astro/textobjects.scm",
"chars": 18,
"preview": "; inherits: html\n\n"
},
{
"path": "queries/bash/textobjects.scm",
"chars": 665,
"preview": "(function_definition) @function.outer\n\n(function_definition\n body: (compound_statement\n .\n \"{\"\n _+ @function.i"
},
{
"path": "queries/bibtex/textobjects.scm",
"chars": 48,
"preview": "(entry) @block.outer\n\n(field) @statement.outer\n\n"
},
{
"path": "queries/c/textobjects.scm",
"chars": 2726,
"preview": "(declaration\n declarator: (function_declarator)) @function.outer\n\n(function_definition\n body: (compound_statement)) @f"
},
{
"path": "queries/c_sharp/textobjects.scm",
"chars": 3741,
"preview": "(class_declaration\n body: (declaration_list\n .\n \"{\"\n _* @class.inner\n \"}\")) @class.outer\n\n(struct_declarati"
},
{
"path": "queries/cmake/textobjects.scm",
"chars": 452,
"preview": "(function_def) @function.outer\n\n(function_def\n .\n (function_command)\n _+ @function.inner\n (endfunction_command) .)\n\n"
},
{
"path": "queries/cpp/textobjects.scm",
"chars": 1528,
"preview": "; inherits: c\n\n(class_specifier\n body: (_) @class.inner) @class.outer\n\n(field_declaration\n type: (enum_specifier)\n de"
},
{
"path": "queries/css/textobjects.scm",
"chars": 268,
"preview": "[\n (integer_value)\n (float_value)\n (color_value)\n] @number.inner\n\n(declaration\n (property_name) @assignment.lhs\n .\n"
},
{
"path": "queries/cuda/textobjects.scm",
"chars": 17,
"preview": "; inherits: cpp\n\n"
},
{
"path": "queries/dart/textobjects.scm",
"chars": 2360,
"preview": "; class\n((annotation)? @class.outer\n .\n (class_definition\n body: (class_body) @class.inner) @class.outer)\n\n(mixin_d"
},
{
"path": "queries/dockerfile/textobjects.scm",
"chars": 52,
"preview": "(expose_instruction\n (expose_port) @number.inner)\n\n"
},
{
"path": "queries/ecma/textobjects.scm",
"chars": 6398,
"preview": "(function_declaration\n body: (statement_block)) @function.outer\n\n(generator_function_declaration\n body: (statement_blo"
},
{
"path": "queries/elixir/textobjects.scm",
"chars": 3672,
"preview": "; Block Objects\n([\n (do_block\n \"do\"\n _+ @block.inner\n \"end\")\n (do_block\n \"do\"\n .\n ((_) @block.inner)"
},
{
"path": "queries/elm/textobjects.scm",
"chars": 1408,
"preview": "; Functions\n; top level function with type annotation and doc comment\n((module_declaration)\n (block_comment) @function."
},
{
"path": "queries/enforce/textobjects.scm",
"chars": 888,
"preview": "[\n (comment_line)\n (comment_block)\n (doc_line)\n (doc_block)\n] @comment.outer\n\n[\n (literal_int)\n (literal_float)\n] "
},
{
"path": "queries/fennel/textobjects.scm",
"chars": 2960,
"preview": "; https://fennel-lang.org/reference\n(comment\n body: (comment_body) @comment.inner) @comment.outer\n\n(_\n .\n \"(\"\n \")\" ."
},
{
"path": "queries/fish/textobjects.scm",
"chars": 1316,
"preview": "; assignment\n(command\n name: (word) @_command\n argument: (word) @_varname @assignment.lhs @assignment.inner\n argument"
},
{
"path": "queries/foam/textobjects.scm",
"chars": 259,
"preview": "(dict) @class.outer\n\n(dict_core) @class.inner\n\n(key_value\n value: _? @function.inner\n (_)* @function.inner\n _? @param"
},
{
"path": "queries/gdscript/textobjects.scm",
"chars": 1049,
"preview": "(function_definition\n body: (_) @function.inner) @function.outer\n\n(constructor_definition\n body: (_) @function.inner) "
},
{
"path": "queries/git_config/textobjects.scm",
"chars": 331,
"preview": "; assignments\n(variable\n (_) @assignment.lhs @assignment.inner\n value: (_) @assignment.rhs) @assignment.outer\n\n(variab"
},
{
"path": "queries/gleam/textobjects.scm",
"chars": 5629,
"preview": "; assignments\n(let\n pattern: (_) @assignment.lhs @assignment.inner\n value: (_) @assignment.rhs) @assignment.outer\n\n(le"
},
{
"path": "queries/glimmer/textobjects.scm",
"chars": 777,
"preview": "[\n (element_node)\n (block_statement)\n] @function.outer\n\n[\n (mustache_statement)\n (block_statement_start)\n] @block.ou"
},
{
"path": "queries/glsl/textobjects.scm",
"chars": 15,
"preview": "; inherits: c\n\n"
},
{
"path": "queries/go/textobjects.scm",
"chars": 2841,
"preview": "; inner function textobject\n(function_declaration\n body: (block\n .\n \"{\"\n _+ @function.inner\n \"}\"))\n\n; inner"
},
{
"path": "queries/hack/textobjects.scm",
"chars": 38,
"preview": "(method_declaration) @function.outer\n\n"
},
{
"path": "queries/haskell/textobjects.scm",
"chars": 2394,
"preview": "(apply\n .\n function: (_)\n _+ @call.inner) @call.outer\n\n(infix\n (_)\n [\n (infix_id\n (variable)) ; x `plus` y\n"
},
{
"path": "queries/hcl/textobjects.scm",
"chars": 1224,
"preview": "(attribute\n (identifier) @assignment.lhs\n (expression) @assignment.inner @assignment.rhs) @assignment.outer\n\n(attribut"
},
{
"path": "queries/heex/textobjects.scm",
"chars": 206,
"preview": "(tag) @function.outer\n\n(tag\n (start_tag)\n .\n (_) @function.inner\n .\n (end_tag))\n\n(attribute_value) @attribute.inner"
},
{
"path": "queries/hlsl/textobjects.scm",
"chars": 17,
"preview": "; inherits: cpp\n\n"
},
{
"path": "queries/html/textobjects.scm",
"chars": 885,
"preview": "(element) @function.outer\n\n(element\n (start_tag)\n .\n (_) @function.inner\n .\n (end_tag))\n\n(attribute_value) @attribu"
},
{
"path": "queries/inko/textobjects.scm",
"chars": 3659,
"preview": "; Classes\n(class) @class.outer\n\n(class\n body: (class_body\n .\n \"{\"\n _+ @class.inner\n \"}\"))\n\n; Traits\n(trait)"
},
{
"path": "queries/java/textobjects.scm",
"chars": 1756,
"preview": "(class_declaration\n body: (class_body) @class.inner) @class.outer\n\n(method_declaration) @function.outer\n\n(method_declar"
},
{
"path": "queries/javascript/textobjects.scm",
"chars": 22,
"preview": "; inherits: ecma,jsx\n\n"
},
{
"path": "queries/json/textobjects.scm",
"chars": 26,
"preview": "(comment) @comment.outer\n\n"
},
{
"path": "queries/jsx/textobjects.scm",
"chars": 124,
"preview": "; inherits: ecma\n\n(jsx_attribute) @attribute.outer\n\n(jsx_attribute\n (property_identifier)\n (_\n (_) @attribute.inner"
},
{
"path": "queries/julia/textobjects.scm",
"chars": 3312,
"preview": "; Blocks\n(compound_statement) @block.outer\n\n(compound_statement\n .\n (_) @block.inner\n (_)? @block.inner .)\n\n(quote_st"
},
{
"path": "queries/kotlin/textobjects.scm",
"chars": 1201,
"preview": "(class_declaration\n [\n (class_body)\n (enum_class_body)\n ]? @class.inner) @class.outer\n\n[\n (function_declaration"
},
{
"path": "queries/latex/textobjects.scm",
"chars": 971,
"preview": "(generic_environment\n .\n (_)\n _+ @block.inner\n (_) .) @block.outer\n\n((generic_environment\n (begin\n name: (curly_"
},
{
"path": "queries/lua/textobjects.scm",
"chars": 85,
"preview": "; block\n(_\n (block) @block.inner) @block.outer\n\n; call\n(function_call) @call.outer\n\n"
},
{
"path": "queries/markdown/textobjects.scm",
"chars": 273,
"preview": "(atx_heading\n heading_content: (_) @class.inner) @class.outer\n\n(setext_heading\n heading_content: (_) @class.inner) @cl"
},
{
"path": "queries/matlab/textobjects.scm",
"chars": 3027,
"preview": "(_\n (block) @block.inner) @block.outer\n\n(block\n (_) @statement.outer)\n\n(source_file\n (_) @statement.outer)\n\n(function"
},
{
"path": "queries/nasm/textobjects.scm",
"chars": 483,
"preview": "; adapted from https://github.com/naclsn/tree-sitter-nasm/blob/main/queries/textobjects.scm\n(preproc_multiline_macro\n b"
},
{
"path": "queries/nim/textobjects.scm",
"chars": 10959,
"preview": "; ==============================================================================\n; @attribute.inner\n; @attribute.outer\n;"
},
{
"path": "queries/nix/textobjects.scm",
"chars": 434,
"preview": "; named function\n(binding\n (function_expression)) @function.outer\n\n; anonymous function\n(function_expression\n (_) ; ar"
},
{
"path": "queries/ocaml/textobjects.scm",
"chars": 2147,
"preview": "(value_definition\n (let_binding\n ; let f x = 1 but not let x = 1\n (parameter)+\n body: (_) @function.inner)) @f"
},
{
"path": "queries/odin/textobjects.scm",
"chars": 1459,
"preview": "; procedures\n(procedure_declaration\n (_\n (block\n .\n \"{\"\n _+ @function.inner\n \"}\"))) @function.ou"
},
{
"path": "queries/perl/textobjects.scm",
"chars": 85,
"preview": "(comment) @comment.outer\n\n(quoted_regexp) @regex.outer\n\n(match_regexp) @regex.outer\n\n"
},
{
"path": "queries/php/textobjects.scm",
"chars": 3514,
"preview": "; functions\n(function_definition\n body: (compound_statement\n .\n \"{\"\n _+ @function.inner\n \"}\"))\n\n(function_d"
},
{
"path": "queries/php_only/textobjects.scm",
"chars": 16,
"preview": "; inherits php\n\n"
},
{
"path": "queries/python/textobjects.scm",
"chars": 3709,
"preview": "(decorated_definition\n (function_definition)) @function.outer\n\n(function_definition\n body: (block)? @function.inner) @"
},
{
"path": "queries/ql/textobjects.scm",
"chars": 526,
"preview": "; class textobject\n(dataclass\n (typeExpr)\n (_) @class.inner) @class.outer\n\n; function textobject\n(charpred\n (classNam"
},
{
"path": "queries/query/textobjects.scm",
"chars": 197,
"preview": "(comment) @comment.outer\n\n[\n (named_node)\n (grouping)\n (list)\n] @block.outer\n\n(program\n [\n (named_node)\n (grou"
},
{
"path": "queries/r/textobjects.scm",
"chars": 1137,
"preview": "; block\n; call\n(call) @call.outer\n\n(arguments) @call.inner\n\n; class\n; comment\n(comment) @comment.outer\n\n; conditional\n(i"
},
{
"path": "queries/readline/textobjects.scm",
"chars": 255,
"preview": "(variable_setting) @statement.outer\n\n(comment) @comment.outer\n\n((comment) @comment.inner)\n\n[\n (alternative)\n (conseque"
},
{
"path": "queries/rst/textobjects.scm",
"chars": 546,
"preview": "(directive\n body: (body) @function.inner) @function.outer\n\n(section\n (title) @class.inner) @class.outer\n\n(transition) "
},
{
"path": "queries/ruby/textobjects.scm",
"chars": 967,
"preview": "; @functions\n(method\n body: (body_statement) @function.inner)\n\n(method) @function.outer\n\n(singleton_method\n body: (bod"
},
{
"path": "queries/rust/textobjects.scm",
"chars": 6614,
"preview": "; functions\n(function_signature_item) @function.outer\n\n(function_item) @function.outer\n\n(function_item\n body: (block\n "
},
{
"path": "queries/scala/textobjects.scm",
"chars": 516,
"preview": "(class_definition\n body: (template_body)? @class.inner) @class.outer\n\n(object_definition\n body: (template_body)? @clas"
},
{
"path": "queries/scss/textobjects.scm",
"chars": 17,
"preview": "; inherits: css\n\n"
},
{
"path": "queries/slang/textobjects.scm",
"chars": 262,
"preview": "; inherits: hlsl\n\n(template_declaration\n (interface_specifier)) @class.outer\n\n(template_declaration\n (extension_specif"
},
{
"path": "queries/supercollider/textobjects.scm",
"chars": 1812,
"preview": "; assignment\n(variable_definition\n name: (_) @assignment.lhs\n value: (_) @assignment.inner @assignment.rhs) @assignmen"
},
{
"path": "queries/svelte/textobjects.scm",
"chars": 787,
"preview": "; inherits: html\n\n; Svelte-specific text objects\n; based on grammar defined at\n; https://github.com/tree-sitter-grammars"
},
{
"path": "queries/swift/textobjects.scm",
"chars": 596,
"preview": "(class_declaration\n body: (class_body\n .\n \"{\"\n _+ @class.inner\n \"}\")) @class.outer\n\n(class_declaration\n bo"
},
{
"path": "queries/systemverilog/textobjects.scm",
"chars": 547,
"preview": "(function_declaration\n (function_body_declaration\n (tf_port_list)\n .\n _+ @function.inner\n .\n \"endfunctio"
},
{
"path": "queries/tact/textobjects.scm",
"chars": 5275,
"preview": "; See: https://github.com/nvim-treesitter/nvim-treesitter-textobjects#built-in-textobjects\n; function.inner & outer\n; --"
},
{
"path": "queries/terraform/textobjects.scm",
"chars": 17,
"preview": "; inherits: hcl\n\n"
},
{
"path": "queries/toml/textobjects.scm",
"chars": 447,
"preview": "[\n (integer)\n (float)\n] @number.inner\n\n(table\n (pair) @parameter.inner @parameter.outer)\n\n(inline_table\n \",\" @parame"
},
{
"path": "queries/tsx/textobjects.scm",
"chars": 28,
"preview": "; inherits: typescript,jsx\n\n"
},
{
"path": "queries/twig/textobjects.scm",
"chars": 434,
"preview": "; comments\n(comment) @comment.outer\n\n; statement\n(statement_directive) @statement.outer\n\n; @parameter\n(arguments\n \",\" @"
},
{
"path": "queries/typescript/textobjects.scm",
"chars": 1482,
"preview": "; inherits: ecma\n\n(interface_declaration) @class.outer\n\n(interface_declaration\n body: (interface_body\n .\n \"{\"\n "
},
{
"path": "queries/v/textobjects.scm",
"chars": 1781,
"preview": "; assignment\n[\n (var_declaration\n var_list: (_) @assignment.lhs\n expression_list: (_)* @assignment.rhs)\n (assign"
},
{
"path": "queries/verilog/textobjects.scm",
"chars": 26,
"preview": "(comment) @comment.outer\n\n"
},
{
"path": "queries/vim/textobjects.scm",
"chars": 853,
"preview": "(comment) @comment.outer\n\n(function_definition\n (body) @function.inner) @function.outer\n\n(parameters\n (identifier) @pa"
},
{
"path": "queries/vue/textobjects.scm",
"chars": 118,
"preview": "(element) @function.outer\n\n[\n (attribute)\n (directive_attribute)\n] @call.outer\n\n(attribute_value) @parameter.outer\n\n"
},
{
"path": "queries/wgsl/textobjects.scm",
"chars": 958,
"preview": "(function_declaration) @function.outer\n\n(function_declaration\n body: (compound_statement\n .\n \"{\"\n _+ @function"
},
{
"path": "queries/wgsl_bevy/textobjects.scm",
"chars": 17,
"preview": "; inherits wgsl\n\n"
},
{
"path": "queries/yaml/textobjects.scm",
"chars": 533,
"preview": "; assignment, statement\n(block_mapping_pair\n key: (_) @assignment.lhs\n value: (_) @assignment.rhs) @assignment.outer @"
},
{
"path": "queries/zig/textobjects.scm",
"chars": 1597,
"preview": "; \"Classes\"\n(variable_declaration\n (struct_declaration)) @class.outer\n\n(variable_declaration\n (struct_declaration\n "
},
{
"path": "queries/zsh/textobjects.scm",
"chars": 665,
"preview": "(function_definition) @function.outer\n\n(function_definition\n body: (compound_statement\n .\n \"{\"\n _+ @function.i"
},
{
"path": "scripts/append-additional-helix-queries",
"chars": 336,
"preview": "#!/bin/sh\n\nset -e\n\nls additional-queries/**/*.scm |\n while read -r file; do\n language=\"$(dirname \"$file\" | xar"
},
{
"path": "scripts/check-available",
"chars": 836,
"preview": "#!/bin/sh\n# Get a list of languages currently supportable and supported\n\ntmpdir=$(mktemp -d)\ngit clone --depth 1 https:/"
},
{
"path": "scripts/fix-queries",
"chars": 213,
"preview": "#!/bin/sh\n\nset -e\n\nfind queries -type f |\n\twhile read -r file; do\n echo \"Processing $file\"\n\t\tgo run converter/mai"
},
{
"path": "scripts/get-helix-queries",
"chars": 1062,
"preview": "#!/bin/sh\n\nset -e\n\ntmpdir=\"$(mktemp -d)\"\ngit clone --depth 1 https://github.com/helix-editor/helix \"$tmpdir\"\n\nHELIX_DIR="
},
{
"path": "scripts/get-neovim-queries",
"chars": 210,
"preview": "#!/bin/sh\n\nset -e\n\nrm -rf /tmp/nts\ngit clone --depth 1 --branch main \\\n https://github.com/nvim-treesitter/nvim-trees"
},
{
"path": "treesit-queries/_jsx/textobjects.scm",
"chars": 235,
"preview": "; See runtime/queries/ecma/README.md for more info.\n\n(jsx_self_closing_element) @xml-element.outer @xml-element.inner\n\n("
},
{
"path": "treesit-queries/_typescript/textobjects.scm",
"chars": 195,
"preview": "[\n (interface_declaration \n body:(_) @class.inner)\n (type_alias_declaration \n value: (_) @class.inner)\n] @class."
},
{
"path": "treesit-queries/ada/textobjects.scm",
"chars": 968,
"preview": ";; Support for high-level text objects selections.\n;; For instance:\n;; maf (v)isually select (a) (f)unction or su"
},
{
"path": "treesit-queries/adl/textobjects.scm",
"chars": 45,
"preview": "(struct (_) @function.inner) @function.outer\n"
},
{
"path": "treesit-queries/amber/textobjects.scm",
"chars": 528,
"preview": "; Functions - capture both definition and body\n(function_definition\n body: (_) @function.inner) @function.outer\n\n; Func"
},
{
"path": "treesit-queries/awk/textobjects.scm",
"chars": 222,
"preview": "\n(func_def name: (identifier) (block) @function.inner) @function.outer\n\n(param_list (_) @parameter.inner) @parameter.out"
},
{
"path": "treesit-queries/bash/textobjects.scm",
"chars": 191,
"preview": "(function_definition\n body: (_) @function.inner) @function.outer\n\n(command\n argument: (_) @parameter.inner)\n\n(comment)"
},
{
"path": "treesit-queries/basic/textobjects.scm",
"chars": 84,
"preview": "(for_statement) @function.outer\n\n(comment) @comment.inner\n(comment)+ @comment.outer\n"
},
{
"path": "treesit-queries/blade/textobjects.scm",
"chars": 17,
"preview": "; inherits: html\n"
},
{
"path": "treesit-queries/c/textobjects.scm",
"chars": 794,
"preview": "(function_definition\n body: (_) @function.inner) @function.outer\n\n(struct_specifier\n body: (_) @class.inner) @class.ou"
},
{
"path": "treesit-queries/c-sharp/textobjects.scm",
"chars": 611,
"preview": "[\n (class_declaration body: (_) @class.inner)\n (struct_declaration body: (_) @class.inner)\n (interface_declaration bo"
},
{
"path": "treesit-queries/caddyfile/textobjects.scm",
"chars": 344,
"preview": "(comment) @comment.inner\n(comment)+ @comment.outer\n\n(directive\n name: (directive_name) @parameter.inner) @parameter.out"
},
{
"path": "treesit-queries/cairo/textobjects.scm",
"chars": 1650,
"preview": "(function_item\n body: (_) @function.inner) @function.outer\n\n(closure_expression\n body: (_) @function.inner) @function."
},
{
"path": "treesit-queries/clojure/textobjects.scm",
"chars": 1393,
"preview": "; Function definitions (defn, defn-, defmacro, defmethod, etc.)\n(list_lit\n .\n (sym_lit) @_keyword\n .\n (sym_lit)\n (_"
},
{
"path": "treesit-queries/cmake/textobjects.scm",
"chars": 202,
"preview": "[\n (macro_def)\n (function_def)\n] @function.outer\n\n(argument) @parameter.inner\n\n[\n (bracket_comment)\n (line_comment)\n"
},
{
"path": "treesit-queries/codeql/textobjects.scm",
"chars": 484,
"preview": "(qldoc) @comment.outer\n(block_comment) @comment.outer\n(line_comment) @comment.inner\n(line_comment)+ @comment.outer\n\n(cla"
},
{
"path": "treesit-queries/cpp/textobjects.scm",
"chars": 136,
"preview": "; inherits: c\n\n(lambda_expression\n body: (_) @function.inner) @function.outer\n\n(class_specifier\n body: (_) @class.inne"
},
{
"path": "treesit-queries/cross-config/textobjects.scm",
"chars": 17,
"preview": "; inherits: toml\n"
},
{
"path": "treesit-queries/crystal/textobjects.scm",
"chars": 593,
"preview": "(class_def\n name: (_)\n (_) @class.inner) @class.outer\n\n(struct_def\n name: (_)\n (_) @class.inner) @class.outer\n\n(modu"
},
{
"path": "treesit-queries/cylc/textobjects.scm",
"chars": 398,
"preview": "(comment) @comment.inner\n\n(comment)+ @comment.outer\n\n(_\n brackets_open: _\n name: _?\n brackets_close: _\n _* @class.in"
},
{
"path": "treesit-queries/d/textobjects.scm",
"chars": 448,
"preview": "(function_declaration (function_body) @function.inner) @function.outer\n(comment) @comment.inner\n(comment)+ @comment.oute"
},
{
"path": "treesit-queries/dart/textobjects.scm",
"chars": 1784,
"preview": "(class_definition\n body: (_) @class.inner) @class.outer\n\n(mixin_declaration\n (class_body) @class.inner) @class.outer\n\n"
},
{
"path": "treesit-queries/dhall/textobjects.scm",
"chars": 378,
"preview": "(lambda_expression\n (label) @parameter.inner\n (expression) @function.inner\n) @function.outer\n\n(forall_expression\n (la"
},
{
"path": "treesit-queries/docker-bake/textobjects.scm",
"chars": 16,
"preview": "; inherits: hcl\n"
},
{
"path": "treesit-queries/docker-compose/textobjects.scm",
"chars": 17,
"preview": "; inherits: yaml\n"
},
{
"path": "treesit-queries/dockerfile/textobjects.scm",
"chars": 53,
"preview": "(comment) @comment.inner\n\n(comment)+ @comment.outer\n\n"
},
{
"path": "treesit-queries/doxyfile/textobjects.scm",
"chars": 100,
"preview": "(option\n value: (_) @entry.inner) @entry.outer\n\n(comment) @comment.inner\n(comment)+ @comment.outer\n"
},
{
"path": "treesit-queries/earthfile/textobjects.scm",
"chars": 49,
"preview": "(target (block) @function.inner) @function.outer\n"
},
{
"path": "treesit-queries/ecma/textobjects.scm",
"chars": 915,
"preview": "(function_declaration\n body: (_) @function.inner) @function.outer\n\n(function_expression\n body: (_) @function.inner) @f"
},
{
"path": "treesit-queries/eiffel/textobjects.scm",
"chars": 316,
"preview": "[\n (comment)+\n (header_comment)+\n] @comment.outer\n[\n (comment)\n (header_comment)\n] @comment.inner\n(formal_arguments)"
},
{
"path": "treesit-queries/elixir/textobjects.scm",
"chars": 1059,
"preview": "; Function heads and guards have no body at all, so `keywords` and `do_block` nodes are both optional\n((call\n target: "
},
{
"path": "treesit-queries/elm/textobjects.scm",
"chars": 1083,
"preview": "(line_comment) @comment.inner\n(line_comment)+ @comment.outer\n(block_comment) @comment.inner\n(block_comment)+ @comment.ou"
},
{
"path": "treesit-queries/env/textobjects.scm",
"chars": 107,
"preview": "(comment) @comment.inner\n\n(comment)+ @comment.outer\n\n(variable_assignment\n (_) @entry.inner) @entry.outer\n"
},
{
"path": "treesit-queries/erlang/textobjects.scm",
"chars": 478,
"preview": "(function_clause\n pattern: (arguments (_)? @parameter.inner)\n body: (_) @function.inner) @function.outer\n\n(anonymous_f"
},
{
"path": "treesit-queries/fga/textobjects.scm",
"chars": 197,
"preview": "(condition_declaration\n body: (_) @function.inner) @function.outer\n\n(param \n ((_) @parameter.inner . \",\"? @parameter.o"
},
{
"path": "treesit-queries/fish/textobjects.scm",
"chars": 91,
"preview": "(function_definition) @function.outer\n\n(comment) @comment.inner\n\n(comment)+ @comment.outer\n"
},
{
"path": "treesit-queries/freebasic/textobjects.scm",
"chars": 159,
"preview": "(function_declaration) @function.outer\n\n(sub_declaration) @function.outer\n\n(for_statement) @function.outer\n\n(comment) @c"
},
{
"path": "treesit-queries/gas/textobjects.scm",
"chars": 51,
"preview": "(comment) @comment.inner\n(comment)+ @comment.outer\n"
},
{
"path": "treesit-queries/gdscript/textobjects.scm",
"chars": 522,
"preview": "\n(class_definition\n (body) @class.inner) @class.outer\n\n(function_definition\n (body) @function.inner) @function.outer\n\n"
},
{
"path": "treesit-queries/git-cliff-config/textobjects.scm",
"chars": 17,
"preview": "; inherits: toml\n"
},
{
"path": "treesit-queries/git-commit/textobjects.scm",
"chars": 51,
"preview": "(comment) @comment.inner\n(comment)+ @comment.outer\n"
},
{
"path": "treesit-queries/git-config/textobjects.scm",
"chars": 96,
"preview": "(comment) @comment.inner\n\n(comment)+ @comment.outer\n\n(variable\n (_) @entry.inner) @entry.outer\n"
},
{
"path": "treesit-queries/github-action/textobjects.scm",
"chars": 17,
"preview": "; inherits: yaml\n"
},
{
"path": "treesit-queries/gitlab-ci/textobjects.scm",
"chars": 17,
"preview": "; inherits: yaml\n"
},
{
"path": "treesit-queries/gjs/textobjects.scm",
"chars": 34,
"preview": "; inherits: _gjs,_javascript,ecma\n"
},
{
"path": "treesit-queries/gleam/textobjects.scm",
"chars": 314,
"preview": "(function\n parameters: (function_parameters (function_parameter)? @parameter.inner)\n body: (block) @function.inner) @f"
},
{
"path": "treesit-queries/glsl/textobjects.scm",
"chars": 14,
"preview": "; inherits: c\n"
},
{
"path": "treesit-queries/go/textobjects.scm",
"chars": 1399,
"preview": "(function_declaration\n body: (block)? @function.inner) @function.outer\n\n(func_literal\n (_)? @function.inner) @function"
},
{
"path": "treesit-queries/godot-resource/textobjects.scm",
"chars": 318,
"preview": "(section \n (identifier) \n (_)\n (property) @class.inner\n) @class.outer\n\n(attribute \n (identifier)\n (_) @parameter.in"
},
{
"path": "treesit-queries/graphql/textobjects.scm",
"chars": 478,
"preview": "(type_definition) @class.outer\n\n(executable_definition) @function.outer\n\n(arguments_definition\n (input_value_definition"
},
{
"path": "treesit-queries/gren/textobjects.scm",
"chars": 954,
"preview": "\n(line_comment) @comment.inner\n(line_comment)+ @comment.outer\n(block_comment) @comment.inner\n(block_comment)+ @comment.o"
},
{
"path": "treesit-queries/gts/textobjects.scm",
"chars": 34,
"preview": "; inherits: _gjs,_typescript,ecma\n"
},
{
"path": "treesit-queries/haskell/textobjects.scm",
"chars": 485,
"preview": "(comment) @comment.inner\n(comment)+ @comment.outer\n\n(newtype\n\t(newtype_constructor\n\t\t(_) @class.inner)) @class.outer\n(da"
},
{
"path": "treesit-queries/hcl/textobjects.scm",
"chars": 212,
"preview": "(comment) @comment.inner\n(comment)+ @comment.outer\n\n(function_arguments\n ((_) @parameter.inner . \",\"? @parameter.outer)"
},
{
"path": "treesit-queries/heex/textobjects.scm",
"chars": 40,
"preview": "(comment) @comment.outer @comment.inner\n"
},
{
"path": "treesit-queries/hocon/textobjects.scm",
"chars": 122,
"preview": "(comment) @comment.inner\n\n(comment)+ @comment.outer\n\n(pair \n (_) @entry.inner) @entry.outer\n\n(array\n (_) @entry.outer)"
},
{
"path": "treesit-queries/html/textobjects.scm",
"chars": 276,
"preview": "(script_element (start_tag) (_) @xml-element.inner (end_tag)) @xml-element.outer\n\n(style_element (start_tag) (_) @xml-e"
},
{
"path": "treesit-queries/hurl/textobjects.scm",
"chars": 97,
"preview": "(comment) @comment.inner\n\n(comment)+ @comment.outer\n\n(entry (_) @function.inner) @function.outer\n"
},
{
"path": "treesit-queries/inko/textobjects.scm",
"chars": 736,
"preview": "(class\n body: (_) @class.inner) @class.outer\n\n(trait\n body: (_) @class.inner) @class.outer\n\n(method\n body: (_) @funct"
},
{
"path": "treesit-queries/java/textobjects.scm",
"chars": 919,
"preview": "(method_declaration\n body: (_)? @function.inner) @function.outer\n\n(constructor_declaration\n body: (_) @function.inner)"
},
{
"path": "treesit-queries/javascript/textobjects.scm",
"chars": 82,
"preview": "; See runtime/queries/ecma/README.md for more info.\n\n; inherits: _javascript,ecma\n"
},
{
"path": "treesit-queries/jjconfig/textobjects.scm",
"chars": 17,
"preview": "; inherits: toml\n"
},
{
"path": "treesit-queries/jq/textobjects.scm",
"chars": 152,
"preview": "(comment) @comment.inner\n(comment)+ @comment.outer\n\n(funcdef\n (query) @function.inner) @function.outer\n\n(objectkeyval\n "
},
{
"path": "treesit-queries/json/textobjects.scm",
"chars": 120,
"preview": "(pair \n (_) @entry.inner) @entry.outer\n\n(array\n (_) @entry.outer)\n\n(comment) @comment.inner\n(comment)+ @comment.outer\n"
},
{
"path": "treesit-queries/json-ld/textobjects.scm",
"chars": 17,
"preview": "; inherits: json\n"
},
{
"path": "treesit-queries/json5/textobjects.scm",
"chars": 121,
"preview": "(member\n (_) @entry.inner) @entry.outer\n\n(array\n (_) @entry.outer)\n\n(comment) @comment.inner\n(comment)+ @comment.outer"
},
{
"path": "treesit-queries/jsonc/textobjects.scm",
"chars": 17,
"preview": "; inherits: json\n"
},
{
"path": "treesit-queries/jsx/textobjects.scm",
"chars": 87,
"preview": "; See runtime/queries/ecma/README.md for more info.\n\n; inherits: _jsx,_javascript,ecma\n"
},
{
"path": "treesit-queries/julia/textobjects.scm",
"chars": 1277,
"preview": "(function_definition (_)? @function.inner) @function.outer\n\n(short_function_definition (_)? @function.inner) @function.o"
},
{
"path": "treesit-queries/just/textobjects.scm",
"chars": 500,
"preview": "; Specify how to navigate around logical blocks in code\n\n(assert_parameters\n ((_) @parameter.inner . \",\"? @parameter.ou"
},
{
"path": "treesit-queries/kdl/textobjects.scm",
"chars": 456,
"preview": "(type (_) @test.inner) @test.outer\n\n(node\n\tchildren: (node_children)? @class.inner) @class.outer\n\n(node\n\tchildren: (node"
},
{
"path": "treesit-queries/kotlin/textobjects.scm",
"chars": 1271,
"preview": "(function_declaration\n (function_body)? @function.inner) @function.outer\n\n; Unlike function_body above, the constructor"
},
{
"path": "treesit-queries/koto/textobjects.scm",
"chars": 660,
"preview": "(comment) @comment.inner\n\n(comment)+ @comment.outer\n\n(function\n body: (_) @function.inner) @function.outer\n\n(args\n ((a"
},
{
"path": "treesit-queries/latex/textobjects.scm",
"chars": 155,
"preview": "[\n (generic_command)\n] @function.outer\n\n[\n (chapter)\n (part)\n (section)\n (subsection)\n (subsubsection)\n (paragrap"
},
{
"path": "treesit-queries/llvm/textobjects.scm",
"chars": 381,
"preview": "(define\n body: (_) @function.inner) @function.outer\n\n(struct_type\n (struct_body) @class.inner) @class.outer\n\n(packed_s"
},
{
"path": "treesit-queries/llvm-mir/textobjects.scm",
"chars": 176,
"preview": "(basic_block) @function.outer\n\n(argument) @parameter.inner\n\n[\n (comment)\n (multiline_comment)\n] @comment.inner\n\n(comme"
},
{
"path": "treesit-queries/lua/textobjects.scm",
"chars": 407,
"preview": "(function_definition\n body: (_) @function.inner) @function.outer\n\n(function_declaration\n body: (_) @function.inner) @f"
},
{
"path": "treesit-queries/luau/textobjects.scm",
"chars": 381,
"preview": "(fn_stmt\n body: (_)? @function.inner) @function.outer\n\n(local_fn_stmt\n body: (_)? @function.inner) @function.outer\n\n(a"
},
{
"path": "treesit-queries/mail/textobjects.scm",
"chars": 239,
"preview": "(atom_block\n (atom) @entry.inner) @entry.outer\n\n(email_address) @entry.outer\n(header_other\n (header_unstructured) @ent"
},
{
"path": "treesit-queries/matlab/textobjects.scm",
"chars": 368,
"preview": "(arguments ((_) @parameter.inner . \",\"? @parameter.outer) @parameter.outer)\n(function_arguments ((_) @parameter.inner . "
},
{
"path": "treesit-queries/miseconfig/textobjects.scm",
"chars": 17,
"preview": "; inherits: toml\n"
},
{
"path": "treesit-queries/mojo/textobjects.scm",
"chars": 19,
"preview": "; inherits: python\n"
},
{
"path": "treesit-queries/nasm/textobjects.scm",
"chars": 412,
"preview": "(preproc_multiline_macro\n body: (body) @function.inner) @function.outer\n(struc_declaration\n body: (struc_declaration_b"
},
{
"path": "treesit-queries/nestedtext/textobjects.scm",
"chars": 17,
"preview": "; inherits: yaml\n"
},
{
"path": "treesit-queries/nim/textobjects.scm",
"chars": 813,
"preview": "(proc_declaration\n body: (_) @function.inner) @function.outer\n(func_declaration\n body: (_) @function.inner) @function."
}
]
// ... and 57 more files (download for full content)
About this extraction
This page contains the full source code of the meain/evil-textobj-tree-sitter GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 257 files (254.1 KB), approximately 75.4k tokens, and a symbol index with 8 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.