Git Product home page Git Product logo

Comments (14)

LunarWatcher avatar LunarWatcher commented on June 22, 2024 1

Leaving a final comment here: if someone is able to reproduce this again at any point in time, please consider leaving a comment (or opening a new issue) with the result of imap <cr>. If imap <cr> only contains auto-pairs, run imap <SNR>1234_AutoPairsOldCRWrapper1234, where both instances of 1234 are replaced with the numbers that appear in the map.

For instance, if imap <CR> yields:

i  <CR>        &@<SNR>129_AutoPairsOldCRWrapper73<SNR>129_AutoPairsReturn
    Last set from ~\vimfiles\plugged\auto-pairs\autoload\autopairs\Keybinds.vim line 245

Run imap <SNR>129_AutoPairsOldCRWrapper73, and include the output of that instead. The numbers will vary. There's a lot of possible causes here, and diagnostic steps will be listed in :help autopairs-bad-cr when 4.0.0 is released soon™️ (it's already available on the 4.0.0 branch, and can be viewed on GitHub without having to switch)

from auto-pairs.

LunarWatcher avatar LunarWatcher commented on June 22, 2024 1

Funny how things work out :) That said, you can also add neo-tree-popup to the filetype blacklist

from auto-pairs.

LunarWatcher avatar LunarWatcher commented on June 22, 2024

I'm aware this could happen in practice, and it's an unfortunate consequence of how Vim's mapping system is built.

Essentially, only two maps of a given type for a given key can exist in a given mode; a global variant, and a buffer-only variant. For insert mode, that means you can have one global mapping for enter, and one buffer mapping for enter. The auto-pairs map and the coc map conflict.

Now, jiangmiao's initial code made some assumptions about the integrity of <CR> that doesn't seem to hold in practice, but is necessary to avoid conflicts with other buffer mappings, but it doesn't extend into global mappings because the mapping system is weird.

I'm not entirely sure why <CR> isn't included; my best guess is some weirdness related to coc.nvim being async and triggering a late <BS>, but the code is too much of a mess for me to figure that out quickly on the fly, so I won't. The last example you have happens when precisely that happens; coc.nvim's mapping is invoked first, because global maps are invoked first. Before the timer expires, auto-pairs' callback has been invoked, which only does O and drops the cr for some reason. (Maybe related to coc's use of <ignore>? Not sure how that works anyway). This creates a line above, coc.nvim then does its thing and inserts user, and voila, you have user where you didn't want it.

Alternatively, it's related to <expr>, but I haven't done much to test and I didn't have much to go on when I inherited the code:

                " remap <expr> to `name` to avoid mix expr and non-expr mode
                execute 'inoremap <buffer> <expr> <script> '. wrapper_name . ' ' . old_cr
                let old_cr = wrapper_name

However, if cr had been included, you would've ended up with a linebreak within the brackets anyway, because the execution of both still takes place.

At this time, I have no better suggestions than to make the else portion of the ternary be \<cr>\<C-r>=autopairs#Keybinds#IgnoreInsertEnter('autopairs#AutoPairsReturn')\<cr>. It's a nasty hack, and I'm aware of that, but it should make sure everything is invoked properly. Disable AutoPairsCR as well, or course

from auto-pairs.

Frederick888 avatar Frederick888 commented on June 22, 2024

Thanks for all the details!

Personally I've only encountered this issue when there are popup menus so may I know how you feel about tackling this case by case? For example,

diff --git a/autoload/autopairs.vim b/autoload/autopairs.vim
index 173333f..25d858d 100644
--- a/autoload/autopairs.vim
+++ b/autoload/autopairs.vim
@@ -482,9 +482,9 @@ fun! autopairs#AutoPairsDetermineCRMovement()
     endif
 endfun
 
 func! autopairs#AutoPairsReturn()
-    if b:autopairs_enabled == 0 || b:AutoPairsIgnoreSingle
+    if b:autopairs_enabled == 0 || b:AutoPairsIgnoreSingle || pumvisible() || (exists('*coc#pum#visible') && coc#pum#visible())
         let b:AutoPairsIgnoreSingle = 0
         return ''
     end
 

from auto-pairs.

LunarWatcher avatar LunarWatcher commented on June 22, 2024

The thing is, that conflicts with people who don't want to make <CR> to coc.nvim, including myself. I got used to ctrl-n and ctrl-y to save pain surrounding <CR> ambiguity (and that was purely from a UX POV, and not from a Vim mapping weirdness one). There's also no guarantee that works consistently; coc.nvim is async, and like I said, that can result in coc.nvim's mapping not being done executing by the time auto-pairs' mapping kicks in.

The beset way to solve it is to make sure there isn't a conflict, but auto-pairs also can't hijack global <CR> on the off chance it has some auto-complete mappings that may or may not conflict.

An option C of sorts to the trigger, actually, though that depends on the execution order of mappings; if vim can stop the mapping from executing in the middle to deal with the timer, it could consistently be stopping immediately after dispatching <CR>, but prior to running AutoPairsReturn. Some weird coc.nvim internals could then treat the newline as it would any character it has to remove, and destroy it. By the time the auto-pairs function is called, the CR is gone and the text inserted. That's the working theory anyway, actually verifying it requires a bit lower level debugging that I can't be arsed to do, because the system is annoying.

The third option is offering mappings compatible with various plugins by default, but as evidenced by coc.nvim recently introducing coc#pum#visible, this results in version incompatibilities between plugins. This doesn't even begin to account for other auto-complete plugins, and there's an obnoxious quantity of them at the moment, or other plugins that add global mappings to <CR>.

And of course, to add insult to injury, there's personal preference on top of that; some people might want to map <CR> to going down the list of completions instead, or do other weird stuff with the map.

So, sorting out the mapping itself in auto-pairs isn't an option, because that's what vimrcs are for, and adding the code you proposed introduces race conditions. Adding a variable for enabling the conditions does solve the user preference bit, but it doesn't solve the race condition.

What would be nice is if Vim had facilities for dealing with conflicting mappings at the editor level rather than on a per-plugin with different practices basis, but that's massively complex onto itself, and I imagine a place where neovim and vim once again fork if it's attempted implemented, which itself isn't stonks. However, that's a pipedream and pipenightmare, and not something we need to think too much about when the problem remains

from auto-pairs.

LunarWatcher avatar LunarWatcher commented on June 22, 2024

... alternatively, if Vim had an equivalent of JavaScript's e.preventDefault(), a bit of code could be amended to the coc bit of the ternary operator to stop any further mappings from executing, but I don't believe that exists at this time either. I imagine it's primarily useful if there's a larger number of mappings, but that typically isn't the case with vim.

Conflict avoidance on keys is preferred as much as possible in Vim. Space and <CR>, along with <BS> to an extent, all represent common keys many plugins and many people use for lots of different things, and Vim's mapping system simply isn't designed to deal with them being used as much as they are. These keys often represent semantic meanings as well, where other keys, subjectively, don't make sense. For auto-pairs, all three keys include extensions to base functionality, and consequently have to be on their equivalent keys. This is with the exception of <CR>, which supports a different key to trigger a "modded" expanding <CR> (IIRC, I haven't touched that system in ages)

from auto-pairs.

Frederick888 avatar Frederick888 commented on June 22, 2024

Understood. Thanks again for the explanation.

Btw you mentioned 'I got used to ctrl-n and ctrl-y', was this talking about assigning them to e.g. g:AutoPairsCRKey?

from auto-pairs.

Frederick888 avatar Frederick888 commented on June 22, 2024

Oh TIL Ctrl-y confirms current pum selection. That's indeed better!

from auto-pairs.

LunarWatcher avatar LunarWatcher commented on June 22, 2024

And ctrl-n goes to the next entry in the popup, yeah. They're default Vim keybinds for operating with the completion menu, so there's strictly speaking no need to remap <CR> to get the completions. It's all about preference; a lot of people have gotten used to <CR> to accept the auto-complete suggestion, and want to keep that in Vim, rather than using Vim's default keybinds. While I sympathise with that, it sure does cause compatibility issues when multiple maps are expected to just work :')

There's also a mapping for going up in the list, but I keep forgetting what it is. The docs are probably more useful than me here. I also believe there's even more keybinds for interacting with the popup, but I just remember the ones I press daily. In either case, if manually invoking auto-pairs yourself in the mapping helps, that's still an option if you prefer <CR>

from auto-pairs.

Frederick888 avatar Frederick888 commented on June 22, 2024

a mapping for going up in the list

That's Ctrl-p I believe. n = next, p = previous :D

there's even more keybinds for interacting with the popup

Yup I just checked :verbose imap output and discovered things like Ctrl-e. Years in Vim still learning new things every day!

from auto-pairs.

LunarWatcher avatar LunarWatcher commented on June 22, 2024

I'll just close this for now; I'll rather reopen if creative ideas for working around incompatible plugins, incompatible plugin versions, and async behavior appear. Until then, amending the map to include an explicit call to auto-pairs (+ disabling the built-in mapping), or preferring ctrl-y for completion insertion are viable workarounds. Imperfect solutions for an imperfect system

from auto-pairs.

LunarWatcher avatar LunarWatcher commented on June 22, 2024

For the record, via #72, I've figured out I was wrong. I assumed async because it sounds plausible for this bug, but I now highly doubt that. I'm unable to reproduce locally now, and it should work fine anyway. The c-y workaround is still solid, but my initial thought on the global vs buffer mappings are blatantly wrong. Buffer maps are always preferred, and auto-pairs includes global maps in its buffer map. That's why coc.nvim's remap works at all

from auto-pairs.

LunarWatcher avatar LunarWatcher commented on June 22, 2024

Good news; finally tracked down the source thanks to an issue from jiangmiao/auto-pairs.

I was partly right. Async stuff causes bad behavior, but this is because both <SNR>s execute in spite of the conditional in the first SNR. It objectively makes sense, just not in the way I thought

The only workaround is

let g:AutoPairsMapCR = 0
inoremap <silent><expr> <cr> coc#pum#visible() ? coc#_select_confirm() : "\<C-g>u\<CR>\<Plug>AutoPairsReturn"

I'll be expanding the documentation with this.

from auto-pairs.

Frederick888 avatar Frederick888 commented on June 22, 2024

from auto-pairs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.