Vim: Repeat previous motion? - vim

Let's say that I'm in visual mode, and I type "aw" to extend the visual area to include the next word. I'd like to then include the next couple of words. Is there a single key that I can press to repeat the previous motion (include text object motions)?
I'm aware that '.' repeats the previous change, and 'n' repeats the previous search, amongst other 'repeat' commands, but I'm unaware of any command to repeat the previous motion (whatever it was).

Well there is a command to repeat every motion made with f,t,F or T
Remember that
fx takes to the next occurrence of the character x
Fx takes to the previous ocurrence of x
tx takes you to the character before the next occurrence of x
Tx takes you you to the character after the previous occurrence of x
to repeat those motions press
;
to repeat them backwards (in the oposite direction) press
,

There are some plugins that provide this functionality:
repmo.vim: repeat motions for which a count was given
repeatable-motions.vim: Make most motions repeatable
repmo.vim: give vim support of repeat motion operations (k,j, h,l, w,b, W,B, e,E, ge,gE)

Instead of repeating the motion, there is a plugin for expanding regions via + and shrinking _: https://github.com/terryma/vim-expand-region

NO PLUGINS use ;.
Here's a detailed example:
int function1(){
some code here;
...
...
return 0;
}
int function2(){
some code here;
...
...
return 0;
}
Now let's say you want to rewrite the part inside {} for function1 and function2.
Place your cursor somewhere inside the {}
From Normal Mode (ESC or ctrl+c), press di} (for "delete" "inner" "{")
Now you've deleted everything in the function
Now bring your cursor inside the {} of function2
Press ;.
For visual mode, I think macros is your only option (maybe overkill for aw)
To start recording a macro, press q + q (that last q can be any letter. It's where you macro will be saved)
... do the actions you want to repeat ...
Press q again to stop recording
To replay these actions (even in visual mode):
#q (or whatever letter you saved it to)
To replay the actions 99 times:
99#q (or whatever letter you saved it to)

Related

Changing case at the end of a word in Vim

I know gUw will turn properties to PROPERTIES and stay at the first character of the word.
But if I use gUb, it will be PROPERTIEs and cursor at the first charactoer.
If I use gUge, it will be PROPERTIES but cursor at last word.
What should I do if I want to turn the word to upper case, and stay at the end of the word(so that i can keep on typing without a w)
All operator+motion edits will leave the cursor on the first character of the motion. From :help motion.txt:
After applying the operator the cursor is mostly left at the start of the text that was operated upon. For example, "yfe" doesn't move the cursor, but "yFe" moves the cursor leftwards to the "e" where the yank started.
So, assuming your cursor is on the last character of the current word:
properties
^
there is no built-in way to ensure that the cursor will stay there after an operator+motion edit.
One can leave a mark and jump back to it after the edit:
m'gUiw``
but that's more work than just pressing w. It could be turned into a mapping, though, if that's a common need:
nnoremap <key> m'gUiw``
but that doesn't sound very scalable.
Another approach would be to record your edit:
qq
m'gUiw``
q
and play it back as needed:
#q
But your last sentence is puzzling:
What should I do if I want to turn the word to upper case, and stay at the end of the word(so that i can keep on typing without a w)
If you are at the end of:
properties
^
and your edit leaves the cursor at the beginning of:
PROPERTIES
^
w will move the cursor to the beginning of the next word:
PROPERTIES foo
^
and not to the end of the current word.
We are missing some context, here.

Undo cursor movement in Vim

Let's say I have my cursor lying in the code below:
internal static SingleSelectList<Country, int> CreateCountrySingleSelectList(List<Country> countries, List<Airport> airPorts)
And the cursor is in the head of the line. Now I want to move my cursor to the second < of this line of code, which is in the WORD List<Country>, and just doing the key sequence of f<; will bring me there.
But what if I did something wrong by pressing another ;, that will bring me to the next < in the line, which is in the word List<Airport>.
In this situation, how can I get back to the second < using the minimum key strokes?
Is there a fastest way to undo cursor movements, instead of F< or pressing the key hfor a very long time?
Try CtrlO to go back in cursor history.
http://www.rosipov.com/blog/open-previously-edited-file-in-vim/
The reversible action of ; is , so the answer to your question would be to use , one time.
You can look up what the command does by :h ;
; Repeat latest f, t, F or T [count] times.
, Repeat latest f, t, F or T in opposite direction
[count] times
Contrary to Ruslan Osipov's wrong answer, the f motion does not store the previous position in the jump list (only motions that usually go to non-adjacent lines do).
But nothing prevents you from explicitly setting a jump yourself with m'. Then, you can return to that position via ``, or <C-O>.

How do I repeat the last n changes in Vim?

Doing . repeats the last change. Doing 2. repeats the last change two times.
But imagine I want to repeat the change before the last one. How do I do it in Vim?
Don't think you can, see :help . However, what you can do is to record a macro for your edits, you have a lot of registers to choose from {0-9a-zA-Z"} (uppercase to append).
Then use e.g. #u for edit 1, #t for edit 2 and so on.
Great tips about recording from Best of VIM Tips
" Recording (BEST TIP of ALL)
qq # record to q
your complex series of commands
q # end recording
#q to execute
## to Repeat
5## to Repeat 5 times
qQ#qq : Make an existing recording q recursive *N*
" editing a register/recording
"qp :display contents of register q (normal mode)
<ctrl-R>q :display contents of register q (insert mode)
" you can now see recording contents, edit as required
"qdd :put changed contacts back into q
#q :execute recording/register q
Have a look at these for more hints for repeating:
:& last substitute
:%& last substitute every line
:%&gic last substitute every line confirm
g% normal mode repeat last substitute
g& last substitute on all lines
## last recording
#: last command-mode command
:!! last :! command
:~ last substitute
:help repeating
I wrote the RepeatLast.vim plugin to address this exact requirement. It provides a 5\. key binding to repeat the last 5 changes (including movements) and 2\D to drop/forget the last 2 actions.
It works by enabling macro recording all the time, which may not be desirable for everyone. But if you can live with that, it works in 99% of use cases.
Latest version: https://github.com/joeytwiddle/RepeatLast.vim (Please feedback!)
Caveats:
Please :set ch=2 so that the first line of output won't be hidden by the "recording" message.
The 1% of times it fails to work as intended are usually due to:
Difficulties triggering the CursorHold event slowly without losing
fast-repeated keystrokes
Undesirable recording of [Space] and
[Enter] keys when the user is responding to a prompt.
Training your q muscle to pre-emptively record macros might be a better approach in the long term. ;-)
Based on Fredrick Phil's answer, here is an example:
Recording your macro
The following shows how to record a macro to delete everything in and including a quoted string and store in register d. The command to delete a string is da". So to store this command in macro register d we can simply do this:
qdda"q
Notice it starts and ends with a q. The second character is the register, in this case d for delete. But we could have given it any letter or number. The remaining characters da" is our command.
Using our macro
Now that our macro is recorded we can invoke it by using the # symbol followed by the register:
#d
Repeating the last macro command
To use the most recently invoked macro command again:
##
Unrelated info:
In this example, we used da" which stands for delete a quoted string. (If you instead wanted to delete everything inside the quoted string, but not the quotation marks themselves you can instead use di" instead.).
Record Your "Edits"
yes! you can do this in vim! 😎
One of Vim's most useful features is its ability to record what you type for later playback. This is most useful for repeated jobs that cannot easily be done with .
To start recording
press q in normal mode followed by a letter (a to z)
That starts recording keystrokes to the specified register. Vim displays recording in the status line
Type any normal mode commands, or enter insert mode and type text
To stop recording
ending in normal mode, come to normal mode if you are not, and press q
ending in insert mode, press Ctrl+O, this will temporarily get you into normal mode, and then press q
To playback your keystrokes/recording
press # followed by the letter previously chosen
Typing ## repeats the last playback
References
Vim Fandom: Recording keys for repeated jobs
Vim Fandom: Macros
Quora - How do you stop recording a Vim macro when in insert mode?

