Skip to content

Commit

Permalink
Multibyte fast wrap + bugfixes
Browse files Browse the repository at this point in the history
  • Loading branch information
LunarWatcher committed Jan 25, 2021
1 parent 9114c45 commit 7402136
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Added
* `g:AutoPairsMultilineCloseDeleteSpace`
* `g:AutoPairsMultibyteFastWrap` -- fast wrap now supports multibyte pairs

## Fixed

Expand All @@ -10,6 +11,7 @@
* `g:AutoPairsCompleteOnlyOnSpace` regex: \S is enough. Newlines appear to be stripped anyway, so EOL is fine
* Revert `g:AutoPairsMultilineClose` to 0; not sure when it changed to 1
* Corrected multiline pair regex (`'^\V'.close` -> `'\v^\s*\zs\V'.close`); not sure why it was changed in the first place, doesn't appear to be relevant for space-only autoinsert. (Objections are welcome on this one; open an issue if you disagree or if this breaks your use of the plugin)
* Slightly saner check for escaped characters

## Changed
* Made `g:AutoPairsOpenBalanceBlacklist` empty by default. Can't remember the rationale behind adding them in the first place
Expand Down
5 changes: 5 additions & 0 deletions TODO.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
TODOs:
* [ ] Improve balance checks to ignore pairs in strings (and either ignore balance checks in strings, or something like that)
- [ ] Ignore comments?
- Note: use highlight groups

