Vim: Vertical "f" and "t" - vim

One tiny piece of functionality I find myself missing increasingly often is the ability to move vertically in a similar fashion to f and t. Usually what I want is to move to the top or bottom of a paragraph without losing my column position, and while I "could" just write a script for it, I wondered if there is any known way around this problem that you guys know of.
Example ( [ ] = current position, < > = destination ):
set tabstop=4
set shiftwidth=4
set <s>ofttabstop=4
set gfn=Source\ Code\ Pro:h14
set encoding=utf-8
set [t]_Co=256
set number
Like a vertical fs, or t<space>.
Again, this is usually useful when working with blocks of code. Any ideas?

vim regex provides \%nc (n is col idx) to match only in certain column.
so without installing plugin, what you could do is :
nnoremap <leader>f :<c-u>exe line('.').'/\%'.col('.').'c'.nr2char(getchar())<cr>
in this way, you press <leader>f, then press a key, vim will search that char in the same col. next, you press n/N
If you want to have the same but search backwards, use ?.

The most basic way is to use forward search, /t_<CR> and backward search, ?so<CR>, ideally with set incsearch.
But there are quite a lot of plugins designed around that idea:
EasyMotion,
Sneak,
Fanfingtastic,
and a few othersā€¦

For moving vertically without changing columns, you can use <n>j or <n>k. That doesn't completely help with "top of paragraph" or "bottom of paragraph" without counting the lines. There's also '{' and '}' for jumping between paragraphs. Not sure there's a single command to do exactly what you want...

I recently implemented the JumpToVerticalOccurrence plugin (just published), which implements an f{char} equivalent as ]V{char}. It also has related mappings that jump to the same character the cursor is under, or to non-whitespace in the same column.

I have a mapping that might be useful in visual selection.
To extend the selection downwards (<leader>j) or upwards (<leader>k) from the current column, but not beyond the block of text:
vnoremap <leader>j <Esc>m`:let b:ss=#/<CR>:let b:zz=col('.') - 1<CR>/\%<C-r>=b:zz<CR>c.\zs.\+\n.\{,<C-r>=b:zz<CR>}$<CR>:let #/=b:ss<CR><C-v>``o
vnoremap <leader>k <Esc>m`:let b:ss=#/<CR>:let b:zz=col('.') - 1<CR>?^.\{,<C-r>=b:zz<CR>}\n.*\%<C-r>=b:zz<CR>c.\zs.<CR>:let #/=b:ss<CR><C-v>``o
It also avoids clobbering the search register. At least, that's how I avoid clobbering the search register.

Related

Cycling and/or highlighting through a vim selection

The feature I am thinking of is kind of inspired by a feature that I really like about sublime text.
In sublime text, if you select a sequence of characters, it automatically puts a little box around it (to distinguish it from the word that you just highlighted). For me, this is very helpful because I can see and find specific things of the code much faster.
It would be awesome to have something similar to my vim environment. It does not have to be exactly the same as the one in sublime though, but it would be awesome if it were as similar as possible plus the additional feature to easy cycling through similar words.
Currently, what I am doing is highlight the work I want and then manually typing it to the search command /. It would be much better if I can just highlight it in visual mode and then automatically highlight similar words on the current screen with a different colour from the highlighting in visual mode and then have a quick key short cut to cycling through them, if I wished to do that.
I am not sure if a there exists a plugin or something that already does that, but that would cool! Ideally, I would want to to know as many details of the commands/changes to the vimrc file, so that I have the most control over this feature and be able to customize it as I wish.
You can get the highlighting you are looking for by enabling the hlsearch option:
:set hlsearch
It will highlight every occurrence of the last search pattern and thus work after all the following commands (and their relatives):
/foo<CR>
?bar<CR>
:s/fizz/buzz/g
*
#
You can use n to jump to the next occurrence in the direction of your search and N to do the same in the opposite direction.
To highlight every occurrence of the current word "without" moving the cursor, you can simply do:
*N
or:
*``
to jump to the next occurrence and jump back immediately.
Doing the same for visually selected text is a bit trickier but still possibleā€¦
either via a lightweight plugin like visualstar or The Search Party,
or with a tiny bit of crude vimscript in your ~/.vimrc:
" this function cleans up the search pattern
function! GetVisualSelection()
let old_reg = #v
normal! gv"vy
let raw_search = #v
let #v = old_reg
return substitute(escape(raw_search, '\/.*$^~[]'), "\n", '\\n', "g")
endfunction
" map * and # in visual mode so that they do the same as *N and #N in normal mode
xnoremap * :<C-u>/<C-r>=GetVisualSelection()<CR><CR>N
xnoremap # :<C-u>?<C-r>=GetVisualSelection()<CR><CR>N
My SearchHighlighting plugin changes the * command so that it just toggles the highlighting for the current word, without the movement to the next match (for which you can press n, or pass a count). This also works in visual mode, using the selection. I find this very handy for highlighting all matches.
There's also a mode that automatically highlights the current word / selection, like what many IDEs offer.
Other plugins
If you want more permanent highlighting, separate from searching, the Mark plugin offers that.
To get an orientation about the number of matches (without highlighting them), I have the SearchPosition plugin.

