If I have a tab in insert mode and I switch to another tab that was in normal mode when I last viewed it, it's changed to insert mode. This throws me off. How can I make changing modes local to a tab?
How do you switch to the other tab? By clicking on the tab line, with the mouse (that's the only way I could reproduce this)?! You should avoid the use of the mouse within Vim, but this will change the behavior:
:autocmd TabEnter * stopinsert
For switching tabs with the keyboard, this is usually done via the gt command in normal mode, so you've already left insert mode (just use <Esc>, not <C-O>).
For more browser-like behavior, I have the following key mappings:
" CTRL-Tab next tab
noremap <C-Tab> :<C-U>tabnext<CR>
inoremap <C-Tab> <C-\><C-N>:tabnext<CR>
cnoremap <C-Tab> <C-C>:tabnext<CR>
" CTRL-SHIFT-Tab previous tab
noremap <C-S-Tab> :<C-U>tabprevious<CR>
inoremap <C-S-Tab> <C-\><C-N>:tabprevious<CR>
cnoremap <C-S-Tab> <C-C>:tabprevious<CR>
Vim's current mode is editor-wide. You cannot force it to follow tabs or buffers or windows or anything.
Something you CAN do, is store off the current mode when you leave a tab, and restore it when you enter the tab.
This works switching between normal and any one of the insert/replace modes; but switching among the insert/replace modes doesn't seem to work for some reason:
augroup TAB_MODES
au!
autocmd TabLeave * let t:lastmode = mode(1)
autocmd TabEnter * if !exists('t:lastmode') | let t:lastmode = 'n' | endif
autocmd TabEnter * if t:lastmode ==# 'n' | stopinsert | endif
autocmd TabEnter * if t:lastmode ==# 'i' | startinsert | endif
autocmd TabEnter * if t:lastmode ==# 'R' | startreplace | endif
autocmd TabEnter * if t:lastmode ==# 'Rv' | startgreplace | endif
augroup END
This uses a tab-local variable to store the current mode when you leave a file, and uses it to start the correct insert or replace mode when you re-enter the tab (or stop insert mode). Some modes are not included here; for example I couldn't get visual mode to work (I tried several ways of invoking gv without success).
Related
When using vimdiff, I'd like to start in the second pane (my changes), instead of the first.
I've tried adding this to my .vimrc, but it doesn't seem to work. Is there a different event I should be hooking?
if &diff
autocmd BufWinEnter * winc l
endif
The following worked for me
if &diff
autocmd VimEnter * normal ^W^L
endif
Note here that ^W and ^L are single characters. You can enter them using ctrlvctrlwctrlvctrll
Is there a .vimrc command for opening blank files in insert mode? Non blank files would still open in command mode.
You can try an autocommand:
au BufNewFile * startinsert
So, with:
vim oldfile
will enter in normal mode, but with:
vim newfile
will enter in insert mode.
Note that
vim
without files will be in normal mode too. Perhaps you would need an additional autocommand for it. (EDIT: See commments for a Ben's solution to this one)
To enter insert mode only on empty new buffers:
autocmd BufNewFile * if wordcount()['chars'] == 0 | startinsert | endif
To do that only when opening vim:
autocmd VimEnter * if wordcount()['chars'] == 0 | startinsert | endif
I’m trying to get Vim to switch to relative line numbering when I enter visual mode, and back to absolute numbering afterwards. I've noticed there's InsertEnter and InsertLeave autocmd events, which I could use like this:
autocmd InsertEnter :set rnu
autocmd InsertLeave :set nu
Problem is, I can’t seem to find an equivalent for visual mode.
There are no such events for visual mode (yet implemented; you could submit a patch). For entering visual mode, you can simply override the few commands that enter visual mode:
:nnoremap <silent> v v:<C-u>set nonu rnu<CR>gv
:nnoremap <silent> V V:<C-u>set nonu rnu<CR>gv
:nnoremap <silent> <C-v> <C-v>:<C-u>set nonu rnu<CR>gv
The restore of 'number' is more difficult, because apart from explicitly exiting via <Esc>, there are many commands that stop visual mode. Best I can come up with is a trigger on CursorMoved:
vnoremap <Esc> <Esc>:set nu<CR>
:autocmd CursorMoved * if mode() !~# "[vV\<C-v>]" | set nu | endif
I have the following in my .vimrc:
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Open NERDTree by default
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
autocmd VimEnter * NERDTree
autocmd VimEnter * wincmd p
So,
% vim file.txt
opens NERDTree and focuses the cursor in the file.txt buffer. I make my edits, and hit :q on the buffer, and I'm left with . . . NERDTree. This is annoying.
I could use :qa to close all buffers, and exit vim, but I'm used to the :q trope. So I'm wondering if there's a way to detect that the only remaining buffer is NERDTree, and "unify" the two buffers, for purposes of :q
Edit
Ask and ye shall receive: https://github.com/scrooloose/nerdtree/issues#issue/21
A script to do exactly this has been posted on the NERDTree issue list. Checkout issue-21 on GitHub for nerdtree.
This leads to the single line command for your vimrc here:
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTree()) | q | endif
function! s:CloseIfOnlyControlWinLeft()
if winnr("$") != 1
return
endif
if (exists("t:NERDTreeBufName") && bufwinnr(t:NERDTreeBufName) != -1)
\ || &buftype == 'quickfix'
q
endif
endfunction
augroup CloseIfOnlyControlWinLeft
au!
au BufEnter * call s:CloseIfOnlyControlWinLeft()
augroup END
From my vimrc, based on a version from janus repo.
Enhancements: also close if only a quickfix window is left.
It uses the BufEnter autocommand instead, which is required for &bt to work properly.
An idea in need of implementation:
You could write a function which, when called, checks if the only buffer remaining (or perhaps the only non-help buffer, if you prefer) is a NERDTree buffer and, if so, deletes it (or just quits).
Then have an autocmd run it whenever a buffer is deleted / hidden / whatever actually happens when you :q (it shames me to admit I'm not entirely sure!).
You could :cabbrv q qa but I'd advise against that because you'll forget about it when you actually want q.
I like to do this: cmap bq :bufdo q<CR> to close all buffers with two keystrokes in command mode.
Is it possible to open NERDTree in every tab with pressing t or T in NERDTree, if yes, How?
autocmd VimEnter * NERDTree
autocmd BufEnter * NERDTreeMirror
edit: The above command seems to open the new tab in NERDTree's buffer. Instead use this as mentioned by wejrowski in the comment below :
autocmd BufWinEnter * NERDTreeMirror
I wrote a vim plugin that does this and also adds some goodies on top (i.e. keeps all trees in sync, ensures meaningful tab captions - not captions like 'NERD_tree_1' etc.).
It's here on Github: https://github.com/jistr/vim-nerdtree-tabs
autocmd VimEnter * NERDTree
autocmd BufEnter * NERDTreeMirror
autocmd VimEnter * wincmd w
This one is a little better than Dustin's one because it places the cursor directly on the file you are intending to edit for quick edits. Thanks dustin for the original example ^^
A better solution is to open NERDTree only if there are no command line arguments set.
" Open NERDTree in new tabs and windows if no command line args set
autocmd VimEnter * if !argc() | NERDTree | endif
autocmd BufEnter * if !argc() | NERDTreeMirror | endif
NERDTree is e.g. not helpful if you do a git commit or something similiar.
This is probably not the best way, but if you edit plugin/NERDTree.vim and change this:
exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenInTab ." :call <SID>openInNewTab(0)<cr>"
to this:
exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenInTab ." :call <SID>openInNewTab(0)<cr>:NERDTree<cr>"
it will alter the binding of 't' in the NERDTree view to first open the file and then open NERDTree. Note, that the NERDTree views will not keep in sync.
How about toggling it.
" in .vimrc
" NERDTree, Use F3 for toggle NERDTree
nmap <silent> <F3> :NERDTreeToggle<CR>
In OSX, you just need to fn-F3 to toggle NERDTree.
This problem was actually mentioned in the official Repository's Readme file including three situations related to opening NERDTree automatically:
How can I open a NERDTree automatically when vim starts up?
Stick this in your vimrc: autocmd vimenter * NERDTree
How can I open a NERDTree automatically when vim starts up if no files were specified?
Stick this in your vimrc:
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif
Note: Now start vim with plain vim, not vim .
How can I open NERDTree automatically when vim starts up on opening a directory?
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 1 && isdirectory(argv()[0]) && !exists("s:std_in") | exe 'NERDTree' argv()[0] | wincmd p | ene | endif
This window is tab-specific, meaning it's used by all windows in the tab. This trick also prevents NERDTree from hiding when first selecting a file.