Closed mattn closed 7 years ago
自分も最近頻度が高いんですが、<C-l>
で直ったりしますね。
Vim を始めてからずっとオフ派で毎日ヘヴィに使ってますが、突然オンになったことは一度もありません。
バージョン言い忘れてました。8.0.972 (Ubuntu on Windows) です。
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Aug 20 2017 16:32:45) Included patches: 1-972 Compiled by tyruHuge version without GUI. Features included (+) or not (-): +acl +cmdline_hist -ebcdic -gettext +listcmds +mouse_sgr +persistent_undo +smartindent +termresponse +wildignore +arabic +cmdline_info +emacs_tags -hangul_input +localmap -mouse_sysmouse +postscript +startuptime +textobjects +wildmenu +autocmd +comments +eval +iconv +lua +mouse_urxvt +printer +statusline +timers +windows -balloon_eval +conceal +ex_extra +insert_expand +menu +mouse_xterm +profile -sun_workshop +title +writebackup -browse +cryptv +extra_search +job +mksession +multi_byte -python +syntax -toolbar -X11 ++builtin_terms +cscope +farsi +jumplist +modify_fname +multi_lang -python3 +tag_binary +user_commands -xfontset +byte_offset +cursorbind +file_in_path +keymap +mouse -mzscheme +quickfix +tag_old_static +vertsplit -xim +channel +cursorshape +find_in_path +lambda -mouseshape +netbeans_intg +reltime -tag_any_white +virtualedit -xpm +cindent +dialog_con +float +langmap +mouse_dec +num64 +rightleft -tcl +visual -xsmp -clientserver +diff +folding +libcall -mouse_gpm +packages -ruby +termguicolors +visualextra -xterm_clipboard -clipboard +digraphs -footer +linebreak -mouse_jsbterm +path_extra +scrollbind +terminal +viminfo -xterm_save +cmdline_compl -dnd +fork() +lispindent +mouse_netterm -perl +signs +terminfo +vreplace system vimrc file: "$VIM/vimrc" user vimrc file: "$HOME/.vimrc" 2nd user vimrc file: "~/.vim/vimrc" user exrc file: "$HOME/.exrc" defaults file: "$VIMRUNTIME/defaults.vim" fall-back for $VIM: "/home/tyru/vim.head/share/vim" Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -march=native -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 Linking: gcc -L/usr/local/lib -Wl,--as-needed -o vim -lm -ltinfo -lnsl -ldl -L/usr/lib/x86_64-linux-gnu -lluajit-5.1
せめてこれくらいの情報は欲しいですね。
:set ft
の値は?'redrawtime'
の値を大きくしても起きる?発生したのは ft=go (vim-go) と ft=vim (runtime) ですね。 redrawtime に関しては試してみます。
あとは、別のターミナルだとどうかとか、GUIでも発生するのかとか。
WSL 上の CUI 版 Vim です。 別のターミナルというのは別で立ち上げたターミナル(wsltty とか)で試してどうかということでしょうか? もしそうだったら試せてませんでした。
ここ最近termresponse関連でいろいろ問題が起きていますので、ターミナルエミュレータを変えたら挙動も変わらないだろうかと気になっています。
vim.exe で発生したことあります。再現しないですが。
On 9/2/17, K.Takata notifications@github.com wrote:
ここ最近termresponse関連でいろいろ問題が起きていますので、ターミナルエミュレータを変えたら挙動も変わらないだろうかと気になっています。
-- You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub: https://github.com/vim-jp/issues/issues/1076#issuecomment-326727632
--
なんでここ 0 を見てるのを殺したんだろう (8.0.970にて)。追試はこれからです。
diff --git a/src/syntax.c b/src/syntax.c
index 730357520..57c13a61f 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -9999,7 +9999,7 @@ highlight_changed(void)
if (ga_grow(&highlight_ga, 28) == FAIL)
return FAIL;
hlcnt = highlight_ga.ga_len;
- if (id_S == -1)
+ if (id_S == -1 || id_S == 0)
{
/* Make sure id_S is always valid to simplify code below. Use the last
* entry. */
追記:これだけの変更で色がつかなくなったので直前で id_S に 0 が返る条件を見るべきかも…というのは自分の手元だけでやった方がよかったですね、すみません。書き込みは残しておきます。 再追記:パッチベースが自分の24bitパッチ未適用のものだったので色がつかなくなるのは当然でした(_vimrcでset tgcしているため)。上記変更点の周囲を再確認してきます。
聞いたところによると端末の実装が始まったころから発生していると聞いています。
コードの流れを長々書いて消していま要約しました → 前述パッチの id_S == 0
がないと id_S
が 0
のまま入る後段 combine_stl_hlt()
でしょっぱな hlt[id_S - 1]
を踏む
端末の実装が始まってハイライトテーブルが 10 単体から 9-9-9-1 の四本体制になるまでは id_S == 0
でしたし、それ以前もそうなっていたようではあります。Coverity の指摘で id_S == -1
にしたとき 0 が持つ意味ごと消してしまった感じはします。ここらの id は 1 オリジンです(バグの元)。
id_S
が 0
になる前提で話をしてきましたが、100%ここが原因だと断言ができるだけの根拠をまだ持っていないので、ハイライト構造を完全に理解するまで読み下します。
すみません、この件は少なくとも自分に関しては自分の設定がまずかったようです。 以下の2行を無効にしたら発生しなくなりました。 https://github.com/tyru/dotfiles/blob/cf70c53eb147512a0d03bb6311adafacb228f39a/dotfiles/.vim/vimrc#L950-L951
トリガを聞いたところ
トリガー:突然(CursorMoved or CursorHold? ・ft:とりあえず ft=ruby と ft=cpp では確認 ・プラグイン:多すぎて不明
との事。
Related? vim/vim#1918
手元の環境で, Yggdroot/indentLine
と syntax on
filetype plugin on
のみで似た事象が常に再現します.( edit: + プラグインマネージャ です.)
let a = foo()
let b = baz
を repro.vim
として, ffyiWj$p
( foo()
を yank して二行目に貼り付け)で2行目の syntax が消え,カーソルを1行目に持っていくとそこの syntax も消えます.環境は以下の通り.
Vim 8.0.1130. Huge version with GTK2 GUI.
'redrawtime'
を 10000
にしてみましたが同様に再現します.ft=vim
ですが,最初に見つけたのは ft=haskell
のときです.ちょっと試した範囲では括弧が絡んでそうです.indentLine
を抜いて vim/vim の issue 1918 に挙げられている再現方法は,手元では再現しないようです.もともと大きいプラグインに絞れたところであまり,,という気もするのですがとりあえず報告です.なにか他に必要な情報があれば教えてください.
上記 vim/vim#1918 によると、8.0.0647 で起きるようになったという情報がありますので、それと同じかというところが気になりますね。
実は先日、僕の環境で100%再現する環境を得ました。
https://gist.github.com/mattn/83c21d26d3cfafd4f8ea604cf5ee8f31#file-jvgrep-go-L812
vim.exe で↑の行にカーソルを移動、$
で行末に行ったあと jjj と移動するとカーソルに合わせてハイライトが消えていきます。
昨日デバッガで追ったところ、cursor_on() のタイミングで色が消えていました。なお gvim.exe では発生しません。
set nocp
syn on
vim --clean -Nu min_vimrc -U NONE jvgrep.go
で再現出来ます。
set nocp
syn on
let loaded_matchparen = 1
だと再現せず。
Linux (putty経由) の vim だと再現せず。
(遅くなりました)
let loaded_matchparen=1
で再現しなくなります.https://gist.github.com/mattn/997375e55ad1b42fa590c50ae3e73e89
8.0.0647 をリバースするパッチを当てたら直った。原因は 8.0.0647 と断定して良いと思います。
syntaxの処理に 'redrawtime' で指定した以上の時間が掛かったら、動作が遅くなるのを防ぐために自動で syntax を off にするパッチ?
なるほど. mattn さんの例が, 手元の Xubuntu + xfce4-terminal でせっせと bisect すると8.0.1123
で初めて再現するのですが(これについては8.0.0647では再現しません.また少なくとも 8.0.1123 では xterm や gvim でも発生します),0647 以降だとどこで再現してもおかしくない感じでしょうか. リバートするパッチで直るのは同様です.
@lesguillemets ちょうど僕の行き着いたところと同じでした。なぜか 8.0.1123 なんですよね。関係なさそうなんですが。
最新のコミットで b_syn_slow で判定してる所を止めたら直るので
diff --git a/src/screen.c b/src/screen.c
index 9f39edf04..dfb4e5af2 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -3208,7 +3208,7 @@ win_line(
#ifdef FEAT_SYN_HL
if (syntax_present(wp) && !wp->w_s->b_syn_error
# ifdef SYN_TIME_LIMIT
- && !wp->w_s->b_syn_slow
+ /* && !wp->w_s->b_syn_slow */
# endif
)
{
@@ -3223,7 +3223,7 @@ win_line(
{
did_emsg = save_did_emsg;
#ifdef SYN_TIME_LIMIT
- if (!wp->w_s->b_syn_slow)
+ /* if (!wp->w_s->b_syn_slow) */
#endif
{
has_syntax = TRUE;
@@ -4570,8 +4570,10 @@ win_line(
else
did_emsg = save_did_emsg;
#ifdef SYN_TIME_LIMIT
+ /*
if (wp->w_s->b_syn_slow)
has_syntax = FALSE;
+ */
#endif
/* Need to get the line again, a multi-line regexp may
どこかで b_syn_slow が立てられている。
nfa_time_limit、グローバル変数だけど大丈夫なんだろうか。
set regexpengine=1
だと再現せず
set regexpengine=2
だと再現するので NFA エンジンに入れたタイムアウト処理がバグってる所まで判明。
怪しそう。構造体の中に移して試してみる。
何か動かんw
あ、構造体の最後に入れたらダメなのか。
「直った」を待っている mattn の様子です。
regexp.h が依存関係に入って無くて、更新してもコンパイルされずにはまった。クソっw
何かうまくいかんですな。改善されていないような気がします。 https://bitbucket.org/k_takata/vim-ktakata-mq/src/0cab886166e7916199088d5a4ecb781ae3280a88/fix-nfa-timeout.patch?at=default&fileviewer=file-view-default
原因違うのかな?
だいたい分かりました。syntax.c で使ってる関数が、1セッションのハイライト以外の目的でも使われている場合があって、syntax_start が呼ばれない(つまり syn_tm が更新されない)まま、チェックされてしまっているのが原因ですね。
matchparen から呼んでる synstack が、syn_get_id を呼んでました。この場合、syntax_start が呼ばれずに処理されるので、中で勝手 syntax がオフになります。
diff --git a/src/syntax.c b/src/syntax.c
index 6361bd7aa..41ff52414 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -6573,9 +6573,12 @@ syn_get_id(
else if (wp->w_buffer == syn_buf
&& lnum == current_lnum
&& col > current_col)
+ {
/* next_match may not be correct when moving around, e.g. with the
* "skip" expression in searchpair() */
next_match_idx = -1;
+ syn_tm = NULL;
+ }
(void)get_syntax_attr(col, spellp, keep_state);
@mattn 上記,Linux 環境で直ることを確認しました.ありがとうございました
@lesguillemets ご協力ありがとうございました。パッチの形は変わるかもしれませんが、原因まで分かったのであとは Bram が良しなにやってくれると思います。
syn_tm
設定する部分を関数に分けて syntax_tm
を定義している側 (update_single_line
とか) でハンドリングさせた方がわかりやすくないですか?
proftime_t syntax_tm;
profile_setlimit(p_rdt, &syntax_tm);
syn_reset_timeout(&syntax_tm); // syn_tm = &syntax_tm
win_line(...); // call syntax_start
syn_reset_timeout(NULL); // syn_tm = NULL
ですね。ちょっとパッチ直します。
こんな感じでどうでしょう?
diff --git a/src/proto/syntax.pro b/src/proto/syntax.pro
index f6ecb8c49..5711ebcb1 100644
--- a/src/proto/syntax.pro
+++ b/src/proto/syntax.pro
@@ -1,5 +1,5 @@
/* syntax.c */
-void syntax_start(win_T *wp, linenr_T lnum, proftime_T *syntax_tm);
+void syntax_start(win_T *wp, linenr_T lnum);
void syn_stack_free_all(synblock_T *block);
void syn_stack_apply_changes(buf_T *buf);
void syntax_end_parsing(linenr_T lnum);
@@ -61,4 +61,5 @@ void set_context_in_highlight_cmd(expand_T *xp, char_u *arg);
char_u *get_highlight_name(expand_T *xp, int idx);
char_u *get_highlight_name_ext(expand_T *xp, int idx, int skip_cleared);
void free_highlight_fonts(void);
+void syn_reset_timeout(proftime_T *tm);
/* vim: set ft=c : */
diff --git a/src/screen.c b/src/screen.c
index 9f39edf04..55eccded8 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -131,7 +131,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
static void fill_foldcolumn(char_u *p, win_T *wp, int closed, linenr_T lnum);
static void copy_text_attr(int off, char_u *buf, int len, int attr);
#endif
-static int win_line(win_T *, linenr_T, int, int, int nochange, proftime_T *syntax_tm);
+static int win_line(win_T *, linenr_T, int, int, int nochange);
static int char_needs_redraw(int off_from, int off_to, int cols);
static void draw_vsep_win(win_T *wp, int row);
#ifdef FEAT_STL_OPT
@@ -930,6 +930,7 @@ update_single_line(win_T *wp, linenr_T lnum)
#ifdef SYN_TIME_LIMIT
/* Set the time limit to 'redrawtime'. */
profile_setlimit(p_rdt, &syntax_tm);
+ syn_reset_timeout(&syntax_tm);
#endif
update_prepare();
@@ -944,13 +945,7 @@ update_single_line(win_T *wp, linenr_T lnum)
start_search_hl();
prepare_search_hl(wp, lnum);
# endif
- win_line(wp, lnum, row, row + wp->w_lines[j].wl_size, FALSE,
-#ifdef SYN_TIME_LIMIT
- &syntax_tm
-#else
- NULL
-#endif
- );
+ win_line(wp, lnum, row, row + wp->w_lines[j].wl_size, FALSE);
# if defined(FEAT_SEARCH_EXTRA)
end_search_hl();
# endif
@@ -960,6 +955,10 @@ update_single_line(win_T *wp, linenr_T lnum)
}
update_finish();
+
+#ifdef SYN_TIME_LIMIT
+ syn_reset_timeout(NULL);
+#endif
}
need_cursor_line_redraw = FALSE;
}
@@ -1805,6 +1804,7 @@ win_update(win_T *wp)
#ifdef SYN_TIME_LIMIT
/* Set the time limit to 'redrawtime'. */
profile_setlimit(p_rdt, &syntax_tm);
+ syn_reset_timeout(&syntax_tm);
#endif
#ifdef FEAT_FOLDING
win_foldinfo.fi_level = 0;
@@ -2109,13 +2109,7 @@ win_update(win_T *wp)
/*
* Display one line.
*/
- row = win_line(wp, lnum, srow, wp->w_height, mod_top == 0,
-#ifdef SYN_TIME_LIMIT
- &syntax_tm
-#else
- NULL
-#endif
- );
+ row = win_line(wp, lnum, srow, wp->w_height, mod_top == 0);
#ifdef FEAT_FOLDING
wp->w_lines[idx].wl_folded = FALSE;
@@ -2275,6 +2269,10 @@ win_update(win_T *wp)
win_draw_end(wp, '~', ' ', row, wp->w_height, HLF_EOB);
}
+#ifdef SYN_TIME_LIMIT
+ syn_reset_timeout(NULL);
+#endif
+
/* Reset the type of redrawing required, the window has been updated. */
wp->w_redr_type = 0;
#ifdef FEAT_DIFF
@@ -3000,8 +2998,7 @@ win_line(
linenr_T lnum,
int startrow,
int endrow,
- int nochange UNUSED, /* not updating for changed text */
- proftime_T *syntax_tm UNUSED)
+ int nochange UNUSED) /* not updating for changed text */
{
int col = 0; /* visual column on screen */
unsigned off; /* offset in ScreenLines/ScreenAttrs */
@@ -3216,7 +3213,7 @@ win_line(
* error, stop syntax highlighting. */
save_did_emsg = did_emsg;
did_emsg = FALSE;
- syntax_start(wp, lnum, syntax_tm);
+ syntax_start(wp, lnum);
if (did_emsg)
wp->w_s->b_syn_error = TRUE;
else
@@ -3614,7 +3611,7 @@ win_line(
# ifdef FEAT_SYN_HL
/* Need to restart syntax highlighting for this line. */
if (has_syntax)
- syntax_start(wp, lnum, syntax_tm);
+ syntax_start(wp, lnum);
# endif
}
#endif
diff --git a/src/syntax.c b/src/syntax.c
index 6361bd7aa..a58223ae6 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -489,6 +489,12 @@ static int get_id_list(char_u **arg, int keylen, short **list, int skip);
static void syn_combine_list(short **clstr1, short **clstr2, int list_op);
static void syn_incl_toplevel(int id, int *flagsp);
+ void
+syn_reset_timeout(proftime_T *tm)
+{
+ syn_tm = tm;
+}
+
/*
* Start the syntax recognition for a line. This function is normally called
* from the screen updating, once for each displayed line.
@@ -497,7 +503,7 @@ static void syn_incl_toplevel(int id, int *flagsp);
* window.
*/
void
-syntax_start(win_T *wp, linenr_T lnum, proftime_T *syntax_tm UNUSED)
+syntax_start(win_T *wp, linenr_T lnum)
{
synstate_T *p;
synstate_T *last_valid = NULL;
@@ -527,9 +533,6 @@ syntax_start(win_T *wp, linenr_T lnum, proftime_T *syntax_tm UNUSED)
}
changedtick = CHANGEDTICK(syn_buf);
syn_win = wp;
-#ifdef FEAT_RELTIME
- syn_tm = syntax_tm;
-#endif
/*
* Allocate syntax stack when needed.
@@ -6569,7 +6572,7 @@ syn_get_id(
if (wp->w_buffer != syn_buf
|| lnum != current_lnum
|| col < current_col)
- syntax_start(wp, lnum, NULL);
+ syntax_start(wp, lnum);
else if (wp->w_buffer == syn_buf
&& lnum == current_lnum
&& col > current_col)
@@ -6645,7 +6648,7 @@ syn_get_foldlevel(win_T *wp, long lnum)
# endif
)
{
- syntax_start(wp, lnum, NULL);
+ syntax_start(wp, lnum);
for (i = 0; i < current_state.ga_len; ++i)
if (CUR_STATE(i).si_flags & HL_FOLD)
いいと思います。
https://github.com/vim/vim/pull/2139
テストこけてるけど、terminal のっぽい。
https://twitter.com/pink_bangbi/status/912553507978403840
モード:normal
トリが:(おそらく)カーソル移動
消え方:カレントのバッファのハイライトが全てオフになる(他のバッファ(ウィンドウ)のハイライトはそのまま
まだ発生するようで。ちなみに僕は 8.0.1133 以降は発生してない。
何でredrawtime
を100に変更してるんでしょうね?
デフォルトは2000(msec)。
純粋に描画時間が100msec超えたから一時的に当該windowのsyntaxがoffになっただけじゃないんでしょうか?
→Vim 8.0.0647以降での仕様です。:h 'redrawtime'
に書かれています。
set redrawtime=10000 で発生するならバグだとは思います。
同じ様なコードをタイプして vim-brightest 入れて、redrawtime=100 にしてウロウロしてみてるんですが、再現しないんすよねー。
redrawtime=30 なら再現した。んー。マシンスペックかなー。
いくらかそういう報告を貰っています。
https://twitter.com/Quramy/status/902441208592531457
https://twitter.com/pink_bangbi/status/901266519111352320