"Minimizing" vertical VIM window splits - vim

I use horizontal and vertical window splits in religiously in VIM and up until recently, I enjoyed the comfort of two commands to effectively hide (or minimize) my horizontal splits. I set them up adding the following lines to my .vimrc file:
set winminheight=0
map <C-J> <C-W>j<C-W>_
map <C-K> <C-W>k<C-W>_
Hitting Control-j or Control-k navigates through horizontal splits by going up or down. What I'd like to accomplish is the same thing for vertical splits by showing or hiding the left or right split using Control-Shift-h and Control-Shift-l; h moving to the left, l moving to the right. I have tried the following with little to no success:
set winminwidth=0
map <S-C-L> 500<C-W>h<C-W>_
map <S-C-H> 500<C-W>l<C-W>_
The action would be similar to utilizing Control-w-< and Control-w->, only moving the vertical split completely to the left or write, not just one line at a time.
Any ideas on how to accomplish this? Thanks.

First up, you won't be able to use <S-C- (shift + control) in your code (see below). But you can use the 'mapleader' as your "shift" and then use the <C-h> and <C-l> like you want to. Like this:
set winminwidth=0
nmap <Leader><C-h> <C-W>h500<C-W>>
nmap <Leader><C-l> <C-W>l500<C-W>>
The common leader keys in vim are comma and back-slash:
:let mapleader = ","
But you'll find that this gets annoying to require 3 keystrokes for this, so you might as well just drop the control key stroke. This way (if your leader is comma) you can just press ",h" and ",l" to go to the splits to your left and right:
set winminwidth=0
nmap <Leader>h <C-W>h500<C-W>>
nmap <Leader>l <C-W>l500<C-W>>
" (FTW) :D
...
A guy named Tony Chapman answers why you can't use control + shift:
Vim maps its Ctrl+printable_key
combinations according to ASCII. This
means that "Ctrl+lowercase letter" is
the same as the corresponding
"Ctrl+uppercase letter" and that
Ctrl+<key> (where <key> is a printable
key) is only defined when <key> is in
the range 0x40-0x5F, a lowercase
letter, or a question mark. It also
means that Ctrl-[ is the same as Esc,
Ctrl-M is the same as Enter, Ctrl-I is
the same as Tab.
So yes, Ctrl-s and Ctrl-S (i.e. Ctrl-s
and Ctrl-Shift-s) are the same to
Vim. This is by design and is not
going to change.

Try
set winminwidth=0
map <S-C-L> <C-W>h<C-W>|
map <S-C-H> <C-W>l<C-W>|
This doesn't move a window completely to the left or right (that's <C-W>H and <C-W>L), it just moves the cursor to the left (or right) window and maximizes that window horizontally.
See :help CTRL-W_bar for more.

Crl-w 1 |
will minimize current window in Vim.

Related

How do I press "<C-L> <C-W>l<C-W>_" in Vim?

In one of the vim config files I have noticed this keyboard mapping
map <C-L> <C-W>l<C-W>_ supposedly for easier moving in tabs and windows. What does that translate to keyboard presses? What is that underscore at the end for?
The command map <C-L> <C-W>l<C-W>_ maps Ctrl-L to Ctrl-W, l, Ctrl-W, _.
You invoke this binding by just pressing Ctrl-L. To invoke what it binds to you would type Ctrl-W, then l, followed by Ctrl-W again, and finally _ (which on a US keyboard is shift-hyphen). This is two separate bindings, <C-W>l moves the cursor to the window to the right, and <C-W>_ resizes current window to the maximum possible vertical size.
The Ctrl+wlCtrl+w_ keys sequence is somewhat too long so someone has created a shortcut ("mapping" in Vim-speak): Ctrl+L for it.
<C-w>l<C-w>_ moves the the cursor to the window on the right (<C-w>l) and maximizes it vertically (<C-w>_).
Mappings always follow the same structure:
map (or imap for insert mode mapping, nmap for normal mode mapping, etc.)
some whitespace
the shortcut you want, here <C-L>
some whitespace
the sequence of commands triggered by the shortcut
See :help windows for more info on window management and :help mapping for more info on mappings.

How to make a shortcut for moving between Vim windows?

