窗口分割时Vim缓冲区位置的改变(烦恼)

17

这真的开始让我感到恼火了,因为这是一个如此微小的问题。

假设我没有插件/没有vimrc,使用gvim 7.3(Windows或Linux)打开一个较长的文件,将其滚动到一半。我将光标定位在主窗口底部。我打开一个垂直分割窗口(CTRL + W v)。

接下来发生的事情让我很烦恼。光标和它所在的行(之前在原始窗口底部)跳到窗口顶部。新窗口右侧的位置与光标所在行在原始窗口中的位置相同。

enter image description here

我的问题:如何避免vim更改我拆分的窗口的光标位置?老实说,如果位置在新窗口中改变,我根本不在意,但是拆分会导致原始窗口位置改变,这让我想抓狂。

以前完全可以忽略。然后我有点生气。然后我慢慢开始变得非常生气。现在,这让我开始感到愤怒。非常感谢任何帮助/技巧/黑客!

编辑:Windows和Linux的vim版本选项(发生在两者上):

Windows:

+arabic +autocmd -balloon_eval -browse ++builtin_terms +byte_offset +cindent
+clientserver +clipboard +cmdline_compl +cmdline_hist +cmdline_info +comments
+conceal +cryptv +cscope +cursorbind +cursorshape +dialog_con +diff +digraphs
-dnd -ebcdic +emacs_tags +eval +ex_extra +extra_search +farsi +file_in_path
+find_in_path +float +folding -footer +gettext/dyn -hangul_input +iconv/dyn
+insert_expand +jumplist +keymap +langmap +libcall +linebreak +lispindent
+listcmds +localmap -lua +menu +mksession +modify_fname +mouse -mouseshape
+multi_byte +multi_lang -mzscheme -netbeans_intg -osfiletype +path_extra -perl
+persistent_undo -postscript +printer -profile -python -python3 +quickfix
+reltime +rightleft -ruby +scrollbind +signs +smartindent -sniff +startuptime
+statusline -sun_workshop +syntax +tag_binary +tag_old_static -tag_any_white
-tcl -tgetent -termresponse +textobjects +title -toolbar +user_commands
+vertsplit +virtualedit +visual +visualextra +viminfo +vreplace +wildignore
+wildmenu +windows +writebackup -xfontset -xim -xterm_save -xpm_w32
   system vimrc file: "$VIM\vimrc"
     user vimrc file: "$HOME\_vimrc"
 2nd user vimrc file: "$VIM\_vimrc"
      user exrc file: "$HOME\_exrc"
  2nd user exrc file: "$VIM\_exrc"
Compilation: cl -c /W3 /nologo  -I. -Iproto -DHAVE_PATHDEF -DWIN32   -DFEAT_CSCOPE       -DWINVER=0x0400 -D_WIN32_WINNT=0x0400  /Fo.\ObjC/ /Ox /GL -DNDEBUG  /Zl /MT -DDYNAMIC_ICONV -DDYNAMIC_GETTEXT -DFEAT_BIG /Fd.\ObjC/ /Zi
Linking: link /RELEASE /nologo /subsystem:console /LTCG:STATUS oldnames.lib kernel32.lib advapi32.lib shell32.lib gdi32.lib  comdlg32.lib ole32.lib uuid.lib /machine:i386 /nodefaultlib  libcmt.lib   user32.lib             /PDB:vim.pdb -debug

Linux:

-arabic +autocmd +balloon_eval +browse +builtin_terms +byte_offset +cindent 
+clientserver +clipboard +cmdline_compl +cmdline_hist +cmdline_info +comments 
-conceal +cryptv -cscope +cursorbind +cursorshape +dialog_con_gui +diff 
+digraphs +dnd -ebcdic -emacs_tags +eval +ex_extra +extra_search -farsi 
+file_in_path +find_in_path +float +folding -footer +fork() +gettext 
-hangul_input +iconv +insert_expand +jumplist -keymap -langmap +libcall 
+linebreak +lispindent +listcmds +localmap -lua +menu +mksession +modify_fname 
+mouse +mouseshape -mouse_dec +mouse_gpm -mouse_jsbterm -mouse_netterm 
-mouse_sysmouse +mouse_xterm +multi_byte +multi_lang -mzscheme +netbeans_intg 
-osfiletype +path_extra -perl +persistent_undo +postscript +printer -profile 
+python -python3 +quickfix +reltime -rightleft -ruby +scrollbind +signs 
+smartindent -sniff +startuptime +statusline -sun_workshop +syntax +tag_binary 
+tag_old_static -tag_any_white -tcl +terminfo +termresponse +textobjects +title
 +toolbar +user_commands +vertsplit +virtualedit +visual +visualextra +viminfo 
