Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

undoを実行したときのメッセージが表示されない場合がある #466

Open
k-takata opened this issue Sep 3, 2013 · 31 comments

Comments

@k-takata
Copy link
Member

k-takata commented Sep 3, 2013

undoを実行すると、1 行 削除しました; 前方 #16 1 秒経過しています というような
メッセージがコマンドライン領域に表示されるはずですが、表示されない場合があります。

7.3.429 (Linux), 7.4.016 (Windows) にて確認しました。

  1. vim -N -u NONE -U NONE
  2. ifoo<CR><Esc> などで適当に1行入力。
  3. . で 25回以上(=画面の行数以上)繰り返し。
  4. gg で1行目に移動し、u で undo。
  5. ggu を繰り返し。

画面の最下行より後にファイルが続いている間は、undoのメッセージが出ません。
行数が少なくなり、画面内にファイルの末尾が収まるようになると、メッセージが出るようになります。バグでしょうか。

@h-east
Copy link
Member

h-east commented Sep 3, 2013

iOS版Vim(7.3.315)でも再現しました。
'report'オプションが関係するのかな?と思ったけど関係なさげ。

@koron
Copy link
Member

koron commented Sep 4, 2013

直感的にはなんかやってそうね。
別のシチュエーションでメッセージが多くなりそうな時に抑制する仕組みが誤作動しているような。

@ichizok
Copy link
Member

ichizok commented Sep 4, 2013

  1. メッセージが出る
  2. undoによってカーソルが変更位置に移動し、画面がスクロールする
  3. メッセージが消える

という流れのようです。

@ichizok
Copy link
Member

ichizok commented Sep 11, 2013

foldmethod が manual 以外だとメッセージ表示されますね。

undo後は常に画面全体を再描画させれば良いとすると、以下の変更でどうでしょうか。
( +conceal がある場合 )

diff --git a/src/undo.c b/src/undo.c
--- a/src/undo.c
+++ b/src/undo.c
@@ -2723,7 +2723,7 @@

        FOR_ALL_WINDOWS(wp)
        {
-           if (wp->w_buffer == curbuf && wp->w_p_cole > 0)
+           if (wp->w_buffer == curbuf)
                redraw_win_later(wp, NOT_VALID);
        }
     }

@k-takata
Copy link
Member Author

とても良さそうな感じですが、-conceal だとダメなんですね。
代わりにこうだとどうでしょうかね。よく分かっていませんが。

diff --git a/src/undo.c b/src/undo.c
--- a/src/undo.c
+++ b/src/undo.c
@@ -2728,6 +2728,7 @@
    }
     }
 #endif
+    redraw_later(NOT_VALID);

     smsg((char_u *)_("%ld %s; %s #%ld  %s"),
        u_oldcount < 0 ? -u_oldcount : u_oldcount,

@ichizok
Copy link
Member

ichizok commented Sep 13, 2013

wp->w_p_cole > 0 を削るなら#ifdef FEAT_CONCEAL ~ #endif のブロックは不要で、
redraw_later(NOT_VALID) だけでよいのかな。

@k-takata
Copy link
Member Author

k-takata commented Oct 1, 2013

よく分からないので、投げてしまいました。問題があれば、Bram氏が直してくれることでしょう。
https://groups.google.com/d/topic/vim_dev/AJU_c4fstWc/discussion

@ichizok さんの名前を出しておくべきだったかなあ?

@k-takata
Copy link
Member Author

k-takata commented Oct 1, 2013

redraw_later() でメッセージ部分だけ再描画の指定ができるようになっていると、一番良さそうな気がしますが…

@k-takata
Copy link
Member Author

k-takata commented Oct 2, 2013

Bram氏からの回答:

No, this forces a redraw of the whole screen. It works because instead
of deleting lines, which causes the message to scroll up and be cleared,
it overwrites the screen.

It's better to find a way to fill keep_msg. Unfortunately there is no
asy way to call smsg() and have msg_attr_keep() called with "keep" set
to TRUE. A global variable would be the easyest, but it's ugly.

ダメ出しされました。
smsg_attr_keep() を新設するのがいいのだろうか?

@ynkdir
Copy link
Member

ynkdir commented Oct 2, 2013

おつかれさまです。

いちおう気づいたので
画面内に納まっててもメッセージが消える手順

$ vim -u NONE -N
Ofoo<Esc>..uuu
$ vim -u NONE -N
ofoo<Esc>..ggobar<Esc>..uuuuuu

@ynkdir
Copy link
Member

ynkdir commented Oct 2, 2013

あと redo も同じですね

@ynkdir
Copy link
Member

ynkdir commented Oct 2, 2013

smsg_attr_keep() を新設するのがいいのだろうか?

すこし試した感じそれで直りそうですね。
影響範囲はわかりませんが。

@k-takata
Copy link
Member Author

k-takata commented Oct 2, 2013

@ynkdir
Copy link
Member

ynkdir commented Oct 2, 2013

GJ!

@ynkdir
Copy link
Member

ynkdir commented Oct 4, 2013

メモ

clear_cmdline が TRUE になって

screen.c:win_do_lines()
 9074     /*
 9075      * when scrolling, the message on the command line should be cleared,
 9076      * otherwise it will stay there forever.
 9077      */
 9078     clear_cmdline = TRUE;
#0  win_do_lines (wp=0x889fc0, row=0, line_count=1, mayclear=0, del=1)
    at screen.c:9089
#1  0x00000000005615d9 in win_del_lines (wp=0x889fc0, row=0, line_count=1, 
    invalid=0, mayclear=0) at screen.c:9002
