windwp / nvim-autopairs

autopairs for neovim written in lua
MIT License
3.28k stars 122 forks source link

Creating a custom tree sitter rule for the angle bracket pair (`<>`) that also escapes does not work #405

Closed j-barnak closed 10 months ago

j-barnak commented 1 year ago

Description

I am trying to add a treesitter rule that creates the <> pair

The only time I don't want <> to pair is when it's used as a binary expression. By that, I mean for the bitshift operator (<<) and the less than operator (<). Here's what I mean

if (x < y) // Do not pair the `<`
    std::cout << "foo"; // Do not pair the <<

The bitshift operator and less than operator are both binary expressions so I thought I could encapsulate the pairing with the following

local npairs = require("nvim-autopairs")
local Rule = require("nvim-autopairs.rule")
local ts_conds = require("nvim-autopairs.ts-conds")

npairs.setup(opts)

npairs.add_rules({
  Rule("<", ">", "cpp"):with_pair(ts_conds.is_not_ts_node({ "binary_expression" })),
})

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

npairs.add_rules({
  Rule("<", ">", "cpp"):with_pair(
    ts_conds.is_ts_node({ "preproc_include", "template_declaration", "template_argument_list" })
  ),
})

This works for preproc_include, but not template_declaration. The AST for templates look like

(template_declaration) ; [3:1 - 55]
 parameters: (template_parameter_list) ; [3:10 - 21]
  (type_parameter_declaration) ; [3:11 - 20]
   (type_identifier) ; [3:20 - 20]

And this is what it looks like for templated class declarations

value: (compound_literal_expression) ; [6:23 - 40]
 type: (qualified_identifier) ; [6:23 - 38]
  scope: (namespace_identifier) ; [6:23 - 25]
  name: (template_type) ; [6:28 - 38]
   name: (type_identifier) ; [6:28 - 33]
   arguments: (template_argument_list) ; [6:34 - 38]
    (type_descriptor) ; [6:35 - 37]
     type: (primitive_type) ; [6:35 - 37]

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 ==

  1. provide result of command :verbose imap <cr>.

Steps to reproduce

No response

Minimal config

vim.cmd [[set runtimepath=$VIMRUNTIME]]
vim.cmd [[set packpath=/tmp/nvim/site]]
local package_root = '/tmp/nvim/site/pack'
local install_path = package_root .. '/packer/start/packer.nvim'
local function load_plugins()
  require('packer').startup {
    {
      'wbthomason/packer.nvim',
      {
        'windwp/nvim-autopairs',
      },
      -- ADD PLUGINS THAT ARE _NECESSARY_ FOR REPRODUCING THE ISSUE
    },
    config = {
      package_root = package_root,
      compile_path = install_path .. '/plugin/packer_compiled.lua',
      display = { non_interactive = true },
    },
  }
end
_G.load_config = function()
  require('nvim-autopairs').setup()
end
if vim.fn.isdirectory(install_path) == 0 then
  print("Installing nvim-autopairs and dependencies.")
  vim.fn.system { 'git', 'clone', '--depth=1', 'https://github.com/wbthomason/packer.nvim', install_path }
end
load_plugins()
require('packer').sync()
vim.cmd [[autocmd User PackerComplete ++once echo "Ready!" | lua load_config()]]

local npairs = require("nvim-autopairs")
local Rule = require("nvim-autopairs.rule")
local ts_conds = require("nvim-autopairs.ts-conds")

npairs.setup(opts)

npairs.add_rules({
  Rule("<", ">", "cpp"):with_pair(ts_conds.is_not_ts_node({ "binary_expression" })),
})
Sam-programs commented 1 year ago
-- 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 but that cases is rare and am not sure we can do better with treesitter

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)
Sam-programs commented 1 year ago

hmm this actually seems like a good idea for cmp completion

j-barnak commented 1 year ago

@Sam-programs

It seems that the suggested doesn't work for for

std::cout << "foo"; 

Attempting the above will generate

std::cout  <> "foo";

Additionally, I've been trying to write a rule to pairs { and }; for classes and structs. And I've tried

npairs.add_rules({
  rule("{", "};", "cpp"):with_pair(
    ts_conds.is_ts_node({ "class_specifier", "type_identifier", "field_declaration_list" })
  ),
})

And a combination of those 3 nodes and no luck?

Sam-programs commented 1 year ago

@j-barnak for the second issue i use this

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

j-barnak commented 1 year ago

@Sam-programs Thanks!

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

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.

require("mini.pairs").map(
  "i",
  "<",
  { action = "open", pair = "<>", neigh_pattern = "\r.", register = { cr = false } }
)

