It took me almost two years of programming till I decided to switch Textmate for Vim and I love it so far. However, after playing with it for a few days I hit a first issue.
As a beginner I reached for Janus as many people do but in the end I decided to create my own configuration from scratch to get to know the stuff better. I backed my configs up and started writing my new .vimrc file. But later on (pretty early) I noticed that leader key isn't working, it does nothing when I press it, well it just beeps. I didn't change the key for a leader nor did any key mapping so I was kinda surprised.
So once again I removed my .vimrc file and .vim directory to start with a clean state. It didn't help. So I opened Vim and tried to reconfigure a leader to a different key to see if it helps.
:let mapleader
> E121: Undefined variable: mapleader
:let mapleader = ','
:let mapleader
> mapleader ,
Looks fine but nothing really happened. Even when I put it under a different key my Mac just beeps and thats it. There's no vim configuration in my home directory, no plugins, nothing. Setting leader in '.vimrc' instead of vim console doesn't help either.
I saw some discussions here on timeouts for key pressing but it have not got me anywhere.
I'm kinda stuck here and not able to use Vim for my day to day job even if I'd love to. Any help would be highly appreciated.
Follow these steps carefully…
Create a blank .vimrc file in your $HOME directory:
$ cd
$ touch .vimrc
Vim should now run in "nocompatible" mode which is what we all want.
Open your blank ~/.vimrc and add these lines:
let mapleader=","
nnoremap <leader>a :echo("\<leader\> works! It is set to <leader>")<CR>
Hit ,a, you should obtain the following message in the command line.
<leader> works! It is set to ,
<leader> may not be useful right from the start, though, there are other things to worry about.
Anyway, from there, I'd suggest you to add these few non-opinionated settings that will make your life considerably easier:
filetype plugin indent on
syntax on
set autoindent
set hidden
set incsearch
filetype plugin indent on allows Vim to recognize the filetype of the files you open and to apply all sorts of built-in filetype-specific settings (indent rules, completion…).
syntax on turns syntax highlighting on.
set autoindent copies the indent of the current line when you do <CR> life sucks so much if this is off.
set hidden allows you to open a new file or switch to another buffer without saving the changes to the current one.
set incsearch makes search-based navigation (/foo, ?bar) instantly awesome by turning incremental search on.
After that, it's up to you to add settings and mappings as you need them.
It's working, but the mappings preceding the change won't understand the changed leader character. For example, if I have a .vimrc that says
nnoremap <Leader>a :echo "test"<cr>
Then I can start up vim and hit \a to get test in the bottom left. However, if you type :let mapleader = ',' then do ,a it doesn't work because you changed leader after the mapping. If you then type :nnoremap <Leader>a :echo "test"<cr> and try ,a again it will work. Thus, :let mapleader = must come before mappings that use <Leader>.
Related
I am having some weird behavior when it comes to VIM.
The behavior that I'm expecting:
When editing a file, if one is in insert mode and doesn't make any file modifications when you exit insert mode the buffer should be considered "saved".
The behavior that I'm actually getting:
When editing a file and when I exit insert mode while making NO MODIFICATIONS, the buffer says that the file has been edited. Even though
I tested if this behavior was normal in vim by opening a clean version of vim, and it seems that the behavior I'm expecting is the default.
This a snippet of my config, my full configuration is here: (https://github.com/TheBabu/Config/blob/master/.vimrc)
I'm assuming whatever is causing this behavior is here otherwise it might be a plugin
"Setup
set shell=bash
set nowrap
set number
set nocompatible
set noshowmode
set directory^=$HOME/.vim/.swapfiles
set undofile
set mouse=a
syntax on
colorscheme neodark
hi Normal ctermbg=none
sign define transparent_sign
augroup SignColFixAu
au!
au BufReadPost *.c,*.cc,*.h,*.cpp,*.hh,*.hpp,*.py,*.js,*.php,*.rs exe "sign place 1111 name=transparent_sign line=1 file=".#%
augroup end
inoremap <cr> <space><bs><cr>
inoremap <esc> ~<bs><esc>
inoremap <expr> <up> pumvisible() ? "\<c-p>" : "~\<bs>\<up>"
inoremap <expr> <down> pumvisible() ? "\<c-p>" : "~\<bs>\<down>"
inoremap <Esc>x <Esc>x
"Tabs
set listchars=tab:➡\
set list
set autoindent
set noexpandtab
set tabstop=4
set shiftwidth=4
..SNIP...
"Plugins
Plugin 'VundleVim/Vundle.vim'
Plugin 'scrooloose/nerdtree'
Plugin 'Valloric/YouCompleteMe'
Plugin 'vim-airline/vim-airline'
Plugin 'vim-airline/vim-airline-themes'
Plugin 'easymotion/vim-easymotion'
Plugin 'w0rp/ale'
Plugin 'godlygeek/tabular'
Plugin 'LukeLike/auto-pairs'
Plugin 'ananagame/vimsence'
Plugin 'preservim/nerdcommenter'
call vundle#end()
filetype plugin indent on
...SNIP...
Thank you for any help!
The problem is caused by your <Esc> mapping:
inoremap <esc> ~<bs><esc>
This mapping is inserting a ~ character then backspacing over it, which in practice doesn't change the contents, but still marks the buffer as modified. (Vim doesn't really track the exact contents of the buffer, but tracks whether any change was introduced, and both inserting ~ and backspacing over a character count as such.)
You mentioned in the comments you use this mapping (together with the <CR> mapping) to change how Vim behaves with indentation. The usual behavior of Vim is to remove auto-indentation when you move to a new line (with <CR> on an otherwise blank line) or leave Insert mode (with <Esc>.)
There doesn't seem to be a way to change this behavior in Vim. But the default Vim behavior is actually very useful, as it prevents ending up with lines with trailing spaces all over the place. (Many use Vim autocmd's to trim trailing whitespace on save and others use git hooks or code review bots to block source code files that have trailing whitespace.)
I imagine your motivation to keep the trailing whitespace is so that you can leave Insert mode and then later enter Insert mode again on that same line, while preserving indentation. But it turns out you don't really need to do that, since Vim has many ways to start Insert mode again with the proper indentation.
For example, if you insert a line above (with O) or below the current one (with o), Vim will insert the appropriate indentation on the new line. If you're on a blank line and want to start inserting there, then instead of using i to start Insert mode, use S to replace the contents of the current line. Since the line is empty, there won't be anything to replace, but the S command will start the replacement with the current indentation, so that should solve that too.
If you're already in Insert mode (and not necessarily at the beginning of a line), you can also use Ctrl+F to have Vim apply the proper indentation to the current line, so that's an option too. With some languages (notably Python), Vim can't always figure out the proper indentation (since you indent to end a block), so Vim might not be able to guess right. In those cases, you also have Ctrl+T to increase indentation and Ctrl+D to decrease it. Both are Insert mode commands and can be executed anywhere in the line.
Hopefully with the use of these commands you'll be able to let go of the trailing spaces that you're using to track indentation and also drop those mappings.
A good starting point to debug this might be comparing both original and modified versions after vim says its been edited.
To see the changes, use git diff if the file is VCS controlled, or vim -d original_copy edited_copy if it's not.
The diff-ed characters should give you an idea of the side-effect of the code that might be causing this. Paste the diff here if you can't figure that out.
I am trying to do a key mapping in vim, yet it doesn't appear to be working how I want it to:
In my ~.vimrc file I have:
syntax on
colorscheme delek
nnoremap < gt
nnoremap > gT
(I only include the first two comments to show that I know my .vimrc is working).
Yet, after I save the file, using < or > does not do anything, though gt and gT are still changing tabs as expected. What is wrong with my character mapping? Or do I need to 'refresh vim' or something, the equivalent of $ source ~/.bash_profile ?
I can confirm that there is nothing wrong with your mapping, and that you are correct about needing to reload/refresh your configuration for it to actually be available. One way to do so is to restart Vim, but we can do it faster with the :so (short for :source) command and the $MYVIMRC environment variable:
:so $MYVIMRC
Simple mappings like let mapleader = "," don't seem to be working, so I reinstalled vim and removed all plugins. Yet some mappings like this still don't work. Where can I find vim plugin config files? I've looked in ~/.vim and ~/.config. When I type a comma in command mode, instead of starting the mapleader command, my mac gives me an alarm bell sound. I included let mapleader = "," as the first line in my .vimrc.
UPDATE To help diagnose, I have this line in my .vimrc:
noremap <silent> <Leader>w :w<CR>
When I type :map in vim, I see, among other mappings:
,w * :w<CR>
The most elaborate information you'll get by running vim via vim -V.
This will give you information on every file that vim looks for, finds and opens.
The most important are ~/.vimrc and /usr/share/vim/*.
Besides, please verify that your mapleader command is at the beginning of your vimrc.
From the manual:
Note that the value of "mapleader" is used at the moment the mapping is
defined. Changing "mapleader" after that has no effect for already defined
mappings.
EDIT
To verify if it's enabled for sure, type :let mapleader in a running vim. It should print something like mapleader ,. Please verify it, so we can think of other causes.
Try placing your mappings in a file called ~/.vimrc.
The ~/.vim directory is used to store plugin files, whereas the ~/.vimrc file is typically used for generic settings like mappings.
Note that the value of "mapleader" is used at the moment the mapping is defined. Changing "mapleader" after that has no effect for already defined mappings.
Are you sure you are defining map leader before you create your mappings? If not, your mapleader is probably , just as your define, but all your macros will be mapped to \.
A Vim plugin usually "configures itself" in ~/.vim/plugin/pluginname.vim, not in an external file. The configuration typically consists of variables (e.g. g:pluginnameSettingName) and mappings, which should appear in this format:
nnoremap <silent> <Plug>(PluginMapping) :<C-u>call pluginname#MyFunc()<CR>
if ! hasmapto('<Plug>(PluginMapping)', 'n')
nmap <Leader>x <Plug>(PluginMapping)
endif
If the default mapping starts with <Leader>, your intended change via :let mapleader should work. Alternatively, you can try to explicitly override the mapping by mapping your own keys to the <Plug>... mapping.
I really suggest you use a practical plugin Vundle to manage your vim plugins. It would enable you to manage your plugins in text format and config parameters of each plugins separately.
For instance, if you want to install a new plugin 'a.vim', you just need to add a line into your bundle.vim
Bundle 'a.vim' (for any plugins you can access from VimScripts you could just type the short name like 'c.vim' or 'Tagbar'). Restart Vim and run :BundleInstall, Vim will install the new plugins automatically.
In the same way, when you want to uninstall the plugin, just remove the line Bundle 'a.vim' in your configuration file and run :BundleClean, the plugin will be removed automatically.
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
Some time ago the line in my vimrc (d:/programs/vim/_vimrc) stopped working (not the only one):
nnoremap <unique> ç :execute ':let #/ = "\\<' . expand('<cword>') . '\\>"'<CR>:set hlsearch<CR>
(This line overwrite the functionality of * but without jumping to the next observation, just highlight the word under the cursor. I mapped it to ç because this char is in my keyboard near * and vim does not uses it, but you could map any other key)
The problem is that for some time it stopped working if placed in _vimrc, but works if placed in $VIM/vimfiles/plugins/myPlugins.vim
Have you experienced this issue?
It could be because of installing a new plugin?
I am mostly intrigued for this behavior. I have tried with :scriptnames and other copies of _vimrc, .vimrc, .vim/vimrc, etc., but can not find the source of the misbehavior.
From :h <unique>:
If the first argument to one of these commands is "" and it is used to
define a new mapping or abbreviation, the command will fail if the mapping or
abbreviation already exists.
Use :verbose nmap ç to see where it is defined.
Or simply drop <unique> which doesn't seem useful at all.