Closed ianconsolata closed 7 years ago
Hi jungziege!
The simplest solution to this situation is to forcibly insert the desired character with <C-v>
.
IMHO, the insert mode mappings do a good job of keeping brackets balanced in most cases, so requiring the user to type <C-v>)
on the rare occasion that they are not is a reasonable demand.
I definitely welcome a solution to this issue if it comes at an imperceptible performance cost. Here is the commit that introduced the change:
https://github.com/guns/vim-sexp/commit/d86afd5c246ca9fa9af65404ae7316835f5c5670
And the previous version of the function:
" Position of nearest _paired_ bracket: 0 for opening, 1 for closing. Returns
" [0, 0, 0, 0] if none found.
function! s:nearest_bracket(closing)
let closest = []
let flags = a:closing ? 'nW' : 'bnW'
let stopline = g:sexp_maxlines ? line('.') + (a:closing ? g:sexp_maxlines : -g:sexp_maxlines) : 0
for [start, end] in s:pairs
let [line, col] = searchpairpos(start, '', end, flags, 's:is_ignored_scope(line("."), col("."))', stopline)
if line < 1
continue
elseif empty(closest)
let closest = [0, line, col, 0]
else
let closest = s:min_by_distance_from(getpos('.'), closest, [0, line, col, 0])
endif
endfor
return empty(closest) ? [0, 0, 0, 0] : closest
endfunction
function! s:min_by_distance_from(pos, a, b)
" First return closest by line difference
let line_delta_a = abs(a:pos[1] - a:a[1])
let line_delta_b = abs(a:pos[1] - a:b[1])
if line_delta_a > line_delta_b
return a:b
elseif line_delta_a < line_delta_b
return a:a
" They are on the same line as the cursor
elseif line_delta_a == 0
let col_delta_a = abs(a:pos[2] - a:a[2])
let col_delta_b = abs(a:pos[2] - a:b[2])
return col_delta_a > col_delta_b ? a:b : a:a
" They are on the same line, but not on the same line as the cursor. If
" below the cursor, proximity is closest to bol and vice versa.
else
let op = a:pos[1] - a:a[1] < 0 ? '<' : '>'
let a_is_closer = eval(a:a[2] . op . a:b[2])
return a_is_closer ? a:a : a:b
endif
endfunction
I recall trying to optimize the above before throwing in the towel, but couldn't get the order of magnitude decrease in runtime that I wanted to keep things snappy. Perhaps you can do better! I would be happy to accept it.
Thanks for reading the source before reporting!
Oh, sweet. Didn't know about <C-v>)
. That works great, thanks! Closing for now.
The insert mode mappings by default don't allow me to match unbalanced parentheses (
|
denotes the cursor). What I have:([(|])
What I want:([()|])
What I get:([(]|)
Rather than recognizing that the internal paren is unmatched, and therefore allowing me to insert, it moves my cursor to the closing
)
. This comment in the source explains that it's a tradeoff made for performance reasons. Is there any way to get the desired functionality without taking the performance hit? I'm happy to do the work if you have a solution in mind.