Not highlighting search in vim if it is a part of a command

In my .vimrc I've enabled highlighting the searched text (which I find to be a handy feature and wouldn't want to disable it).
set hlsearch
And, following answers to this question, I've made a mapping to be able to clear the highlight:
nmap <silent> ,/ :nohlsearch<CR>
The problem comes with commands which include search. For example, delete to next character 'x':
d/x
This will automatically highlight all the instances of 'x'. To remove this highlight I have to punch ,/ to clear it, which is quite annoying.
The question. Is it possible to enforce :nohl if the search is a part of a preceding command? Maybe, it is possible at least for a selected list of commands (say, d, y and c) before / character is hit?
d/x does not work for me as you describe. (I'm on vim 7.3 here and it can't make sense of the / following d in normal mode, so disregards the d and starts a regular / search.)
If you want to delete to the next x, then dfx or dtx are what I would use (depending on whether you want to also delete the x itself or not).
No highlighting involved.
Hope that helps.
[Following some clarification in the comments.]
I'm thinking that it should be possible to write a custom function to do what you want, and then assign a custom key sequence to call that function.
I played around a little, but am not very well versed in vim functions and couldn't make it work.
Here's what I tried:
function! g:DeleteToSearchAndNohls(term)
:normal d/a:term
:nohlsearch
endfunc
If 'x' is on the same line than the cursor, you can use dtx (meaning delete to x).

Vim: move around quickly inside of long line

