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

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.

Related

vim move position of the closing bracket

Editing in Vim I often find myself in a situation where I want to move the position of a closing bracket.
e.g.
First i type
if a == 1 then
Then I realize I really wanted to have brackets around the 'a == 1' part so I go back and put a bracket in and end up with
if ()a == 1 then
I'm using auto-pairs plugin so the paired bracket is correctly generated.
My question is, what is the quickest way to get this to look like:
if (a == 1) then
For example currently I might
escape
use x to delete the second character
f1 to move to the 1
a to append and type ')'
It seems like there should be a way to
escape
move the second bracket a word forward.
With lh--brackets, you would simply have to select a == 1 and press (.
The surround plugin have similar mappings (they require several keys pressed, but they follow more the vim spirit).
If you really want to stay in insert mode, you can press CTRL-V twice, once before pressing (, then before ).
You can also select a == 1, and type s(^R"). (^R is for CTRL-R)

How to provide parameter in vim macro

Is it possible to provide some parameter when recording a macro in vim via prompt or some other ways?
Edit:
I have such code:
foo
bar
And I would like to surround each with ruby block:
expect do
foo
end.to raise_error(CustomClass)
expect do
foo
end.to raise_error(OtherCustomClass)
So, it is easy to create a macro that will result with:
expect do
foo
end.to raise_error()
expect do
foo
end.to raise_error()
But it will be nice to have prompt that will be used to set raise_error method parameter. In each use of macro this parameter will be different.
While I agree with everyone else that if you need this feature, you're probably going about things inefficiently, it is possible to insert a variable text string into a document as part of a macro. The trick is to store the text you want to use in your macro in a register.
yank some text into a named register, for example "xyw to yank a word into the x register
record your macro, qq, when you want to place the variable text, put it, for example "xp to put the text in the x register into the document where the cursor is
now, when you play your q macro, #q, it will use whatever is currently in the x register, so you can yank different text into the x register, play your q macro, and the newly yanked text will be used.
If you are talking about recording a macro with qx...q, this is not possible.
However you could still do : :let #y = substitute(#x, 'old_pattern', 'replacement', 'g') and then use #y.
You could also define a function:
function Play(myArg)
execute 'normal sequence_of_characters' . a:myArg . 'other_sequence_of_characters'
endfunction
call Play('foo')
Very particularly in the OP's situation, where you really only have precisely two variable pieces of content, I find the easiest method to be a bastardisation of #mkomitee's approach above.
Instead of manually saving the two ‘parameters’ into registers before each usage of the macro, I prefer to type the “first parameter,” visual-select it, evaluate the macro, then type the “second parameter.” To achieve this, I start the macro with a deletion command (a simple d, assuming you're always going to invoke the macro in visual-mode, for instance); then finish it with a command that switches to insert mode (like c or i), and finally, while still in insert mode, a Ctrl-O q to cause the macro to also leave Vim in insert mode when it's done.
As a slightly simple example, if the two “parameters” are single words, here's the keystrokes to create (and then invoke) a macro to manipulate widget.snog() to a parameterised widgetFoo.fooSnog(bar):
foob qq "zdw — we're now recording to the q register, with the first ‘argument’ in z
‸
"aP — prefix-paste from a fixed register used elsewhere in the document
widget.snog()‸
^ea␣Ctrl-rEscb~hx — paste the first arg, and capitalize
widget‸Foo.snog()
2w~b"zP — capitalize existing word, then paste the first arg again
widgetFoo.fo‸oSnog()
$Ctrl-Oq — move to the last position, enter insert-mode, and end the macro
widgetFoo.fooSnog(‸)
After finishing the first instance with bar, we can now use it several times:
obazEscb — set up our first ‘argument’,
widgetFoo.fooSnog(bar)
‸baz
#qquuxEsc — invoke the macro, and finish with the second one
widgetFoo.fooSnog(bar)
widgetBaz.bazSnog(quux‸)
ocorgeEscb##graultEsc — repeat a third time
widgetFoo.fooSnog(bar)
widgetBaz.bazSnog(quux)
widgetCorge.corgeSnog(grault‸)
ogarplyEscb##waldoEsc — … and so on
widgetFoo.fooSnog(bar)
widgetBaz.bazSnog(quux)
widgetCorge.corgeSnog(grault)
widgetGarply.garplySnog(waldo‸)
Of course, it looks laborious, typed out in such a long fashion — but it's surprisingly few key-strokes in practice, and very easy to train into your fingers.
tl;dr: type the first argument; enter macro-recording before deleting it into a register; manipulate your text as desired; then leave vim in insert-mode at the position of the second argument with Ctrl-Oq.
If you need to generate a code, which is the case, the best way for this is to use vim snippets. You can configure snippet to put cursor where you need when you [tab].

goto definition (gd) while inside function call

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.

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.

Command to surround a character with spaces in vim

I am trying to use vim properly - to aid me I've mapped my arrow keys to "" so that I am forced to use {hjlk} to move around.
This is causing me a problem when I want to just surround a character with spaces, eg:
"2+3" is better formatted "2 + 3"
Previously I would have put my cursor over the + and typed:
i[space][arrow-right][space][Esc]
That's 5 presses.
To do this without the arrow I seem to need to put the cursor over the + and go:
i[space][Esc]lli[space][Esc]
That's 8 presses.
I can convert the "li" into an "a" which reduces it to 7 presses:
i[space][Esc]la[space][Esc]
Short of writing this into a macro is there a better way of doing it? Is there some magic vim command which will allow me to do it in less than even 5 presses - and some way to generalise it so that I can do it to entire words or symbols, eg if I want to convert 3==4 to 3 == 4?
Personally, I think it makes most sense to destroy what you want to surround, and then repaste it.
c w "" ESC P
Obviously, you can replace both the object and the quotes with whatever you like. To change just one character + to be [space]+[space], you would do
s [space] [space] ESC P
on the +
The first thing that jumps to mind after reading just the title is surround.vim which is an excellent script to do all kinds of useful things along the lines of what you've described.
To solve your specific problem, I would probably position the cursor on the + and:
s[space]+[space][esc]
To change 3==4 into 3 == 4, I might position the cursor on the first =, and:
i[space][esc]ww.
i have been wondering about this as well. i tried with surround.vim, but the naive approach
S<space>
(after making a visual selection) does not work since the space is already taken up as a modifier for adding space to other surrounding character pairs. S<space><cr> adds a ^M in the output. Ss almost works but inserts a space only before.
after asking at tpope/surround.vim on github:
S<space><space>
in visual mode works. alternatively, from normal mode, ysl<space><space> works for a single character
Hah! I've been trying to figure out how to surround a block in spaces for quite a while and I finally found the right combination.
Using surround.vim you say surround selector space space.
So for this specific case I would use visual mode (a good trick for operating on single characters under the cursor BTW) thus: "vs " <- four key presses!
I also have a habit of typing things like argument lists without spaces. With this technique you can just navigate to the second argument using w and say "vws " to visually select a word and surround with spaces.
I prefer visual select mode generally. Also the alternate surround syntax "ysw " excludes the word final comma that is caught by "vw".
You could create a macro with one of the described actions and call it everytime you need it (Like amphetamachine proposed while I was writing) or you could simply search & replace:
:%s/\(\d\)\(+\|-\)\(\d\)/\1 \2 \3/g
You probably have to execute this command two times because it will only find every second occurence of +/-.
EDIT:
This will replace everything without the need to be called twice:
:%s/\d\#<=+\|-\d\#=/ \0 /g
Try positioning your cursor over the '+' and typing this:
q1i[space][right arrow][space][left arrow][esc]q
This will record a quick macro in slot 1 that you can re-use whenever you feel like it, that will surround the character under the cursor with spaces. You can re-call it with #1.
There is also the more versatile one:
q1ea[space][esc]bi[space][right arrow][esc]q
Which will surround the word under the cursor ("==" counts as a word) with spaces when you hit #1.
You could set up a mapping like this (press enter in visual mode to wrap spaces):
:vnoremap <CR> <ESC>`<i<SPACE><ESC>`>la<SPACE><ESC>h
This method allows you to use . to repeat the command at the next +.
Put your cursor over the + and type:
s[SPACE][CTRL-R]"[SPACE][ESC]
I know this is and old thread, but this might be useful to someone. I've found that the map (map it to anything else you want!)
noremap <leader>ss diwi<SPACE><C-R>"<SPACE><ESC>B
works ok both for turning 'a+b' into 'a + b' (when used over the '+' char) and for turning 'a==b' into 'a == b' (when used over either the first or the second '=' sign).
I hope it's useful to someone.

Resources