Vim's key mapping behaving differently between gui mode and cli mode - vim

I've been trying to figure this out for so long but still failed, some of my customized key-mapping (majority of them are for plugins) behaves totally different between gui-mode and cli-mode, even if I use gui-mode command with -v flag (like mvim -v) or using :gui command in terminal Vi.
For example, the Emmet plugin which is handy for expanding HTML/CSS expressions, the default trigger key <C-y> never works at first (in Cli-mode which I often used to), I always don't know why, until one day I use MacVim for a while and suddenly find out it works!
After that, I try to re-map the default trigger from <C-y> to <C-e> or <C-k>, both of them works fine in MacVim but still unlucky in terminal Vim.
Is there any particular reason to cause this issue? Maybe something wrong with my configuration?
Any suggestion will be appreciated, thanks!

Finally I solved it by myself, but thank for #ebenezer 's reminding.
We often use set timeoutlen and set ttimeoutlen to tweak the latency for a key code or a mapping sequence to complete. Most of us can't tolerate with the default value for ttimeoutlen (which is -1), because it forces us to waiting for so long when quit from Insert mode by press ESC or Ctrl-[.
For this particular reason, I changed this value to 10 (in ms), but I copy this setting from somewhere I don't remember now, and it place set ttimeoutlen in a autocmd for all filetypes, like below:
if ! has('gui_running')
set ttimeoutlen=10
autocmd InsertEnter * set timeoutlen=0
autocmd InsertLeave * set timeoutlen=1000
endif
I don't know why this will make some plugins not work properly, and I change it a little to make it works for me now:
if ! has('gui_running')
autocmd InsertEnter * set ttimeoutlen=100
autocmd InsertLeave * set ttimeoutlen=-1
endif
Hope this will help you if you encounter same problems.

Related

Vim -- detecting ex mode in vimrc

I have previously asked this in comp.editors, but without getting any replies.
This ought to be simple: I want to configure vim to set number whenever the editor is in ex mode (to get visible line numbers), but never have that option set in visual mode. How?
If the solution involves having to start ex instead of vim, that's fine, but the solution should ideally also cover the case of entering ex mode from visual mode (using Q in vim visual mode, for example).
A solution that also works in nvi would be nice, but not necessary.
You can try something like this:
let &number = mode(1) ==# 'ce'
nnoremap <silent> Q :set number<CR>Q
This will set number when you run vim -e and when you enter ex mode with Q, but it won't clear it when you go back to visual mode. As far as I can tell there is no way to detect the actual event of switching modes. shrug
Vim's Autocmd seemed like your best bet, since it has event listeners. An example would be
:autocmd InsertLeave * :set nonumber
:autocmd InsertEnter * :set number
which shows/hides line numbers
However, I couldn't find any events for Ex mode when I looked.

How to prevent <Esc> from waiting for more input in Insert Mode

