vim-jp / issues

有志で既知のバグや要望を検討・管理し、オフィシャルへの還元をしていきます。
https://vim-jp.org/
342 stars 11 forks source link

補完候補の表示位置が本来の位置からズレる #609

Closed kamichidu closed 10 years ago

kamichidu commented 10 years ago

現象としては表題の通りですが、わかりにくいと思ったのでgif用意しました。

vimのバージョンは7.4.383、linuxでもwindowsでも再現します。 macは未確認です。

また、再現用の最小vimrcを以下に置いています。 最小vimrc 再現用javaコード 最小vimrcを手元に落としてきて、再現用javaコードを以下のように読み込み、 vim -u vimrc -U NONE S.java or gvim -u vimrc -U NONE S.java o.| (|はカーソル位置) で<C-X><C-O>とすると、再現可能です。

現状わかっているポイントは、set nowrapした状態でnormal ggwとすると再現するということです。 また、normal ggwは、call cursor(1, 1)した後にnormal wでも再現しますので、ファイル先頭にカーソルがある状態でnormal wすることがポイントだと思います。

--- 2014-08-15 01:53 追記 --- ソースコード短いので、直接貼っておきます。

filetype indent on

set nocompatible

set omnifunc=XXX

set nowrap

" This function is used for the 'omnifunc' option.    {{{1
function! XXX(findstart, base)
    if a:findstart
        return match(getline('.'), '\.\zs\w*$')
    endif

    let save_pos= getpos('.')
    try
        normal ggw
    finally
        call setpos('.', save_pos)
    endtry

    return ['aaa', 'bbb', 'ccc', 'ddd']
endfunction

" vim:ft=vim:nocompatible
public class S
{
    public static void main(String[] args)
    {
        final Object o;

        o.
    }
}
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Jul 27 2014 19:29:13)
Included patches: 1-383
Compiled by kamichidu
Huge version with GTK2 GUI.  Features included (+) or not (-):
+acl             +clientserver    +cscope          +emacs_tags      +folding         +keymap          +menu            +mouse_netterm   +netbeans_intg   -python3         -sniff           -tcl             +virtualedit     +writebackup
+arabic          +clipboard       +cursorbind      +eval            -footer          +langmap         +mksession       +mouse_sgr       +path_extra      +quickfix        +startuptime     +terminfo        +visual          +X11
+autocmd         +cmdline_compl   +cursorshape     +ex_extra        +fork()          +libcall         +modify_fname    -mouse_sysmouse  +perl            +reltime         +statusline      +termresponse    +visualextra     -xfontset
+balloon_eval    +cmdline_hist    +dialog_con_gui  +extra_search    +gettext         +linebreak       +mouse           +mouse_urxvt     +persistent_undo +rightleft       -sun_workshop    +textobjects     +viminfo         +xim
+browse          +cmdline_info    +diff            +farsi           -hangul_input    +lispindent      +mouseshape      +mouse_xterm     +postscript      +ruby            +syntax          +title           +vreplace        +xsmp_interact
++builtin_terms  +comments        +digraphs        +file_in_path    +iconv           +listcmds        +mouse_dec       +multi_byte      +printer         +scrollbind      +tag_binary      +toolbar         +wildignore      +xterm_clipboard
+byte_offset     +conceal         +dnd             +find_in_path    +insert_expand   +localmap        +mouse_gpm       +multi_lang      +profile         +signs           +tag_old_static  +user_commands   +wildmenu        -xterm_save
+cindent         +cryptv          -ebcdic          +float           +jumplist        +lua             -mouse_jsbterm   -mzscheme        +python          +smartindent     -tag_any_white   +vertsplit       +windows         +xpm
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
  system gvimrc file: "$VIM/gvimrc"
    user gvimrc file: "$HOME/.gvimrc"
2nd user gvimrc file: "~/.vim/gvimrc"
    system menu file: "$VIMRUNTIME/menu.vim"
  fall-back for $VIM: "/home/maple/local/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_GTK  -pthread -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/libdrm -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng16 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz    -g -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1      
Linking: gcc   -L. -Wl,-O1,--sort-common,--as-needed,-z,relro -fstack-protector -rdynamic -Wl,-export-dynamic -Wl,-E   -L/usr/local/lib -Wl,--as-needed -o vim   -lgtk-x11-2.0 -lgdk-x11-2.0 -lpangocairo-1.0 -latk-1.0 -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lfontconfig -lfreetype  -lSM -lICE -lXpm -lXt -lX11 -lXdmcp -lSM -lICE  -lm -lncurses -lelf -lnsl   -lacl -lattr -lgpm -ldl  -L/usr/lib -lluajit-5.1 -Wl,-E  -fstack-protector -L/usr/local/lib  -L/home/maple/perl5/perlbrew/perls/perl-5.16.3/lib/5.16.3/x86_64-linux-thread-multi/CORE -lperl -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc -L/usr/lib/python2.7/config -lpython2.7 -lpthread -ldl -lutil -lm -Xlinker -export-dynamic   -lruby -lpthread -lgmp -ldl -lcrypt -lm  -L/usr/lib   
kamichidu commented 10 years ago

すみません、vimのバージョンを誤記していました。 7.4.383です。 細かいコンパイルオプションは、 :version output こちらに置いておきます。

koron commented 10 years ago

@kamichidu

まとめると

