## SYSTEM
You are a Treesiter Query Assistant specializing in generating and testing Tree-sitter textobject queries. Your expertise includes:
1. Understanding Tree-sitter syntax and query patterns
2. Creating queries for different programming languages
3. Testing and debugging Tree-sitter queries
4. Understanding Abstract Syntax Tree (AST) structures
When a user asks for a query:
1. Generate a comprehensive Tree-sitter query based on their requirements
2. Save the user's code to a temporary file
3. Use tree-sitter-debugger to view the Tree-sitter parse tree of the code
4. Test the query against the code using tree-sitter-debugger
5. Provide the results along with explanations
Supported languages:
- bash
- c
- cpp
- css
- go
- html
- java
- javascript
- js
- php
- py
- python
- ruby
- rust
- ts
- tsx
- typescript
- yaml
- yml
Example:
I need a query to select conditional statement in golang
(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
Always remember to:
- View the tree structure first to understand the syntax nodes
- Test queries thoroughly before presenting results
- Explain the query and how it matches the code
- Suggest improvements or alternatives if the query doesn't work as expected
- Keep the query simple and generic, do not be too specific. See the examples above
- Only provide simple inner and outer textobjects
- Give just the queries at the end of the session
- Never include comments in your query
## USER
golang loop textobj
## ASSISTANT
I'll create Tree-sitter textobject queries for loops in Golang. First, let's understand the structure of different loop types in Go by examining their parse tree structure.
**Tool Calls**
Tool: `show_tree_structure` (ID: `tooluse_PzOeCujKQ8iAgef4XeC3UA`)
**`language`**: go
**`content`**
```
package main
func main() {
// for loop
for i := 0; i < 10; i++ {
println(i)
}
// while-style loop
j := 0
for j < 10 {
println(j)
j++
}
// infinite loop
for {
break
}
// range loop
nums := []int{1, 2, 3}
for index, value := range nums {
println(index, value)
}
}
```
## TOOL
**Tool Result** (for call `tooluse_PzOeCujKQ8iAgef4XeC3UA`, tool `show_tree_structure`):
```
Command: tree-sitter-debugger --lang go
Output:
(source_file
(package_clause
"package"
(package_identifier "main")
)
"\n\n"
(function_declaration
"func"
(identifier "main")
(parameter_list
"("
")"
)
(block
"{"
(comment "// for loop")
(for_statement
"for"
(for_clause
(short_var_declaration
(expression_list
(identifier "i")
)
":="
(expression_list
(int_literal "0")
)
)
";"
(binary_expression
(identifier "i")
"<"
(int_literal "10")
)
";"
(inc_statement
(identifier "i")
"++"
)
)
(block
"{"
(expression_statement
(call_expression
(identifier "println")
(argument_list
"("
(identifier "i")
")"
)
)
)
"\n"
"}"
)
)
"\n"
(comment "// while-style loop")
(short_var_declaration
(expression_list
(identifier "j")
)
":="
(expression_list
(int_literal "0")
)
)
"\n"
(for_statement
"for"
(binary_expression
(identifier "j")
"<"
(int_literal "10")
)
(block
"{"
(expression_statement
(call_expression
(identifier "println")
(argument_list
"("
(identifier "j")
")"
)
)
)
"\n"
(inc_statement
(identifier "j")
"++"
)
"\n"
"}"
)
)
"\n"
(comment "// infinite loop")
(for_statement
"for"
(block
"{"
(break_statement
"break"
)
"\n"
"}"
)
)
"\n"
(comment "// range loop")
(short_var_declaration
(expression_list
(identifier "nums")
)
":="
(expression_list
(composite_literal
(slice_type
"["
"]"
(type_identifier "int")
)
(literal_value
"{"
(literal_element
(int_literal "1")
)
","
(literal_element
(int_literal "2")
)
","
(literal_element
(int_literal "3")
)
"}"
)
)
)
)
"\n"
(for_statement
"for"
(range_clause
(expression_list
(identifier "index")
","
(identifier "value")
)
":="
"range"
(identifier "nums")
)
(block
"{"
(expression_statement
(call_expression
(identifier "println")
(argument_list
"("
(identifier "index")
","
(identifier "value")
")"
)
)
)
"\n"
"}"
)
)
"\n"
"}"
)
)
)
```
## ASSISTANT
Now that I can see the parse tree structure for various loop types in Go, I'll create textobject queries for them. In Go, there are several types of loops:
1. Standard for loops (with init, condition, update)
2. While-style loops (just condition)
3. Infinite loops (no condition)
4. Range-based loops (for ... range)
Let's create queries for these loops and test them:
**Tool Calls**
Tool: `run_query` (ID: `tooluse_yRje5DbmRlq_KAmPXCzM-Q`)
**`language`**: go
**`content`**
```
package main
func main() {
// for loop
for i := 0; i < 10; i++ {
println(i)
}
// while-style loop
j := 0
for j < 10 {
println(j)
j++
}
// infinite loop
for {
break
}
// range loop
nums := []int{1, 2, 3}
for index, value := range nums {
println(index, value)
}
}
```
**`query`**
```
(for_statement
(block) @loop.inner) @loop.outer
```
## TOOL
**Tool Result** (for call `tooluse_yRje5DbmRlq_KAmPXCzM-Q`, tool `run_query`):
```
Command: tree-sitter-debugger --lang go --query '(for_statement (block) @loop.inner) @loop.outer'
Output:
@loop.outer
start: 5:4
end: 7:5
content:
for i := 0; i < 10; i++ {
println(i)
}
@loop.inner
start: 5:28
end: 7:5
content:
{
println(i)
}
@loop.outer
start: 11:4
end: 14:5
content:
for j < 10 {
println(j)
j++
}
@loop.inner
start: 11:15
end: 14:5
content:
{
println(j)
j++
}
@loop.outer
start: 17:4
end: 19:5
content:
for {
break
}
@loop.inner
start: 17:8
end: 19:5
content:
{
break
}
@loop.outer
start: 23:4
end: 25:5
content:
for index, value := range nums {
println(index, value)
}
@loop.inner
start: 23:35
end: 25:5
content:
{
println(index, value)
}
```
## ASSISTANT
Great! This basic query successfully matches all types of for loops in Go. The query:
```
(for_statement
(block) @loop.inner) @loop.outer
```
Captures:
- `@loop.outer`: The entire for statement including the `for` keyword, any conditions or clauses, and the code block
- `@loop.inner`: Just the block (code between curly braces)
Let's refine this to be more specific for different loop types:
**Tool Calls**
Tool: `run_query` (ID: `tooluse_V0pcEL48QmGJVkFA2WbYEA`)
**`language`**: go
**`content`**
```
package main
func main() {
// for loop
for i := 0; i < 10; i++ {
println(i)
}
// while-style loop
j := 0
for j < 10 {
println(j)
j++
}
// infinite loop
for {
break
}
// range loop
nums := []int{1, 2, 3}
for index, value := range nums {
println(index, value)
}
}
```
**`query`**
```
(for_statement
(for_clause)
(block) @for_loop.inner) @for_loop.outer
(for_statement
(range_clause)
(block) @range_loop.inner) @range_loop.outer
(for_statement
condition: (_)
(block) @condition_loop.inner) @condition_loop.outer
(for_statement
(block) @infinite_loop.inner) @infinite_loop.outer
```
## TOOL
**Tool Result** (for call `tooluse_V0pcEL48QmGJVkFA2WbYEA`, tool `run_query`):
```
**ERROR:** Error: exit status 1
Command: tree-sitter-debugger --lang go --query '(for_statement (for_clause) (block) @for_loop.inner) @for_loop.outer (for_statement (range_clause) (block) @range_loop.inner) @range_loop.outer (for_statement condition: (_) (block) @condition_loop.inner) @condition_loop.outer (for_statement (block) @infinite_loop.inner) @infinite_loop.outer'
Output: Error executing query: invalid query: invalid unknown at line 1 column 0
condition: (_) (block) @condition_loop.inner) @condition_loop.outer (for_statement (block) @infinite_loop.inner) @infinite_loop.outer
^
```
## ASSISTANT
I see the error in my query. Let me correct it by removing the field name that isn't in the AST:
**Tool Calls**
Tool: `run_query` (ID: `tooluse_cMmgip99SD2LUxp7CVf7pA`)
**`content`**
```
package main
func main() {
// for loop
for i := 0; i < 10; i++ {
println(i)
}
// while-style loop
j := 0
for j < 10 {
println(j)
j++
}
// infinite loop
for {
break
}
// range loop
nums := []int{1, 2, 3}
for index, value := range nums {
println(index, value)
}
}
```
**`query`**
```
(for_statement
(for_clause)
(block) @for_loop.inner) @for_loop.outer
(for_statement
(range_clause)
(block) @range_loop.inner) @range_loop.outer
```
**`language`**: go
## TOOL
**Tool Result** (for call `tooluse_cMmgip99SD2LUxp7CVf7pA`, tool `run_query`):
```
Command: tree-sitter-debugger --lang go --query '(for_statement (for_clause) (block) @for_loop.inner) @for_loop.outer (for_statement (range_clause) (block) @range_loop.inner) @range_loop.outer'
Output:
@for_loop.outer
start: 5:4
end: 7:5
content:
for i := 0; i < 10; i++ {
println(i)
}
@for_loop.inner
start: 5:28
end: 7:5
content:
{
println(i)
}
@range_loop.outer
start: 23:4
end: 25:5
content:
for index, value := range nums {
println(index, value)
}
@range_loop.inner
start: 23:35
end: 25:5
content:
{
println(index, value)
}
```
## ASSISTANT
Let's add the remaining loop types:
**Tool Calls**
Tool: `run_query` (ID: `tooluse_ZaODeiiJQm65YdtVH9NLXA`)
**`language`**: go
**`content`**
```
package main
func main() {
// for loop
for i := 0; i < 10; i++ {
println(i)
}
// while-style loop
j := 0
for j < 10 {
println(j)
j++
}
// infinite loop
for {
break
}
// range loop
nums := []int{1, 2, 3}
for index, value := range nums {
println(index, value)
}
}
```
**`query`**
```
(for_statement
(_) @_cond
(block) @loop.inner) @loop.outer
(for_statement
(block) @loop.inner) @loop.outer
```
## TOOL
**Tool Result** (for call `tooluse_ZaODeiiJQm65YdtVH9NLXA`, tool `run_query`):
```
Command: tree-sitter-debugger --lang go --query '(for_statement (_) @_cond (block) @loop.inner) @loop.outer (for_statement (block) @loop.inner) @loop.outer'
Output:
@loop.outer
start: 5:4
end: 7:5
content:
for i := 0; i < 10; i++ {
println(i)
}
@_cond
start: 5:8
end: 5:27
content:
i := 0; i < 10; i++
@loop.inner
start: 5:28
end: 7:5
content:
{
println(i)
}
@loop.outer
start: 5:4
end: 7:5
content:
for i := 0; i < 10; i++ {
println(i)
}
@loop.inner
start: 5:28
end: 7:5
content:
{
println(i)
}
@loop.outer
start: 11:4
end: 14:5
content:
for j < 10 {
println(j)
j++
}
@_cond
start: 11:8
end: 11:14
content:
j < 10
@loop.inner
start: 11:15
end: 14:5
content:
{
println(j)
j++
}
@loop.outer
start: 11:4
end: 14:5
content:
for j < 10 {
println(j)
j++
}
@loop.inner
start: 11:15
end: 14:5
content:
{
println(j)
j++
}
@loop.outer
start: 17:4
end: 19:5
content:
for {
break
}
@loop.inner
start: 17:8
end: 19:5
content:
{
break
}
@loop.outer
start: 23:4
end: 25:5
content:
for index, value := range nums {
println(index, value)
}
@_cond
start: 23:8
end: 23:34
content:
index, value := range nums
@loop.inner
start: 23:35
end: 25:5
content:
{
println(index, value)
}
@loop.outer
start: 23:4
end: 25:5
content:
for index, value := range nums {
println(index, value)
}
@loop.inner
start: 23:35
end: 25:5
content:
{
println(index, value)
}
```
## ASSISTANT
I notice there are some duplications in the captures because both patterns are matching. Let me create a more precise set of queries for different loop types:
**Tool Calls**
Tool: `run_query` (ID: `tooluse_-0K6bGbHRIKQT6DbpOEvYw`)
**`language`**: go
**`content`**
```
package main
func main() {
// for loop
for i := 0; i < 10; i++ {
println(i)
}
// while-style loop
j := 0
for j < 10 {
println(j)
j++
}
// infinite loop
for {
break
}
// range loop
nums := []int{1, 2, 3}
for index, value := range nums {
println(index, value)
}
}
```
**`query`**
```
(for_statement
(block) @loop.inner) @loop.outer
```
## TOOL
**Tool Result** (for call `tooluse_-0K6bGbHRIKQT6DbpOEvYw`, tool `run_query`):
```
Command: tree-sitter-debugger --lang go --query '(for_statement (block) @loop.inner) @loop.outer'
Output:
@loop.outer
start: 5:4
end: 7:5
content:
for i := 0; i < 10; i++ {
println(i)
}
@loop.inner
start: 5:28
end: 7:5
content:
{
println(i)
}
@loop.outer
start: 11:4
end: 14:5
content:
for j < 10 {
println(j)
j++
}
@loop.inner
start: 11:15
end: 14:5
content:
{
println(j)
j++
}
@loop.outer
start: 17:4
end: 19:5
content:
for {
break
}
@loop.inner
start: 17:8
end: 19:5
content:
{
break
}
@loop.outer
start: 23:4
end: 25:5
content:
for index, value := range nums {
println(index, value)
}
@loop.inner
start: 23:35
end: 25:5
content:
{
println(index, value)
}
```
## ASSISTANT
Perfect! After analyzing all the loop types in Go, I can see that a simple query works well for all cases:
```
(for_statement
(block) @loop.inner) @loop.outer
```
This query captures all types of loops in Go:
- Traditional for loops (with initialization, condition, and increment)
- While-style loops (just a condition)
- Infinite loops (no condition)
- Range-based loops (using `range` keyword)
For each loop:
- `@loop.outer` captures the entire loop statement including the `for` keyword, any conditions/clauses, and the code block
- `@loop.inner` captures just the block content (the code between curly braces)
The query is simple and effective for all Go loop types. Since Go uses the same `for` keyword for all loop constructs and they all have the same basic structure in the AST, a single pattern works well.
Here's the final textobject query for Go loops:
```
(for_statement
(block) @loop.inner) @loop.outer
```