How to scroll horizontally repeatedly? - vim

When i press and hold zl, first the window is moved left by one char and than the cursor starts moving to right. I want to be able to hold zl and the behavior to be the window moving to left, like it is when holding ctrl+e.

You can write 2zl for 2 characters and 4zl for 4 characters and thus you can also use 100zl for 100, so you just have to write any number before zl.

If you want to hold some key to achieve "repeat" zl or zh, you have to create a mapping for that, with keys like ctrl. That is because, the z doesn't work in this way.
E.g. (just an example, you can pick the keys you like to combine with ctrl)
nnoremap <c-l> zl
nnoremap <c-h> zh

Related

Vim and assigning function to a key

Hi!
For about 3 last weeks, I have been using Vim. I must say, I love the navigation keys on the home row!
A week ago I switched to Dvorak, and the new location of the movement keys, simply doesn't let me use Vim. It's terrble.
So, I wonder, is there a way to keep movement keys in Dvorak, in the same location as in qwerty?
I don't want to remap keys, as that would be super-confusing. One way I can think of is to assign the function i.e go up one line from key k to t.
So I could have my movement keys in dvorak(d h t n) layed out as in qwerty (h j k l)
Is it possible? How can I do that?
I don't want to remap keys, as that would be super-confusing
You probably want to remap keys, but just in Vim. However the fine people over at vim.wikia.com doesn't think this is such a good idea.
One alternative, as mentioned in the linked article, is to use dvorak in insert mode, and qwerty-position of binds in normal mode, i.e. w = ", i = c etc.
set
langmap='q,\,w,.e,pr,yt,fy,gu,ci,ro,lp,/[,=],aa,os,ed,uf,ig,dh,hj,tk,nl,s\;,-',\;z,qx,jc,kv,xb,bn,mm,w\,,v.,z/,[-,]=,\"Q,E,PR,YT,FY,GU,CI,RO,LP,?{,+},AA,OS,ED,UF,IG,DH,HJ,TK,NL,S:,_\",:Z,QX,JC,KV,XB,BN,MM,W<,V>,Z?
-
One way I can think of is to assign the function i.e "go up one line" from key k to t, so I could have my movement keys in dvorak(d h t n) layed out as in qwerty (h j k l)
Is it possible? How can I do that?
Remember that doing such a thing could break other keys, I can't really tell as it's hard without actually trying/comparing each key. You could however remap all of those keys to custom positions if you'd want to using nnoremap etc.
A basic remapping would be just to remap the home row like this.
nnoremap d <Left>
nnoremap h <Down>
nnoremap t <Up>
nnoremap n <Right>
All in all I don't think it's such a good idea to combine two keyboard layouts, so just remapping home row is probably the safest, and then learn that e etc. has custom positions compared to qwerty.
These problems is why I never bothered to switch to Dvorak og Colemak, because I'd have to relearn all those binds that I have in my muscle memory, for a new vim user it might not be such a big issue though, so you're lucky that way!

Map 'f' to PageUp in vi

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.

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

How to jump down X amount of lines, over and over

I'm using 10j to jump down 10 lines, but I want to easily jump 10 lines over and over. I don't want to have to perform the jump with a macro qv10jq#v##..
I wish there was a method for repeating down keys like motion has f then ; to continually jump (, to go back) to the next character(s).
is there anything shorter than my macro?
Instead of 10j, you can run:
:+10
Then you can repeat the last ex-mode command with #:.
Here's repmo.vim - a plugin to do what you want. It maps ; to repeat the last motion command given with a count.
The solution to this gave me the idea to use noremap to map 10j (or any other number) and 10k to my up and down arrows. I don't know if anyone would be interested in something obscure like this but figured I would comment.
added to .vimrc:
noremap <Up> 5k
noremap <Down> 5j
There is no plugin or edit to .vimrc here, but I've found this simple and low tech method works pretty well because it requires no control keys and you can keep both hands stationary while scrolling up or down in any increment of lines or order (e.g. down, down, up):
Let's say you want to move down in increments of 44 lines at a time.
44j (of course)
Now just leave your left index finger above the "4" key and repeat this to continue scrolling down in increments of 44 lines. Although it's 3 keystrokes, you can do this very quickly as long as you stick to numbers like 22, 33, etc.
Now what is nice about this is that you can quickly reverse direction with no hand movement by just hitting "k" instead of "j", e.g.
44j
44j
44j (oops, too far, lets go back now...)
44k
Also, you can start with a higher number like 55 (for speed scrolling) and then drop to 22 or 11 to home in on your target. Unfortunately numbers like 77 don't work as well b/c you want to do the number with your left hand, although you could still do higher numbers like 77 with your left hand, it's just that you have strayed from standard touch typing hand position at that point.
Try ctrl+f to move a whole page down and ctrl+b to move a whole page back. Not necessarily 10 lines though.
Taken from this site: http://www.thegeekstuff.com/2009/03/8-essential-vim-editor-navigation-fundamentals/
I found that mapping 10char jumps to arrow keys work perfectly for navigating. ( ^d, ^u, ^f, & ^b are too big of jumps for my liking). Just paste this into your .vimrc file :)
noremap <Up> 10k
noremap <Down> 10j
noremap <Left> 10h
noremap <Right> 10l
Alternatively, you can map the custom jumps to replacing any of these: ^d, ^u, ^f, & ^b, such as:
map <C-d> 10j
map <C-u> 10k
There's a great solution in this answer:.
I found this to have some excellent info:
:help scroll-cursor
The thread also references:
:help motion.txt
You can configure how many lines to move at a time by for example: 15<C-d>
Then subsequent <C-d> or <C-u> strokes will move by the same amount of lines

"Minimizing" vertical VIM window splits

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.

Resources