-
-
Notifications
You must be signed in to change notification settings - Fork 126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Creating a custom tree sitter rule for the angle bracket pair (<>
) that also escapes does not work
#405
Comments
-- add <> pairs if not in a statement
npairs.add_rules({
rule("<", ">", "cpp"):with_pair(ts_conds.is_not_ts_node({ "compound_statement"})),
}) sadly this doesn't work in cases like this std::vector<int> a = std::vector<int>{1,2,3};
compound_statement----- the second vector won't get pairs u can check it out yourself if u want local ts_utils = require('nvim-treesitter.ts_utils')
vim.keymap.set("i", "<C-q>", function()
print(ts_utils.get_node_at_cursor())
end) |
hmm this actually seems like a good idea for cmp completion |
It seems that the suggested doesn't work for for
Attempting the above will generate
Additionally, I've been trying to write a rule to pairs
And a combination of those 3 nodes and no luck? |
@j-barnak local cpp_cond = function ()
local line = vim.api.nvim_get_current_line()
-- match for() while() functions()
-- the regex won't work if 'magic' is not set
local pattern = '^.*(.*)'
if vim.fn.match({ line }, pattern) == 0 then
return false
end
end
npairs.add_rules({
rule("{", "};", "cpp"):with_pair(
cpp_cond
),
}) i am trying to figure out a way for the first one we might have to restore to checking if template is on the line rather than using treesitter |
@Sam-programs Thanks!
I've been scratching my head over this problem for the past few days and I couldn't come up with anything. Is it possible to just escape the pairs and not complete the pair. For example, with mini.pairs, the following does just that.
|
i don't really understand what the mini example is doing local pair_cond = function ()
local line = vim.api.nvim_get_current_line()
-- only variable inits and structs/classes need semicolons
local pattern = '^\\s*template'
local c_node = ts_utils.get_node_at_cursor():type()
if vim.fn.match({ line }, pattern) ~= 0 and
(c_node ~= "initializer_list")
then
return false
end
end it is just missing global templated variables |
i just tested the mini example it's only putting the pairs at the start of the line local pair_cond = function()
return vim.api.nvim_win_get_cursor(0)[2] == 0
end
npairs.add_rules({
rule("<", ">", "cpp"):with_pair(
pair_cond
),
}) |
I was under the impression that the
I also ran into bumps when dealing with the less than operator. |
@j-barnak |
local cmp = require('cmp')
local function template_on_confirm(event)
if vim.o.filetype ~= "cpp" then
return
end
local entry = event.entry
local item = entry:get_completion_item()
local pairs = '<>'
local functionsig = item.label
if functionsig:sub(#functionsig, #functionsig) == '>' or functionsig == ' template' then
pairs = vim.api.nvim_replace_termcodes(pairs .. "<left>", true, false, true)
vim.api.nvim_feedkeys(pairs, "n", false)
end
end
cmp.event:on('confirm_done', template_on_confirm) best part is you don't even have to write the pairs anymore |
@j-barnak sorry if the mentions are annoying |
@Sam-programs No worries about the mentions. I appreciate them. Awesome work. Do you know if it's possible to add a I'm currently using
to escape the I'm doing this for the
And one last small thing, when you select the snipped for for
Is it possible to do generate
Thanks for everything. Huge help! |
the |
@j-barnak rule("<", ">", "cpp"):
with_pair(conds.none()): -- never add the end pair
with_move(conds.done()), -- move when endpair is pressed and here is a modified version of local kind = cmp.lsp.CompletionItemKind
local function template_on_confirm(event)
if not (vim.o.filetype == "c" or vim.o.filetype == "cpp") then
return
end
local entry = event.entry
local item = entry:get_completion_item()
local _, c = unpack(vim.api.nvim_win_get_cursor(0))
local line = vim.api.nvim_get_current_line()
local pairs = ''
local functionsig = item.label
local is_function = item.kind == kind.Function
if line:sub(c, c) ~= '>' and
(vim.fn.match(functionsig,'<.*>') ~= -1 or
functionsig == ' template')
then
if functionsig:sub(2, 8) == 'include' then
pairs = ' '
end
pairs = pairs .. '<>'
local old_lz = vim.o.lz
vim.o.lz = true
pairs = vim.api.nvim_replace_termcodes(
(is_function and "<C-g>u<left>" or "") .. pairs .. "<C-g>u<left>" .. "<cmd>lua vim.o.lz =" .. (old_lz and "true" or "false") .. "<cr>", true, false, true)
vim.api.nvim_feedkeys(pairs, "n", false)
end
end also you can do i think i should make a pr with something like this it seems really useful |
hold your horses the first check is failing |
@Sam-programs Awesome stuff! I'll test it in the morning. And just to clarify, we include rule("<", ">", "cpp"):
with_pair(conds.none())-- never add the end pair
with_move(conds.done()), -- move when endpair is pressed because And |
yes |
great... 12 void foo(){
13 std::vector<int> a;
14 std::vector<int> b;
15 std::vector
16 } vector<typename Tp, typename Alloc> Class
~ vector(…) Constructor
// NOT A > i think there could be a work around with cmp's sorting i haven't used it before tho |
yea this sorting = {
comparators = {function (entry1,entry2)
local item1 = entry1.completion_item
local item2 = entry2.completion_item
if item1.kind == item2.kind then
return nil
end
if math.max(item1.kind,item2.kind) == item1.kind then
return true
end
return false
end}
}, not sure of a nice way to make it fit into autopairs |
local config = require('cmp.config')
local cmp_comparetors = config.get().sorting.comparators
local unpack = unpack or table.unpack
local function cpp_sort_cmp(entry1, entry2)
local kind1 = entry1.completion_item.kind
local kind2 = entry2.completion_item.kind
if vim.o.filetype ~= "cpp" then
return nil
end
if kind1 == kind.Constructor and kind2 == kind.Class then
return false
end
if kind1 == kind.Class and kind2 == kind.Constructor then
return true
end
return nil
end
cmp.setup({
sorting = {
comparators = {
cpp_sort_cmp,
unpack(cmp_comparetors),
}
}
}) this seems to work best |
after learning how to interact with lsp vim.keymap.set("i", "<C-q>", function()
vim.lsp.handlers["textDocument/signatureHelp"] = function (_,info)
print(info.signatures[1].label)
end
vim.lsp.buf.signature_help()
end) which would make it possible for the -- only works for templated variables those are the hard part
local is_tempalate = function()
local line = vim.api.nvim_get_current_line()
line = line .. '<'
vim.api.nvim_set_current_line(line)
local r,c = unpack(vim.api.nvim_win_get_cursor(0))
vim.api.nvim_win_set_cursor(0,{r,c + 1})
vim.cmd("redraw") -- redraw to add the first <
local old_handler = vim.lsp.handlers["textDocument/signatureHelp"]
vim.lsp.handlers["textDocument/signatureHelp"] = function(_, info)
if info then
if info.signatures[1] then
local functionsig = info.signatures[1].label
if vim.fn.match({functionsig},'^\\w\\+<') == 0 then
vim.api.nvim_set_current_line(line .. '>')
end
end
end
end
vim.lsp.buf.signature_help()
vim.lsp.handlers["textDocument/signatureHelp"] = old_handler
end
vim.keymap.set("i","<",is_tempalate) |
i need to learn to shut up |
Thanks for everything. I'll test this to see if it works well. I'll also test #407 as well! Thanks
That'd be awesome if you got this to work!
Maybe adjust the priority so that it's at the top? |
Just having the following: local conds = require("nvim-autopairs.conds")
local rule = require("nvim-autopairs.rule")
rule("<", ">", "cpp"):with_pair(conds.none()):with_move(conds.done()) doesn't seem to work? |
@Sam-programs A small correction. It seems that Edit: Seems like you address this in the PR. My bad! |
i almost got the function working |
#405 (comment) local is_tempalate = function()
local line = vim.api.nvim_get_current_line()
local r, c = unpack(vim.api.nvim_win_get_cursor(0))
if not (vim.o.filetype == "cpp" or vim.o.filetype == "c") then
line = line:sub(1, c) .. '<' .. line:sub(c + 1)
vim.api.nvim_set_current_line(line)
vim.api.nvim_win_set_cursor(0, { r, c + 1 })
return
end
if vim.fn.match({ line }, 'template') == 0 then
-- c - 1 = 2 chars before the cursor
line = line:sub(1, c) .. '<>' .. line:sub(c + 1)
vim.api.nvim_set_current_line(line)
vim.api.nvim_win_set_cursor(0, { r, c + 1 })
return
end
if vim.fn.match({ line }, '#include') == 0 then
line = line:sub(1, c) .. '<>' .. line:sub(c + 1)
if line:sub(c, c) ~= ' ' then
line = line:sub(1, c) .. ' ' .. line:sub(c + 1)
c = c + 1
end
vim.api.nvim_set_current_line(line)
vim.api.nvim_win_set_cursor(0, { r, c + 1 })
return
end
if vim.fn.match({ line:sub(0, c) }, 'cast\\s*$') == 0 then
-- c - 1 = 2 chars before the cursor
line = line:sub(1, c) .. '<>' .. line:sub(c + 1)
vim.api.nvim_set_current_line(line)
vim.api.nvim_win_set_cursor(0, { r, c + 1 })
return
end
-- c is 1 before the cursor
line = line:sub(1, c) .. '<' .. line:sub(c + 1)
vim.api.nvim_set_current_line(line)
vim.api.nvim_win_set_cursor(0, { r, c + 1 })
vim.cmd("redraw") -- redraw to add the first <
-- since we added < the lsp can detect it
local old_handler = vim.lsp.handlers["textDocument/signatureHelp"]
vim.lsp.handlers["textDocument/signatureHelp"] = function(_, info)
if info and info.signatures and info.signatures[1] and info.signatures[1].label then
local functionsig = info.signatures[1].label
if vim.fn.match({ functionsig }, '^\\w\\+<') == 0 then
-- c + 1 is after including the openning pair very shady code lol
vim.api.nvim_set_current_line(line:sub(0, c + 1) .. '>' .. line:sub(c + 2))
end
end
end
vim.lsp.buf.signature_help()
vim.lsp.handlers["textDocument/signatureHelp"] = old_handler
end
vim.keymap.set("i", "<", is_tempalate)
|
that's also fixed in the pr with a global variable |
DAMN IT COUT BROKE AGAIN |
changing the info if statement to check everything fixes it if info and info.signatures and info.signatures[1] and info.signatures[1].label then |
Replacing local r, c = unpack(vim.api.nvim_win_get_cursor(0)) with local r, c = table.unpack(vim.api.nvim_win_get_cursor(0)) yields the following error
I opted to switch |
And just noting, npairs.add_rules({
rule("<",">"):
with_pair(cond.none()):
with_move(cond.done()):
use_key('<kPoint>') -- a random key so it doesn't map <
}) The above doesn't allow you to escape the end pair |
oh i didn't notice the that |
i have no clue why but this works npairs.add_rules({
rule("<",">"):
with_pair(cond.none()):
with_move(cond.done()):
use_key('>') -- a random key so it doesn't map <
}) |
@j-barnak local unpack = unpack or table.unpack |
With regards to this npairs.add_rules({
rule("<",">"):
with_pair(cond.none()):
with_move(cond.done()):
use_key('>') -- a random key so it doesn't map <
}) I think this works because the |
i thought it meant pair start trigger |
I've done some testing with this snippet and it's been working great. Thanks for the awesome work! Anything you want to add or should I close the issue? Is there anything you want to add or should I wait until #407 gets merged? |
@j-barnak good to know that snippet works ,i am curious to why u prefer it over the cmp snippet #405 (comment) |
I was under the impression that this was better Edit: it works. Though, is there any reason you specifically prefer this one? And personally local npairs = require("nvim-autopairs")
local cmp = require("cmp")
npairs.setup(opts)
local function template_on_confirm(event)
if not (vim.o.filetype == "c" or vim.o.filetype == "cpp") then
return
end
local entry = event.entry
local item = entry:get_completion_item()
local _, c = unpack(vim.api.nvim_win_get_cursor(0))
local line = vim.api.nvim_get_current_line()
local pairs = ""
local functionsig = item.label
if
line:sub(c, c) ~= ">"
and (functionsig:sub(#functionsig, #functionsig) == ">" or functionsig == " template")
then
if functionsig:sub(2, 8) == "include" then
pairs = " "
end
pairs = pairs .. "<>"
pairs = vim.api.nvim_replace_termcodes(pairs .. "<left>", true, false, true)
vim.api.nvim_feedkeys(pairs, "n", false)
end
end
cmp.event:on("confirm_done", template_on_confirm)
|
Mind sharing this hotkey? |
phew the pr is safe to merge
damn you learnt vim properly and didn't use the arrow keys unlike me lol vim.keymap.set({ "i", "c" }, "<A-l>", "<right>") -- the c mode is command mode edit:
not having to press < |
@Sam-programs Thanks! You might also want to add to your config npairs.add_rules({
rule("{", "}", "cpp"):with_pair(ts_conds.is_ts_node({ "namespace_definition" })),
}) because local cpp_cond = function ()
local line = vim.api.nvim_get_current_line()
-- match for() while() functions()
-- the regex won't work if 'magic' is not set
local pattern = '^.*(.*)'
if vim.fn.match({ line }, pattern) == 0 then
return false
end
end
npairs.add_rules({
rule("{", "};", "cpp"):with_pair(
cpp_cond
),
}) triggers |
thanks @j-barnak i also noticed that the cmp autocomplete doesn't detect static_cast and other kinds of casts u will need to add the template_on_confirm to cmp's events after autopairs for functions cmp.event:on("confirm_done",cmp_autopairs.on_confirm_done())
cmp.event:on('confirm_done', template_on_confirm) but now template_on_confirm sadly doesn't work on it's own |
@Sam-programs Thanks! How would you make casts work with this rule? Thank you so much! You've been awesome. |
i am really not sure how to make it work as i won't have access to cmp's entry that might conflict with a variable ending with cast but i don't have that much time to read/test the lsp requests for now edit: |
@j-barnak mention lol |
@Sam-programs That works! My one and last problem is that I when I mix these two local cpp_cond = function ()
local line = vim.api.nvim_get_current_line()
-- match for() while() functions()
-- the regex won't work if 'magic' is not set
local pattern = '^.*(.*)'
if vim.fn.match({ line }, pattern) == 0 then
return false
end
end
npairs.add_rules({
rule("{", "};", "cpp"):with_pair(
cpp_cond
),
})
pairs.add_rules({
rule("{", "}", "cpp"):with_pair(ts_conds.is_ts_node({ "namespace_identifier" })),
}) The |
@Sam-programs I also tried this local npairs = require("nvim-autopairs")
local rule = require("nvim-autopairs.rule")
local ts_conds = require("nvim-autopairs.ts-conds")
npairs.add_rules({
rule("<", ">"):with_pair(cond.none()):with_move(cond.done()):use_key(">"),
rule("{", "};", { "cpp", "c" }):with_pair(cpp_cond),
rule("{", "}", "cpp"):with_pair(ts_conds.is_ts_node({ "namespace_identifier" })),
}) And it did not work. |
don't use translation_unit node
namespace| i matched the line with namespace which should do it local cpp_cond = function()
local line = vim.api.nvim_get_current_line()
-- match for() while() functions()
local pattern = '\\m^.*(.*)'
if vim.fn.match(line, pattern) ~= -1 or
vim.fn.match(line,"namespace") ~= -1
then
return false
end
end
local npairs = require("nvim-autopairs")
npairs.setup{}
local rule = require("nvim-autopairs.rule")
npairs.add_rules({
rule("{", "};", { "cpp", "c" }):with_pair(cpp_cond),
}) you could also use my expand plugin to make expanding pairs for all statement with 1 hotkey |
Edit: Ignore, I fixed this @Sam-programs Thanks! I really appreciate it. I'm trying to tweak the above line so that it only returns I want the default rule("{", "};", { "cpp", "c" }):with_pair(struct_or_class), It seems to default to local function get_relative_line(offset)
local line = vim.api.nvim_win_get_cursor(0)[1]
local target = line + offset
return vim.api.nvim_buf_get_lines(0, target - 1, target, false)[1]
end
local struct_or_class = function()
local line = get_relative_line(0)
local previous_line = get_relative_line(-1)
if vim.fn.match(line, "struct") ~= -1 or vim.fn.match(line, "class") ~= -1 then
return true
end
if vim.fn.match(previous_line, "struct") ~= -1 or vim.fn.match(previous_line, "class") ~= -1 then
return true
end
return false -- fixed
end
local npairs = require("nvim-autopairs")
local rule = require("nvim-autopairs.rule")
local cond = require("nvim-autopairs.conds")
npairs.setup(opts)
npairs.add_rules({
rule("{", "};", { "cpp", "c" }):with_pair(struct_or_class),
}) |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Description
I am trying to add a treesitter rule that creates the
<>
pairThe only time I don't want
<>
to pair is when it's used as a binary expression. Bythat, I mean for the bitshift operator (
<<
) and the less than operator (<
). Here's what I meanThe bitshift operator and less than operator are both binary expressions so I thought
I could encapsulate the pairing with the following
but this doesn't work.
I've also tried to manually add all the instances of where the bracket is used as a pair with
This works for
preproc_include
, but nottemplate_declaration
. The AST for templates look likeAnd this is what it looks like for templated class declarations
How could I get this rule to work?
Mapping bug
1.If you report a bug about indent. Please remember that plugin doesn't do anything about indent.
It just trigger the indent of your vim config so if you have wrong indent config then it will do wrong indent.
You can check by select a block of code and press
==
2. provide result of command
:verbose imap <cr>
.Steps to reproduce
No response
Minimal config
The text was updated successfully, but these errors were encountered: