goto definition (gd) while inside function call - vim

If I am editing a function call like:
many_params(param1, "a long...string", p|aram3); // Cursor located at |
Then typing gd will jump to the definition of param3, not many_params. What is the most efficient idiom for moving the cursor to many_params, without using ^.
To clarify, please do not answer with ^, because I want an idiom that is also compatible with:
// Lets jump to func3's definition
func1(func2(123, "aaaaa"), func3("bbbbb", 3|, 4, 5));

The only idea I have is to:
go to the left opening parenthesis - F(
move one word backwards - b
so the command is F(b. However it won't work with text like func1("abc(d", 222|2)

It feels a bit dirty to me, but you can handle nested parentheses as well with ya(h. Note that this yanks the parenthesized bits to your yank buffer, which may not be desirable, but you would work around that by mapping to "_ya(h. This will go to the open paren of the enclosing parens, and subsequent executions of it will go to subsequent levels of parenthesization. I don't know of another way to get to the enclosing parentheses without being interrupted by intervening parentheticals.
If you're using this, you need to use the h instead of b in case you have multiple parentheses in a row. ...but then again, maybe the behavior with b would be desirable.

Related

Insert visual vim selection in the line below at the same position

I have a tedious task of converting chords from leadsheets into an inline format.
The format I have
G A
Never gonna give you up
F#m Bm
Never gonna let you down
G A F# Bm
Never gonna run around and desert you
And the format I need would b
Never gonna g[G]ive you [A]up
Never gonna l[F#m]et you do[Bm]wn
Never gonna r[G]un a[A]round and d[F#]esert [Bm]you
The problem with a script in Ruby or Python is, that the format isn't very consistent. So there could be newlines, weird characters, sometimes the chords are seperated with a dash... I haven't looked through all of the files, but I suspect more malformed stuff.
So I thought, if I have to go through of every leadsheet by hand, at least I can save some time using vim. This is the mapping I've come up with so far:
nmap <C-X> viWc[]<ESC>PviWx<down>p
Select the chord: viW
delete it and go into insert mode: c
add brackets
exit insert mode: <ESC>
paste the register to the left: P
select the chord again, including the brackets: viW
delete the selection: x
move cursor down, and paste it: p
But I few things I can't figure out is:
Sometimes the chords already have brackets, then I don't want to surround them with more brackets. Any idea how to only add brackets, if the chord isn't already surrounded with them?
It would be cool to do this with whole lines of chords. Sometimes there are multiple chords on the same line, and selecting them one by one is tedious. Any idea on how to operate the mapping above on a whole line?
well point 1 could be solved by adding the brackets around the chords on every second line:
:g/^/s/\[\=\zs[a-zA-Z#]\+\ze]\=/\[\0\]/g|+t+|-d
Credits: https://vi.stackexchange.com/questions/34785/search-and-replace-on-odd-even-numbered-lines-using-g
This however sucks, because it moves arround the chords, so we have to remove all brackets first and replace them with space
:%s/\[\([a-zA-Z#]\+\)\]/\1 /g
Then we can do the first line again, but remove some space too. Since there are no brackets left, it gets simpler (Note we use other brackets to get ride of some side effect the following code has):
:g/^/s/\([a-zA-Z#]\+\) \{0,3\}/\{\1\} /g|+t+|-d
Also we add a trailing whitespace at the end of the line so that the df} command will not move the cursor to a wrong place
Now that we have curly brackets everywhere, we can use reverse search with ?{ and then create a macro that jumps from results to result and moves it down, replaces the curly brackets with normal brackets and then calls itself (recursive macro):
gg0
qqq
?{<CR>
qq
df}jPr]F{r[n#qq
#q
And nearly all should be done.
The result:
Never gonna g[G]ive you [A]up
Never gonna l[F#m]et you dow[Bm]n
Never gonna r[G]un a[A]round and d[F#]esert [Bm]you
Note, we have to search backwards (? instead of /) so we can delete the chords directly.
If you have problems understanding what I did, feel free to ask.

How to quickly navigate function arg lists in vim

I have the following function definition:
def test(these, are=0, args=1):
pass
I want to find a quick and intuitive way to hop between each argument.
For example, pressing w/b is too slow because it will hit the commas, but even worse it is it will hit the =. W/B works great except with that first argument because test(these is a "WORD".
Is there an existing way to navigate this list that works the same for all arguments, or is there a common modification to do this? For example, can I redefine what a WORD is and make the (/) break up a WORD? I can't think of a good example of when I would have a legitimate WORD with a paren right in the middle.
The big complication with argument lists is complex expressions and nested function calls (e.g. foo(1, bar(2, 3), 4)). To handle those, at least some basic parsing is necessary; simple pattern matching (as can be done with built-in commands) won't do.
I personally use a combination of basic Vim commands, tailored to the current situation (i.e. w / W / f{char}), and the following plugins:
sideways has mappings to jump to next / previous arguments, to move arguments around, and corresponding text objects
fieldtrip builds on top of sideways and offers a submode, where individual keypresses can then be used to jump / move
Just try using ft f0 or f1 to see if these jumps can help you.

Structured Haskell Mode [SHM]: How to delete single bracket or string quote by <backspace> or <del>?

Suppose I want to remove parentheses around some expression, e.g. I want to unwrap (not True).
Pressing <backspace> with the cursor standing right after closing parenthesis does not delete it, but the cursor jumps inside the parentheses (runs shm/del).
Pressing <delete> when the cursor is placed over opening parenthesis deletes everything inside, including the parentheses themselves (runs delete-char).
The same goes with string double quote delimiters, curly brackets, square brackets, and I believe something else.
Is there some predefined function to unwrap expression in SHM? Or should I override this behaviour with some manual key bindings/actions?
structured-haskell-mode is very heavily influenced by paredit, which is where it gets the basic movement and editing bindings from. You can see what commands paredit provides either by looking it up in the Emacs help system (easiest way: open up a lisp buffer, enable paredit, C-h m) or using this handy cheatsheet (which looks reasonable but I haven't read).
Also, this video introduction to paredit for Lisp is probably worth watching.
For your specific question: M-s deletes the current level of nesting. In paredit this works for parentheses, brackets or quotes, but it looks like shm only supports parentheses at the moment. You can invoke it anywhere inside an expression:
((a |b c) d e f)
M-s
(a b c d e f)
EDIT: As #ReinHenrichs pointed out, you have to expand the selection to the whole node using M-a before using M-s to delete the surrounding parentheses, which is why it wasn't working for me earlier.
In the meantime, a decent workaround would be to rebind DEL to something like haskell-indentation-delete-backward-char (or whatever is appropriate for your setup) so that you can delete structural characters as before. From a bit of experimenation, shm seems to gracefully degrade for code that doesn't parse properly, so this isn't too inconvenient.
Put this keybinding into your emacs configuration file:
(global-set-key (kbd "C-c C-d") 'delete-pair)
Now you can place the point before the opening part of the pair (parentheses, square brackets, quotes etc.) or use M-a in SHM to go to the next outer pair and press C-c C-d to delete the pair.

Move from first character of function declaration to ending brace in VIM

If I have a function declared as such:
public static void main(String[] args){
blahblahlbah;
}
Is there anyway to move from the "p" in public to the ending "}" of the function?
It can be assumed that the method body is of considerable length and does contain curly braces if that makes a difference.
Thanks!
Try this key sequence: f{% Should do it.
There is not a few ways to accomplish the movement.
The most appropriate motion command is
]M
which is short and to the point: It moves the cursor to the end of the next
method in a Java-like source code.
There are also three satellite motions that together with ]M give
possibility to jump to next or previous starts and ends of methods, see :help
]m and below. Therefore, in addition to ]M, in this situation one can
issue
]m%
The rest of the answer contains discussion of some tricks that should be used
only if the aforementioned motion commands for some reason have failed to
solve the problem in your case.
Another simple idea to take advantage of is to jump over the argument list,
find the next opening curly brace and move to its closing counterpart,
%l%
or
f{%
or even
/%Enter%
A similar idea to move the cursor to the very beginning of the method's body
and than jump to the next unmatched closing curly brace leads to the following
command,
j]}
Note, though, that three of the last four commands work only if the function
header is a single line. If that is not the case, they need modifications.
Under some assumptions on the code formatting, it is also possible to achieve
the same result using plain-text-oriented movements. If the opening curly
brace is the last character on the method header line, one can use
$%
or
g_%
if that brace is the last non-blank character.
In conclusion, stick to the ]M movement as far as it works for you (it
should, in the vast majority of cases), fall back upon tricks based on
combinations of other text motion commands, otherwise.
/{ will take you to the opening brace and % will jump to the matching closing one.
][ moves to the next } in the first column. So this will work for you as long as your function is properly indented.
See :help ][ and :help section
I use this while searching through a file and my cursor is positioned over a particular search result in the middle of some long function. Often, I'll want to know which function I'm in so ][% gets me to the function signature, and then n returns me to the search result where I started.

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.

Resources