vim-jp / issues

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

switchbuf=useopen + quickfix + <C-w><CR> で無名バッファが開く #162

Open thinca opened 12 years ago

thinca commented 12 years ago
:set switchbuf=useopen
:grep hoge *   " 適当にquickfixを作成。空でなければ何でもいい
" この時点で最初にヒットしたファイルが開かれている
:copen
<C-w><CR>
" 無名バッファが開かれつつさきほど開かれたファイルにカーソルが移動する

switchbuf の「すでに開かれている場合は同じウィンドウを使って開く」という挙動と、 quickfix での :help CTRL-W_<CR> の「新しいウィンドウを開いてそこにジャンプする」という挙動がバッティングしています。 この場合どちらに傾けるか(バッファを使い回すか新しく開くか)は微妙なところですが、 無名バッファが開くのは明らかに間違いかと思います。

thinca commented 12 years ago

どちらに傾けるかは、個人的には新しく開く方に1票。 理由は<C-w>とユーザが明示的にタイプしているから。

koron commented 12 years ago

CTRL-W_<CR> を優先に+1

mattn commented 12 years ago

僕も CTRL-W_<CR> を優先に+1

h-east commented 12 years ago

スギちゃんのブログ風 ・ のキーストロークを追いかけるぜぇ(^-^) ・ノーマルモードとビジュアルモードのキーテーブルは nv_cmds[] だぜぇ(^-^) :tj nv_cmdsは内部では Ctrl_W だぜぇ(^-^) /Ctrl_W ・nv_window() が処理関数だぜぇ(^-^) :tj nv_window以後のキーが確定したら do_window() を呼んでいるぜぇ(^-^) :tj do_windowは内部では CAR だぜぇ(^-^) /CAR ・カレントバッファがquickfix windowだったら do_cmdline_cmd("split +1cc") を呼んでいるぜぇ(^-^) :tj do_cmdline_cmd ・do_cmdline_cmd()はdo_cmdline()を呼んでいるぜぇ(^-^) :tj do_cmdline :tj do_one_cmd ・なんやかんやあるけどEXモードのコマンドテーブルは cmdnames[] だぜぇ(^-^) :tj cmdnames ・split を探すぜぇ(^-^) /"split" ・処理関数は ex_splitview() だぜぇ(^-^) :tj ex_splitview ・カレントバッファがquickfix windowで:tab指定がなければsplitはnewに、vsplitはvnewに変換しているぜぇ(^-^) [ex_docmd.c 7321~7331] あれぇ? 'switchbuff'の設定を見てないぜぇ(^-^) if (swb_flags & SWB_USEOPEN) の時にどうにかすれば良いんだぜぇ(^-^)

あとは任せたぜぇ(^-^) ワイルドだろ~

h-east commented 12 years ago

set switchbuf=useopen設定でqfで<C-W><CR>した時に無名バッファが開く原因

解説

補足 (先頭括弧内の数値はgdbトレースバックの番号)

gdbトレースバック

(gdb) bt
#0  buflist_getfile (n=2, lnum=1, options=5, forceit=0) at buffer.c:1941
#1  0x00000000005268e4 in qf_jump (qi=0x85ab80, dir=0, errornr=1, forceit=0)
    at quickfix.c:1775
#2  0x00000000005291a4 in ex_cc (eap=0x7fff8cf68100) at quickfix.c:2941
#3  0x000000000046c4e1 in do_one_cmd (cmdlinep=0x7fff8cf68778, sourcing=1,
    cstack=0x7fff8cf682d0, fgetline=0, cookie=0x0) at ex_docmd.c:2668
#4  0x0000000000469b70 in do_cmdline (cmdline=0xacdab7 "1cc", fgetline=0,
    cookie=0x0, flags=1) at ex_docmd.c:1122
#5  0x000000000045c696 in do_ecmd (fnum=0, ffname=0x0, sfname=0x0, eap=
    0x7fff8cf68a80, newlnum=1, flags=1, oldwin=0x0) at ex_cmds.c:3814
#6  0x0000000000474e4e in do_exedit (eap=0x7fff8cf68a80, old_curwin=0xbdbe10)
    at ex_docmd.c:7743
#7  0x0000000000474512 in ex_splitview (eap=0x7fff8cf68a80) at ex_docmd.c:7417
#8  0x000000000046c4e1 in do_one_cmd (cmdlinep=0x7fff8cf690f8, sourcing=1,
    cstack=0x7fff8cf68c50, fgetline=0, cookie=0x0) at ex_docmd.c:2668
#9  0x0000000000469b70 in do_cmdline (cmdline=0x7fff8cf69210 "split +1cc",
    fgetline=0, cookie=0x0, flags=11) at ex_docmd.c:1122
#10 0x000000000046933c in do_cmdline_cmd (cmd=0x7fff8cf69210 "split +1cc")
    at ex_docmd.c:727
#11 0x00000000005a2c0d in do_window (nchar=13, Prenum=0, xchar=0)
    at window.c:575
#12 0x00000000004fbf69 in nv_window (cap=0x7fff8cf692e0) at normal.c:7819
#13 0x00000000004f04b2 in normal_cmd (oap=0x7fff8cf693a0, toplevel=1)
    at normal.c:1193
#14 0x00000000005cbed0 in main_loop (cmdwin=0, noexmode=0) at main.c:1294
#15 0x00000000005cb8ae in main (argc=9, argv=0x7fff8cf696d8) at main.c:998
h-east commented 12 years ago

patch書いた。 # 11でdo_cmdline_cmd()を呼ぶ直前にswitchbuffからuseopenを抜いて後で戻すパターンのやつです。


diff -r 8201108e9cf0 src/window.c
--- a/src/window.c  Tue May 01 21:14:34 2012 +0200
+++ b/src/window.c  Sun May 06 19:50:46 2012 +0900
@@ -569,10 +569,32 @@
         */
        if (bt_quickfix(curbuf))
        {
+#ifdef FEAT_WINDOWS
+           char_u  *org_swb = p_swb;
+           unsigned    org_swb_flags = swb_flags;
+
+           p_swb = empty_option;
+           /* Against that blank window is opened. */
+           swb_flags &= ~SWB_USEOPEN;
+#endif
            sprintf((char *)cbuf, "split +%ld%s",
                (long)curwin->w_cursor.lnum,
                (curwin->w_llist_ref == NULL) ? "cc" : "ll");
            do_cmdline_cmd(cbuf);
+#ifdef FEAT_WINDOWS
+           if (p_swb != org_swb)
+           {
+           /* Restore org 'switchbuf' value, but not when
+            * an autocommand or modeline has changed the value. */
+           if (p_swb == empty_option)
+           {
+               p_swb = org_swb;
+               swb_flags = org_swb_flags;
+           }
+           else
+               free_string_option(org_swb);
+           }
+#endif
        }
 #endif
        break;
mattn commented 12 years ago

@h-east ++

h-east commented 12 years ago

ううむ、usetabも抜いた方が良いですね。(別タブに対象バッファがない時だけ) あと

au WinEnter * set swb+=usetab

みたいにautocmdで+= されたら。。微妙だなー。

thinca commented 11 years ago

これはまだ懸念事項が残っている感じですかね。

h-east commented 11 years ago

はい、そうです。