Let’s say I have single Vim tab displaying 9 buffers (equally separated, like a 3×3 table).
Currently, to get from the top left window to the bottom right one, I have to press 3, Ctrl+W, J, and then 3, Ctrl+W, L. This is cumbersome, and I would like to just be able to press Ctrl+9 to go to the 9th window, and Ctrl+3 to go to the 3rd window, etc.
Is there any easy way I can map something like this in Vim?
There's a much simpler solution than using the mouse or hard-set movement mappings; they will break if the window numberings are different from what you have in mind for a 3x3 matrix, or if you decide to work with less than 9 windows. Here's how:
Include the following in your .vimrc:
let i = 1
while i <= 9
execute 'nnoremap <Leader>' . i . ' :' . i . 'wincmd w<CR>'
let i = i + 1
endwhile
Now you can just press <Leader><number> and be taken to the window number you want. I wouldn't recommend going beyond 9, because IMO, the utility of having multiple viewports follows a Rayleigh distribution and quickly becomes useless with too many viewports in one window.
It will be helpful if you have the window number displayed in your statusline to aid you in quickly figuring out which window you're on and which window you want to go to. To do that, use this little function and add it accordingly in your statusline.
function! WindowNumber()
let str=tabpagewinnr(tabpagenr())
return str
endfunction
See it in action in your statusline:
set laststatus=2
set statusline=win:%{WindowNumber()}
Note that the above line will replace your statusline. It was just meant for illustration purposes, to show how to call the function. You should place it where ever you think is appropriate in your statusline. Here's what mine looks like:
Update
romainl asked for my status line in the comments, so here it is:
"statusline
hi StatusLine term=bold cterm=bold ctermfg=White ctermbg=235
hi StatusHostname term=bold cterm=bold ctermfg=107 ctermbg=235 guifg=#799d6a
hi StatusGitBranch term=bold cterm=bold ctermfg=215 ctermbg=235 guifg=#ffb964
function! MyGitBranchStyle()
let branch = GitBranch()
if branch == ''
let branchStyle = ''
else
let branchStyle = 'git:' . branch
end
return branchStyle
endfunction
function! WindowNumber()
let str=tabpagewinnr(tabpagenr())
return str
endfunction
set laststatus=2
set statusline=%#StatusLine#%F%h%m%r\ %h%w%y\ col:%c\ lin:%l\,%L\ buf:%n\ win:%{WindowNumber()}\ reg:%{v:register}\ %#StatusGitBranch#%{MyGitBranchStyle()}\ \%=%#StatusLine#%{strftime(\"%d/%m/%Y-%H:%M\")}\ %#StatusHostname#%{hostname()}
The last line should be a single line (be careful if your setup automatically breaks it into multiple lines). I know there are ways to keep it organized with incremental string joins in each step, but I'm too lazy to change it. :) The GitBranch() function (with other git capabilities) is provided by the git.vim plugin. There's a bug in it as noted here and I use the fork with the bug fix. However, I'm leaving both links and the blog here to give credit to all.
Also, note that I use a dark background, so you might have to change the colours around a bit if you are using a light scheme (and also to suit your tastes).
Better, more general answer:
Use countCtrl+wCtrl+w to jump to the count window below/right of the current one.
For example, if you're in the top left of a 3x3 grid and want to jump to the bottom left you'd use 7Ctrl+wCtrl+w.
Specific 3x3 grid answer:
If you're always using a 3x3 layout you could try these mappings for the numpad, which always jump to the top left and then move the appropriate amount from there, with the key's position on the keypad jumping to the window's with 'equivalent' position on the screen:
noremap <k7> 1<c-w><c-w>
noremap <k8> 2<c-w><c-w>
noremap <k9> 3<c-w><c-w>
noremap <k4> 4<c-w><c-w>
noremap <k5> 5<c-w><c-w>
noremap <k6> 6<c-w><c-w>
noremap <k1> 7<c-w><c-w>
noremap <k2> 8<c-w><c-w>
noremap <k3> <c-w>b
Edited: turns out c-w c-w goes to the top left at the start automatically. The explicit 1 is required in the first mapping, as c-w c-w without a count toggles between the current and the previously selected window.
(The Ctrl-W t mapping always goes to the top-left most window, the Ctrl-W b mapping always goes to the bottom-rightmost).
Alternatively you could map each number to jump to the Nth window, so k6 would be 6 c-w c-w, rather than trying to lay out the keys as on screen.
I prefer use standard vim keys(jkhl).
noremap <C-J> <C-W>w
noremap <C-K> <C-W>W
noremap <C-L> <C-W>l
noremap <C-H> <C-W>h
There is a trick if you notice that the first two maps can jump clock wise or the reverse, rather than just jumping up or down.
And you can also switch to any window directly with <Number><C-J>, for example, 2<C-J> will go to the 2nd window.
Not exactly what you're looking for, but if you're using a terminal that supports it, you can set the following options:
:set mouse+=a
:set ttymouse=xterm2
and click on a buffer to switch to it. Yes, with the mouse.
A bunch of other mouse behavior works too - you can click to move the insertion point, drag to select text or resize splits, and use the scroll wheel.
Ermmm... I'm pretty sure that this will not keep window layout as it is, but I use
:buf sys
to go to system.h,
:buf Sing
to go to MyLargeNamedClassSingleton.cpp
buf will do autocomplete (possibly menucompletion if so configured) so you can do
:buf part<Tab>
to list what files could match the part you typed. Beats the crap out of navigating buffers all around.
But I understand, this doesn't answer your specific question of course :)
I like to move around with the arrow keys.
I map ctr+direction to move to the next window partition in that direction.
map <C-UP> <C-W><C-UP>
map <C-DOWN> <C-W><C-DOWN>
map <C-LEFT> <C-W><C-LEFT>
map <C-RIGHT> <C-W><C-RIGHT>
You cant jump directly from one window to another but I find that it makes it very easy to move between windows

Quickly switching buffers in Vim normal mode

