feat: set scope from node captures and add basic query documentation (#318)

* Process scope captures

This lets us avoid complex querying when extracting scope.
As long as the capture includes a scoping node in a `@scope` capture,
its text will be extracted and used as a scope value.
If "public" is named differently in some language,
`#set @scope "text" "public"` will do the trick for a cost of an
additional query.

* Add basic query documentation to readme and vimdoc

* Add reusable language extensions info to readme
This commit is contained in:
Slotos 2023-11-10 16:39:37 +01:00 committed by GitHub
parent 21e3358617
commit 2d169d3497
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 18 deletions

View file

@ -15,6 +15,8 @@ A code outline window for skimming and quick navigation
- [Lualine](#lualine)
- [Highlight](#highlight)
- [API](#api)
- [TreeSitter queries](#treesitter-queries)
- [Language extensions](#language-extensions)
- [FAQ](#faq)
<!-- /TOC -->
@ -724,6 +726,24 @@ hi AerialGuide2 guifg=Blue
<!-- /API -->
## TreeSitter queries
When writing queries, the following captures and metadata are used by Aerial:
- `@symbol` - **required** capture for the logical region being captured
- `kind` - **required** metadata, a string value matching one of `vim.lsp.protocol.SymbolKind`
- `@name` - capture to extract a name from its text
- `@start` - a start of the match, influences matching of cursor position to aerial tree, defaults to `@symbol`
- `@end` - an end of the match, influences matching of cursor position to aerial tree, defaults to `@start`
- `@selection` - position to jump to when using Aerial for navigation, falls back to `@name` and `@symbol`
- `@scope` - a node naming a scope for the match, its text is used to generate a custom "Comment" linked highlight for the entry, with exception of "public"
A `@scope` node with text "developers" will result in its entry in the tree having an "AerialDevelopers" highlight applied to it.
- `scope` - a metadata value serving the same role as `@scope` capture, overriding aforementioned capture
Note: a capture's text can be set or modified with `#set!` and `#gsub!` respectively.
## FAQ
**Q: I accidentally opened a file into the aerial window and it looks bad. How can I prevent this from happening?**

View file

@ -710,6 +710,31 @@ for each of these, but a migration cheat-sheet is provided below.
close_behavior = "close" --> close_automatic_events = { "switch_buffer" }
<
*aerial-treesitter-queries*
Aerial utilizes the following captures and metadata from its queries:
`@type` **required** capture for the logical region being captured
`kind` **required** metadata, a string value matching one of
`vim.lsp.protocol.SymbolKind`
`@name` capture to extract a name from its text
`@start` a start of the match, influences matching of cursor position
to aerial tree, defaults to `@type`
`@end` an end of the match, influences matching of cursor position
to aerial tree, defaults to `@start`
`@selection` position to jump to when using Aerial for navigation, only used
if `treesitter.experimental_selection_range` is enabled,
falls back to `@name` and `@type`
`@scope` a scope for the match, its text is used to generate a custom
"Comment" linked highlight for the entry, with exception of "public"
For example:
A `@scope` node with text `developers` will result in its entry
in the tree having an "AerialDevelopers" highlight applied to it.
`scope` a metadata value serving the same role as `@scope` capture,
overriding aforementioned capture
Note: a capture's text can be set or modified with `#set!` and `#gsub!` respectively.
*SymbolKind* *symbol*
A quick note on SymbolKind. An authoritative list of valid SymbolKinds can be
found in the LSP spec:

View file

@ -78,6 +78,8 @@ M.elixir = {
module_attribute = "Field",
spec = "TypeParameter",
},
---@note Additionally processes the following captures:
--- `@protocol` - extends the name to "@name > @protocol"
postprocess = function(bufnr, item, match)
local identifier = node_from_match(match, "identifier")
if identifier then
@ -131,6 +133,8 @@ M.markdown = {
}
M.go = {
---@note Additionally processes the following captures:
--- `@receiver` - extends the name to "@receiver @name"
postprocess = function(bufnr, item, match)
local receiver = node_from_match(match, "receiver")
if receiver then
@ -218,6 +222,8 @@ M.rust = {
}
M.ruby = {
---@note Additionally processes the following captures:
--- `@method`, `@receiver`, `@separator` - extends the name to "@method @reciever[@separator]@name", with @separator defaulting to "."
postprocess = function(bufnr, item, match)
-- Reciever modification comes first, as we intend for it to generate a ruby-like `reciever.name`
local receiver = node_from_match(match, "receiver")
@ -255,6 +261,8 @@ M.lua = {
}
M.javascript = {
---@note Additionally processes the following captures:
--- `@method`, `@string`, and `@modifier` - replaces name with "@method[.@modifier] @string"
postprocess = function(bufnr, item, match)
local method = node_from_match(match, "method")
local modifier = node_from_match(match, "modifier")
@ -327,6 +335,8 @@ M.rst = {
}
M.typescript = {
---@note Additionally processes the following captures:
--- `@method`, `@string`, and `@modifier` - replaces name with "@method[.@modifier] @string"
postprocess = function(bufnr, item, match)
local value_node = node_from_match(match, "var_type")
if value_node then

View file

@ -117,14 +117,20 @@ M.fetch_symbols_sync = function(bufnr)
else
name = "<Anonymous>"
end
local scope
if match.scope and match.scope.node then -- we've got a node capture on our hands
scope = get_node_text(match.scope.node, bufnr, match.scope)
else
scope = match.scope
end
---@type aerial.Symbol
local item = {
kind = kind,
name = name,
level = level,
parent = parent_item,
scope = match.scope,
selection_range = selection_range,
scope = scope,
}
for k, v in pairs(range) do
item[k] = v

View file

@ -3,37 +3,30 @@
(#set! "kind" "Class")
) @symbol
(method
name: (_) @name
(#set! "kind" "Method")
) @symbol
(call
(identifier) @scope_switch
(#any-of? @scope_switch "private" "protected")
(
(identifier) @scope
(#any-of? @scope "private" "protected" "public")
)?
.
(argument_list
(method
name: (_) @name
(#set! "kind" "Method")
(#set! "scope" "private")
) @symbol
)
)
(body_statement
(identifier) @scope @later_scope
(#any-of? @scope "private" "protected")
.
[
(_)
((identifier) @later_scope (#not-eq? @later_scope "public"))
((identifier) @scope
(#any-of? @scope "private" "protected" "public"))
]*
.
(method
name: (_) @name
(#set! "kind" "Method")
(#set! "scope" "private")
) @symbol
)

View file

@ -443,7 +443,7 @@
"level": 1,
"lnum": 64,
"name": "protected_1",
"scope": "private",
"scope": "protected",
"selection_range": {
"col": 6,
"end_col": 17,
@ -474,7 +474,7 @@
"level": 1,
"lnum": 73,
"name": "protected_2",
"scope": "private",
"scope": "protected",
"selection_range": {
"col": 6,
"end_col": 17,
@ -490,6 +490,7 @@
"level": 1,
"lnum": 76,
"name": "inline_public",
"scope": "public",
"selection_range": {
"col": 13,
"end_col": 26,
@ -505,7 +506,7 @@
"level": 1,
"lnum": 79,
"name": "protected_3",
"scope": "private",
"scope": "protected",
"selection_range": {
"col": 6,
"end_col": 17,
@ -521,6 +522,7 @@
"level": 1,
"lnum": 83,
"name": "public_2",
"scope": "public",
"selection_range": {
"col": 6,
"end_col": 14,
@ -536,6 +538,7 @@
"level": 1,
"lnum": 86,
"name": "public_setter=",
"scope": "public",
"selection_range": {
"col": 6,
"end_col": 20,