Hubro
Hubro

Reputation: 59388

Why does one of these two key binds crash when they are virtually identical?

This problem clearly far transcends my understanding of Vim. These two key binds only differ by two characters, otherwise they are completely identical.

" Move viewport up/down.
noremap <C-d> :exe "normal! " . (winheight(".") / 4) . "\<C-e>"<CR>
noremap <C-u> :exe "normal! " . (winheight(".") / 4) . "\<C-y>"<CR>

And yet, the bottom one (<C-u>) works as perfectly as intended, while the top one causes this error:

E114: Missing quote: "\" E15: Invalid expression: "normal! " . (winheight(".") / 4) . "\"

I have restarted Vim twice and made triply sure that only these commands are bound to their keys. I also tried switching them, in case that was relevant for some reason, but the <C-d> command still crashes.

So where's Waldo?


Output of gvim.exe --version:

VIM - Vi IMproved 7.3 (2010 Aug 15, compiled Aug 16 2010 10:31:31)
MS-Windows 64-bit GUI version with OLE support
Compiled by [email protected]
Huge version with GUI.  Features included (+) or not (-):
+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 +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_ime/dyn +multi_lang -mzscheme +netbeans_intg +ole 
-osfiletype +path_extra -perl +persistent_undo +postscript +printer +profile 
+python/dyn -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"
  system gvimrc file: "$VIM\gvimrc"
    user gvimrc file: "$HOME\_gvimrc"
2nd user gvimrc file: "$VIM\_gvimrc"
    system menu file: "$VIMRUNTIME\menu.vim"
Compilation: cl -c /W3 /nologo  -I. -Iproto -DHAVE_PATHDEF -DWIN32   -DFEAT_CSCOPE 
-DFEAT_NETBEANS_INTG      -DWINVER=0x0400 -D_WIN32_WINNT=0x0400  /Fo.\ObjGOY/ /Ox /GL -DNDEBUG  
/Zl /MT -DFEAT_OLE -DFEAT_MBYTE_IME -DDYNAMIC_IME -DFEAT_MBYTE -DFEAT_GUI_W32 
-DDYNAMIC_ICONV -DDYNAMIC_GETTEXT -DFEAT_PYTHON -DDYNAMIC_PYTHON  
-DDYNAMIC_PYTHON_DLL=\"python27.dll\" -DMSWINPS -DFEAT_HUGE /Fd.\ObjGOY/ /Zi
Linking: link /RELEASE /nologo /subsystem:windows /LTCG:STATUS oldnames.lib kernel32.lib advapi32.lib 
shell32.lib gdi32.lib  comdlg32.lib ole32.lib uuid.lib /machine:AMD64 /nodefaultlib gdi32.lib version.lib   
winspool.lib comctl32.lib advapi32.lib shell32.lib  /machine:AMD64 /nodefaultlib libcmt.lib oleaut32.lib  user32.lib

I downloaded Vim from the link on the official Vim download page:

http://code.google.com/p/vim-win3264/downloads/list

Upvotes: 2

Views: 312

Answers (1)

Nikita Kouevda
Nikita Kouevda

Reputation: 5756

noremap interprets <C-e> and <C-y> before exe does, so exe is then fed the control sequences, which are not necessarily interpreted properly. A possible workaround is to define commands and then map to them:

com! ShiftDown exe "norm!" winheight(".")/4 . "<C-e>"
com! ShiftUp exe "norm!" winheight(".")/4 . "<C-y>"
noremap <C-d> :ShiftDown<CR>
noremap <C-u> :ShiftUp<CR>

It's also possible to directly map the commands by using <C-v> <C-e> and <C-v> <C-y> to insert those characters:

noremap <C-d> :exe "norm!" winheight(".")/4 . "<C-v><C-e>"<CR>
noremap <C-u> :exe "norm!" winheight(".")/4 . "<C-v><C-y>"<CR>

Alternatively, <LT> can be used to insert a literal <:

noremap <C-d> :exe "norm!" winheight(".")/4 . "<Bslash><LT>C-e>"<CR>
noremap <C-u> :exe "norm!" winheight(".")/4 . "<Bslash><LT>C-y>"<CR>

N.B. While a literal \ may work, :help map suggests using <Bslash> to be safe.

Upvotes: 6

Related Questions