Recently I found out that I'm "using tabs incorrectly" in Vim. I've been trying to just use buffers in Vim since, assisted through MiniBufExplorer, but I find it painful because of how many keystrokes it takes to change buffers from normal mode. With tabs, I can just do gt or gT to hop back and forth between tabs in normal mode, and I can also do NUMBERgt to go to a specific tab.
With buffers, I either have to enter command mode with :bn, :bp, or with MiniBufExplorer, use Ctrl + k or Ctrl + Up to hop up to the buffer window, scroll left or right with h and l and then hit Enter to select the buffer I want. Or I can do something involving a leader sequence, but it always requires removing multiple fingers away from home row. That's a real pain.
How can I get something equivalent switching tabs in normal mode to switch buffers in normal mode, so I can do something like gn/gp for :bn/:bp and NUMBERgn for :buf NUMBER?
Add this to your .vimrc
map gn :bnext<cr>
map gp :bprevious<cr>
map gd :bdelete<cr>
" I personally use <leader>
map <leader>n :bnext<cr>
map <leader>p :bprevious<cr>
map <leader>d :bdelete<cr>
Note that you are remapping gp and gd, but maybe you don't care about that (:help gp, :help gd).
For more information on how to map key strokes see :help map-overview and :help map.txt.
Btw, I personally use <leader> instead of g in the mapping. My <leader> is set to ;. This puts my <leader> key on the home row which makes me willing to map all kinds of stuff using <leader>. :help mapleader if you want to change your <leader> key.
The way I usually switch between buffers is to use the :buffer command with the built-in autocompletion, e.g. :b prof<Tab> to switch to folder/path/LoginProfileFactory.php.
You can just start typing any part of the file name of the buffer you need, which is nice.
Less often, I actually remember the numbers of the buffers I want and I use something like :b 3 or :3b.
I see you mention you don't like :buf 3 though, so Rumple Stiltskin has an alternative to the :3b style that you may prefer.
{count}CTRL-^ switches to the count numbered buffer.
I have the following lines in .vimrc:
nnoremap <silent> <tab> :if &modifiable && !&readonly && &modified <CR> :write<CR> :endif<CR>:bnext<CR>
nnoremap <silent> <s-tab> :if &modifiable && !&readonly && &modified <CR> :write<CR> :endif<CR>:bprevious<CR>
Now a Tab let you go to the next buffer and a Shift-Tab to the previous.
This is based on Nick Knowlson's answer, but I wanted to expand on my comment there ...
Type :b <Tab> (note the space), then cycle through the open buffers with Tab or ← / →.
... which gets us closer to the Ctrl + Tab in all the other editors and browsers I use.
It's actually even better in some ways, you can then go backwards and forwards with ← / → arrows. It avoids the thumb + finger fu to type Ctrl + Shift + Tab to go backwards through the tabs in editors and browsers.
N.B. Shift + Tab just does the same as Tab
This is then actually something like Win + Tab in Windows 10, where once you first open up the window and you can then move around using the arrow keys.
Edit: I have two further tricks that I picked up for using buffers:
From this answer I have this in my .vimrc:
nnoremap <leader>bb :buffers<cr>:b<space>
it opens the :ls / :buffers command and pre-types the :b so that you just have to type the buffer number as you'll see a list with all the buffers and their numbers.
I also have
nnoremap <leader><tab> :b#<cr>
which toggles between the current and most recently used buffers, it's a bit like doing cd - when switching back and forth between directories
I use the plugin unimpaired.vim
it defines mappings [b and ]b that jump to the previous and next buffer in the list.
For jumping for a specific buffer the best option I know is the one you mentioned: :b<number>
If you go into another buffer you can came back quickly by typing <c-^>
Expanding on Rumple Stiltskin's answer, if you know that the file you want to get to is in buffer 4, for example, you can get there quickly with
4Ctrl-^
On my UK keyboard, I can actually do 4Ctrl-6, as explained in
:help CTRL-^
By the way, you can see the buffer numbers with
:buffers
or
:ls
I use LustyExplorer: I hit <leader>b to open a list of buffers then a couple of letters from the name of the buffer I want to open then enter. Easy.
But, you are not "using tabs incorrectly", you are using tabs the way you want. If it worked for you why go through the pain of unlearning your way to learn "the right way"?
I use F9 and F10 to move between the previous/next buffer with this mapping:
map <F9> :bprevious<CR>
map <F10> :bnext<CR>
For me this is the fastest way to switch buffers.
fzf.vim is another fast way to changes buffers using fuzzy matching. This plug-in ships with the default command:
:Buffers
which opens the list of all open buffers similar to :ls but a buffer can be (fuzzy) searched and selected.
Opening the buffer in the current window is through enter, but can can also be opened in a new split (h or v) or tab using ^X ^V or ^T respectively.
Noteworthy is also:
:Lines
Which allows to search through the content of all open buffers. This can be handy if you forget the name of a buffer but you know what it should contain.
Here is my solution:
" `<leader><Tab>` - next buffer;
nnoremap <silent> <leader><Tab> :bnext<CR>
" `<leader><S-Tab>` - previous buffer;
nnoremap <silent> <leader><S-Tab> :bprevious<CR>
" `_bufferNumber_ + <Tab>` - go exact the buffer number;
nnoremap <silent> <Tab> <C-^>
By the way, I use 'buftabline' plugin and set let g:buftabline_numbers = 1 to spread my buffer on the tabline.
I make it easier for myself:
In .vimrc :
nnoremap <leader>bf :buffers<CR>:buffer "<- Last spaces is necessary
For example, in normal mode, say your leader key is \(default it is), type \bf, then you have a list of opened buffers, type number of buffer you want and hit enter key.
NOTE: remember that last spaces not necessary at all if you wich type it after :D
Jut like that ;)
More detail:
<C-O> Navigate backward
<C-I> Navigate forward
So there is no need extra remapping, otherwise you remapped them.
I think bufexplorer is a nice plugin to use. <leader>be brings up an interactive buffer explorer that lists all open buffers. You could quickly move through the list and Enter puts you in the selected buffer. Unlike LustyExplorer It has no dependency to ruby.
I prefer navigating between buffers similarly to how I'm navigating between window panes: <alt-h> and <alt-l>. This is to straightforward to set on Mac because <alt>/<option> key binds are bounded to specific characters.
" Buffer navigation
map ˙ :bp<cr>
map ¬ :bn<cr>
map § <c-^>
Here is a good answer that shows how you can see characters maped to <alt-..> combinations