#2  0x0000000000554658 in win_update (wp=0x889fc0) at screen.c:1879
#3  0x0000000000552588 in update_screen (type=10) at screen.c:681
#4  0x00000000005eab31 in main_loop (cmdwin=0, noexmode=0) at main.c:1232
#5  0x00000000005ea710 in main (argc=6, argv=0x7fffffffe0a8) at main.c:1020

コマンドラインがクリアされる

screen.c:showmode()
 9826     else if (clear_cmdline && msg_silent == 0)
 9827         /* Clear the whole command line.  Will reset "clear_cmdline". */
 9828         msg_clr_cmdline();
#0  screen_fill (start_row=23, end_row=24, start_col=0, end_col=80, c1=32, 
    c2=32, attr=0) at screen.c:8052
#1  0x00000000004c8ce5 in msg_clr_eos_force () at message.c:3043
#2  0x00000000004c8d40 in msg_clr_cmdline () at message.c:3058
#3  0x00000000005629d4 in showmode () at screen.c:9828
#4  0x000000000055262a in update_screen (type=10) at screen.c:719
#5  0x00000000005eab31 in main_loop (cmdwin=0, noexmode=0) at main.c:1232
#6  0x00000000005ea710 in main (argc=6, argv=0x7fffffffe0a8) at main.c:1020

ここで分岐

win_update():1767
 1767                     && (lnum == mod_top
消える場合: lnum=1, mod_top=1
消えない場合: lnum=1, mod_top=4
foldmethod=marker: lnum=1, mod_top=0

@ynkdir
Copy link
Member

ynkdir commented Oct 4, 2013

あなるほどそれでNOT_VALIDか

@ynkdir
Copy link
Member

ynkdir commented Oct 4, 2013

smsg_attr_keep()

すいませんマクロかなんかで複数のコマンドを実行したときにまずかったみたいです。

$vim -u NONE -N
ofoo<Esc>.....:normal ukkk3dd

パッチ前
3 fewer lines

パッチ後
1 line less; before #6  5 seconds ago

@k-takata
Copy link
Member Author

k-takata commented Oct 4, 2013

うっ、何かいい案あります?

@ynkdir
Copy link
Member

ynkdir commented Oct 5, 2013

メッセージを適当なタイミングで消すのがうまくいってないので
フラグかカウンタかで表示済みのメッセージかどうかをみるとか
タイミングを変えるとか (例えばCursorHold) ですか
表示系は難しいですね…

@ynkdir
Copy link
Member

ynkdir commented Oct 6, 2013

フラグは msg_didout があるっぽいです
がなんにしろ厳しそうな感じです。

けっきょく NOT_VALID が安定なんですかねえ
でもこれもよくわからないので確実とはいいがたい

@k-takata
Copy link
Member Author

k-takata commented Nov 3, 2013

todo入りしましたが、"Doesn't work properly" なのでどうしたものか…

Undo message is not always properly displayed.  Patch by Ken Takata, 2013 oct
3.  Doesn't work properly according to Yukihiro Nakadaira.

@k-takata
Copy link
Member Author

元の redraw_later(NOT_VALID); を追加するパッチの方は、:normal ukkk3dd の動作には影響なさそうですね。(ようやく試した)
ただ、一度却下されているだけに、やはり何か別の方法を考えないといけないのか…

@ghost
Copy link

ghost commented Feb 7, 2014

コメントの意味を考えるとこれではBram氏の意図とは違う動作になるのかという気も…

diff -r e91143b9ad7a src/screen.c
--- a/src/screen.c      Wed Feb 05 22:46:52 2014 +0100
+++ b/src/screen.c      Fri Feb 07 22:27:43 2014 +0900
@@ -9086,7 +9086,7 @@
      * when scrolling, the message on the command line should be cleared,
      * otherwise it will stay there forever.
      */
-    clear_cmdline = TRUE;
+    clear_cmdline = FALSE;

     /*
      * If the terminal can set a scroll region, use that.

@ynkdir
Copy link
Member

ynkdir commented Feb 8, 2014

それもありますが、
それだと再現手順で行数を増やすと一定以上でやっぱりメッセージが消えちゃうみたいです。

@ghost
Copy link

ghost commented Feb 9, 2014

ではこんな感じで…

diff -r e91143b9ad7a src/screen.c
--- a/src/screen.c      Wed Feb 05 22:46:52 2014 +0100
+++ b/src/screen.c      Mon Feb 10 01:51:44 2014 +0900
@@ -8497,21 +8497,11 @@
        LineWraps[i] = FALSE;
     }

-    if (can_clear(T_CL))
-    {
-       out_str(T_CL);          /* clear the display */
-       clear_cmdline = FALSE;
-       mode_displayed = FALSE;
-    }
-    else
-    {
-       /* can't clear the screen, mark all chars with invalid attributes */
-       for (i = 0; i < Rows; ++i)
-           lineinvalid(LineOffset[i], (int)Columns);
-       clear_cmdline = TRUE;
-    }
-
-    screen_cleared = TRUE;     /* can use contents of ScreenLines now */
+    for (i = 0; i < cmdline_row; ++i)
+        lineinvalid(LineOffset[i], (int)Columns);
+    clear_cmdline = TRUE;
+
+    screen_cleared = FALSE;

     win_rest_invalid(firstwin);
     redraw_cmdline = TRUE;
