On Sa, 05 Mai 2018, Lifepillar wrote:

> I have posted this on the Vim mailing list, but I am opening an issue here 
> because I think that this is a bug, or at least a shortcoming, of 
> `feedkeys()` (but I may be missing something about some internal character 
> processing in Vim).
> 
> The following test code, which is supposed to automatically trigger keyword 
> completion upon typing `o`, fails using `vim --clean`:
> 
> ```vim
> let s:o_char_pressed = 0
> 
> fun! s:act_on_text_changed()
>   if s:o_char_pressed
>     let s:o_char_pressed = 0
>     call feedkeys("\<c-x>\<c-n>", 'i')
>   endif
> endf
> 
> fun! Test_complete_o_tab()
>   set completeopt=menu,noselect
>   new
>   imap <expr> <buffer> <tab> pumvisible() ? "\<c-p>" : "X"
>   autocmd! InsertCharPre <buffer> let s:o_char_pressed = (v:char ==# 'o')
>   autocmd! TextChangedI <buffer> call <sid>act_on_text_changed()
>   call setline(1,  ['hoard', 'hoax', 'hoarse', ''])
>   let l:expected = ['hoard', 'hoax', 'hoarse', 'hoax', 'hoax']
>   call cursor(4,1)
>   call test_override("char_avail", 1)
>   call feedkeys("Ahoa\<tab>\<tab>\<c-y>\<esc>", 'tx')  " OK
>   call feedkeys("oho\<tab>\<tab>\<c-y>\<esc>", 'tx')   " FAILS
>   call assert_equal(l:expected, getline(1,'$'))
>   call test_override("char_avail", 0)
>   bwipe!
>   set completeopt&
> endf
> ```
> 
> The output is:
> 
> ```
> hoard
> hoax
> hoarse
> hoax
> hoXX
> ```
> 
> Note that the last line was not completed correctly, likely because 
> `pumvisible()` is evaluated to `0` when expanding `<tab>` in the second call 
> to `feedkeys()` (but not in the first—why?).
> 
> Note also that, if you replace (at least) the first occurrence of `<tab>` 
> with `<c-p>` in the second call to `feedkeys()` then the test passes.

It is a bit tricky to follow your script, since you are doing quite some 
automatic processing in combination with TextChangedI and InsertCharPre 
autocommands to add some keys into the type buffer, plus some of them 
are mapped.

However, I think I managed to find the problem.

There is a comment in edit.c:
,----
|        * If there's any pending input, grab up to INPUT_BUFLEN at once.
|        * This speeds up normal text input considerably.
|        * Don't do this when 'cindent' or 'indentexpr' is set, because we might
|        * need to re-indent at a ':', or any other character (but not what
|        * 'paste' is set)..
|        * Don't do this when there an InsertCharPre autocommand is defined,
|        * because we need to fire the event for every character.
`----

However the test for the insert char pre autocommand fires after the 
call to vpeekc(), which already changes the input typebuf. Sligthly 
re-ordering the conditions, made the test pass.

I attach the patch plus your test. Thanks for the test, this made it 
easy to convert it into the test suite.


Best,
Christian
-- 
Gesunder Menschenverstand ist das Talent, die Dinge zu sehen, wie sie
sind, und Dinge zu tun, wie sie getan werden sollten.
                -- Calvin Ellis Stowe

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
From 0c5ad633c677a5c6cd96512c6a927393504ff23b Mon Sep 17 00:00:00 2001
From: Christian Brabandt <[email protected]>
Date: Mon, 7 May 2018 10:39:47 +0200
Subject: [PATCH] Earlier test for autocmd insert_char_pre

---
 src/edit.c                 |  5 ++++-
 src/testdir/test_popup.vim | 28 ++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/src/edit.c b/src/edit.c
index eaf690ce9..e1e5c6f79 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -6185,6 +6185,8 @@ insertchar(
      * 'paste' is set)..
      * Don't do this when there an InsertCharPre autocommand is defined,
      * because we need to fire the event for every character.
+     * Do the check for InsertCharPre before the call to vpeekc() because the
+     * InsertCharPre autocommand could change the input buffer.
      */
 #ifdef USE_ON_FLY_SCROLL
     dont_scroll = FALSE;		/* allow scrolling here */
@@ -6194,6 +6196,7 @@ insertchar(
 #ifdef FEAT_MBYTE
 	    && (!has_mbyte || (*mb_char2len)(c) == 1)
 #endif
+	    && !has_insertcharpre()
 	    && vpeekc() != NUL
 	    && !(State & REPLACE_FLAG)
 #ifdef FEAT_CINDENT
@@ -6202,7 +6205,7 @@ insertchar(
 #ifdef FEAT_RIGHTLEFT
 	    && !p_ri
 #endif
-	    && !has_insertcharpre())
+       )
     {
 #define INPUT_BUFLEN 100
 	char_u		buf[INPUT_BUFLEN + 1];
diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim
index d682dd211..9521e0dea 100644
--- a/src/testdir/test_popup.vim
+++ b/src/testdir/test_popup.vim
@@ -831,4 +831,32 @@ func Test_popup_complete_backwards_ctrl_p()
   bwipe!
 endfunc
 
+fun! Test_complete_o_tab()
+  let s:o_char_pressed = 0
+
+  fun! s:act_on_text_changed()
+    if s:o_char_pressed
+      let s:o_char_pressed = 0
+      call feedkeys("\<c-x>\<c-n>", 'i')
+    endif
+  endf
+
+  set completeopt=menu,noselect
+  new
+  imap <expr> <buffer> <tab> pumvisible() ? "\<c-p>" : "X"
+  autocmd! InsertCharPre <buffer> let s:o_char_pressed = (v:char ==# 'o')
+  autocmd! TextChangedI <buffer> call <sid>act_on_text_changed()
+  call setline(1,  ['hoard', 'hoax', 'hoarse', ''])
+  let l:expected = ['hoard', 'hoax', 'hoarse', 'hoax', 'hoax']
+  call cursor(4,1)
+  call test_override("char_avail", 1)
+  call feedkeys("Ahoa\<tab>\<tab>\<c-y>\<esc>", 'tx')
+  call feedkeys("oho\<tab>\<tab>\<c-y>\<esc>", 'tx')
+  call assert_equal(l:expected, getline(1,'$'))
+  call test_override("char_avail", 0)
+  bwipe!
+  set completeopt&
+  delfunc s:act_on_text_changed
+endf
+
 " vim: shiftwidth=2 sts=2 expandtab
-- 
2.17.0

Raspunde prin e-mail lui