When I leave insert mode by pressing Esc, there is a half-second pause before Vim actually returns to normal mode.
Normally this wouldn't be an issue, since pressing a normal mode command like j after pressing Esc executes the normal-mode command immediately (without the above-mentioned wait), but I have the mapping inoremap <Esc> <Esc>:w<CR>, so that every time I leave insert mode the file is written. I would like the write to occur immediately when I press Esc, but instead there is that half-second pause.
I'm assuming that the pause is because Vim is waiting for more input before it decides that I just meant to type a single, simple Esc. This must be because there is a mapping somewhere who's first character is <Esc>, but I've looked in my .vimrc and there is no such mapping.
Furthermore, I even ran :map <Esc>, and it returned No such mapping. So, if there is no such mapping, why does Vim appear to be waiting for more input, and how can I avoid that behavior?
Extra Information
It appears that this is not reproduceable, so here is some more information in case anyone really wants to get to the bottom of this:
I am using Steve Francia's spf13 distribution of Vim, with my own .vimrc.local on top of it. I have also installed several additional plugins using Vundle.
Notes: .vimrc.local is sourced last in .vimrc.
UPDATE (3/19/2014)
I found a far better solution than trying to hunt down all the mappings that start with <Esc>, courtesy of Powerline, from the Tips & Tricks section of the docs. Put this somewhere in your .vimrc:
" leave insert mode quickly
if ! has('gui_running')
set ttimeoutlen=10
augroup FastEscape
autocmd!
au InsertEnter * set timeoutlen=0
au InsertLeave * set timeoutlen=1000
augroup END
endif
Note that this will make it impossible to use mappings that start with <Esc> while in insert mode, but there shouldn't be any of those anyway, because of the problem this solves.
I found the lines in spf13's .vimrc that were causing the problem:
" Fix home and end keybindings for screen, particularly on mac
" - for some reason this fixes the arrow keys too. huh.
map ^[F $
imap ^[F $
map ^[H g0
imap ^[H g0
The reason I couldn't find them before is because they weren't mapped using <Esc>, but ^[ instead. Very irritating! Hope this helps some equally disgruntled spf13 user :)
UPDATE:
If removing those mappings doesn't work, then it's probably a mapping from a plugin.
Type :verbose map <Esc> to get a list of all mappings involving Esc. The verbose part instructs Vim to print where the mapping was set. That should help find out what's causing the problem.
Also, the command unmap <Esc> might be useful—it removes any mappings for the Esc key.
Note that unmap does not remove mappings in all modes; type :h unmap for more info.
In my case, it was tmux injecting that delay (this came as a complete surprise for me!).
I fixed it by adding set -g escape-time 0 to my tmux.conf.
This may not strictly help the author, but this question comes up first when searching for this issue with many different keyword combinations, so I hope it helps someone.
Source: first comment from here.
I'm not exactly sure what the problem is with the mapping you describe, in my opinion it should be fine. However, I think that what you want to accomplish can be reached in a better way. Your mapping is basically an attempt at creating a InsertLeave event, which Vim actually already has built in!
Try adding something like this to your .vimrc:
au InsertLeave * if &mod && expand('%')!=''|write|endif
As an added bonus, this one only saves your buffer if it has a filename and was actually modified.
set timeoutlen=1000 ttimeoutlen=0
timeoutlen - mapping delays.
ttimeoutlen - key code delays.
Source

Enable Syntax highlighting in vim on a per-buffer basis

I currently have to edit some very large XML files, which slows down syntax highlighting to a point where it's absolutely unusable - it takes multiple seconds to update the screen after a search operation, for example.
When disabling syntax highlighting (:syn off), the same operations happen instantaneously. Unfortunately, disabling syntax highlighting appears to happen globally, so all other files now have it disabled as well.
So: Is there a way to only disable syntax highlighting for a given buffer?
You can set :syntax manual and then enable it with set syntax=ON in the buffers you like. Also see :help :syn-manual.
Answering my own question: A simple hack would be to force the syntax of the file to something that vim doesn't know how to highlight: :set syntax=unknown
However, this seems a bit hacky - maybe there's another solution?
For large-file editing I usually use Chip's LargeFile plugin. It disables syntax highlighting, undo database and other features that give trouble with large files.
Old topic, but answer may be helpful to others.;)
This is what I lastly use for switching between syntax ON/OFF in the buffer. The change is local to the buffer. Works OK to me.
nnoremap <leader><leader> :call MyLocalSyntaxOnOff()<cr>
function! MyLocalSyntaxOnOff ()
if getbufvar("%", "&syntax") ==# "OFF"
setl syntax=ON
redraw | echo 'Syntax: ON - <space><space> to change.'
else
setl syntax=OFF
redraw | echo 'Syntax: OFF - <space><space> to change.'
endif
endfunction
Just add it to your .vimrc and You should by fine.
ADVISE: Set your leader key (my one is <space> currently), if not - the standard one should be slash (or backslash(?)) key - \.
Best regards.

How to autosave in Vim 7 when focus is lost from the window?

I've tried the following in my .vimrc:
:au FocusLost * silent! wa
autocmd BufLeave,FocusLost silent! wall
And also tried:
How can I make Vim autosave files when it loses focus?
but can't get it to work, when I do a Ctrl+Z or switch to another tab in Terminal (mac) it still doesn't auto save.
BufLeave is triggered when you go to another buffer. Neither <C-z> nor switching to another Terminal.app tab will trigger this because you are using CLI Vim which doesn't care at all about the terminal emulator's GUI or environment and… you are not leaving your buffer.
The same is true for FocusLost (more or less, the doc says that it's GUI only but can work in some terminals without telling which one).
So, these setting will probably work in MacVim but definetly not in CLI Vim.
Actually, since Vim is not aware of your terminal emulator's tabs or about it being put in the background, I doubt you can achieve your goal in CLI Vim.
I happen to have autocmd FocusLost * :wa in my ~/.vimrc but I've put it in an if has("gui_running") conditional and also inoremap <Esc> <Esc>:w<CR> to save on ESC. Hope it helps.
On OS X and Vim CLI, I use this plugin http://www.vim.org/scripts/script.php?script_id=4521
AutoSave - automatically save changes to disk without having to use :w
(or any binding to it) every time a buffer has been modified.
AutoSave is disabled by default, run :AutoSaveToggle to enable/disable
AutoSave. If you want plugin to be always enabled it can be done with
g:auto_save option (place 'let g:auto_save = 1' in your .vimrc).

What are ways to reduce mode errors while learning vim?

I frequently make mode errors while using vim, i.e. I'll start typing text while in Normal mode, or start typing commands while in Insert mode. I understand this goes away with time as vim's quirks seep into your bones, but are there any ways to speed the process?
I use these autocmd's to highlight the entire line containing the cursor while in insert mode, and not while in normal mode:
if v:version >= 700
autocmd InsertEnter * set cursorline
autocmd InsertLeave * set nocursorline
endif
This provides a little bit more visual feedback about the mode.
If you haven't done so already you can display the current mode by using :set showmode. That'll display -- INSERT -- in the status bar when in insert mode.
Try to remember to always leave vim in normal mode.
Switch "Esc" and "Caps Lock" keys.
If you accidentally click on "Caps Lock" you will start inputing commands that has nothing to do with what you like to do. It is annoying if you are an experienced user; if you are a beginner it may be a hassle to understand what went wrong.
Every time you need to press the Esc key you have to move you entire hand and to get your pinky finger to touch the Esc key and then replace the entire hand again.
Some Vim users will tell you that after a while you get used to doing that and it is not a big deal. I think that argument falls short because you can pretty much get used to mapping any key any where. It is a matter of efficiency.
I believe "Esc" is used very frequently and "Caps Lock" is used seldomly if it is used at all.
So switching the two makes sense as it prevents errors and increases typing speed.
With gvim, the cursor changes from a block to a vertical bar when going between modes. This at least gives you a little visual feedback.
Insert mode should only be temporary. Normal mode is, as its name tells, the favourite mode for edition tasks.
Usually, you should spend more time in normal mode, and always hit ESC when you are done inserting something.
Maybe I speak only for myself, but now I have the habit of assuming that I am in normal mode at all times, and I am almost never wrong.
Here is my variant of Ned's Answer. It toggles on window switches (window focus is another modal behavior that provides little visual feedback).
if v:version >= 700
set cursorline cursorcolumn
au WinLeave * set nocursorline nocursorcolumn
au WinEnter * set cursorline cursorcolumn
au InsertEnter * set nocursorline nocursorcolumn
au InsertLeave * set cursorline cursorcolumn
endif
I use it with the zenburn color scheme, and I also turn off cursor blink:
if has("gui_running")
colorscheme zenburn
set guicursor+=a:blinkon0
endif

Resources