Closed kamichidu closed 10 years ago
すみません、vimのバージョンを誤記していました。 7.4.383です。 細かいコンパイルオプションは、 :version output こちらに置いておきます。
@kamichidu
まとめると
補完関数内の候補決定フェーズで、 カーソルを特定の方法で動かす(ファイル先頭で単語移動)と、 補完候補の表示位置が本来の位置からズレる
ということで良いですかね。 あと気になるのは以下の2点です。
もし情報があったらお願いします。
GIFを見ている限りでは、 ポップアップの初回の描画時に位置が間違って、 それが残ってしまっている感じ。
@koron
まとめると
補完関数内の候補決定フェーズで、 カーソルを特定の方法で動かす(ファイル先頭で単語移動)と、 補完候補の表示位置が本来の位置からズレる ということで良いですかね。
はい、その通りです。 (補完位置がずれる点については、認識していませんでした。)
- 症状が発生しない移動パターンは存在するか?
- その他にどのような移動パターンで症状が発生するか?
これは、ファイル先頭からの移動パターンで合ってますか? ファイル先頭への移動パターンなら複数試していますが、ファイル先頭からの移動パターンは試していないです。 試してみます。
これは、ファイル先頭からの移動パターンで合ってますか?
です。
ファイル先頭からの移動パターンは試していないです。試してみます。
ありがとうございます。比較のために、 ファイルの先頭に行くだけで移動しないパターンもあると 助かります。
何パターンか試してみました。
コマンド | 再現 |
---|---|
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 | ○ |
試すなら、:normal!
の方が良いと思います。
:normal!
はジャンプリストを変更したり副作用も大きいので、この副作用がなにか関係しているかもですね。
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 だと再現しないです。
パターン追加。
コマンド | 再現 |
---|---|
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! でもあまり関係なさそう。
omnifunc は再描画を抑制する為に補完中の画面スクロール等を無視しているかもしれないので setpos の後で redraw すれば直るかと思います。まぁバグと言うべきかどうかはありますが。
遅くなりましたが、 @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
わおw
ユーザ関数呼び出し前に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));
:+1:
他に同様の機構(カーソルを動かしても実行後に復元されるぜフハハハ系 ex.E839
)があればそこもチェックしておきたい。これ以外にあったっけ?
@h-east さん、修正頂きありがとうございます!
posted to vim_dev. https://groups.google.com/d/msg/vim_dev/dBHXU9XnYuA/KEefnxafN0cJ
Patch 7.4.440 :+1: https://groups.google.com/forum/#!topic/vim_dev/qqFJVTjWtAk
現象としては表題の通りですが、わかりにくいと思ったのでgif用意しました。
vimのバージョンは7.4.383、linuxでもwindowsでも再現します。 macは未確認です。
また、再現用の最小vimrcを以下に置いています。 最小vimrc 再現用javaコード 最小vimrcを手元に落としてきて、再現用javaコードを以下のように読み込み、
vim -u vimrc -U NONE S.java
orgvim -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 追記 --- ソースコード短いので、直接貼っておきます。