Enclosing the function call in another function call (retval as parameter)

Having this LOC:
printf("%s (%d)\t(%d)\t%d-%d\t", meta_scanner_token_name($ret['major']), $ret['major'], (string)$ret['dirty'], $ret['start_line'], $ret['minor']);
What is the fastest way in terms of key strokes to enclose the call to meta_scanner_token_name in another function call to foo, yelding:
printf("%s (%d)\t(%d)\t%d-%d\t", foo(meta_scanner_token_name($ret['major'])), $ret['major'], (string)$ret['dirty'], $ret['start_line'], $ret['minor']);
given that
first scenario: my cursor is on 'm' at the beginning of the function?
second scenario: my cursor is somewhere on meta_scanner_token_name?
va)oB would select the entire line, and ys%) would enclose only the m, resulting in:
... (m)eta_sca...
Please answer to both scenarios.
(I am using spf13-vim with default settings except some visual changes, if that has any relevance)
ifoo(<Esc> then f)i)<Esc>
bifoo(<Esc> then f)i)<Esc>
but I'm still a Vim noob
-- EDIT --
I see "Surrounding.vim" is a modified version of "Surround.vim" if it's compatible with Surround you can do:
Scenario 1
vt,sffoo<CR>
vt, to select everything until the first ,
s to launch Surround.vim
f to instruct Surround to input a "function"
foo the identifier
<CR> Enter key.
That's 6 keystrokes not including typing foo which — I think — can't really be avoided.
Scenario 2
bvt,sffoo<CR>
It's the same as scenario 1 except that you type b first to go back to the first letter of meta_scanner_token_name.
Using normal vim you could do this (prefix with b for scenario 2)
`cf)foo()<esc>P`
If your vim plugins add the closing paren for you, you can drop that from the sequence. Depending on where it leaves your cursor, you might need to use p instead of P.

