vim: command like f{char} but for series of chars instead of single char - vim

In vim I can navigate to char in current line using f{char} -- To [count]'th occurrence of {char} to the right. The cursor is placed on {char} (inclusive).
Lets look on next line:
from fmodule import futility
-- there are three words starting from f letter and assume that I want to jump to futils. To do it (with cursor at the beginning of line) I will execute 2ff, but instead I would really like to do something like f{fut} (providing first chars of word not single one).
What are the ways to accomplish this task?

You can use the / search as a motion, also in visual mode and in combination with a command like d. You need to conclude the search with <Enter>, as usual. In contrast to f, this will also find matches in following lines. Some consider this a feature (and change f accordingly via plugins), others don't like this. If you're in the latter camp, the following mapping will restrict the pattern to the current line automatically:
noremap <expr> <Leader>/ '/\%' . line('.') . 'l'
You might also want to define <Leader>? for the opposite direction.

Related

How to set the regex to "w", "e" and "b" keys in Vim?

Is there a way to define what vim should recognize as a word? I want to assign \w+ regex to all word key motions such as "w", "e", "b"... I can do it for normal mode like this:
nnoremap <silent> w :call search('\w\+')<CR>
but it doesn't work for visual mode and operator-pending modes. It would be great if there is a setting to do this.
From what I understand from your question, and the discussion on Kaz' answer, I think what you're looking for is Kana's smartword plugin: http://www.vim.org/scripts/script.php?script_id=2470.
You're going to have to check the documentation with :help smartword, but the short version is, if you install the plugin and map the built-in word mappings to the plugin ones...
map w <Plug>(smartword-w)
map b <Plug>(smartword-b)
map e <Plug>(smartword-e)
map ge <Plug>(smartword-ge)
... then the built-ins will skip any non-word characters along the way. I've been using this for many, many years, and I'm quite happy with the way it behaves.
For the lower-case motions like w and e, the definition of a "word" is controlled by the :iskeyword option; see the :help iskeyword on that. Basically it consists of a list of characters given as individual characters or ranges, separated by commas. I think that various syntax files tweak this for different languages, so that these commands move by identifiers. It doesn't look like you can specify a regular expression for this.
The upper-case motions like W and E don't look like they can be reprogrammed. Their definition of a "WORD" is nonblank characters separated by whitespace, plus that each empty line counts as a "WORD".
However, unfortunately, it looks like there is a behavior in effect whereby the iskeyword characters simply separate the input into sequences of iskeyword characters, non-iskeyword characters and whitespace. When the w and related commands are used, they skip whitespace, but visit both the iskeyword tokens and the non-iskeyword tokens.
Remapping using :map to just a / or ? keystroke sequence works in both visual and command mode:
:map w /\<\w/^M
:map b ?\</\w^M
:map e /\w\>^M
It works in both because the / and ? searches work in both modes. Of course, it's an ugly solution because it clobbers the current search pattern and if you have :set hls (highlightsearch) on, the tips/tails of the words highlight.
The above searches are not very satisfactory because of the way the anchoring operators are behaving. For instance, I can't get them to "land" on the a in something like {abc or (abc.
The following mappings work a better. Each triggers several searches. The /. and ?. searches are used as a trick to go to the
next or previous character, such that if we are on the last character of a line, we go to the first one on the next line and vice versa.
:map b ?\w^M?\W^M/.^M
:map w /\W^M/\w^M
:map e /\w^M/\W^M?.^M
There are still some quirks. For instance, a list of words like:
abc
def
ghi
contains no match for the non-word class \W. The matching has to include line endings. Moving forward, an improvement to the w one in this regard is to add a match for the line ending like this:
:map w /\(\W\\|$\)^M/\w^M
Note the double backslash before the pipe! The rightmost backslash escapes the pipe so the processing of the :map command doesn't treat it as a command delimiter. Then we are left with \| which is the regex operator for branching. In a similar vein, the other two mappings can be improved; I'm leaving that as an exercise.

How to move through words in camel-cased identifiers in Vim?