require("mini.pairs").map("i", ">", { action = "close", pair = "<>", register = { cr = false } })
Sam-programs commented 1 year ago

i don't really understand what the mini example is doing and i almost got a working one

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 actually it still doesn't work with cout nvm

Sam-programs commented 1 year ago

i just tested the mini example it's only putting the pairs at the start of the line if that's what u want then this should do

local pair_cond = function()
   return vim.api.nvim_win_get_cursor(0)[2] == 0
end

npairs.add_rules({
   rule("<", ">", "cpp"):with_pair(
      pair_cond
   ),
})
Sam-programs commented 1 year ago

@j-barnak

j-barnak commented 1 year ago

@Sam-programs

I was under the impression that the mini.pairs snippet just allowed you to escape <> pair by pressing >.

actually it still doesn't work with cout nvm

I also ran into bumps when dealing with the less than operator.

Sam-programs commented 1 year ago

@j-barnak i think i found something that could be helpful cmp returns this as the label for vector vector<typename Tp, typename Alloc> which has a > at the end WE COULD CHECK FOR THAT TO ADD THE PAIR! and for the case of writing a template we could check for a template match

Sam-programs commented 1 year ago
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

Sam-programs commented 1 year ago

@j-barnak sorry if the mentions are annoying

j-barnak commented 1 year ago

@Sam-programs No worries about the mentions. I appreciate them.

Awesome work. Do you know if it's possible to add a with_move to escape the <> pair?

I'm currently using mini.pairs, but only using

require("mini.pairs").map("i", ">", { action = "close", pair = "<>", register = { cr = false } })

to escape the <> pairing.

I'm doing this for the preproc_include rule

local rule = require("nvim-autopairs.rule")
local cond = require("nvim-autopairs.conds")
local npairs = require("nvim-autopairs")

npairs.add_rules({
  rule("<", ">", "cpp")
    :with_pair(ts_conds.is_ts_node({ "preproc_include" }))
    :with_move(cond.not_before_regex(">", 1)),
})

And one last small thing, when you select the snipped for for #include, it creates (the | represents the cursor)

`#include<|>`

Is it possible to do generate