What is the best way to do smooth scrolling in Vim?

The main scrolling commands in Vim are:
Ctrl-B and Ctrl-F, as well as PageUp and PageDown scroll by full page
Ctrl-U and Ctrl-D scroll half a page by default
Ctrl-Y and Ctrl-E scroll one line
I lose visual context every time for the former two, so I have developed the bad habit of hitting the latter (Ctrl-Y and Ctrl-E) repetitively.
Since there is currently no first party support for smooth scrolling, what are the least objectionable workarounds/plugins?
I use both Vim and GVim depending on the task, and am happy to customize them separately if there is no one really good hack that works for both. The mouse scroll wheel works nicely in GVim, but I'm looking for keyboard based solutions.
Update: I have now pushed this code, refactored somewhat according to the guidelines at :help write-plugin, to a Github repo.
Using the Keyboard
Here is what I have in my .vimrc:
function SmoothScroll(up)
if a:up
let scrollaction="^Y"
else
let scrollaction="^E"
endif
exec "normal " . scrollaction
redraw
let counter=1
while counter<&scroll
let counter+=1
sleep 10m
redraw
exec "normal " . scrollaction
endwhile
endfunction
nnoremap <C-U> :call SmoothScroll(1)<Enter>
nnoremap <C-D> :call SmoothScroll(0)<Enter>
inoremap <C-U> <Esc>:call SmoothScroll(1)<Enter>i
inoremap <C-D> <Esc>:call SmoothScroll(0)<Enter>i
Features:
Scroll on the base of the Vim scroll option.
Customizable scrolling speed (adjust time argument of the sleep command; I use ten milliseconds). Note: just like slowing down the frame rate on a video, if you slow down the smooth scroll too much it will be jerky scroll, not smooth scroll. But whatever works best for you.
Works in normal or insert mode.
Note: all you copy-and-pasters, remember that the ^ character indicates a control character; copy-paste will produce invalid results and these must be entered manually!
^Y – CTRL-V then CTRL-Y
^E – CTRL-V then CTRL-E
However, the <C-U> and <Enter> style syntaxes are literally typed as those characters; the map command intelligently converts them to control characters.
Using the Mouse
The question mentions that scrolling with the mouse works well in GVim, but a keyboard solution is desired. This implies to me that the asker may be interested in a mouse solution if it works in regular terminal Vim.
For me, turning mouse support on allows smooth scrolling through the mouse wheel. Also, for me, smooth scrolling is most important when I am looking around (i.e. in normal mode), not when I am editing (in insert mode), and if I am not actively editing, the need for my hands to stay on the keyboard at all times is removed, so this works well.
On the basis of this question, though, it would seem that some people have to do some more manual setup beyond simply turning the mouse on (I just use set mouse=n):
My .vimrc has the following lines
set mouse=a
map <ScrollWheelUp> <C-Y>
map <ScrollWheelDown> <C-E>
There is a simple remap hack in vim's tips.txt:
Smooth scrolling *scroll-smooth*
If you like the scrolling to go a bit smoother, you can use these mappings:
:map <C-U> <C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y>
:map <C-D> <C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E>
Shameless plug, but I created a plugin here that you can use to easily adjust the distance, speed, and duration of the scrolling animation: https://github.com/terryma/vim-smooth-scroll
A Recent Plugin
I have posted something similar here, but basically there is a great plugin that we can use now for scrolling, called terryma/vim-smooth-scroll. It provides a very nice and smooth scrolling.
The install is quite easy:
1 I use Vundle so I simply appended this in .vimrc.bundles :
Bundle terryma/vim-smooth-scroll
In the latest version of Vundle available today, 29th April of 2016, you can put this in your .vimrc:
Plugin 'terryma/vim-smooth-scroll'
2 As stated in the doc, you can set up 3 arguments: distance, duration and speed.
I am using this in my .vimrc file:
noremap <silent> <c-b> :call smooth_scroll#up(&scroll*2, 10, 4)<CR>
noremap <silent> <c-f> :call smooth_scroll#down(&scroll*2, 10, 4)<CR>
What I do is I set the keyboard repeat to very fast, about 120 chars / second, and the delay small.
Then I map to 4j and to 4k
I navigate up and down source code using j and k which moves the cursor up and down nice and quick, pretty smooth.
But here's the good part, and this works on Linux, not Windows.
For a number of years now, X11's keyboard input works in such a way that when you press and hold j it obviously starts putting out j characters. But when you then keep holding down j and then also press the ctrl key, X11 starts putting out c-j characters without you having to re-press the j key. Then when you let go of the ctrl key and still keep on pressing j, X11 continues to put j's again.
So j makes the cursor start moving nice and smooth downwards, and you can periodically hit ctrl without letting go of j to give it a boost, a jolt.
Also, I do what Devin does, and I set scrolloffset to 5.
Lastly, I swap ctrl and cap lock. The default position of the ctrl key is completely retarded (no offense intended). It makes you have to rotate your left hand. I almost never use caps lock, so I swap them. Then my left pink finger can reach the ctrl key without any yoga moves.
These things have worked for me for years. I only use vim, never gvim.
This isn't exactly smooth scrolling, but it's how I handle not losing context when jumping pages.
set so=7
'scrolloff' 'so' number (default 0)
global
{not in Vi}
Minimal number of screen lines to keep above and below the cursor.
This will make some context visible around where you are working. If
you set it to a very large value (999) the cursor line will always be
in the middle of the window (except at the start or end of the file or
when long lines wrap).
For scrolling horizontally see 'sidescrolloff'.
NOTE: This option is set to 0 when 'compatible' is set.
The Plugin cskeeters/vim-smooth-scroll supports smooth scrolling and requires no configuration. It supports to support smooth scrolling with zt, zz, and zb. It's a fork of terryma's plugin. Some of the open pull requests have been applied.
This combines many of these answers, and this is what I use.
noremap <expr> <C-u> repeat("\<C-y> :sleep 10m<CR>", winheight('%')/2)
noremap <expr> <C-d> repeat("\<C-e> :sleep 10m<CR>", winheight('%')/2)
N <CR-E>
N <CR-Y>
...where 'N' is the number of single lines you want to scroll.
Not smooth in literal sense, but you keep the keyboard.
This may be controversial for hardcore users, but... the best way to smooth scroll in Vim is... mouse wheel.
I just found this plugin called "accelerated-smooth-scroll" ("Vim plugin for accelerated smooth scroll (mapping to <C-D>/<C-U>, <C-F>/<C-B>)") which can be for example used through Vundle by putting this line in your .vimrc:
Plugin 'yonchu/accelerated-smooth-scroll'
Then by restarting Vim and running the :PluginInstall command, then again restart Vim and use the <C-D> (Ctrl+D) and <C-O> (Ctrl+O) commands normally.
Sadly, this plugin also moves the cursor instead of what I wanted: to just scroll the screen like the <C-E> and <C-Y> commands.
I slightly modified #Keith Pinson's code so that ctrl-f and ctrl-b can be mapped too:
function SmoothScroll(scroll_direction, n_scroll)
let n_scroll = a:n_scroll
if a:scroll_direction == 1
let scrollaction=""
else
let scrollaction=""
endif
exec "normal " . scrollaction
redraw
let counter=1
while counter<&scroll*n_scroll
let counter+=1
sleep 10m " ms per line
redraw
exec "normal " . scrollaction
endwhile
endfunction
" smoothly scroll the screen for some scrolling operations
nnoremap <C-U> :call SmoothScroll(1,1)<cr>
nnoremap <C-D> :call SmoothScroll(2,1)<cr>
nnoremap <C-B> :call SmoothScroll(1,2)<cr>
nnoremap <C-F> :call SmoothScroll(2,2)<cr>