I have word-wrap enabled and tend to have quite long lines.
But moving around inside a line that's actually 4 lines high with "w" is cumbersome. I keep using / to jump to the word I'm looking for, but that seems overdoing it a bit.
Any hints on how to move more quickly inside of a line?
Thanks,
MrB
You can use $, 0, and ^ to move to line endpoints and then use w and b. Also, adding a numeric argument to w and b can accelerate the process, so using 6w instead of just w can put you about to where ou need to be.
Using f and t to move to individual characters will help also. (I use this typically with punctuation. If, for example, I have four sentences on one long line 2f. will go to the end of the second sentence)
Using the ( and ) keys are an alternative way to navigate entire sentences.
Splitting out long lines into multiple lines (manually, or with set tw=72 [or 80]) can make editing them simpler. You can always join them later with J.
Something I just discovered, you can move up and down one displayed line by using gj and gk. That way, you can treat your one wrapped line as multiple lines.
If you comment on the type of data you're editing, it might make it easier for us to make suggestions.
I think you can benefit from gk and gj instead of just k and j.
Also look at 'virtualedit' for some options that allow you to cursor through 'void' areas without flicking the cursor to the next best physical character.
You might want to (temporarily)
nnoremap <buffer> k gk
nnoremap <buffer> j gj
Leave out the <buffer> part to apply this globally.
You can use ( and ) to navigate by sentence; it just looks for ., but that can be immensely helpful, especially if you don't like the sentence and want to change it: (c) will jump to the beginning of the current sentence, then change the entire sentence.
You can also use w and e, with count modifiers, to move words. 3w will move three words at a time.
You can also use f and F to search forward and backwards for a specific character. This is much more useful if you're looking for the word quite or syzygy than the. :)
My preferred strategy while jumping around long lines is to use f F and t T to zero in on the character. What makes this family of motions supercharged is that you can utilize the ; and , motions, so you don't have to count the position of character relative to cursor, but just step through them (extremely useful with
' " . etc)
Let's say we have a line:
reallyLongObjectName.longMethod().prettyPrettyLongMethod().burp();
If we need to jump to, say, the third dot from the beginning of the line, we can use either 3f. or f.;; visiting two dots and landing on third.
While the ; , style can use more keystrokes, I found it more agile and fun overall.
If you choose to go the route of remapping these:
nnoremap k gk
nnoremap j gj
here are a couple others along the same lines:
nnoremap 0 g0
nnoremap $ g$
nnoremap ^ g^
I recently started using a plugin that I find really nice to move very quickly inside a line (or the whole file).
The plugin's name is PreciseJump and you can find it here.
When you use this plugin it defines to mappings _f and _F.
If you type _f followed by x it will highlight all x characters and will replace temporarily with other characters that you can press to jump to that location. Check the script page for an illustration.
You can also move around with W B that will skip to the next space :)
G moves to the end of the document
Please notice that using "g" followed by Up or Down arrows indeed works fine, but if you have long lines and move quickly you may enter "gg" by mistake and end-up at the top of the text...! (Undo will not bring you back, and AFAIK there is not one-key-pressed way to go back to where you were.)
It happened to me too many times.
What I did was, and I suggest you, to modify (or create) your "~/.vimrc" and add these two lines:
map <C-Up> g<Up>
map <C-Down> g<Down>
This will map you control-up and control-down to the movements commands. Will make mistyping "gg" impossible and is perfectly coherent with control-right and control-left to move around long lines.
If you add these other two lines, you can use the same command in insert mode (!)
imap <C-Up> <C-[> g<Up> i
imap <C-Down> <C-[> g<Down> i
(VIM is great !)
Greg Ruo

Automatically go to next line in vim

One frustrating behavior in vim is that when i move my cursor right or left (respectively "l" or "h)" and i am at the end or the beginning of the line, my cursor doesn't move to first column of next line or last column of previous line.
Is there a way to change this behavior ?
You can use the whichwrap setting to make h and l wrap around the start and end of individual lines:
set whichwrap+=h,l
However, Vim's documentation recommends against this, probably because it could have unexpected side effects (like breaking plugins, or changing how common key mappings work).
As an alternative, you can do what what Matti Virkkunen recommended:
set whichwrap+=<,>,[,]
This leaves h and l with their default behavior, but allows the left and right arrow keys to wrap around lines. (This is what I do, and it works well.)
You might also want to take a look at the backspace setting, to control how Backspace, Delete, Control+W, and Control+U work in Insert mode. I set mine like this:
set backspace=indent,eol,start
That allows me to backspace over pretty much everything.
For more info, see these topics in the Vim help:
:help 'whichwrap
:help 'backspace
Put the following into your .vimrc:
set whichwrap+=<,>,[,]

Is there a way to emulate ReSharper's "extend selection" feature in Vim?

ReSharper has a nice feature called "extend selection": by pressing CTRL+W (I think this is the default) repeatedly, you select more and more from your current caret location. First it's a word, then more and more words, a line, inner then outer block of lines (for example an if-block), then a function, etc...
Basically, by pressing the key combination repeatedly, you can end up selecting the entire file. I'm sure at least some of you will be familiar with it.
I have just started learning all the intricacies of vim and I don't have enough experience to see how something like this could be implemented in Vim (although I assume it's possible). So my question is meant for Vim gurus out there: can this be done and how?
Update: a bit of a background story. I've been talking to my ex-boss about all the benefits of Vim, and he thinks it's all great. His only question/problem was: does it have "extend selection"? My question so far has been no. So, if someone knows the answer, I'll finally win a discussion :P (and maybe create a new Vim convert:-))
I had a quick go at this problem. It doesn't work as is. Feel Free to make edits and post on the vim wiki or as a plugin if you get it refined.
chances are you'd want to make a g:resharp_list for each language (eg. one for paranthesised languages, etc.)
All that is needed is a marker for the original cursor position :he markers and a timeout autocommand that resets the index.
"resharp emulator
"TODO this needs a marker
"also c-w is bad mapping as it has a lag with all the other-
"window mappings
"
let g:resharp_index = 0
let g:resharp_select = ['iw', 'is', 'ip', 'ggVG']
func! ResharpSelect()
if g:resharp_index >= len (g:resharp_select)
let g:resharp_index = 0
endif
exe "norm \<esc>v" . g:resharp_select[g:resharp_index]
let g:resharp_index = g:resharp_index + 1
endfun
nnoremap <c-w> :call ResharpSelect()<cr>
vnoremap <c-w> :call ResharpSelect()<cr>
"Something to reset on timeout. TODO this doesn't work
au CursorHold :let g:resharp_index = 0<cr>
The answer is yes. Once in Visual mode you can use all the regular navigation methods as well as some extra ones.
Some of my favourites? First hit v while in normal mode to get to visual mode then hit:
iw - to select the inner word. Great for selecting a word while excluding surrounding braces or quotes
w - hit multiple times to keep selecting each subsequent word.
b - select wordwise backwords
^ - select all from current position to beginning of text on line
$ - select all from current position to end of line
I'm sure others here could add to this list as well. Oh and don't forget Visual Block mode C-v try it out in vim with the above commands it works in two dimensions :-)
If you're talking about Vim (and you should be :-), you can start marking text with the v command, then you have all the standard cursor movement commands (and, as you know, there are a lot of them) which will extend the selection, as well as moving the cursor.
Then you just do whatever you want with the selected text.
See here for the gory details.
One would need to write a function that would save the current selection, then try increasingly wide selections, until the new selection exceeds the saved one or selects all text. Some possible selections are:
viW - select word
vis - select sentence
vip - select paragraph
viB - select text within the innermost brackets
v2iB - select text within the next most innermost brackets
ggVG - select all text
I think Jeremy Wall's heading in the right direction. And to get a little further in that direction, you might look at the "surround.vim" script from Tim Pope. A good description is available on github. Or, if you'd rather, get it from vim.org. It'll probably help you do some of the things you'd like to do, though it doesn't seem to have a feature for say, simply selecting within a tag. Let me know if I'm wrong.
Ultimately, what you'd really like is a hierarchy of enclosing text-objects. You should read up on text-objects if you haven't. A nice overview is here. Note that you can grab multiple objects in one go using counts, or do this iteratively (try vawasap}}} from normal mode).
You can also get scripts which define other text-objects, like this one that uses indentation to define a text-object. It'll work for many languages if you're formatting according to common standards, and guaranteed for python.
One annoyance is that the cursor ends up at the end of the visual block, so, for example, you can't easily select everything between some ()'s, then get the function name that precedes them...
...BUT, I just found in this post that you can change this behavior with o. Cool!
I suspect you'll find yourself more efficient being able to skip over intermediate selections in the long run.
Anyway, I'll be curious to see if anyone else comes up with a more general solution as well!
In Rider [on a Mac with VS Mac bindings with IdeaVim], I bind:
Ctrl+= to Extend Selection
Ctrl+- to Shrink Selection
Doesn't clash with any other bindings of consequence and doesn't require a v for mode switching, and easier than Cmd+Option+-> and Cmd+Option+<-
Putting it here as I always hit this question with any Rider Vim selection searches. If I get enough harassment, I'll create a self-answered "How to use Extend Selection with Rider Vim mode".

Resources