80 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local M = {}
 | |
| 
 | |
| local ok, ts = pcall(require, "nvim-treesitter.ts_utils")
 | |
| 
 | |
| if not ok then
 | |
|     vim.notify "my.tab requires nvim-treesitter to work"
 | |
| end
 | |
| 
 | |
| local pairs = {
 | |
|     ["("] = ")",
 | |
|     ["{"] = "}",
 | |
|     ["["] = "]",
 | |
|     ["<"] = ">",
 | |
|     ["'"] = "'",
 | |
|     ['"'] = '"',
 | |
|     ["`"] = "`",
 | |
| }
 | |
| 
 | |
| local get_new_position = function(node, direction)
 | |
|     local is_single_line = function()
 | |
|         local row_start, _, row_end, _ = node:range()
 | |
|         return row_start == row_end
 | |
|     end
 | |
| 
 | |
|     local is_wrapped = function()
 | |
|         local text = vim.treesitter.get_node_text(node, 0)
 | |
|         local first = string.sub(text, 1, 1)
 | |
|         local last = string.sub(text, -1)
 | |
|         return pairs[first] == last
 | |
|     end
 | |
| 
 | |
|     if is_wrapped() and is_single_line() then
 | |
|         if direction == "backward" then
 | |
|             return node:start()
 | |
|         end
 | |
|         return node:end_()
 | |
|     end
 | |
| end
 | |
| 
 | |
| --- @param direction string The direction of the tab ('forward' | 'backward')
 | |
| --- @return nil
 | |
| M.tab = function(direction)
 | |
|     -- Normal tab action
 | |
|     local tab_action
 | |
|     if direction == "forward" then
 | |
|         tab_action = function()
 | |
|             local codes = vim.api.nvim_replace_termcodes("<Tab>", true, true, true)
 | |
|             vim.api.nvim_call_function("feedkeys", { codes, "n" })
 | |
|         end
 | |
|     else
 | |
|         tab_action = function()
 | |
|             local codes = vim.api.nvim_replace_termcodes("<S-Tab>", true, true, true)
 | |
|             vim.api.nvim_call_function("feedkeys", { codes, "n" })
 | |
|         end
 | |
|     end
 | |
| 
 | |
|     local node = ts.get_node_at_cursor()
 | |
| 
 | |
|     if not node or not node:parent() then
 | |
|         return tab_action()
 | |
|     end
 | |
| 
 | |
|     local line, col = get_new_position(node, direction)
 | |
| 
 | |
|     if not line then
 | |
|         return tab_action()
 | |
|     end
 | |
| 
 | |
|     vim.api.nvim_win_set_cursor(0, { line + 1, col })
 | |
| end
 | |
| 
 | |
| M.forwards = function()
 | |
|     M.tab "forward"
 | |
| end
 | |
| 
 | |
| M.backwards = function()
 | |
|     M.tab "backward"
 | |
| end
 | |
| 
 | |
| return M
 |