補完関数内の候補決定フェーズで、 カーソルを特定の方法で動かす(ファイル先頭で単語移動)と、 補完候補の表示位置が本来の位置からズレる

ということで良いですかね。 あと気になるのは以下の2点です。

もし情報があったらお願いします。

koron commented 10 years ago

GIFを見ている限りでは、 ポップアップの初回の描画時に位置が間違って、 それが残ってしまっている感じ。

kamichidu commented 10 years ago

@koron

まとめると

補完関数内の候補決定フェーズで、 カーソルを特定の方法で動かす(ファイル先頭で単語移動)と、 補完候補の表示位置が本来の位置からズレる ということで良いですかね。

はい、その通りです。 (補完位置がずれる点については、認識していませんでした。)

  • 症状が発生しない移動パターンは存在するか?
  • その他にどのような移動パターンで症状が発生するか?

これは、ファイル先頭からの移動パターンで合ってますか? ファイル先頭への移動パターンなら複数試していますが、ファイル先頭からの移動パターンは試していないです。 試してみます。

koron commented 10 years ago

これは、ファイル先頭からの移動パターンで合ってますか?

です。

ファイル先頭からの移動パターンは試していないです。試してみます。

ありがとうございます。比較のために、 ファイルの先頭に行くだけで移動しないパターンもあると 助かります。

kamichidu commented 10 years ago

何パターンか試してみました。

コマンド 再現
call cursor(1, 1) ×
call setpos('.', [0, 1, 1, 0]) ×
normal gg
normal ggw
normal ggW
normal gge
normal ggE
normal ggb
normal ggB
normal ggge
normal gggE
Shougo commented 10 years ago

試すなら、:normal! の方が良いと思います。 :normal!はジャンプリストを変更したり副作用も大きいので、この副作用がなにか関係しているかもですね。

kamichidu commented 10 years ago

normal! もパターンを試してみました。

コマンド 再現
normal! gg
normal! ggw
normal! ggW
normal! gge
normal! ggE
normal! ggb
normal! ggB
normal! ggge
normal! gggE
normal ggG ×
normal! ggG ×

normal ggすると再現するけれど、 normal ggG だと再現しないです。

kamichidu commented 10 years ago

パターン追加。

コマンド 再現
normal gg$
normal! gg$
normal gg0
normal! gg0
normal gg^
normal! gg^
normal ggh
normal! ggh
normal ggj
normal! ggj
normal ggk
normal! ggk
normal ggl
normal! ggl

normal でも normal! でもあまり関係なさそう。

mattn commented 10 years ago

omnifunc は再描画を抑制する為に補完中の画面スクロール等を無視しているかもしれないので setpos の後で redraw すれば直るかと思います。まぁバグと言うべきかどうかはありますが。

kamichidu commented 10 years ago

遅くなりましたが、 @mattn さんの言ってたredrawを試してみましたが、直りませんでした。 最小vimrcはこんな感じです。 redrawでもredraw!でも変化なしでした。

filetype indent on

set nocompatible

set omnifunc=XXX

set nowrap

" This function is used for the 'omnifunc' option.    {{{1
function! XXX(findstart, base)
    if a:findstart
        let res= match(getline('.'), '\.\zs\w*$') + 1
        if res >= 0 && res <= col('.')
            return res
        else
            return -1
        endif
    endif

    let save_pos= getpos('.')
    try
        normal! ggw
    finally
        call setpos('.', save_pos)
        redraw
    endtry

    return ['aaa', 'bbb', 'ccc', 'ddd']
endfunction

" vim:ft=vim:nocompatible
mattn commented 10 years ago

わおw

h-east commented 10 years ago

ユーザ関数呼び出し前にcurwin->w_cursorを退避、呼び出し後に復帰しているけど、それだけだとカーソル位置関連のキャッシュ(w_valid_cursorとかw_wrowとか)がユーザ関数内でカーソル移動した時の情報のままなのでカーソル位置がおかしくなる。 なので、curwin->w_cursor復帰後にその辺のキャッシュをクリアするようにしました。

diff -r c21bd8e7346c src/edit.c
--- a/src/edit.c    Fri Aug 22 23:05:54 2014 +0200
+++ b/src/edit.c    Sat Aug 23 11:11:47 2014 +0900
@@ -4035,7 +4035,7 @@
    goto theend;
     }
     curwin->w_cursor = pos;    /* restore the cursor position */
-    check_cursor();
+    validate_cursor();
     if (!equalpos(curwin->w_cursor, pos))
     {
    EMSG(_(e_compldel));
@@ -5273,7 +5273,7 @@
        return FAIL;
        }
        curwin->w_cursor = pos; /* restore the cursor position */
-       check_cursor();
+       validate_cursor();
        if (!equalpos(curwin->w_cursor, pos))
        {
        EMSG(_(e_compldel));
Shougo commented 10 years ago

:+1:

h-east commented 10 years ago

他に同様の機構(カーソルを動かしても実行後に復元されるぜフハハハ系 ex.E839)があればそこもチェックしておきたい。これ以外にあったっけ?

kamichidu commented 10 years ago

@h-east さん、修正頂きありがとうございます!

h-east commented 10 years ago

posted to vim_dev. https://groups.google.com/d/msg/vim_dev/dBHXU9XnYuA/KEefnxafN0cJ

mattn commented 10 years ago

Patch 7.4.440 :+1: https://groups.google.com/forum/#!topic/vim_dev/qqFJVTjWtAk