vim-jp / issues

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

syntax が突然オフになる #1076

Closed mattn closed 7 years ago

mattn commented 7 years ago

いくらかそういう報告を貰っています。

https://twitter.com/Quramy/status/902441208592531457

https://twitter.com/pink_bangbi/status/901266519111352320

tyru commented 7 years ago

自分も最近頻度が高いんですが、<C-l> で直ったりしますね。

ghost commented 7 years ago

Vim を始めてからずっとオフ派で毎日ヘヴィに使ってますが、突然オンになったことは一度もありません。

tyru commented 7 years ago

バージョン言い忘れてました。8.0.972 (Ubuntu on Windows) です。

:version
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Aug 20 2017 16:32:45)
Included patches: 1-972
Compiled by tyru 
Huge 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
h-east commented 7 years ago

せめてこれくらいの情報は欲しいですね。

tyru commented 7 years ago

発生したのは ft=go (vim-go) と ft=vim (runtime) ですね。 redrawtime に関しては試してみます。

k-takata commented 7 years ago

あとは、別のターミナルだとどうかとか、GUIでも発生するのかとか。

tyru commented 7 years ago

WSL 上の CUI 版 Vim です。 別のターミナルというのは別で立ち上げたターミナル(wsltty とか)で試してどうかということでしょうか? もしそうだったら試せてませんでした。

k-takata commented 7 years ago

ここ最近termresponse関連でいろいろ問題が起きていますので、ターミナルエミュレータを変えたら挙動も変わらないだろうかと気になっています。

mattn commented 7 years ago

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

--

ghost commented 7 years ago

なんでここ 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しているため)。上記変更点の周囲を再確認してきます。

mattn commented 7 years ago

聞いたところによると端末の実装が始まったころから発生していると聞いています。

ghost commented 7 years ago

コードの流れを長々書いて消していま要約しました → 前述パッチの id_S == 0 がないと id_S0 のまま入る後段 combine_stl_hlt() でしょっぱな hlt[id_S - 1] を踏む

端末の実装が始まってハイライトテーブルが 10 単体から 9-9-9-1 の四本体制になるまでは id_S == 0 でしたし、それ以前もそうなっていたようではあります。Coverity の指摘で id_S == -1 にしたとき 0 が持つ意味ごと消してしまった感じはします。ここらの id は 1 オリジンです(バグの元)。

ghost commented 7 years ago

id_S0 になる前提で話をしてきましたが、100%ここが原因だと断言ができるだけの根拠をまだ持っていないので、ハイライト構造を完全に理解するまで読み下します。

tyru commented 7 years ago

すみません、この件は少なくとも自分に関しては自分の設定がまずかったようです。 以下の2行を無効にしたら発生しなくなりました。 https://github.com/tyru/dotfiles/blob/cf70c53eb147512a0d03bb6311adafacb228f39a/dotfiles/.vim/vimrc#L950-L951

mattn commented 7 years ago

トリガを聞いたところ

トリガー:突然(CursorMoved or CursorHold? ・ft:とりあえず ft=ruby と ft=cpp では確認 ・プラグイン:多すぎて不明

との事。

k-takata commented 7 years ago

Related? vim/vim#1918

lesguillemets commented 7 years ago

手元の環境で, Yggdroot/indentLinesyntax on filetype plugin on のみで似た事象が常に再現します.( edit: + プラグインマネージャ です.)

let a = foo()
let b = baz

repro.vim として, ffyiWj$p ( foo() を yank して二行目に貼り付け)で2行目の syntax が消え,カーソルを1行目に持っていくとそこの syntax も消えます.環境は以下の通り.

もともと大きいプラグインに絞れたところであまり,,という気もするのですがとりあえず報告です.なにか他に必要な情報があれば教えてください.

k-takata commented 7 years ago

上記 vim/vim#1918 によると、8.0.0647 で起きるようになったという情報がありますので、それと同じかというところが気になりますね。

mattn commented 7 years ago

実は先日、僕の環境で100%再現する環境を得ました。

https://gist.github.com/mattn/83c21d26d3cfafd4f8ea604cf5ee8f31#file-jvgrep-go-L812

vim.exe で↑の行にカーソルを移動、$ で行末に行ったあと jjj と移動するとカーソルに合わせてハイライトが消えていきます。

terminal3

昨日デバッガで追ったところ、cursor_on() のタイミングで色が消えていました。なお gvim.exe では発生しません。

set nocp
syn on
vim --clean -Nu min_vimrc -U NONE jvgrep.go

で再現出来ます。

mattn commented 7 years ago
set nocp
syn on
let loaded_matchparen = 1

だと再現せず。

mattn commented 7 years ago

Linux (putty経由) の vim だと再現せず。

lesguillemets commented 7 years ago

(遅くなりました)

mattn commented 7 years ago

https://gist.github.com/mattn/997375e55ad1b42fa590c50ae3e73e89

8.0.0647 をリバースするパッチを当てたら直った。原因は 8.0.0647 と断定して良いと思います。

k-takata commented 7 years ago

syntaxの処理に 'redrawtime' で指定した以上の時間が掛かったら、動作が遅くなるのを防ぐために自動で syntax を off にするパッチ?

lesguillemets commented 7 years ago

なるほど. mattn さんの例が, 手元の Xubuntu + xfce4-terminal でせっせと bisect すると8.0.1123 で初めて再現するのですが(これについては8.0.0647では再現しません.また少なくとも 8.0.1123 では xterm や gvim でも発生します),0647 以降だとどこで再現してもおかしくない感じでしょうか. リバートするパッチで直るのは同様です.

mattn commented 7 years ago

@lesguillemets ちょうど僕の行き着いたところと同じでした。なぜか 8.0.1123 なんですよね。関係なさそうなんですが。

mattn commented 7 years ago

最新のコミットで 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 が立てられている。

mattn commented 7 years ago

nfa_time_limit、グローバル変数だけど大丈夫なんだろうか。

mattn commented 7 years ago
set regexpengine=1

だと再現せず

set regexpengine=2

だと再現するので NFA エンジンに入れたタイムアウト処理がバグってる所まで判明。

k-takata commented 7 years ago

怪しそう。構造体の中に移して試してみる。

k-takata commented 7 years ago

https://bitbucket.org/k_takata/vim-ktakata-mq/src/e74d0a1e03ce020e09f7707a44671a857ebf3e7e/fix-nfa-timeout.patch?fileviewer=file-view-default これから動作確認。

k-takata commented 7 years ago

何か動かんw

k-takata commented 7 years ago

あ、構造体の最後に入れたらダメなのか。

mattn commented 7 years ago

「直った」を待っている mattn の様子です。 sadou_man

k-takata commented 7 years ago

regexp.h が依存関係に入って無くて、更新してもコンパイルされずにはまった。クソっw

何かうまくいかんですな。改善されていないような気がします。 https://bitbucket.org/k_takata/vim-ktakata-mq/src/0cab886166e7916199088d5a4ecb781ae3280a88/fix-nfa-timeout.patch?at=default&fileviewer=file-view-default

k-takata commented 7 years ago

原因違うのかな?

mattn commented 7 years ago

だいたい分かりました。syntax.c で使ってる関数が、1セッションのハイライト以外の目的でも使われている場合があって、syntax_start が呼ばれない(つまり syn_tm が更新されない)まま、チェックされてしまっているのが原因ですね。

mattn commented 7 years ago

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);
lesguillemets commented 7 years ago

@mattn 上記,Linux 環境で直ることを確認しました.ありがとうございました

mattn commented 7 years ago

@lesguillemets ご協力ありがとうございました。パッチの形は変わるかもしれませんが、原因まで分かったのであとは Bram が良しなにやってくれると思います。

ichizok commented 7 years ago

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
mattn commented 7 years ago

ですね。ちょっとパッチ直します。

mattn commented 7 years ago

こんな感じでどうでしょう?

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)
ichizok commented 7 years ago

いいと思います。

mattn commented 7 years ago

https://github.com/vim/vim/pull/2139

テストこけてるけど、terminal のっぽい。

mattn commented 7 years ago

8.0.1133

mattn commented 7 years ago

https://twitter.com/pink_bangbi/status/912553507978403840

モード:normal
トリが:(おそらく)カーソル移動
消え方:カレントのバッファのハイライトが全てオフになる(他のバッファ(ウィンドウ)のハイライトはそのまま

まだ発生するようで。ちなみに僕は 8.0.1133 以降は発生してない。

h-east commented 7 years ago

何でredrawtimeを100に変更してるんでしょうね? デフォルトは2000(msec)。 純粋に描画時間が100msec超えたから一時的に当該windowのsyntaxがoffになっただけじゃないんでしょうか? →Vim 8.0.0647以降での仕様です。:h 'redrawtime'に書かれています。

set redrawtime=10000 で発生するならバグだとは思います。

mattn commented 7 years ago

同じ様なコードをタイプして vim-brightest 入れて、redrawtime=100 にしてウロウロしてみてるんですが、再現しないんすよねー。

mattn commented 7 years ago

redrawtime=30 なら再現した。んー。マシンスペックかなー。