steelsojka / pears.nvim

Auto pair plugin for neovim
208 stars 5 forks source link

Support for vim-endwise style pairs #32

Open jasonrhansen opened 3 years ago

jasonrhansen commented 3 years ago

I'd like to be able to configure pairs to do things similar to what endwise does. I would just use endwise in combination with this plugin, but it doesn't work when treesitter is enabled.

Here are some examples of what I'd like to be able to do in Lua:

if condition then|
-- press enter key
if condition then
  |
end
for i, v in ipairs(t) do|
-- press enter key
for i, v in ipairs(t) do
  |
end
local function foo()|
-- press enter key
local function foo()
  |
end

The first two I've been able to configure using #30 to expand on enter in addition to a rule I haven't created a PR for yet called opener_child_of_node. This rule works like child_of_node, but instead of using the current cursor position, it uses the position of the opener.

  conf.pair("then", {
    close = "end",
    filetypes = {"lua"},
    expand_when = R.virtual_key(R.VirtualKey.ENTER),
    should_expand = R.opener_child_of_node("if_statement")
  })

  conf.pair("do", {
    close = "end",
    filetypes = {"lua"},
    expand_when = R.virtual_key(R.VirtualKey.ENTER),
    should_expand = R.any_of(
      R.opener_child_of_node("do_statement"),
      R.opener_child_of_node("for_in_statement"),
      R.opener_child_of_node("while_statement")
    )
  })

I'm happy with how these work, but adding an end for function definitions is more problematic. My first thought was to add a rule similar to the other two and use ")" as the opener. But if the ")" was inserted automatically to complete "(" then it can't be the opener for another pair. If there's currently a way to work around this, I don't know what it is.

Are you interested in having this plugin support endwise style pairs? If so, maybe this issue could be used to track the changes that will be necessary. I haven't yet tried adding configurations for the other languages that endwise supports, but it's possible new features will need to be added to support them.

bluz71 commented 3 years ago

Ruby functions, which also close with end, have optional parenthesis:

def foo
  puts "foo"
end

def foo2(arg)
  puts "foo #{arg}"
end

What is the opener here for the two foo-style functions?

I think it will be very difficult to integrate true endwise functionality into the pairing plugin.

The nvim-autopairs plugin has their own endwise implementation but it has the same limitation from what I can see.

I think vim-endwise simply hooks into the insert mode <CR> character and then uses Vim's regex based syntax tree to figure out if the preceeding line was the opening of a new block.

I think a new Treesitter sitter aware plugin will need to be created to solve this issue and it will probably need to be designed in such a way as to not interfere with nvim-compe which also sometimes uses the <CR> key.

My 2cents.

P.S. I really really want Treesitter endwise since I dabble in Ruby, but I am not sure this plugin is the right place (though I could be wrong).

steelsojka commented 3 years ago

I think endwise is out of scope for this plugin. I would rather get this to play nicely with endwise instead of duplicating all that functionality.

jasonrhansen commented 3 years ago

Yeah, it's probably best to leave endwise out of the scope of this plugin. I would just try to get endwise to play nicely with this plugin, but I use treesitter, and endwise doesn't work with treesitter enabled.

I agree with @bluz71 that it would be nice if there were a treesitter aware endwise plugin that could focus on just that use case. It could then be used in addition to plugins like this one.

bluz71 commented 3 years ago

I think a new plugin will need to be created since:

For the moment I am learning to live without endwise and instead I am using insert mode mappings instead, for example Ctrl-e inserts end followed by normal mode O.

jasonrhansen commented 2 years ago

For anyone that misses endwise while using treesittter, there's a new plugin that implements endwise functionality using treesitter: https://github.com/RRethy/nvim-treesitter-endwise

It currently only supports ruby and lua, but adding support for other languages isn't too difficult. I've opened a PR to support vimscript, and I plan on adding support for julia.