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
support for jumpout&jumpnext pairs #167
Comments
https://github.com/abecodes/tabout.nvim |
This is another good visualization of what is being asked for. At least for me personally, I'd rather not install treesitter to use tabout just to get this functionality. In #125 , you mention that adding this functionality might be possible since you export all the rules. In #190, @noib3 makes a good point that the plugin could expose I guess I'm just trying to understand if it is not possible in this plugin, or if it's something you will not add. No worries either way! Nice work on this plugin! |
the problem come from find a match pair if it place on different line and you need treesitter. if you want to just move a cursor to left you can create a normal mapping to do that or a rule if you want to check condition. |
I used to use https://github.com/jiangmiao/auto-pairs which provides jumpout behavior like this:
Is it possible to configure this plugin to achieve something similar? It's really intuitive to just close whatever pair you're in to jump out. |
@tlindsay I managed to get This is a slightly improved version of the code I posted there: local nap = require('nvim-autopairs')
local rule = require('nvim-autopairs.rule')
local cond = require('nvim-autopairs.conds')
local utils = require('nvim-autopairs.utils')
local function multiline_close_jump(open, close)
return rule(close, '')
:with_pair(function()
local row, col = utils.get_cursor()
local line = utils.text_get_current_line()
if #line ~= col then --not at EOL
return false
end
local unclosed_count = 0
for c in line:gmatch("[\\" .. open .. "\\" .. close .. "]") do
if c == open then unclosed_count = unclosed_count + 1 end
if unclosed_count > 0 and c == close then unclosed_count = unclosed_count - 1 end
end
if unclosed_count > 0 then return false end
local nextrow = row + 1
if nextrow < vim.api.nvim_buf_line_count(0)
and vim.regex("^\\s*" .. close):match_line(0, nextrow) then
return true
end
return false
end)
:with_move(cond.none())
:with_cr(cond.none())
:with_del(cond.none())
:set_end_pair_length(0)
:replace_endpair(function()
return '<esc>xEa'
end)
end
nap.add_rules {
multiline_close_jump('(', ')'),
multiline_close_jump('[', ']'),
multiline_close_jump('{', '}'),
} IIRC I fixed it preferring to jump over closing braces instead of inserting a closing brace when an unclosed opener exists within another set of braces. |
Amazing! Thanks @Diomendius! |
Trying your solution does it still work for you guys @tlindsay @Diomendius are there any other plugins I need as prerequisits I seem to keep getting error: E5113: Error while calling lua chunk: .../pack/packer/start/nvim-autopairs/lua/nvim-autopairs.lua:115: attempt to index field 'config' (a nil value). TLDR; does it still work? |
I'd also like to suggest delete functionality, this is done in https://github.com/jiangmiao/auto-pairs if (true) {| <-- Press backspace here.
} Expected output: if (true) |
@vitek-borovsky it is not working for me either. This could be an issue with Neovim 0.8. |
Not nearly as good a solution, but a simple mapping I've been using for a while that will essentially accomplish the same thing and works in 0.8 is: vim.keymap.set("i", "<C-l>", "<esc>:exe 'norm! l%%'<CR>a", { silent = true }) It's always worked well within paragraphs for me with the two caveats being that you can't really jump between paragraphs easily and it's only one way (you can't jump backwards). |
Updated version of @Diomendius rule, thanks by the way. local npairs = require('nvim-autopairs')
local Rule = require('nvim-autopairs.rule')
local cond = require('nvim-autopairs.conds')
local utils = require('nvim-autopairs.utils')
local function multiline_close_jump(open, close)
return Rule(close, '')
:with_pair(function()
local row, col = utils.get_cursor(0)
local line = utils.text_get_current_line(0)
if #line ~= col then --not at EOL
return false
end
local unclosed_count = 0
for c in line:gmatch('[\\' .. open .. '\\' .. close .. ']') do
if c == open then
unclosed_count = unclosed_count + 1
end
if unclosed_count > 0 and c == close then
unclosed_count = unclosed_count - 1
end
end
if unclosed_count > 0 then
return false
end
local nextrow = row + 1
if nextrow < vim.api.nvim_buf_line_count(0) and vim.regex('^\\s*' .. close):match_line(0, nextrow) then
return true
end
return false
end)
:with_move(cond.none())
:with_cr(cond.none())
:with_del(cond.none())
:set_end_pair_length(0)
:replace_endpair(function(opts)
local cleanup = '' == trim(opts.line)
and 'dd' -- test
or 'xj' --test
return ('<esc>%s0f%sa'):format(cleanup, opts.char)
end)
end
npairs.add_rules({
multiline_close_jump('(', ')'),
multiline_close_jump('[', ']'),
multiline_close_jump('{', '}'),
}) For the index issue it was because of a missing fallback to
local t = {
y = {
|
},
} After: local t = {
y = {
}|,
} |
My take on this: local function multiline_close_jump(open, close)
return rule(close, "")
:with_pair(function()
local row, col = utils.get_cursor(0)
local line = utils.text_get_current_line(0)
if #line ~= col then --not at EOL
return false
end
local unclosed_count = 0
for c in line:gmatch("[\\" .. open .. "\\" .. close .. "]") do
if c == open then unclosed_count = unclosed_count + 1 end
if unclosed_count > 0 and c == close then unclosed_count = unclosed_count - 1 end
end
if unclosed_count > 0 then return false end
local nextrow = row + 1
if nextrow < vim.api.nvim_buf_line_count(0) and vim.regex("^\\s*" .. close):match_line(0, nextrow) then
return true
end
return false
end)
:with_move(cond.none())
:with_cr(cond.none())
:with_del(cond.none())
:set_end_pair_length(0)
:replace_endpair(function(opts)
local row, _col = utils.get_cursor(0)
local action = vim.regex("^" .. close):match_line(0, row + 1) and "a" or ("0f%sa"):format(opts.char)
return ("<esc>xj%s"):format(action)
end)
end @camilledejoye 's version almost works for me, but doesn't leave me in insert mode when the matching local t = {
y = {
|
}
} works fine and results in local t = {
y = {
}|
} but pressing local t = {
y = {
}
}| -- Cursor here, but in Normal mode, not Insert After playing around with different variations for My fix just checks if the first character on the line is the matching pair and runs |
To get back to the original question, I have put together this quick & dirty solution for using a single key to jump over multiple nested ending pairs, though it only works in the single line case: local check_next_delim = function(line, col)
for _, rule in ipairs(npairs.get_buf_rules(vim.api.nvim_get_current_buf())) do
if rule.start_pair then
local delim = rule.end_pair
if line:find(delim, col, true) == col then return delim end
end
end
end
local skip_pairs = function()
local col = vim.fn.col('.')
local line = vim.fn.getline('.')
local next_delim = check_next_delim(line, col)
while next_delim do
for _ = 1, vim.fn.strdisplaywidth(next_delim) do
vim.fn.feedkeys(vim.api.nvim_replace_termcodes("<Right>", true, true, true))
end
col = col + #next_delim
if col > #line then return end
next_delim = check_next_delim(line, col)
end
end
vim.keymap.set("i", "<Tab>", skip_pairs) |
Is your feature request related to a problem? Please describe.
Used another autopairs plugin writen in vimscript for a long time, is it possiable support the same feature
Describe the solution you'd like
{ | } ... [ ]
--type C-n to jump out
{ } | ... [ ]
--type C-n to jump next
{ } ...[ | ]
The text was updated successfully, but these errors were encountered: