Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ziontee113/syntax-tree-surfer
A plugin for Neovim that helps you surf through your document and move elements around using the nvim-treesitter API.
https://github.com/ziontee113/syntax-tree-surfer
lua neovim nvim treesitter-api
Last synced: 7 days ago
JSON representation
A plugin for Neovim that helps you surf through your document and move elements around using the nvim-treesitter API.
- Host: GitHub
- URL: https://github.com/ziontee113/syntax-tree-surfer
- Owner: ziontee113
- License: mit
- Created: 2022-04-13T01:11:59.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2024-02-02T08:29:42.000Z (9 months ago)
- Last Synced: 2024-10-10T23:30:52.090Z (29 days ago)
- Topics: lua, neovim, nvim, treesitter-api
- Language: Lua
- Homepage:
- Size: 66.4 KB
- Stars: 470
- Watchers: 11
- Forks: 10
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-neovim - ziontee113/syntax-tree-surfer - Navigate and swap Treesitter's AST Nodes. Step into, step out, step over, step back. (Motion / Treesitter Based)
README
# 🌳 syntax-tree-surfer 🌳🌊
### Syntax Tree Surfer is a plugin for Neovim that helps you surf through your document and move elements around using the nvim-treesitter API.
![tree surfing cover](https://user-images.githubusercontent.com/102876811/163170119-89369c35-a061-4058-aaeb-1706ea6fa4cf.jpg)
## Table of Contents
1. [Version 1.0 Functionalities](#version-10-functionalities)
1. [How do I install?](#how-do-i-install)
1. [Version 1.1 Update](#version-11-update)
1. [Version 2.0 Beta Update](#version-20-beta-update)
1. [Version 2.2 Update](#version-22-update)# Version 1.0 Functionalities
### **Navigate** around your document based on Treesitter's abstract Syntax Tree. Step into, step out, step over, step back.
https://user-images.githubusercontent.com/102876811/163170843-a7c9f1a1-4ffb-4a39-9636-fc81521bd9b5.mp4
---
### **Move / Swap** elements around based on your visual selection
https://user-images.githubusercontent.com/102876811/163171686-4ad49b7a-9fd3-41d5-a2c2-deae1bb41c3d.mp4
### **Swap in Normal Mode** - Now supports Dot (.) Repeat
https://user-images.githubusercontent.com/102876811/174811583-52b7beb0-853f-4ac9-9498-eb718ce626d9.mp4
# How do I install?
#### Use your favorite Plugin Manager with the link [ziontee113/syntax-tree-surfer](ziontee113/syntax-tree-surfer)
For Packer:
```lua
use "ziontee113/syntax-tree-surfer"
```# How do I set things up?
### Here's my suggestion:
```lua
-- Syntax Tree Surfer
local opts = {noremap = true, silent = true}-- Normal Mode Swapping:
-- Swap The Master Node relative to the cursor with it's siblings, Dot Repeatable
vim.keymap.set("n", "vU", function()
vim.opt.opfunc = "v:lua.STSSwapUpNormal_Dot"
return "g@l"
end, { silent = true, expr = true })
vim.keymap.set("n", "vD", function()
vim.opt.opfunc = "v:lua.STSSwapDownNormal_Dot"
return "g@l"
end, { silent = true, expr = true })-- Swap Current Node at the Cursor with it's siblings, Dot Repeatable
vim.keymap.set("n", "vd", function()
vim.opt.opfunc = "v:lua.STSSwapCurrentNodeNextNormal_Dot"
return "g@l"
end, { silent = true, expr = true })
vim.keymap.set("n", "vu", function()
vim.opt.opfunc = "v:lua.STSSwapCurrentNodePrevNormal_Dot"
return "g@l"
end, { silent = true, expr = true })--> If the mappings above don't work, use these instead (no dot repeatable)
-- vim.keymap.set("n", "vd", 'STSSwapCurrentNodeNextNormal', opts)
-- vim.keymap.set("n", "vu", 'STSSwapCurrentNodePrevNormal', opts)
-- vim.keymap.set("n", "vD", 'STSSwapDownNormal', opts)
-- vim.keymap.set("n", "vU", 'STSSwapUpNormal', opts)-- Visual Selection from Normal Mode
vim.keymap.set("n", "vx", 'STSSelectMasterNode', opts)
vim.keymap.set("n", "vn", 'STSSelectCurrentNode', opts)-- Select Nodes in Visual Mode
vim.keymap.set("x", "J", 'STSSelectNextSiblingNode', opts)
vim.keymap.set("x", "K", 'STSSelectPrevSiblingNode', opts)
vim.keymap.set("x", "H", 'STSSelectParentNode', opts)
vim.keymap.set("x", "L", 'STSSelectChildNode', opts)-- Swapping Nodes in Visual Mode
vim.keymap.set("x", "", 'STSSwapNextVisual', opts)
vim.keymap.set("x", "", 'STSSwapPrevVisual', opts)
```# Now let's start Tree Surfing! 🌲💦
### Version 1.1 update
This feature will help you save some keystrokes & brain power when you want to create some code at the top level node of your current cursor position.
```lua
lua require("syntax-tree-surfer").go_to_top_node_and_execute_commands(false, { "normal! O", "normal! O", "startinsert" })
```The .go_to_top_node_and_execute_commands() method takes 2 arguments:
1. boolean: if false then it will jump to the beginning of the node, if true it jumps to the end.
1. lua table: a table that contains strings, each string is a vim command example: { "normal! O", "normal! O", "startinsert" }
---
# Version 2.0 Beta Update
### Targeted Jump with Virtual Text
https://user-images.githubusercontent.com/102876811/169820839-5ec66bd9-bf14-49f6-8e5a-3078b8ec43c4.mp4
### Filtered Jump through user-defined node types
https://user-images.githubusercontent.com/102876811/169820922-b1eefa5e-6ed9-4ebd-95d1-f3f35e0388da.mp4
### These are experimental features and I wish to expand them even further. If you have any suggestions, please feel free to let me know 😊
Example mappings for Version 2.0 Beta functionalities:
```lua
-- Syntax Tree Surfer V2 Mappings
-- Targeted Jump with virtual_text
local sts = require("syntax-tree-surfer")
vim.keymap.set("n", "gv", function() -- only jump to variable_declarations
sts.targeted_jump({ "variable_declaration" })
end, opts)
vim.keymap.set("n", "gfu", function() -- only jump to functions
sts.targeted_jump({ "function", "arrrow_function", "function_definition" })
--> In this example, the Lua language schema uses "function",
-- when the Python language uses "function_definition"
-- we include both, so this keymap will work on both languages
end, opts)
vim.keymap.set("n", "gif", function() -- only jump to if_statements
sts.targeted_jump({ "if_statement" })
end, opts)
vim.keymap.set("n", "gfo", function() -- only jump to for_statements
sts.targeted_jump({ "for_statement" })
end, opts)
vim.keymap.set("n", "gj", function() -- jump to all that you specify
sts.targeted_jump({
"function",
"if_statement",
"else_clause",
"else_statement",
"elseif_statement",
"for_statement",
"while_statement",
"switch_statement",
})
end, opts)-------------------------------
-- filtered_jump --
-- "default" means that you jump to the default_desired_types or your lastest jump types
vim.keymap.set("n", "", function()
sts.filtered_jump("default", true) --> true means jump forward
end, opts)
vim.keymap.set("n", "", function()
sts.filtered_jump("default", false) --> false means jump backwards
end, opts)-- non-default jump --> custom desired_types
vim.keymap.set("n", "your_keymap", function()
sts.filtered_jump({
"if_statement",
"else_clause",
"else_statement",
}, true) --> true means jump forward
end, opts)
vim.keymap.set("n", "your_keymap", function()
sts.filtered_jump({
"if_statement",
"else_clause",
"else_statement",
}, false) --> false means jump backwards
end, opts)-------------------------------
-- jump with limited targets --
-- jump to sibling nodes only
vim.keymap.set("n", "-", function()
sts.filtered_jump({
"if_statement",
"else_clause",
"else_statement",
}, false, { destination = "siblings" })
end, opts)
vim.keymap.set("n", "=", function()
sts.filtered_jump({ "if_statement", "else_clause", "else_statement" }, true, { destination = "siblings" })
end, opts)-- jump to parent or child nodes only
vim.keymap.set("n", "_", function()
sts.filtered_jump({
"if_statement",
"else_clause",
"else_statement",
}, false, { destination = "parent" })
end, opts)
vim.keymap.set("n", "+", function()
sts.filtered_jump({
"if_statement",
"else_clause",
"else_statement",
}, true, { destination = "children" })
end, opts)-- Setup Function example:
-- These are the default options:
require("syntax-tree-surfer").setup({
highlight_group = "STS_highlight",
disable_no_instance_found_report = false,
default_desired_types = {
"function",
"arrow_function",
"function_definition",
"if_statement",
"else_clause",
"else_statement",
"elseif_statement",
"for_statement",
"while_statement",
"switch_statement",
},
left_hand_side = "fdsawervcxqtzb",
right_hand_side = "jkl;oiu.,mpy/n",
icon_dictionary = {
["if_statement"] = "",
["else_clause"] = "",
["else_statement"] = "",
["elseif_statement"] = "",
["for_statement"] = "ïœ",
["while_statement"] = "ﯩ",
["switch_statement"] = "ﳟ",
["function"] = "ïž”",
["function_definition"] = "ïž”",
["variable_declaration"] = "",
},
})
```### Because every languages have different schemas and node-types, you can check the node-types that you're interested in with https://github.com/nvim-treesitter/playground
#### You can also do a quick check using the command :STSPrintNodesAtCursor
# Version 2.2 Update
### Hold and swap nodes
https://user-images.githubusercontent.com/8104435/225992362-4e82d677-2ff5-463a-a910-6a6bdbf4fc9c.mp4This feature allows marking a node and then swapping it with another node.
Example mapping:
```lua
-- Holds a node, or swaps the held node
vim.keymap.set("n", "gnh", "STSSwapOrHold", opts)
-- Same for visual
vim.keymap.set("x", "gnh", "STSSwapOrHoldVisual", opts)
```The lower-level functionality can be accessed via:
```lua
require("syntax-tree-surfer").hold_or_swap(true) -- param is_visual boolean
require("syntax-tree-surfer").clear_held_node()
```
note that `STSSwapOrHoldVisual` will clear the visual selection, but `hold_or_swap(true)` will not.# Special Thanks To:
### Dr. David A. Kunz for creating [Let's create a Neovim plugin using Treesitter and Lua](https://www.youtube.com/watch?v=dPQfsASHNkg)
### NVIM Treesitter Team - https://github.com/nvim-treesitter/nvim-treesitter
### @lmburns for [#9](https://github.com/ziontee113/syntax-tree-surfer/pull/9)
### @spiderforrest for [#14](https://github.com/ziontee113/syntax-tree-surfer/pull/14)