Jump to current function declaration from middle of function - vim

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\{

Related

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.

Vim shortcut for unindenting till the start of the line

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

variable search and replace in vim

I have a list of items that I want to add a method call to. An example is easiest. Here's what I have now:
assists: 12,
level: 14,
deaths: 5,
...
I want to change that list to look like this:
assists: build_average(:assists),
level: build_average(:level),
deaths: build_average(:deaths),
...
Is it possible to add that method call to the end of every line with the name of the key as the argument with a neat Vim expression?
More of a regular expression:
:%s/\(\w\+\):.\+/\1: build_average(:\1),/
Note that this applies to all lines in your file. To only replace in a region, select the region (using V) and then use :s (which results in :<,>s/...).
Using more complex regular expressions in VIM can be tricky, because metacharacters are different from "normal" regular expression syntax (you need to write \+ instead of +, but can use . without escaping it, for example). I found this guide very handy to refer to the special VIM-syntax of regular expressions: http://vimregex.com/#pattern
Alternatively you can record a macro:
q // record macro
q // assign it to letter 'q'
0 // go to start of line
/:<ENTER> // search for ':'
l // move cursor 1 position to the right
d$ // delete to end of line (line is now 'assists:')
yyp // duplicate current line (cursor moves 1 line down)
k // move cursor up
A build_average( // append " build_average("
<ESC> // exit edit mode
J // join next line
A ), // append " ),"
<ESC> // exit edit mode
j // move 1 line down
q // stop recording macro
2#q // execute macro 'q' 2 times
More regexp gymnastics:
:%s/\v(\w+):\s+\zs.*\ze,/build_average(:\1)/
Decrypting it:
:help \v
:help \w
:help \s
:help \zs
:help \ze
:help \1

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.

Jump to the end of a long list of repeated pattern

I have a big file with a lot of lines that share the same pattern, something like this:
dbn.py:206 ... (some other text) <-- I am here
dbn.py:206 ... (some other text)
...
(something I don't know) <-- I want to jump here
Is there a quick way in Vim to jump to the place where the succession of dbp.py:206 ends?
/^\(dbn.py\)\#!
Matches first line which does not start with the text inside the escaped parentheses.
If you want quick access to this you could add a vmap which yanks the visually selected text and inserts it in the right spot (but first escaping it with escape(var, '/').
Try this vmap: vmap <leader>n "hy<Esc>/^\(<C-R>=escape(#h,'/')<CR>\)\#!<CR>
Press n when visually selecting the text you wish to skip and you should be placed on the next first line which does not begin with the selection.
I just write a function to select identical lines:
nnoremap vii :call SelectIdenticalLines()<CR>
fun! SelectIdenticalLines()
let s = getline('.')
let n = line('.')
let i = n
let j = n
while getline(i)==s && i>0
let i-=1
endwhile
while getline(j)==s && j<=line('$')
let j+=1
endwhile
call cursor(i+1, 0)
norm V
call cursor(j-1, 0)
endfun
type vii to select identical lines (feel free to change the key-binding)
type zf to fold them.
type za to toggle folding
It's handy when you want to squeeze several empty line.
It acts like C-x C-o in emacs.
One option is to go to the bottom of the file and search backwards for the last line you want, then go down one:
G ?^dbn\.py:206?+1

Resources