How to script in Vim to yank only lines from a visual selection (or fold) that match a certain pattern? - vim

I'd like to add a command to my .vimrc that allows to, within a visual selection or the range of the current fold level to
yank all, but only those lines that match a certain pattern.
and as a bonus to
reverse their order
and
perform a small pattern substitution.
Specifically the idea is to reduce the legwork in writing the common C idiom fail-goto-rollback, i.e. (can be found in lot of C projects most prominently the Linux kernel) if the body of a function (or a block) is this
someErrorType errorcode;
if(fail1) {
errorcode = someError1;
goto error_1;
}
prepare_a();
if(fail2) {
errorcode = someError2;
goto error_2;
}
then the result of the desired transformation shall be this.
error_2:
/* <insert cleanup code operation that did not fail1 here> */
error_1:

for the "yanking all", you can do:
normal mode: qaq to clear reg a
do visual selection
press :, vim will auto add '<,'>, then g/pattern/y A<Enter>
all your needed lines are in reg a, you can "ap to paste. for the reversing order requirement, I don't understand. What output do you expect. A concrete before/after example may help.

For adding boilerplate code, the usual solution is via a snippets plugin, which solves this (at least partially) in a generic way, instead of building a (possibly brittle) special solution with Vim built-ins.
snippets are like the built-in :abbreviate on steroids, usually with parameter insertions, mirroring, and multiple stops inside them. One of the first, very famous (and still widely used) Vim plugins is snipMate (inspired by the TextMate editor); unfortunately, it's not maintained any more; though there is a fork. A modern alternative (that requires Python though) is UltiSnips. There are more, see this list on the Vim Tips Wiki.
There are three things to evaluate: First, the features of the snippet engine itself, second, the quality and breadth of snippets provided by the author or others; third, how easy it is to add new snippets.

Related

Vim generate text expansion from shortcut