Traversing text in Insert mode

While in Insert Mode in Vim, is there any way to traverse the text moving some characters forward and backward other than using the arrow keys?
If I press h, j, k and l while in Insert mode, the actual characters are printed on screen instead of moving through the text.
The way I'm doing it at the moment is having to resort to Ctrl + [ (Esc) and traversing the text then; but obviously that is not productive.
While it may make sense that you should be able to use the h j k l keys to traverse the editor in insert mode, but that is actually not the way Vim is intended to be used! There are many commands that Vim provides to make editing faster and easier.
The right way is to press Esc, go where you want to do a small correction, fix it, go back and keep editing. It is effective because Vim has much more movements than usual character forward/backward/up/down. After you learn more of them, this will happen to be more productive.
Here are a couple of use-cases:
You accidentally typed "accifentally". No problem, the sequence EscFfrdA will correct the mistake and bring you back to where you were editing. The Ff movement will move your cursor backwards to the first encountered "f" character. Compare that with Ctrl+←→→→→DeldEnd, which does virtually the same in a casual editor, but takes more keystrokes and makes you move your hand out of the alphanumeric area of the keyboard.
You accidentally typed "you accidentally typed", but want to correct it to "you intentionally typed". Then Esc2bcw will erase the word you want to fix and bring you to insert mode, so you can immediately retype it. To get back to editing, just press A instead of End, so you don't have to move your hand to reach the End key.
You accidentally typed "mouse" instead of "mice". No problem - the good old Ctrl+w will delete the previous word without leaving insert mode. And it happens to be much faster to erase a small word than to fix errors within it. I'm so used to it that I had closed the browser page when I was typing this message...!
Repetition count is largely underused. Before making a movement, you can type a number; and the movement will be repeated this number of times. For example, 15h will bring your cursor 15 characters back and 4j will move your cursor 4 lines down. Start using them and you'll get used to it soon. If you made a mistake ten characters back from your cursor, you'll find out that pressing the ← key 10 times is much slower than the iterative approach to moving the cursor. So you can instead quickly type the keys 12h (as a rough of guess how many characters back that you need to move your cursor), and immediately move forward twice with ll to quickly correct the error.
But, if you still want to do small text traversals without leaving insert mode, follow rson's advice and use Ctrl+O. Taking the first example that I mentioned above, Ctrl+OFf will move you to a previous "f" character and leave you in insert mode.
While in insert mode, use CtrlO to go to normal mode for just one command:
CTRL-O h move cursor left
CTRL-O l move cursor right
CTRL-O j move cursor down
CTRL-O k move cursor up
which is probably the simplest way to do what you want and is easy to remember.
Other very useful control keys in insert mode:
CTRL-W delete word to the left of cursor
CTRL-O D delete everything to the right of cursor
CTRL-U delete everything to the left of cursor
CTRL-H backspace/delete
CTRL-J insert newline (easier than reaching for the return key)
CTRL-T indent current line
CTRL-D un-indent current line
these will eliminate many wasteful switches back to normal mode.
Insert mode
Movement
hjkl
Notwithstanding what Pavel Shved said - that it is probably more advisable to get used to Escaping Insert mode - here is an example set of mappings for quick navigation within Insert mode:
" provide hjkl movements in Insert mode via the <Alt> modifier key
inoremap <A-h> <C-o>h
inoremap <A-j> <C-o>j
inoremap <A-k> <C-o>k
inoremap <A-l> <C-o>l
This will make Alt+h in Insert mode go one character left, Alt+j down and so on, analogously to hjkl in Normal mode.
You have to copy that code into your vimrc file to have it loaded every time you start vim (you can open that by typing :new $myvimrc starting in Normal mode).
Any Normal mode movements
Since the Alt modifier key is not mapped (to something important) by default, you can in the same fashion pull other (or all) functionality from Normal mode to Insert mode. E.g.:
Moving to the beginning of the current word with Alt+b:
inoremap <A-b> <C-o>b
inoremap <A-w> <C-o>w
(Other uses of Alt in Insert mode)
It is worth mentioning that there may be better uses for the Alt key than replicating Normal mode behaviour: e.g. here are mappings for copying from an adjacent line the portion from the current column till the end of the line:
" Insert the rest of the line below the cursor.
" Mnemonic: Elevate characters from below line
inoremap <A-e>
\<Esc>
\jl
\y$
\hk
\p
\a
" Insert the rest of the line above the cursor.
" Mnemonic: Y depicts a funnel, through which the above line's characters pour onto the current line.
inoremap <A-y>
\<Esc>
\kl
\y$
\hj
\p
\a
(I used \ line continuation and indentation to increase clarity. The commands are interpreted as if written on a single line.)
Built-in hotkeys for editing
CTRL-H delete the character in front of the cursor (same as <Backspace>)
CTRL-W delete the word in front of the cursor
CTRL-U delete all characters in front of the cursor (influenced by the 'backspace' option)
(There are no notable built-in hotkeys for movement in Insert mode.)
Reference: :help insert-index
Command-line mode
This set of mappings makes the upper Alt+hjkl movements available in the Command-line:
" provide hjkl movements in Command-line mode via the <Alt> modifier key
cnoremap <A-h> <Left>
cnoremap <A-j> <Down>
cnoremap <A-k> <Up>
cnoremap <A-l> <Right>
Alternatively, these mappings add the movements both to Insert mode and Command-line mode in one go:
" provide hjkl movements in Insert mode and Command-line mode via the <Alt> modifier key
noremap! <A-h> <Left>
noremap! <A-j> <Down>
noremap! <A-k> <Up>
noremap! <A-l> <Right>
The mapping commands for pulling Normal mode commands to Command-line mode look a bit different from the Insert mode mapping commands (because Command-line mode lacks Insert mode's Ctrl+O):
" Normal mode command(s) go… --v <-- here
cnoremap <expr> <A-h> &cedit. 'h' .'<C-c>'
cnoremap <expr> <A-j> &cedit. 'j' .'<C-c>'
cnoremap <expr> <A-k> &cedit. 'k' .'<C-c>'
cnoremap <expr> <A-l> &cedit. 'l' .'<C-c>'
cnoremap <expr> <A-b> &cedit. 'b' .'<C-c>'
cnoremap <expr> <A-w> &cedit. 'w' .'<C-c>'
Built-in hotkeys for movement and editing
CTRL-B cursor to beginning of command-line
CTRL-E cursor to end of command-line
CTRL-F opens the command-line window (unless a different key is specified in 'cedit')
CTRL-H delete the character in front of the cursor (same as <Backspace>)
CTRL-W delete the word in front of the cursor
CTRL-U delete all characters in front of the cursor
CTRL-P recall previous command-line from history (that matches pattern in front of the cursor)
CTRL-N recall next command-line from history (that matches pattern in front of the cursor)
<Up> recall previous command-line from history (that matches pattern in front of the cursor)
<Down> recall next command-line from history (that matches pattern in front of the cursor)
<S-Up> recall previous command-line from history
<S-Down> recall next command-line from history
<PageUp> recall previous command-line from history
<PageDown> recall next command-line from history
<S-Left> cursor one word left
<C-Left> cursor one word left
<S-Right> cursor one word right
<C-Right> cursor one word right
<LeftMouse> cursor at mouse click
Reference: :help ex-edit-index
If you are a vim purist, skip reading this answer. OTOH, if you are new to vim and are looking for a few helpful tips you wont find in the many hundred of vim tutorials and blogs, read on... :-)
A few un-orthodox (vim) ways
It's 2014, and as someone who's recently gone back to vim I can offer a few, potentially contrarian, points of view and tips.
Use shift+left or shift+right to traverse words
While repetition is a powerful concept in vim, I (personally) find it strange that using it either forces me to count (lines, characters, words, etc.) or make guesses. My brain usually works like "I want the cursor there" and not like "I want the cursor _5_words_to_the_left_". Quickly being able to move the cursor, and visually observe where the insertion point this way allows me to keep my mind on what I'm editing instead of having to count how many hops I need to make to get to where I need to edit.
Turn on mouse mode, and use the mouse wheel and clicking
...to navigate large bodies of text.
Most (all) modern computers have a touchpad that is closely integrated with the keyboard (e.g. MacBooks). Industrial designers have spent many man years optimizing these designs so that the old problem of having to move the hand away from the keyboard is no longer a real issue. Okay, it is if you are used to a mouse and don't like to switch, but for anyone new to vim (like those that might find this post via a search), this should not be much of an issue.
As a bonus, click + drag puts you in visual mode
With mouse enabled, clicking and dragging has the effect of switching to visual mode and marking a region for yanking.
And use the scroll wheel
Using the mouse (wheel) to scroll around, and clicking to position the cursor (duh) just works. See http://usevim.com/2012/05/16/mouse/ for more on this.
And so...
These are what I'd call more modern (using mouse, scroll wheel, etc.) ways of navigating in vim, equally effective depending on your preference of input.
HTH
Many people in the Vim community argue that you should not navigate in Insert mode, that it is not the Vim way. I think this is an incorrect sentiment learned when transitioning from standard editors to Vim.
Vim is most powerful when you use its tools to create atomic, repeatable actions or finds.
It is ok to navigate while in Insert mode if you are fixing a mistake you made in the same Insert session. You should not navigate outside of the range of text you modified.
If you make a mistake while entering text and escape out of Insert mode to fix it you will not be able to repeat the intended action, . will repeat the correction.
Vim does support many Insert mode navigation keys. Obviously there are the arrow keys, Home, and End, but there are also many other shortcuts. See :h ins-special-keys.
To have a little better navigation in insert mode, why not map some keys?
imap <C-b> <Left>
imap <C-f> <Right>
imap <C-e> <End>
imap <C-a> <Home>
" <C-a> is used to repeat last entered text. Override it, if its not needed
If you can work around making the Meta key work in your terminal, you can mock emacs mode even better. The navigation in normal-mode is way better, but for shorter movements it helps to stay in insert mode.
For longer jumps, I prefer the following default translation:
<Meta-b> maps to <Esc><C-left>
This shifts to normal-mode and goes back a word
In GVim, you can use the mouse. But honestly, what's wrong with using the arrow keys? There's a reason why they are on a keyboard.
I believe Home and End (and PageUp/PageDn) also work normally while in insert mode, but aside from that, I don't believe there are any other standard keys defined for text traversal.
Sorry but vim don't work that way.
You should switch to "normal" mode, navigate and then go back to insert again.
You can create mappings that work in insert mode. The way to do that is via inoremap. Note the 'i' at the beginning of the command (noremap is useful to avoid key map collisions). The corollary is 'n' for 'normal' mode. You can surmise what vim thinks is 'normal' ;)
HOWEVER, you really want to navigate around in text using 'normal' mode. Vim is super at this kind of thing and all that power is available from normal mode. Vim already provides easy ways to get from normal mode to insert mode (e.g., i, I, a, A, o, O). The trick is to make it easy to get into normal mode. The way to do that is to remap escape to a more convient key. But you need one that won't conflict with your regular typing. I use:
inoremap jj <Esc>
Since jj (that's 2 j's typed one after the other quickly) doesn't seem to appear in my vocabulary. Other's will remap to where it's comfortable.
The other essential change I make is to switch the CAPSLOCK and CONTROL keys on my keyboard (using the host computer's keyboard configuration) since I almost never use CAPSLOCK and it has that big, beautiful button right where I want it. (This is common for Emacs users. The downside is when you find yourself on an 'unfixed' keyboard! Aaarggh!)
Once you remap CAPSLOCK, you can comfortably use the following insert mode remappings:
Keeping in mind that some keys are already mapped in insert mode (backwards-kill-word is C-w (Control-w) by default, you might already have the bindings you want. That said, I prefer C-h so in my .vimrc I have:
inoremap <C-h> <C-w>
BUT, you probably want the same muscle memory spasm in normal mode, so I also map C-h as:
nnoremap <C-h> db
(d)elete (b)ackwards accomplishes the same thing with the same key chord. This kind of quick edit is one that I find useful in practice for typos. But stick to normal mode for moving around in text and anything more than killing the previous word. Once you get into the habit of changing modes (using a remap of course), it will be much more efficient than remapping insert mode.
Yes, there is a way. You can use gj and gk inside Insert Mode to move up (backwards) and down (forwards) within a single logical-line that wraps around numerous visual-lines. That is handy if you have very long lines and/or a narrow width terminal and can be much faster than the arrow keys, or hitting ESC to use the other navigation shortcuts. Also you can use CTRL-O to issue one normal-mode command. Neither of these navigation movements will escape you out of insert mode.
It can be disruptive to productivity to hit ESC (which was besides home-row on terminal keyboards when Vi was invented). I work with text files that have extremely long logical-lines, whole paragraphs of sentences full of plain text. These two options are a real time saver for me. It's still handy to escape out to normal-mode if I need to hunt for a particular word within the paragraph, but many times I just need to move a visual-line up or down, and then continue inserting.
I actually edit my .vimrc to map out my nearly useless ALT key, so my left hand presses ALT while my right uses the arrow keys. (and it does not escape out of insert-mode: notice the "i" at the end of each entry).
imap <A-UP> <ESC>gki
imap <A-DOWN> <ESC>gji
I also add lines to .vimrc so that my arrow keys work in normal-mode to traverse up and down within many visual-lines that are contained by one logical-line (the code is identical to the above except you use map or nmap rather than imap) And I use keyboard's other navigation keys with the ALT-KEY, all within insert-mode.
I add additional navigation lines for my ALT key, to use with my keyboards preassigned navigation keys, to navigate more quickly within insert-mode. None of these will escape you out of insert-mode:
" <ALT> navigation within insert-mode
imap <A-UP> <ESC>gki
imap <A-DOWN> <ESC>gji
imap <A-LEFT> <ESC>bi
imap <A-RIGHT> <ESC>ea
imap <A-END> <ESC>A
imap <A-PageUp> <ESC>(i
imap <A-PageDown> <ESC>l)i
imap <A-Home> <Esc>I
" so that <ALT> behaves the same in normal mode
nmap <A-UP> gk
nmap <A-DOWN> gj
nmap <A-LEFT> b
nmap <A-RIGHT> le
nmap <A-END> $
nmap <A-PageUp> (
nmap <A-PageDown> )
nmap <A-Home> ^
My "within" insert-mode navigation short cuts utilize the ALT key with PgUp, PgDn, Home & End keys too, to jump around far more quickly. I use alt-pgup and alt-pgdn presses to jump forward or backward by sentences. And, I use alt-home and alt-end to jump to the beginning and end of my paragraph long logical lines. None of this escapes me out of insert mode. (I figured that I might as well program all the preassigned navigation keys to work quickly within insert-mode, without leaving it). And if I want to move one character at a time, I just let up on the ALT key while still using the arrow keys.
All of those are really simple modifications to the .vimrc. You can get creative and do all sorts of things to improve navigation within insert-mode. Otherwise, if you use the plain ole ARROW keys within insert-mode on long lines, then you need a cup of coffee in your left hand to sip while you hold the arrow keys down with the right. That takes forever!
By the way, the key already works with all the other normal mode navigation commands, like h,j,k,l and w,W,b,B,e and search: /,% etc. EXCEPT that it automatically escapes you out of insert mode without having to press the ESC key. So using with the normal-mode navigation characters will leave you stranded in normal-mode, until you take the effort to press i,I,a,A,o,O again, which I find easy to forget to do.
Since the keyboards preassigned navigation commands: arrows: UP, DOWN, RIGHT, LEFT and PGUP, PGDN, HOME, END don't do anything special with the key, I found that I might as well map them out in .vimrc to help my navigation within insert-mode, while staying within insert-mode. And, to reiterate, its helpful to me because I work with very long text documents that have paragraph long logical-lines that span across a lot of visual-lines, and the arrow keys and h,j,k,l don't acknowledge the visual-lines. This fixes that particular problem, both within insert-mode and normal-mode.
I give credit to my knowledge above, which I found in the book HACKING VIM 7.2 by Kim Schulz
You could use imap to map any key in insert mode to one of the cursor keys. Like so:
imap h <Left>
Now h works like in normal mode, moving the cursor. (Mapping h in this way is obviously a bad choice)
Having said that I do not think the standard way of moving around in text using VIM is "not productive". There are lots of very powerful ways of traversing the text in normal mode (like using w and b, or / and ?, or f and F, etc.)
For some frequently used movements and actions, I have defined the following mappings. This saves a keystroke compared to the CTRL+O combination and since I need them frequently, they pay off in the long
run.
inoremap <A-$> <C-o>$
inoremap <A-^> <C-o>^
inoremap <A-h> <Left>
inoremap <A-l> <Right>
inoremap <A-O> <C-O>O
inoremap <A-o> <C-o>o

Resources