Vim: replacing text within function body

I have some very useful plugins to find and replace text through files (see EasyGrep vim script - it's very helpful for programmers). I can even replace text only in the current buffer - by using plugins or :%s .... But what if I just want replace text within the current function body?
Consider the following example:
void f0()
{
int foo = 0;
// ...
}
// 99 other functions that uses foo as local variable.
void f100()
{
int foo = 0; // I want to replace foo with bar only in this function
// 1000 lines of code that uses foo goes below
// ...
}
Of course, I can use :%s ... with c flag for confirmation, but I believe there is a faster way to do this.
Thanks.
You can apply a substitution to the whole file using % or on a selection.
To create a selection :
Go in Visual mode Linewise for example, with Shift+v, select a few line and then type :.
Your prompt will look like :
:'<,'> it means : current selection
Type then s/foo/bar/g and it will replace foo by bar in the current selected line.
The better way to select a function content is to go inside a function with your cursor and type :
vi} it will select everything between { and }.
See :help text-objects for more tips on selection.
You could mark the function with V. Then when you type a command in :, it'll automatically be prefixed by and only be executed in the marked area.
There's probably a command for jumping to beginning of function and end of function, so you could do begin-function, V, end-function, substitute very quickly. Don't know those commands though.
I've always used [[ to jump to the beginning of the function, then use % to jump to the end of the function. I used mt and mb to mark the top and bottom of the function, respectively. Then to search and replace within the marked top and bottom, :'t,'bs/pattern/newpattern/g. This has always worked for me. I'm sure you can create a macro for this.
The visual select (vi}) is much easier and faster. It is aware of the cursor position. So, if the cursor is inside a fucntion sub block, then vi} selects all lines in that block. If you want to select the entire function, one needs to place the cursor outside of the sub blocks then do vi}. This is great for function blocks that fits in the current window. For functions that spans beyond the current window, the selection is lost once scroll up.
I really like the visual select of the vi} because it's so much easier and faster, but I have to resort the old school method on occasion.

Resources