How to move the cursor before or after the first uppercase letter of a word in Vim?
My motivation is removing or selecting the first word of a camel-case identifier in code. For example, if the cursor is on the m character in the word camelCase, I can use the FcdtC sequence of Normal-mode commands to delete the camel prefix.
Is there a general way to jump to the next occurrence of an uppercase letter in an identifier?
In situations where approaches using only built-in Vim instruments are
preferred, the following search commands can be used.
For jumping to the next uppercase character:
/\u
For moving the cursor one character to the right of the next uppercase
character:
/\u/s+
or
/\u\zs
If one expects to use a movement like that often, one can always
define a key mapping for it as a shorthand, e.g.:
:nnoremap <leader>u /\u/s+<cr>
I don't think there is anything built-in.
As #ib. indicates, you can use a regular expression motion, but it’s not particularly easy to type. However, there is camelcasemotion plugin that adds the necessary motions, for this, as well as underscore seperated identifiers.
Updated Answer (using #ib.'s contribution)
"select from first char up to First uppercase letter ( after first char )
map ,b bv/[A-Z]<cr>h
Original Answer
Regarding jumping before and after the first uppercase letter—
You can map it if you want to.
"Before next uppercase letter
map ,A /[A-Z]<cr>l
"After next uppercase letter
map ,B /[A-Z]<cr>h
:D. Hope this helps. I'm reading your second question now.
Ok, read it. Now you can do this
bv,A
:D
I think I thought maybe "the vim way" to do it :
Vim allow us to define our own operator !
" movement mapping {
" Delete yank or change until next UpperCase
" o waits for you to enter a movement command : http://learnvimscriptthehardway.stevelosh.com/chapters/15.html
" M is for Maj (as in french)
" :<c-u>execute -> special way to run multiple normal commande in a map : learnvimscriptthehardway.stevelosh.com/chapters/16.html
onoremap M :<c-u>execute "normal! /[A-Z]\r:nohlsearch\r"<cr>
That way giving
DailyAverage.new(FooBarBaz)
If my cursor is on a (from DailyMesure) and I press dM It delete to A and give
Average.new(FooBarBaz)
It works with all command waiting for a movement (c y ........)
This snippet need to be improved because of bad highlight.

Vim whole word search - but faster

I know that to search for a whole word in vim you need to type:
/\<word\><CR>
Now, what I would like to do is to map this behaviour to ? (as I never search backwards, and if needed I could search forward and then NN). I.e. I'd like to type:
?word<CR>
and have the same result as above (vim searches the whole word). I've been fiddling around with vim commands and mappings for some weeks now, but I'm not sure about how to accomplish this one. Thank you for any help.
Update: (insead of ? I use \ now).
I tend to use * and # (as suggested by Brian Agnew), but if you want a method that involves typing
?word<CR>
you could do something like this:
function! SearchWord(word)
let #/ = '\<' . a:word . '\>'
normal n
endfunction
command! -nargs=1 SearchWord call SearchWord(<f-args>)
nmap ? :SearchWord
Note there is a space after SearchWord on the last line.
Explanation:
The mapping will make ? open up a command prompt and type SearchWord (including the space). The command makes SearchWord myword do the equivalent of call SearchWord('myword') (i.e. it puts the quotes round the argument in order to make it into a string). The function sets the search register #/ equal to your word surrounded by \< and \> and then does a normal-mode n to find the next instance of the contents of the search register.
Of course you lose the benefits of incremental searching if you do this, but hopefully it's useful anyway.
You can search for words under the cursor using * and # (forwards and back). g* and g# will do the same but finding words containing what's under your cursor initially.
Obviously (!) you need to have found the first instance already for this to work, but it's very effective for successive searches.
Al's solution is very nice, but wouldn't it be simpler to just enter the \<\> pattern, then move the cursor back twice? This works for me:
nmap ? /\<\><Left><Left>
This way you still get incremental search (kinda).

Vim: Split Words Into Lines?

I frequently use Shift+J in visual mode to join several selected lines into a single line with the original lines separated by spaces. But I am wondering if there is an opposite shortcut such that it will split selected words into separate lines (one word per line).
Of course I can do:
:'<,'>s/ /^M/g
But something more succinct in terms of keystrokes would be very useful. Has anyone else found a way to do this?
Thanks in advance,
-aj
Map it if you are using it often in your ~/.vimrc file or similar
vnoremap \ll :'<,'>s/ /^M/g<cr>
nnoremap \ll :s/ /^M/g<cr>
if you are only wanting to to it multiple times now you can use & command to repeat last search also
Theres also gqq but thats for textwidth eg 80 chars
Recently I stumbled across the same problem. My solution is the following vim function (put in my .vimrc):
function SplitToLines() range
for lnum in range(a:lastline, a:firstline, -1)
let words = split(getline(lnum))
execute lnum . "delete"
call append(lnum-1, words)
endfor
endfunction
This can be used with line ranges, e.g., as follows
:26call SplitToLines()
which would split line number 26. But the code also handles ranges of lines gracefully (that's why the range in the for loop is built in reverse order).
1,10call SplitToLines()
will split lines 1 to 10 into several lines. However, I mostly use this in visual mode, like
'<,'>call SplitToLines()
which splits all lines that are visually marked. Of course you may define some single letter abbreviation for this function call (with auto completion by Tab I do not find it necessary). Also note that by adding an additional argument which would also be used by 'split' you can have a function that does split lines at specific patterns (instead of just white space).
I use this in my config to Un-Join/split the last word on current line:
nnoremap <C-J> g_F<Space><Space>i<CR><Esc>k
It maps CTRL-j to do the opposite of Join, I think of it as Counter-Join :) I mostly use it to convert between K&R style vs ...the other kind of curly brace placement.
g_ : search for the last non-whitespace on current line
F<Space> : reverse-find first space
<Space> : go one character forward
i : enter insert mode
<CR> : insert a line break
<Esc> : return to normal mode
k : go up one line to where we begun

Vim copy and paste

My previous question seems to be a bit ambiguous, I will rephrase it:
I have a file like this:
copythis abc
replacethis1 xyz
qwerty replacethis2
hasfshd replacethis3 fslfs
And so on...
NOTE: replacethis1, replacethis2, replacethis3, ... could be any words
How do I replace "replacethis1","replacethis2","replacethis3",.. word by "copythis" word by using minimum vim commands.
One way I can do is by these steps:
delete "replacethis1","replacethis2","replacethis3",.. by using 'dw'
copy "copythis" using 'yw'
move cursor to where "replacethis1" was and do 'p'; move cursor to where "replacethis2" was and do 'p' and so on...
Is there a better way to do this in VIM (using less number of vim commands)?
Since you changed your question, I'd do it this way:
Move to the first "replacethis1" and type cw (change word), then type "copythis" manually.
Move to the next "replacethis", hit . (repeat last operation)
Move to the next "replacethis", hit .,
and so on, and so on.
If "copythis" is a small word, I think this is the best solution.
The digit needs to be included, and there could be more than one instance per line:
:%s/replacethis\d/copythis/g
Given that "replacethis[1-3]" can be arbitrary unrelated words, the quickest/simplest way to do this globally would be:
:%s/replacethis1\|replacethis2\|replacethis3/copythis/g
(Note that you need to use \| to get the pipes to function as "or". Otherwise, vim will look for the literal | character.)
I've been struggling with this for a long time too, I think I just worked out the cleanest way:
Use whichever command is cleanest to put copythis into register r:
/copythis
"rye
Then go to the replacement and replace it with the contents of r:
/replacethis
cw<CTRL-R>r<ESC>
Then you can just n.n.n.n.n.n.n. for the rest of them, or if they're wildly different just go to the beginning of each and hit .
The key is replacing and pasting in one step so you can use . later.
:%s/copythis/replacethis/g
To replace all occurrences of copythis with replacethis. Or you can specify a range of line numbers like:
:8,10 s/copythis/replacethis/g
Note, the /g on the end will tell it to replace all occurrences. If you leave that off it will just do the first one.
create this mapping:
:map z cwcopythis^[
( ^[ is the escape character, you can type it in vim using Ctrl+V Ctrl+[ )
go to each word you want to replace and press z
if u need to do essentially the same action multiple times - swap 1st word of one line with second word of the next line, I say you could record a macro and call it whenever you need to
Have you tried string replacement?
%s/replacethis/copythis
A host of other parameters are possible to fine-tune the replacement. Dive into the Vim help for more details. Some more examples here.
You can remap e.g. the m key in normal mode to delete the word under the cursor and paste the buffer: :nnoremap m "_diwP.
Then you can just copy the desired word, move the cursor anywhere onto the to-be-replaced word and type m.
EDIT: Mapping to m is a bad idea since it is used to mark locations. But you can use e.g. ; anyway.

Resources