+vreplace +wildignore +wildmenu +windows +writebackup +X11 -xfontset +xim 
+xsmp_interact +xterm_clipboard -xterm_save 
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
      user exrc file: "$HOME/.exrc"
  system gvimrc file: "$VIM/gvimrc"
    user gvimrc file: "$HOME/.gvimrc"
    system menu file: "$VIMRUNTIME/menu.vim"
  fall-back for $VIM: "/usr/local/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_GTK  -I/usr/include/gtk-2.0 -I/usr/lib64/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng14     -g -O2 -D_FORTIFY_SOURCE=1      
Linking: gcc   -L/usr/local/lib -o vim   -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lgdk_pixbuf-2.0 -lpangocairo-1.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lglib-2.0   -lXt -lncurses -lacl -lgpm     -L/usr/lib64/python2.6/config -lpython2.6 -lpthread -lutil -lm -Xlinker -export-dynamic     

2
我无法在Linux上使用Vim 7.3重现此问题,即使运行vim -u NONE -U NONE也是如此。从Vim运行时目录中删除“mswin.vim”是否可以解决问题? - Dan Hulme
我也无法在使用“VIM - Vi IMproved 7.3”的Linux系统中重现此行为。 - Birei
谢谢大家,我会尝试删除mswin.vim。就像我说的,在Linux中也会出现这种情况。编辑:已删除mswin.vim,问题依旧存在。有比较构建选项的方法吗? - andrew
感谢您仔细解释问题并表达出对这种状态的烦恼,这让我们非常感激。 - Sundeep
2个回答

9
我可以重现您描述的行为,乍一看似乎确实是一个错误。但我注意到以下几点:
  • :vert split 的行为与 ^Wv 相同。

  • :debug ver split(...cont)确认没有明显的脚本/自动命令干扰。

  • 这只会在第一次拆分时发生。换句话说,这是一个解决方法:^Wv^Wc^Wv

  • 光标实际上并没有在原始窗口中移动。'新窗口' 出现在左侧(您称之为原始窗口)。这不能用 :echo winnr() 或类似的命令显示,但您可以通过执行例如 :vert new 而不是 :vert split 来使其更加明显:新的空白窗口出现在左侧。

相比之下,您可以通过在拆分之前执行一些“无用”的操作来欺骗拆分以具有“第二次拆分”的行为。

 :tabnew|bwipeout

现在,^Wv 第一次使用时具有所需的行为。
TL;DR:
1. 这不是一个 bug (你对“新”窗口的期望有误)。 2. 可以通过创建另一个窗口来解决它。
其他背景:
  1. The splitright, splitbelow options

    can be used to control (to an extent) where newly created (split) windows appear

  2. The winrestview() function

    Can be used to explicitely restore the exact view of a window. Use it like so:

      :let savex=winsaveview()
    

    savex now contains something like {'lnum': 1, 'leftcol': 0, 'col': 0, 'topfill': 0, 'topline': 1, 'coladd': 0, 'skipcol': 0, 'curswant': 0} describing the state of the current view.

    (do stuff, like ^Wv)

      :call winrestview(savex)
    

    This is obviously a lot more flexible but you might not need it.


5
你迂回地找到了答案:1)根本问题在于OP期望新窗口出现在右侧,但它出现在左侧,2)这种行为可以通过“set splitright”命令来反转。 - David Pope
1
@DavidPope 我认为你的总结是正确的,比这个答案更清晰,但对于这个答案也要点赞。 - Randy Morris
啊,太好了!我一直在寻找类似于splitright的东西。感谢你指出来。 - andrew
1
@DavidPope:我对更好地描述这种现象很感兴趣。在第一次分割时会出现一些意外的行为,实际上各种解决方法比splitright更好,这取决于OP的喜好。例如使用^Wv^Wc^Wv,两个窗口的光标位置相同,光标不会跳到最右边的窗口。不需要设置splitright可能更好。最后,看到后续使用^Wv进行分割似乎可以达到OP想要的效果,这确实有点奇怪。称其为迂回,我称其为彻底(或好奇)。 - sehe
1
@sehe 同意;我不是在批评,只是在总结。很好的回答。 - David Pope

1

我在Windows机器上使用gvim进行了测试,并且能够重现您的问题,这里是一个解决方法,对于我来说,将下一个命令添加到vimrc中有效(我使用:e $MYVIMRC获取它):

set splitright

function MySplit()
    vsplit
    execute "normal \<C-w>\<C-w>"
endfunction

nmap <C-w>v :call MySplit()<CR>

有更简单的解决方法,不需要更改配置。考虑使用nnoremap来避免与其他脚本/映射的干扰。此外,斜杠似乎放错了位置。 - sehe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接