@@ -9086,7 +9076,7 @@
      * when scrolling, the message on the command line should be cleared,
      * otherwise it will stay there forever.
      */
-    clear_cmdline = TRUE;
+    clear_cmdline = FALSE;

     /*
      * If the terminal can set a scroll region, use that.

@ghost
Copy link

ghost commented Feb 10, 2014

上記パッチは失敗しています。
画面全体を T_CL で消しているのが遠因ですが、素因ではありませんでした。追及しています。

@ghost
Copy link

ghost commented Feb 10, 2014

特殊処理で失敗してるパターンかな…

diff -r e91143b9ad7a src/screen.c
--- a/src/screen.c      Wed Feb 05 22:46:52 2014 +0100
+++ b/src/screen.c      Mon Feb 10 16:57:40 2014 +0900
@@ -1470,33 +1470,10 @@
            }
        }

-       /* When starting redraw in the first line, redraw all lines.  When
-        * there is only one window it's probably faster to clear the screen
-        * first. */
        if (mid_start == 0)
        {
            mid_end = wp->w_height;
-           if (lastwin == firstwin)
-           {
-               /* Clear the screen when it was not done by win_del_lines() or
-                * win_ins_lines() above, "screen_cleared" is FALSE or MAYBE
-                * then. */
-               if (screen_cleared != TRUE)
-                   screenclear();
-#ifdef FEAT_WINDOWS
-               /* The screen was cleared, redraw the tab pages line. */
-               if (redraw_tabline)
-                   draw_tabline();
-#endif
-           }
-       }
-
-       /* When win_del_lines() or win_ins_lines() caused the screen to be
-        * cleared (only happens for the first window) or when screenclear()
-        * was called directly above, "must_redraw" will have been set to
-        * NOT_VALID, need to reset it here to avoid redrawing twice. */
-       if (screen_cleared == TRUE)
-           must_redraw = 0;
+       }
     }
     else
     {
@@ -9086,7 +9063,7 @@
      * when scrolling, the message on the command line should be cleared,
      * otherwise it will stay there forever.
      */
-    clear_cmdline = TRUE;
+    clear_cmdline = FALSE;

     /*
      * If the terminal can set a scroll region, use that.

@ynkdir
Copy link
Member

ynkdir commented Feb 11, 2014

Bramしだいですけど、メッセージがずっと残るのは厳しい気がします。わかりませんが。

@ghost
Copy link

ghost commented Feb 11, 2014

多少核心には近くなったんですが、パッチ後半の clear_cmdline = TRUE は根本的解決ではないのでさらに追及します。
完動品をポンと出したい気持ちはあるんですけども、いまいち追いついておりません…。

@ghost
Copy link

ghost commented Mar 13, 2014

私はVimを使いこんでいないので(単にPCの前にあまりいない)、いつメッセージが消えるのが望ましいか、また残すべきタイミングを把握できていない、という問題を持っていることに気づかされました。もうしばらく使い込んでみて、きっちり把握できたら再挑戦します。

@k-takata
Copy link
Member Author

Related: vim/vim#1635

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants