Skip to content

Commit

Permalink
feat: set scope from node captures and add basic query documentation (#…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Slotos committed Nov 10, 2023
1 parent 21e3358 commit 2d169d3
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 18 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 -->
Expand Down Expand Up @@ -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?**
Expand Down
25 changes: 25 additions & 0 deletions doc/aerial.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
10 changes: 10 additions & 0 deletions lua/aerial/backends/treesitter/extensions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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
Expand Down
8 changes: 7 additions & 1 deletion lua/aerial/backends/treesitter/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 7 additions & 14 deletions queries/ruby/aerial.scm
Original file line number Diff line number Diff line change
Expand Up @@ -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
)

Expand Down
9 changes: 6 additions & 3 deletions tests/symbols/ruby_test.json
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@
"level": 1,
"lnum": 64,
"name": "protected_1",
"scope": "private",
"scope": "protected",
"selection_range": {
"col": 6,
"end_col": 17,
Expand Down Expand Up @@ -474,7 +474,7 @@
"level": 1,
"lnum": 73,
"name": "protected_2",
"scope": "private",
"scope": "protected",
"selection_range": {
"col": 6,
"end_col": 17,
Expand All @@ -490,6 +490,7 @@
"level": 1,
"lnum": 76,
"name": "inline_public",
"scope": "public",
"selection_range": {
"col": 13,
"end_col": 26,
Expand All @@ -505,7 +506,7 @@
"level": 1,
"lnum": 79,
"name": "protected_3",
"scope": "private",
"scope": "protected",
"selection_range": {
"col": 6,
"end_col": 17,
Expand All @@ -521,6 +522,7 @@
"level": 1,
"lnum": 83,
"name": "public_2",
"scope": "public",
"selection_range": {
"col": 6,
"end_col": 14,
Expand All @@ -536,6 +538,7 @@
"level": 1,
"lnum": 86,
"name": "public_setter=",
"scope": "public",
"selection_range": {
"col": 6,
"end_col": 20,
Expand Down

0 comments on commit 2d169d3

Please sign in to comment.