In VSCode you can copy and paste selected lines of text up or down using Alt+Shift + Up or Down.
I switched to vim a few months ago, and I really miss this feature.
I found out you can move selected lines in visual mode up or down using these visual mode bindings,
vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv
but it'd be great if you could copy and paste up and down as well without using yy and p because when you're done yanking, the cursor is placed at the initial position, exiting visual mode and reducing productivity.
Well, that, here, is the problem with copying and pasting random snippets from the internet without understanding what they do: they are little black boxes that one can't modify or extend at will by lack of knowledge.
Let's deconstruct the first mapping:
vnoremap J :m '>+1<CR>gv=gv
:[range]m {address} moves the lines covered by [range] to below line {address}. Here, the range is automatically injected by Vim: '<,'> which means "from the first line of the latest visual selection to its last line", and the address is '>+1, meaning "the last line of the latest visual selection + 1 line". So :'<,'>m '>+1<CR> effectively moves the selected lines below themselves,
gv reselects the latest visual selection,
= indents it,
gv reselects it again for further Js or Ks.
Now, we want a similar mapping but for copying the given lines. Maybe we can start with :help :m and scroll around?
Sure enough we find :help :copy right above :help :move, which we can try right away:
xnoremap <key> :co '>+1<CR>gv=gv
Hmm, it doesn't really work the way we want but that was rather predictable:
the address is one line below the last line of the selection,
the selection is reselected and indented, which is pointless.
We can fix the first issue by removing the +1:
xnoremap <key> :co '><CR>gv=gv
and fix the second one by selecting the copied lines instead of reselecting the latest selection:
xnoremap <key> :co '><CR>V'[=gv
See :help :copy and :help '[.
I'm using wrap in vim, but I want vim to otherwise behave as though the lines have actual breaks in them (rather than "soft breaks" for screen rendering).
I've mapped j to gj and k to gk for navigation. However, line operations (such as dd) still act upon the whole line, rather than the "screen line". Is there any way to alter this behavior such that 'dd' is limited to the screen line?
You can create a key mapping:
:nnoremap dd g0dg$
I would rather create a new operator, for example x in operator-pending mode:
onoremap x :norm! g0vg$<cr>
xnoremap x g$og0o
With the first mapping, dx will delete a screen line, yx will yank a screen line (beware, it will not be pasted linewise, but characterwise), cx will delete a screen line and start insert mode, and so on.
With the 2nd mapping, x in visual mode will extend to screen lines the visual selection.
I wouldn't advise remapping dd, because this might break plugins (if they use :normal instead of :normal! or if they use :×××map instead of :×××noremap.
When I'm writing a long line of text in vim (such as a paragraph in latex), it wraps my text into multiple lines which is good. However, if I then try to navigate these lines with 'j' and 'k' (or the up/down arrows) it will skip the entire paragraph. I fixed this problem by highlighting the paragraph and pressing gq. This inserts line breaks at the end of each line.
My question is, is there a way to automate this, so I don't have to keep highlighting text and pressing gq?
You can limit the width of a line with the textwidth option
(see :help tw).
For example, if you want to limit the width to 80 columns, you can use:
:set tw=80
With this option, when you will type something longer than 80 columns, Vim
will automatically insert a newline character.
You need to step back a little and use gj and gk which go down and up inside wrapped lines.
Since gjand gk work exactly the same as j and k in non-wrapped lines you can safely map j or <down> to gj and k or <up> to gk making it all seamless.
-- EDIT --
Yes it doesn't adress Eddy's immediate problem but it solves his original problem (vertical movement in wrapped lines) which led him to a poor workaround that, in turn, put him in this situation.
I can map 'jj' to
imap jj <Esc>
and I can even map letters to tab navigation
map tj :tabprevious<CR>
map tk :tabnext<CR>
But I can't map g to page up (even though spacebar acts as page down)
map <Space> <PageDown>
map g <PageUp>
According to this "When you try to map multiple key sequences, you won't be able to start them with lower or upper case letters ("Too dangerous to map that"), but the punctuation and control characters are fair game." Can anyone confirm this?
If so, how does one assign a function to an unmapped key like 'g'
This isn't answering your question, but I thought it may be helpful to the problem you are having with your RSI. It maps the spacebar to toggle between fast and slow move modes. Normally pressing j or k will scroll down one line. Pressing space will turn on fast move mode, where pressing j or k will scroll down/up 10 lines. Press space again to go back to normal. This will only work in vim, not just plain vi (most "vi" programs are just symlinks to vim anyway though).
It works in both normal and visual edit modes.
To use it, put this code somewhere in your ~/.vimrc file:
map <Space> :call ToggleFastMoveMode()<CR>
vmap <Space> :call ToggleFastMoveMode()<CR>gv
let g:fastMoveMode = 0
function! ToggleFastMoveMode()
let g:fastMoveMode = 1 - g:fastMoveMode
if (g:fastMoveMode == 0)
noremap j j
vnoremap j j
noremap k k
vnoremap k k
else
noremap j 10j
vnoremap j 10j
noremap k 10k
vnoremap k 10k
endif
endfunction
(Edit - original answer suggested native Ctrl-f and Ctrl-b, but answer was updated as the goal here is to avoid using Ctrl and Shift)
A few points to add
Leaving the issue of choosing the right character to you, assuming we chose X for now.
I can think of two reasons why map X <PageUp> isn't working for you.
Your version of vi may not support PageUp/PageDown. If this is the issue then try instead to map to vi's page jumping (B for back, accompanied by for forward) eg. map X <C-b>.
Another other option is that it doesn't work 'as expected'. In vi PageUp/PageDown act on the 'viewport' not the cursor. So if you'r looking at the top of the file, but the cursor is not at the top or won't do anything. PageDown won't 'work' if your cursor is two lines from the bottom either.
To address this you could combine the 'move viewport up' <C-b> and the 'move cursor to the top of viewport' H eg. map X <C-b>H (The opposite being map X <C-f>L). Or specifying the number of lines to jump yourself map X 30k (Op. map X 30j).
Then the issue of choosing the right character to overwrite. Vi has a lot of native commands, so many in fact that only a handful of characters don't do something natively.
So if your goal is to avoid RSI, then of course overwrite something. But make sure to overwrite something that isn't too useful for you personally.
Natively:
f searches for a given symbol on the line you are currnetly on (can be very useful, but not critical I guess)
g on it's own does nothing, but gg moves cursor to top of file. Choosing g may cause issus as vim (not the original vi) will interpret two quick keypresses as go to top of file instead of do two PageUp's.
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