-
-
Save JoosepAlviste/43e03d931db2d273f3a6ad21134b3806 to your computer and use it in GitHub Desktop.
| ---@param types string[] Will return the first node that matches one of these types | |
| ---@param node TSNode|nil | |
| ---@return TSNode|nil | |
| local function find_node_ancestor(types, node) | |
| if not node then | |
| return nil | |
| end | |
| if vim.tbl_contains(types, node:type()) then | |
| return node | |
| end | |
| local parent = node:parent() | |
| return find_node_ancestor(types, parent) | |
| end | |
| ---When typing "await" add "async" to the function declaration if the function | |
| ---isn't async already. | |
| local function add_async() | |
| -- This function should be executed when the user types "t" in insert mode, | |
| -- but "t" is not inserted because it's the trigger. | |
| vim.api.nvim_feedkeys('t', 'n', true) | |
| local buffer = vim.fn.bufnr() | |
| local text_before_cursor = vim.fn.getline('.'):sub(vim.fn.col '.' - 4, vim.fn.col '.' - 1) | |
| if text_before_cursor ~= 'awai' then | |
| return | |
| end | |
| -- ignore_injections = false makes this snippet work in filetypes where JS is injected | |
| -- into other languages | |
| local current_node = vim.treesitter.get_node { ignore_injections = false } | |
| local function_node = find_node_ancestor( | |
| { 'arrow_function', 'function_declaration', 'function', 'method_definition' }, | |
| current_node | |
| ) | |
| if not function_node then | |
| return | |
| end | |
| local function_text = vim.treesitter.get_node_text(function_node, 0) | |
| if vim.startswith(function_text, 'async') then | |
| return | |
| end | |
| local start_row, start_col = function_node:start() | |
| vim.api.nvim_buf_set_text(buffer, start_row, start_col, start_row, start_col, { 'async ' }) | |
| end | |
| vim.keymap.set('i', 't', add_async, { buffer = true }) |
Great plugin. Additionally, you could include the
method_definitionancestor so it will work also with classes:local function_node = find_node_ancestor( { 'arrow_function', 'function_declaration', 'function', 'method_definition' }, current_node )
Looks great, thanks! Updated the Gist 🎉
Hi @JoosepAlviste, thanks for the gist! Is there an easy way to identify if the cursor is currently in a comment when triggering the keymap t in insert mode? I'm not having any luck with my attempts, such as
-- 1: doesn't work, nodetype is `statement_block`
vim.keymap.set("i", "t", function()
if vim.treesitter.get_node():type() == "comment" then
return
end
add_async()
end, { buffer = true, desc = "trigger add_async" })
-- 2: also doesn't work, attempting to reparse the unknown tree before getting node
vim.keymap.set("i", "t", function()
vim.treesitter.get_parser():parse()
if vim.treesitter.get_node():type() == "comment" then
return
end
add_async()
end, { buffer = true, desc = "trigger add_async" })For example, leaving a comment mentioning "await". Typing within this comment will unnecessarily add async to bar()
class FooClass {
bar() {
// we don't need to await[CURSOR HERE]
const baz = doThing();
}
}Hey! I made another addition for the sake of completion of this amazing script. I have modified the script so that it also works for access modified functions inside of classes. I was using this script all the time at work, and since most of the functions I write are inside classes, it made sense to me to modify it for the public, private and protected modifiers. Here is the updated script:
---@param types string[] Will return the first node that matches one of these types
---@param node TSNode|nil
---@return TSNode|nil
local function find_node_ancestor(types, node)
if not node then
return nil
end
if vim.tbl_contains(types, node:type()) then
return node
end
local parent = node:parent()
return find_node_ancestor(types, parent)
end
---When typing "await" add "async" to the function declaration if the function
---isn't async already.
local function add_async()
-- This function should be executed when the user types "t" in insert mode,
-- but "t" is not inserted because it's the trigger.
vim.api.nvim_feedkeys('t', 'n', true)
local buffer = vim.fn.bufnr()
local text_before_cursor = vim.fn.getline('.'):sub(vim.fn.col '.' - 4, vim.fn.col '.' - 1)
if text_before_cursor ~= 'awai' then
return
end
-- ignore_injections = false makes this snippet work in filetypes where JS is injected
-- into other languages
local current_node = vim.treesitter.get_node { ignore_injections = false }
local function_node = find_node_ancestor(
{ 'arrow_function', 'function_declaration', 'function', 'method_definition' },
current_node
)
if not function_node then
return
end
local function_text = vim.treesitter.get_node_text(function_node, 0)
if vim.startswith(function_text, 'async') then
return
end
if vim.startswith(function_text, 'public async') then
return
end
if vim.startswith(function_text, 'private async') then
return
end
if vim.startswith(function_text, 'protected async') then
return
end
local start_row, start_col = function_node:start()
if vim.startswith(function_text, 'public') then
start_col = start_col + 7
end
if vim.startswith(function_text, 'private') then
start_col = start_col + 8
end
if vim.startswith(function_text, 'protected') then
start_col = start_col + 10
end
vim.api.nvim_buf_set_text(buffer, start_row, start_col, start_row, start_col, { 'async ' })
end
vim.keymap.set('i', 't', add_async, { buffer = true })
Great plugin.
Additionally, you could include the
method_definitionancestor so it will work also with classes: