[vim/vim] Popup with filter eats up Ctrl-C (#8695)

59 views
Skip to first unread message

Sergey Vlasov

unread,
Aug 3, 2021, 10:24:25 AM8/3/21
to vim/vim, Subscribed

Describe the bug

When popup has filter function set then Ctrl-C is always consumed by popup and cannot be caught inside filter function.

To Reproduce
Detailed steps to reproduce the behavior:

  1. Create test.vim:
function! Filter(id, key)
  if a:key == "\<C-C>" " <- never reached
    echo "C-C from popup"
  endif

  return v:false
endfunction

" comment out to see that Filter() is not receiving <C-C>:
nnoremap <C-C> <Cmd>echo "C-C from global mapping"<CR>

help
only
call popup_create("hello", #{filter: "Filter"})
" terminal is important to reproduce the problem:
term sleep 100
  1. Run vim --clean -g -S test.vim.
  2. Press Ctrl-C several times

Expected behavior

  1. First Ctrl-C is sent to terminal and stops the process.
  2. Second and following Ctrl-C print C-C from global mapping.

Actual behavior

  1. First Ctrl-C closes popup.
  2. Second Ctrl-C is sent to terminal and stops the process.
  3. Third and following Ctrl-C print C-C from global mapping.

Environment

  • Vim 8.2.3187
  • OS: Ubuntu 20.04
  • Terminal: GUI


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.

Bram Moolenaar

unread,
Aug 3, 2021, 1:01:00 PM8/3/21
to vim/vim, Subscribed


Sergey Vlasov wrote:

> **Describe the bug**
>
> When popup has filter function set then <kbd>Ctrl-C</kbd> is always consumed by popup and cannot be caught inside filter function.
>
> **To Reproduce**

> Detailed steps to reproduce the behavior:
> 1. Create `test.vim`:
> ```vim

> function! Filter(id, key)
> if a:key == "\<C-C>" " <- never reached
> echo "C-C from popup"
> endif
>
> return v:false
> endfunction
>
> " comment out to see that Filter() is not receiving <C-C>:
> nnoremap <C-C> <Cmd>echo "C-C from global mapping"<CR>
>
> help
> only
> call popup_create("hello", #{filter: "Filter"})
> " terminal is important to reproduce the problem:
> term sleep 100
> ```
> 2. Run `vim --clean -g -S test.vim`.
> 3. Press <kbd>Ctrl-C</kbd> several times
>
> **Expected behavior**
> 1. First <kbd>Ctrl-C</kbd> is sent to terminal and stops the process.
> 2. Second and following <kbd>Ctrl-C</kbd> print `C-C from global mapping`.
>
> **Actual behavior**
> 1. First <kbd>Ctrl-C</kbd> closes popup.
> 2. Second <kbd>Ctrl-C</kbd> is sent to terminal and stops the process.
> 3. Third and following <kbd>Ctrl-C</kbd> print `C-C from global mapping`.

When CTRL-C is pressed the filter is not invoked. The popup should be
closed. Perhaps this isn't clear from the help text, I'll add a note.

As far as I can see the popup is indeed closed with your example.
Not sure why "term sleep 100" is relevant.


--
PRINCE: He's come to rescue me, father.
LAUNCELOT: (embarrassed) Well, let's not jump to conclusions ...
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

/// Bram Moolenaar -- ***@***.*** -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

Sergey Vlasov

unread,
Aug 3, 2021, 1:07:55 PM8/3/21
to vim/vim, Subscribed

If there is a terminal with a job - popup will always get closed by ctrl-c. If there is no job in terminal then my global <C-C> will get executed as expected.

I would like my global <C-C> work even when terminal has a job running. In both cases I would like my popup to ignore <C-C> if there is global mapping for the same keys.

bfrg

unread,
Aug 3, 2021, 2:15:27 PM8/3/21
to vim/vim, Subscribed

@noscript Set the mapping entry to v:true:

call popup_create('hello', #{filter: "Filter", mapping: v:true})

Then all your mappings take precedence over the popup filter keys. There is a flaw with the current implementation though, see #7459.

Sergey Vlasov

unread,
Aug 3, 2021, 3:02:53 PM8/3/21
to vim/vim, Subscribed

@bfrg According to documentation mapping is true by default. Setting it to true explicitly doesn't make a difference.

In #7459 Bram says:

The filter gets all keys, no matter whether they were mapped or not.

This doesn't happen for me. For example I cannot handle <C-C> in the filter. Otherwise I could return v:false and let other handlers (terminal or global mappings) process the keys.

bfrg

unread,
Aug 3, 2021, 3:35:22 PM8/3/21
to vim/vim, Subscribed

When I set 'mapping' to v:true and press <c-c>, Vim will print "C-C from global mapping". It won't work in the terminal window while the job is running since you didn't set tnoremap. And you're right, <c-c> cannot be handled in the popup filter. I don't know why.

Try this:

function Filter(id, key)
    if a:key == 'q'
        call popup_close(a:id)
        return v:true
    endif
    return v:false
endfunction

nnoremap <C-C> <Cmd>echo "C-C from global mapping"<CR>
tnoremap <C-C> <Cmd>echo "C-C from terminal mapping"<CR>
call popup_create('Hello Vim world...', #{filter: 'Filter', filtermode: 'n', mapping: 1, border: []})
terminal

Sergey Vlasov

unread,
Aug 3, 2021, 4:11:44 PM8/3/21
to vim/vim, Subscribed

@bfrg according to my report Vim was expected to print "C-C from global mapping" on the second <c-c> invocation, because the focus on the terminal was intentional.

But thanks, adding filtermode: 'n' fixes the original problem. However in my other code I still have a situation that popup swallows <c-c> and gets closed. I'll try to narrow it down and post an update.

Christian Brabandt

unread,
Aug 3, 2021, 5:31:09 PM8/3/21
to vim/vim, Subscribed

Isn't that expected? Ctrl-C is the key to generally cancel/kill all running commands. You can only catch it, if you mapped it previously.

Sergey Vlasov

unread,
Aug 3, 2021, 6:12:18 PM8/3/21
to vim/vim, Subscribed

Isn't that expected? Ctrl-C is the key to generally cancel/kill all running commands. You can only catch it, if you mapped it previously.

Correct. If Ctrl-C is mapped - it should be caught by mapping and never by popup. However sometimes Ctrl-C is intercepted by popup that has filter set and never happen if popup doesn't have a filter.

I managed to narrow down the problem and terminal is not needed anymore (@bfrg filtermode: 'n' doesn't help here):

function! Filter(id, key)
  if a:key == "\<C-C>" " <- never reached
    echo "C-C from popup"
  endif

  return v:false
endfunction

nnoremap <C-C> <Cmd>echo "C-C from global mapping"<CR>

help
only
call popup_create("hello", #{filter: "Filter", filtermode: 'a', mapping: v:true})

To reproduce:

  • Click somewhere and start pressing C-C periodically while moving mouse cursor without clicking anything.
  • If popup didn't disappear - click in some other place of the buffer and continue C-C pressing and moving mouse.
  • Eventually popup will eat up C-C - that should not happen, because there is already noremap mapping.

And no, that's NOT how I'm using Vim but this is one of the ways I found how to reproduce the problem that I'm facing in my code.

nda-cunh

unread,
Jul 11, 2026, 10:49:23 PM (22 hours ago) Jul 11
to vim/vim, Subscribed
nda-cunh left a comment (vim/vim#8695)

Personally, I’ve created a pop-up where you can select text and press Ctrl+C to copy it, but unfortunately that’s not possible. I think it should be up to the developer of the pop-up plugin to provide another way to close the pop-up; for example, in my case, it’s the Esc key.


Reply to this email directly, view it on GitHub, or unsubscribe.

Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/8695/4949688645@github.com>

Reply all
Reply to author
Forward
0 new messages