Vim shortcut for unindenting till the start of the line - vim

So I'm aware that you can unindent a line with the shortcut Shift+, (or <) and that you can repeatedly apply it by pressing a number before the shortcut -- for example, 5 + < will unindent 5 times.
Is there a way to repeatedly apply unindent until it reaches the start of the line?

One option is ^d0: move to the start of the indented line, then delete to the start of the entire line.
Sometimes it’s just easier to << then mash . to repeat, though.

Moving to the :left
You can move lines to the left with :left . This will remove all indention.
:left
See :h :left for more information.
Putting with indentation
I often find myself wanting to move/cut a block of code and put/paste with the current line's indention level. This can be done with ]p & [p.
Example:
def foo():
pass
if x == 'bar'
print "hello world"
Assuming you are on the if line you can do the following:
dj]p
This will put/paste the block inline with pass yielding:
def foo():
pass
if x == 'bar'
print "hello world"
Note: ]p & [p need the register to be linewise for this to work correctly or use unimpaired.vim
For more help see::h ]p & :h linewise

Related

Jump to current function declaration from middle of function

Is there a way to jump to the signature of the function my cursor is currently in, then jump back to where I was?
For example, when I have a 1000 line function, where the prefix x + y: refers to line numbers, is there a way from me to jump from my cursor location at x + 555 to the signature at x + 0 then back to where I was at (x + 555):
x + 000: void theFn(int arg) {
x + ...: ...
x + 555: /// where my cursor starts
x + ...: ...
x + 999: }
And, yes, I couldn't agree with you more that there shouldn't be 1000 line functions.
Also, is there a way to automatically jump to the end of function without being at the opening bracket of the function?
Useful motions in such case are [[, ][ and <C-o>.
As we can read in help:
*[[*
[[ [count] sections backward or to the previous '{' in
the first column. |exclusive|
Note that |exclusive-linewise| often applies.
*][*
][ [count] sections forward or to the next '}' in the
first column. |exclusive|
Note that |exclusive-linewise| often applies.
*CTRL-O*
CTRL-O Go to [count] Older cursor position in jump list
(not a motion command).
{not available without the |+jumplist| feature}
In short:
[[ to got to the beginning
<C-o> to go back to previous place
][ to go to end
Those motions will have the desired effect only when braces are in the first column, but from your example seems like this requirement is not met.
In such case at the end of :h section we can read:
If your '{' or '}' are not in the first column, and you would like to use "[["
and "]]" anyway, try these mappings: >
:map [[ ?{<CR>w99[{
:map ][ /}<CR>b99]}
:map ]] j0[[%/{<CR>
:map [] k$][%?}<CR>
Unfortunately, Vim doesn't offer better solution as it doesn't parse syntax.
It may change though as Neovim experiments with Tree-sitter.
It also wouldn't be surprising if there was a plugin which provides better support for such motion.
Tagbar could fit this role:
Toggle Tagbar window
Switch to it
Cursor should be already over the current tag
Press enter
Toggle window
You are at beginning of the function
Use <C-o> to get back
I also once found and had in my config a mapping which could also be useful in such case:
nnoremap <Leader>gd ?\v%(%(if|while|for|switch)\_s*)#<!\([^)]*\)\_[^;(){}]*\zs\{

How to multi-line the import functions in {} in VIM?

Sorry for the bad title but
With this code,,,
import { amethod, methodb, methodc } from '../../utils/mockData';
how do you make this
import {
amethod,
methodb,
methodc
} from '../../utils/mockData';
with VIM? I mean how can I do it fast?
What I do is to
go to the first method.
press Enter
go to the end of the method..
press Enter...
go to the second method.
6....
...
It's so slow with VIM. Can we do this fast in VIM? I think I can this much faster with my mouse :(
import { amethod, methodb, methodc } from '../...';
^
f ;r<CR>;.;.;.
doesn't strike me as particularly slow. A tad too repetitive, maybe?
Here is a slightly smarter (but probably not that smart) approach:
ciB " change in brackets
<CR><CR> " insert two carriage returns
<Up> " move up one line
<C-r>" " insert previous content of brackets
<Esc> " leave insert mode
:s/,/,\r/g<CR> " put each symbol on its own line
=iB " re-indent the content of brackets
that can be mapped for convenience:
nnoremap <key> ciB<CR><CR><Up><C-r>"<Esc>:s/,/,\r/g<CR>=iB
Or you can look for a proper plugin that handles corner cases gracefully.
#romainl had a good answer, but you can also use replace for this particular case:
:%s/\([,{]\)/\1\n/g
With the cursor on line1 and col1, you can press this in normal mode:
f 4#=';r^M'
then press ENTER.
Note: for the ^M you press Ctrl-v then Enter
I have got this
import {
amethod,
methodb,
methodc
} from '../../utils/mockData';
Using this:
:%s/\v\{\zs( \w+,?)+ \ze}/\=substitute(submatch(0), " ", "\n\t", "g")
\v ............ very magic regex (avoid many backslashes)
{ ............ literal {
\zs ........... vim trick that marks the start of the pattern
( ............ start of regex group 1
<Space> ....... literal space inside group 1
\w+ ........... one word or more
,? ........... optional coma
+ ............ quantifier for the group (at least one)
<Space>
\ze ........... end of our vim search
The substitute function has three parts like a normal vim substitution and the submatch(0) corresponds to our regex, hence we are substituting in our regex one space for one line breake and two tabs.

Quickest way to switch order of comma-sparated list in Vim

Supose I have a function such as
myfunc(arg1 = whatever, arg2 = different)
I would like to transform it to
myfunc(arg2 = different, arg1 = whatever)
What is the quickest command sequence to achieve this? suppose the cursor is on the first "m". My best attempt is fadt,lpldt)%p.
There is a vim plugin: vim-exchange
visual select arg1 = whatever
press Shiftx
visual select arg2 = different
press Shiftx
I would recommend you change it a bit so it will work from wherever the cursor is and so that it will work on any arguments:
0f(ldt,lpldt)%p
All I changed from your method was I added 0 to move the cursor to the beginning and I changed fa to f(l so that it will work regardless of argument name.
Now you can either put this into a macro, or, if you use it a lot, you can make it a mapping:
nnoremap <C-k> 0f(ldt,lpldt)%p
I arbitrarily chose Ctrl-k here put you can use whatever you like.
I wrote a plugin for manipulating function arguments called Argumentative. With it you just execute >, and the argument your cursor is on will shift to the right. It also provides argument text object in the form of i, and a,.
With pure vim, with your cursor at the start of the line:
%3dB%pldt,lp
This is the quickest I could think of on the spot (12 strokes).
This should work for all names as long as there is always a space around the equal signs.
% " Jump to closing brace
3dB " Delete to the beginning of 3 WORDS, backwards
% " Jump to the beginning brace
p " Paste the deleted text from the default register
l " Move right one character
dt, " Delete until the next comma
l " Move right one character
p " paste the deleted text from the default register
You could also turn this into a Macro to use at any time.

Mark a block of characters in VI/M ex command

It's quite straitforward for VI/M to mark a block of lines from Mth line to Nth line ready to delete, cut & past, or copy & paste.
:M,N d
:M,N m p
:M,N t p
If it's further required for VI/M to mark a block of characters from Ith character of Mth line to Jth character of Nth line, is it possible to accomplish similarly to the above?
#EDIT
Except the next answer asked for visual block mode, how about the option on typing a succinct ex command?
#EDIT 2
To clarify the meaning of a block of characters:
a square block of characters, addressed by visual block mode, directly called upon by pressing Ctrl-v in normal mode
a zipzag area of successive characters, addressed by visual character mode, directly called upon by pressing v in normal mode
a rows region of successive lines, addressed by visual line mode, directly called upon by pressing V in normal mode. In this case, the handy solution in ex mode has been illustrated above when this topic was originally raised.
#SOLUTION
Selecting abitrary zipzag area of successive characters from line M, column I to line N, column J in ex mode exactly like in visual character mode :
mark:
:normal! MggI|vNggJ|
delete:
:normal! MggI|vNggJ|d
yank:
:normal! MggI|vNggJ|y
move to line X column Y
:normal! MggI|vNggJ|dXggY|p
copy to line X column Y
:normal! MggI|vNggJ|yXggY|p
#SOLUTION 2
Selecting abitrary square block of characters from line M, column I to line N, column J in ex mode exactly like in visual block mode :
mark:
:execute "normal! MggI|\<C-v>NggJ|"
delete:
:execute "normal! MggI|\<C-v>NggJ|d"
yank:
:execute "normal! MggI|\<C-v>NggJ|y"
move to line X column Y
:execute "normal! MggI|\<C-v>NggJ|dXggY|p"
copy to line X column Y
:execute "normal! MggI|\<C-v>NggJ|yXggY|p"
You can use visual block mode from an ex command mode using normal!: for example, to select a block (line, column) from (42, 10) to (54, 20) and yank it (both lines must have at least 20 characters or virtualedit=block should be set):
execute "normal! 42gg10|\<C-v>54gg20|y"
. It is very straightforward way to do this, useful only in scripts.
Note that this command has at least following side-effects:
Setting marks '<, '>, '[, '], ''.
Moving a cursor.
Changing registers #", #0.
Adding one item to the jumplist.
Overwriting previous visual selection.
Altering v:count and v:count1 variables.
Ctrl+V enables visual block mode, then you can use the arrow keys to select the block.

How can I quickly add something to a few lines in vim?

I'm trying to get away from my arrow use but there is one thing I've yet to solve without using the arrow keys. Take this example:
var1 = "1"
var2 = "2"
var3 = "3"
var4 = "4"
Now I want this to be:
var_1 = "1"
var_2 = "2"
var_3 = "3"
var_4 = "4"
Using arrows I would just goto the var1, insert and add the underscore and then arrow down and do the same thing. The problem with using hjkl is I can't be in insert mode so I have to esc out, move down, insert...rinse repeat which required more work. Is there another way to accomplish this?
You can also use a visual block insert:
go to the "1" in "var1"
press CTRL+V
go down with j to select all the rows you wish to affect
I (that's capital i)
_
<ESC>
The underscore should now be inserted at the correct place in all the rows selected (for some reason it takes a second for it to happen on my machine)
There are many ways to do this. Using movement commands for example:
1G0 → Go to the start of the first line
f1 → go to the first occurence of "1"
i_<ESC> → insert "_" and go back to normal mode
j. → go down a line and repeat the insert command
j. → go down a line and repeat the insert command
...
Or, better yet, use an "ex" command:
:%s/var/var_/
Or even with the visual block command, as johusman notes.
Assuming you're at line 1, character 1...
Using a macro:
qqfra_<Esc>+q3#q
q Record macro
q Into register q
f find
r 'r'
a append
_ underscore
Esc Normal mode
+ Start of next line
3 Three times
# Play macro
q from register q
Par 11.
Or (better) using substitute:
:%s!r!&_<CR>
Par 9!
[Sorry... too much VimGolf!]
I tend to prefer :substitute over the visual block mode.
%s/var\zs\ze\d/_/
I always have line numbers turned on, so I'd do e.g.
1,4 s/var/var_/
This is similar to the
% s/var/var_/
answer, but it only functions on the named lines. You can use visual mode to mark the lines, if you don't like typing the range (the 1,4 prefix) in your command.

Resources