The codebase I'm working on requires standard comments around any modifications that we make:
// -----------ABCD---------------
and then
// ----------\ABCD---------------
What's the best way to map a short combination of keys like -abcd and \abcd to generate these longer strings?
The simplest, built-in :help abbreviations:
inoreab abcd // -----------ABCD---------------
inoreab abcD // ----------\ABCD---------------
Why did I choose different triggers? There are some rules (documented as "three types of abbreviations" under the above help link) for the allowed keys; the easiest is that it's all keyword characters.
If you insist on those exact triggers, you'd have to fiddle with the 'iskeyword' option (which can affect syntax highlighting and motions!), or switch to :inoremap. The downside of that is that you won't see the typed characters until any ambiguity has been resolved (try it; you'll see what I mean).
ABCD is just a dummy; I need dynamic text here
If multiple abbreviations won't do, you'll need snippets.
snippets are like the built-in :abbreviate on steroids, usually with parameter insertions, mirroring, and multiple stops inside them. One of the first, very famous (and still widely used) Vim plugins is snipMate (inspired by the TextMate editor); unfortunately, it's not maintained any more; though there is a fork. A modern alternative (that requires Python though) is UltiSnips. There are more, see this list on the Vim Tips Wiki and this comparison by Mark Weber.
A snippet would look like this (snipMate syntax):
snippet abcd
// -----------${1:ABCD}---------------
${2:content}
// ----------\$1---------------
${3}

A better way to write int main(){}

I recently started to use vim.
When I start coding, I usually start with following format.
('_' denotes the location of a cursor.)
int main(){
_
}
Here is what I have done
1. type int main(){}
2. ctrl-o h (move left)
3. enter twice
4. ctrl-o k (move up)
5. tab (indent)
The problem is that, it takes so many key strokes.
I am wondering if there is a better way to do this.
snippets are like the built-in :abbreviate on steroids, usually with parameter insertions, mirroring, and multiple stops inside them. One of the first, very famous (and still widely used) Vim plugins is snipMate (inspired by the TextMate editor); unfortunately, it's not maintained any more; though there is a fork. A modern alternative (that requires Python though) is UltiSnips. There are more, see this list on the Vim Tips Wiki.
There are three things to evaluate: First, the features of the snippet engine itself, second, the quality and breadth of snippets provided by the author or others; third, how easy it is to add new snippets.
Things as simple as C&C++ main() are already defined in all snippet plugins and even in specialized plugins like lh-cpp (I'm maintaining this one) or c.vim.
You could also do it by yourself with abbreviations, but then you'll have to detect whether you're in a code or a string/comment context. You could define your own snippet plugin, but there already are many of them.

Faster way to type control flow statements (in C and php etc)?

I am new to Vim and I need to speed up my typing for this kind of statements.
if (a == 'e') {
foo();
}
In other text editors, I usually type if() {} first and then insert the text in to the parenthesis and curly braces. If I do this in Vim, I need to switch back to normal, move cursor to middle of () then middle of {}... switch between i and esc ...
What is your suggestion on typing this kind of syntax for Vim beginner? I would be grateful if you can show me the commands for that example step by step.
This is a job for snippet expansion. Take a look at SnipMate or UltiSnips.
snippets are like the built-in :abbreviate on steroids, usually with parameter insertions, mirroring, and multiple stops inside them. One of the first, very famous (and still widely used) Vim plugins is snipMate (inspired by the TextMate editor); unfortunately, it's not maintained any more; though there is a fork. A modern alternative (that requires Python though) is UltiSnips. There are more, see this list on the Vim Tips Wiki.
There are three things to evaluate: First, the features of the snippet engine itself, second, the quality and breadth of snippets provided by the author or others; third, how easy it is to add new snippets.
There are two approaches that solves your goal:
abbreviations
and snippets engines
Abbreviations and the old way of doing things. You just type if and space, and tada! You'll find plenty examples around the web. Only a few will be context-sensitive (i.e. they won't expand within comment or string contexts), or able to take the current project spacing style into consideration. In lh-cpp, you'll find the usual control-statement abbreviations for C and C++, they'll need to be duplicated for similar languages (a runtime ftplugin/c/c_snippets.vim from a php ftplugin should do it in your case)-- in lh-misc I support a couple of others languages (for VimL and shell)
Snippet engines are the trendy way of doing the same thing. This time, you will be able to type i or if and then <tab> (or CTRL+SPACE, or ...). Control-statement snippets won't need to be aware of the current context as we need to explicitly require the expansion. Others have already given links to the trendy snippets engines. Snippets from lh-cpp (which relies on mu-template) take the project style into account when expanding control-statement snippets (i.e. some projects want ) and { on a same line, other want a newline in between, ...)
Here's my answer in case you want to go with vanilla Vim.
In the majority of the cases I guess there is no point in entering the parentheses first and filling in the condition later, just type it all in right away:
if (a == 'e')
Then you can either continue
by typing {}<ESC>:
if (a == 'e') {}
^ cursor is here
The cursor is already placed so you can continue with i<CR> and type the body (if properly configured, Vim should indent for you).
or by typing {<CR>}<ESC>:
if (a == 'e') {
}
^ cursor is here
Then you can enter the body by pressing O (open new line above cursor). Possibly Vim also automatically indents here (it doesn't in my configuration).
If you really want to fill in the condition after you have entered this:
if () {
}
^ cursor
you can do so by typing kf(a.
If anybody knows better ways to do this without plugins, suggestions are welcome.

How to paste previously prepared code snippets in Vim?

In Windows, using the AutoHotkey utility, it's possible to write simple scripts to expand some text in an editor of choice (e.g. Visual Studio's editor).
For example, if in Visual Studio editor I type:
d1 [TAB]
(i.e. press the keys in sequence: d,1,Tab) the above "d1" text can be replaced with one or more lines of code snippets. The mapping between "d1" and the expanded lines of code is specified in a AutoHotkey script.
This is very convenient e.g. for demos; for example: at some point if I'd like to enter a whole function body, assuming that I associated it to e.g. "d3", I can simply press d3Tab on the keyboard, and I get the function body automatically pasted in the editor in current cursor location; and I can have different code snippets associated to different key combinations, e.g.
d1 --> DoSomething() function definition
d2 --> class Foo definition
d3 --> test code xyz...
Is it possible to achieve the same goal using Vim?
In other words, I'd like to have a set of code snippets previously prepared, and I'd like to paste each one of them in my currently edited source code file in Vim, in a way similar to what I described above.
Basic expansion can be done via the built-in abbreviations, for example:
:inoreabb d1 DoSomething()<CR>{<CR><CR>}<CR><Up><Up>
Read more at :help abbreviations.
snippets are like the built-in :abbreviate on steroids, usually with parameter insertions, mirroring, and multiple stops inside them. One of the first, very famous (and still widely used) Vim plugins is snipMate (inspired by the TextMate editor); unfortunately, it's not maintained any more; though there is a fork. A modern alternative (that requires Python though) is UltiSnips. There are more, see this list on the Vim Tips Wiki.
There are three things to evaluate: First, the features of the snippet engine itself, second, the quality and breadth of snippets provided by the author or others; third, how easy it is to add new snippets.
I have previously used snipMate that does something like what you're describing.
http://www.vim.org/scripts/script.php%3Fscript_id%3D2540

Vim Visual Select around Variables

I'm wondering if there's a way to select variables intelligently in the same way that one can select blocks using commands like va}. There's some language-specific parsing going on to differentiate php and ruby, for example. For future reference, It'd be nice to tap into that - ideally selecting around various syntactic elements.
For example. I'd like to select around $array['testing'] in the following line of php:
$array['testing'] = 'whatever'
Or, lets say I want to select the block parameter list |item, index| here:
hash.each_with_index { |item, index| print item }
EDIT:
Specific regexps might address the various questions individually, but I have a sense that there ought to be a way to leverage syntactic analysis to get something far more robust here.
Though your given examples are quick to select with built-in Vim text objects (the first is just viW, for the second I would use F|v,), I acknowledge that Vim's syntax highlighting could be a good source for motions and text objects.
I've seen the first implementation of this idea in the SyntaxMotion plugin, and I've recently implemented a similar plugin: SameSyntaxMotion. The first defines motions for normal and visual mode, but no operator-pending and text objects. It does not skip over contained sub-syntax items and uses same color as the distinguishing property, whereas mine uses syntax (which can be more precise, but also more difficult to grasp), and has text objects (ay and iy), too.
You can define your own arbitrary text objects in Vim.
The simplest way to do custom text objects is defining a :vmap (or :xmap) for the Visual mode part and an :omap for the Operator-pending mode part. For example, the following mappings
xnoremap aC F:o,
onoremap aC :normal! F:v,<CR>
let you select a colon-enclosed bit of text. Try doing vaP or daP on the word "colon" below:
Some text :in-colon-text: more of the same.
See :h omap-info for another short example of :omap.
If you don't mind depending on a plugin, however, there is textobj-user. This is a general purpose framework for custom text objects written by Kana Natsuno. There are already some excellent text objects written for that framework like textobj-indent which I find indispensable.
Using this you can easily implement filetype-dependent text objects for variables. And make it available for everybody!

Resources