62 changes: 56 additions & 6 deletions autoload/autopairs.vim
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ call s:define("g:AutoPairs", {'(': ')', '[': ']', '{': '}', "'": "'", '"': '"',
" The last paragraph of the help is extremely important.
call s:define("g:AutoPairsLanguagePairs", {
\ "erlang": {'<<': '>>'},
\ "tex": {'``': "''" },
\ "tex": {'``': "''", '$': '$'},
\ "html": {'<': '>'},
\ 'vim': {'\v(^\s*\zs"\ze|".*"\s*\zs"\ze$|^(\s*[a-zA-Z]+\s*([a-zA-Z]*\s*\=\s*)?)@!(\s*\zs"\ze(\\\"|[^"])*$))': ''},
\ 'rust': {'\w\zs<': '>', '&\zs''': ''},
Expand Down Expand Up @@ -224,6 +224,8 @@ call s:define('g:AutoPairsMultilineFastWrap', 0)
call s:define('g:AutoPairsFlyModeList', '}\])')
call s:define('g:AutoPairsJumpBlacklist', [])

call s:define('g:AutoPairsMultibyteFastWrap', 1)

fun! autopairs#AutoPairsScriptInit()
" This currently does nothing; see :h autopairs#AutoPairsScriptInit()
endfun
Expand Down Expand Up @@ -278,7 +280,8 @@ func! autopairs#AutoPairsInsert(key)
let [before, after, afterline] = s:getline()

" Ignore auto close if prev character is \
if before[-1:-1] == '\'
" And skip if it's double-escaped
if before[-1:-1] == '\' && before[-2:-1] != "\\\\"
return a:key
end

Expand Down Expand Up @@ -485,7 +488,46 @@ endf
func! autopairs#AutoPairsFastWrap(...)
let movement = get(a:, 1, 'e')
let c = @"
normal! x
if b:AutoPairsMultibyteFastWrap
let [before, after, ig] = s:getline()
" At this point, after refers to the bit after the cursor.
" We haven't cut anything yet.
if after == ''
" While we do have multiline fast wrap, we actually do need
" something to wrap.
return ''
endif
let length = 1
for [open, close, opt] in b:AutoPairsList
if close == ''
continue
endif

let match = []
let esc = substitute(close, "'", "''", "g")
let esc = substitute(esc, '\', '\\\\', "g")

let res = substitute(after, '^\V' . esc, '\=add(match, submatch(0))', '')

if len(match) > 0 && len(match[0]) > length

let length = len(match[0])
endif
endfor

exec "normal! " . length . "x"
let cursorOffset = length - 1
else
let cursorOffset = 0
normal! x
endif

" Note regarding the previous note: an after == "" check doesn't make
" sense here, because we've already cut at this point. We may want
" multiline wrapping.
" I think xd This has always been a bit weird. Might be better to
" outsource the above check to outside the if-check to prevent weird
" moves
let [before, after, ig] = s:getline()

if after[0] =~ '\v[{[(<]'
Expand All @@ -510,6 +552,9 @@ func! autopairs#AutoPairsFastWrap(...)
call search(close, 'We')
endif
normal! p
if cursorOffset > 0
exec "normal! " . repeat('h', cursorOffset)
endif
let @" = c
return ""

Expand All @@ -521,11 +566,15 @@ func! autopairs#AutoPairsFastWrap(...)
normal! p
else
normal! p
end
end
endif
if cursorOffset > 0
exec "normal! " . repeat('h', cursorOffset)
endif

endif
let @" = c
return ""
endf
endfun

" TODO: determine whether this should be linked against g:AutoPairs or not
" This function calls a manual jump. It jumps to the next character, which may
Expand Down Expand Up @@ -674,6 +723,7 @@ func! autopairs#AutoPairsInit()
call s:define('b:AutoPairsFlyModeList', g:AutoPairsFlyModeList)
call s:define('b:AutoPairsJumpBlacklist', g:AutoPairsJumpBlacklist)
call s:define('b:AutoPairsMultilineCloseDeleteSpace', g:AutoPairsMultilineCloseDeleteSpace)
call s:define('b:AutoPairsMultibyteFastWrap', g:AutoPairsMultibyteFastWrap)

let b:autopairs_return_pos = 0
let b:autopairs_saved_pair = [0, 0]
Expand Down
40 changes: 40 additions & 0 deletions doc/AutoPairs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,29 @@ You can set |b:AutoPairs| before |BufEnter|: >
This sets |AutoPairs| to only match for parenthesis for 'FILETYPE'. See also
|g:AutoPairsLanguagePairs|.
|autopairs-weird-behavior|


Open is used in a regex search, and because auto-pairs applies stuff directly,
there's a minor input escape issue. Most people aren't going to experience it,
but if you i.e. wanna add `'\left(': '\right)'`, there is actually a "right
way" to add it. `\left` may cause `\l` to be interpreted as a group; |\l|
to be specific.

Consequentially, the pair has to be declared as `'\\left(': '\right)'` . The
close pair is also used as a regex in some places, but shouldn't cause any
problems. Additional escaping will be added soon to mitigate problems, but
it's fairly niche. TL;DR: if you use backslash in an open pair, you _need_ to
escape it with `\\` for it to work properly

This is a bit of a double-sided blade, though; forcing escape of the close
pair in certain places means regex cannot be used. Regex groups for replace
cannot be used either way, so there should be relatively few reasons to have
regex in the closing pair.

Note that all the pairs are run through a \V, so some characters should be
entirely escaped. Direct use consequentially means you can `\v` and get
creative with regexes for pairs.

------------------------------------------------------------------------------
*g:AutoPairsCompleteOnlyOnSpace*
Expand Down Expand Up @@ -803,6 +826,23 @@ outcome: >
}|
<

------------------------------------------------------------------------------
*g:AutoPairsMultibyteFastWrap*
|g:AutoPairsMultibyteFastWrap| int
This variable also exists in a buffer variant.~

Default: 1

Whether or not to enable multibyte fast wrap. Note that this is currently
considered experimental even though it's enabled by default. If you experience
that it doesn't work, please open an issue.

When this is enabled, it enables wrapping multibyte pairs -- note that it only
does this for pairs registered in *g:AutoPairs* , as arbitrary selections
would be unpredictable.

If a multibyte pair or a normal pair isn't found, it'll fall back to standard
behavior and assume the next character is what you want to wrap.

==============================================================================
6. Troubleshooting *autopairs-troubleshooting*
Expand Down

0 comments on commit 7402136

Please sign in to comment.