`#include <|> // Note the space

Thanks for everything. Huge help!

Sam-programs commented 1 year ago

the #include was an accidental side effect lol

Sam-programs commented 1 year ago

@j-barnak for escaping you can add this rule

   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 template_on_confirm that adds a space for include

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 ```LANG ``` to highlight syntax

i think i should make a pr with something like this it seems really useful

Sam-programs commented 1 year ago

hold your horses the first check is failing update: was an off by 1 error fun fact i didn't know that escaping meant pressing the endpair moves the cursor because i have 1 hotkey that moves the cursor 1 column alt-l <A-l> since most pair keys are far from letters i think this is a better idea

j-barnak commented 1 year ago

@Sam-programs Awesome stuff! I'll test it in the morning.

And just to clarify, we include with_pair(conds.none()) for the following snippet

rule("<", ">", "cpp"):
    with_pair(conds.none())-- never add the end pair
    with_move(conds.done()), -- move when endpair is pressed

because template_on_confirm is used to complete the pairing.

And with_move(conds.done()) enables escaping the <> pair by typing >?

Sam-programs commented 1 year ago

yes

Sam-programs commented 1 year ago

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

Sam-programs commented 1 year ago

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 and i don't suggest using this for now because it might make cmp's results ugly i am gonna try to find a good range/way to sort them (or yoink cmp's)

Sam-programs commented 1 year ago
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 sadly i couldn't check if cpp_sort_cmp was already in the comparator list i hope windwp doesn't think of this as too shady

Sam-programs commented 1 year ago

after learning how to interact with lsp i found that this actually gives the template signature when under a templated class

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 <> pairs to work on their own but i think it's way too overkill tho not gonna stop me for making it in case anyone is curious

-- 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)
Sam-programs commented 1 year ago

i need to learn to shut up this is the most relevant comment https://github.com/windwp/nvim-autopairs/issues/405#issuecomment-1762761811

j-barnak commented 1 year ago

@Sam-programs

Thanks for everything. I'll test this to see if it works well. I'll also test #407 as well!

Thanks

which would make it possible for the <> pairs to work on their own but i think it's way too overkill tho not gonna stop me for making it in case anyone is curious

That'd be awesome if you got this to work!

sadly i couldn't check if cpp_sort_cmp was already in the comparator list

Maybe adjust the priority so that it's at the top?

j-barnak commented 1 year ago

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?

j-barnak commented 1 year ago

@Sam-programs A small correction. It seems that unpack was deprecated in lua 5.4. Changing it to table.unpack fixes it.

Edit: Seems like you address this in the PR. My bad!

Sam-programs commented 1 year ago

i almost got the function working just losing my sanity with lua 1 indexing rn

Sam-programs commented 1 year ago

https://github.com/windwp/nvim-autopairs/issues/405#issuecomment-1762973584 i am not sure what isn't working it shouldn't place a pair in that case i haven't done too much testing but this huge snippet should fix everything

         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)
Sam-programs commented 1 year ago

@j-barnak

Sam-programs commented 1 year ago

sadly i couldn't check if cpp_sort_cmp was already in the comparator list

that's also fixed in the pr with a global variable also don't worry about unpack

Sam-programs commented 1 year ago

DAMN IT COUT BROKE AGAIN

Sam-programs commented 1 year ago

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
j-barnak commented 1 year ago

Replacing

local r, c = unpack(vim.api.nvim_win_get_cursor(0))

with

@Sam-programs

local r, c = table.unpack(vim.api.nvim_win_get_cursor(0))

yields the following error

E5108: Error executing lua: /home/jared/.config/nvim/lua/plugins/pair.lua:19: attempt to call upvalue 'unpack' (a nil value)
stack traceback:
        /home/jared/.config/nvim/lua/plugins/pair.lua:19: in function </home/jared/.config/nvim/lua/plugins/pair.lua:17>

I opted to switch unpack with table.unpack because I got an error say that unpack was deprecated.

j-barnak commented 1 year ago

@Sam-programs

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 >.

Sam-programs commented 1 year ago

oh i didn't notice the that

Sam-programs commented 1 year ago

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 < 
})
Sam-programs commented 1 year ago

@j-barnak use this if u really care about that warning

local unpack = unpack or table.unpack
j-barnak commented 1 year ago

@Sam-programs

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 move is triggered when the pair is completed and use_key triggers the completion. I'll let you know if this runs into errors.

Sam-programs commented 1 year ago

i thought it meant pair start trigger because that key is used in the completion to add the () pair https://github.com/windwp/nvim-autopairs/blob/master/lua/nvim-autopairs/completion/handlers.lua#L52 also the completion starting has nothing to do with npairs unless you mean end pair completion then you are correct

j-barnak commented 1 year ago

@Sam-programs

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?

Sam-programs commented 1 year ago

@j-barnak good to know that snippet works ,i am curious to why u prefer it over the cmp snippet https://github.com/windwp/nvim-autopairs/issues/405#issuecomment-1762690355 because it feels like it's worse than cmp's

j-barnak commented 1 year ago

@Sam-programs

i am curious to why u prefer it over the cmp snippet

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)

~This didn't work for me.~

j-barnak commented 1 year ago

@Sam-programs

because i have 1 hotkey that moves the cursor 1 column alt-l <A-l>

Mind sharing this hotkey?

Sam-programs commented 1 year ago

@j-barnak https://github.com/windwp/nvim-autopairs/issues/405#issuecomment-1763449711

~This didn't work for me~

phew the pr is safe to merge maybe you were messing the sorter here https://github.com/windwp/nvim-autopairs/issues/405#issuecomment-1762761811 without the sorter it sometimes doesn't add the <> pairs add the last cmp.setup after your own cmp.setup or you can just wait until the pr gets merged

Mind sharing this hotkey?

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:

Edit: it works. Though, is there any reason you specifically prefer this one?

not having to press <

j-barnak commented 1 year ago

@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{}; when you type namespace.

Sam-programs commented 1 year ago

thanks @j-barnak i actually thought it was required there

i also noticed that the cmp autocomplete doesn't detect static_cast and other kinds of casts i fixed it by using a regex to detect templated stuff the thing is i am having a hard time making it not conflict with the existing pair adder for functions i got a work around by making it reverse the cursor position for now https://github.com/windwp/nvim-autopairs/issues/405#issuecomment-1762690355

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

j-barnak commented 1 year ago

@Sam-programs Thanks!

How would you make casts work with this rule?

Thank you so much! You've been awesome.

Sam-programs commented 1 year ago

i am really not sure how to make it work as i won't have access to cmp's entry but maybe i could find a lsp method to detect that i made it look if the last few characters are cast to detect casts for now updated

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: i don't really write much c++ so please tell me if there are cases that aren't covered ill fix them when i can

Sam-programs commented 1 year ago

@j-barnak mention lol

j-barnak commented 1 year ago

@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 cpp_cond rule gets overwritten and no longer works.