How to create short snippets in Vim? - vim

I have recently started using Vim as my text editor and am currently working on my own customizations.
I suppose keyboard mappings can do pretty much anything, but for the time being I'm using them as a sort of snippets facility almost exclusively.
So, for example, if I type def{TAB} (:imap def{TAB} def ():<ESC>3ha), it expands to:
def |(): # '|' represents the caret
This works as expected, but I find it annoying when Vim waits for a full command while I'm typing a word containing "def" and am not interested in expanding it.
Is there a way to avoid this or use this function more effectively to this end?
Is any other Vim feature better suited for this?
After taking a quick look at SnippetsEmu, it looks like it's the best option and much easier to customize than I first thought.
To continue with the previous example:
:Snippet def <{}>():
Once defined, you can expand your snippet by typing def{TAB}.

Snipmate - like texmate :)
http://www.vim.org/scripts/script.php?script_id=2540
video:
http://vimeo.com/3535418
snippet def
""" ${1:docstring} """
def ${2:name}:
return ${3:value}

As another suggestion (although slightly different) using vim's built in functionality:
:iabbrev def def(): #<LEFT><LEFT><LEFT><LEFT><LEFT>
Now whenever you type def followed by a space or other non-word character, it will expand to the same as what you've given as the output of SnippetsEmu (the space comes from the space you entered to trigger the completion).
This approach doesn't suffer the "lag" issue you encountered using :inoremap, and is built-into vim. For more information on this feature, look at :help abbrev.
You may be concerned that being triggered by space not tab it will trigger unnecessarily, but in general vim is pretty smart about when to trigger it. The issue can be additionally mitigated by enabling the abbreviation only for certain file-types (eg, python):
au filetype python :iabbrev ... etc
Snip[ets] (Manager|Emu|Mate|.vim) is of course also a perfect solution, but it's nice to be aware of the alternatives (especially when they are built in).

If SnippetsEmu is too heavy or ambitious for what you need (it was for me), I wrote a plugin that manages snippets based on filetype. It even has tab completion when picking the snippet! :)
Get it here: snippets.vim

I just installed UltiSnips. There’s a good article that explains why you might choose UltiSnips: Why UltiSnips?
I haven’t used any of the other snippet plugins; I decided to take the plunge with one that seemed full-featured and would be able to accommodate me as I gain more Vim skills and want to do more sophisticated things.

SnippetsEmu is a useful snippets plugin.

As noted by MDCore, SnippetsEmu is a popular Vim script that does just that and more. If you need only expanding (without moving back the caret), you can use the standard :ab[breviate] command.
:ab[breviate] [<expr>] {lhs} {rhs}
add abbreviation for {lhs} to {rhs}. If {lhs} already
existed it is replaced with the new {rhs}. {rhs} may
contain spaces.
See |:map-<expr>| for the optional <expr> argument.

Related

Complete space-separated words in Vim

I often like to complete more just a Vim keyword. For example, I want to complete an arbitrary pathname or something like self.logger.debug("...") which I already have somewhere in my text file.
C-n and C-p use the 'iskeyword' option and thus only complete Vim keywords.
What is the best way to implement a space-separated word completion?
inoremap <C-m> ???
My only idea is to change 'iskeyword', use normal word completion, and reset 'iskeyword' it after that.
Both #Ingo Karkat and #Luc Hermitte provide excellent solutions. However if you want to do this natively then Vim provides some solutions which might help you. Typically completion uses plain <c-n>/<c-p> however there is an completion submode accessed via <c-x>.
Filename completion
Use <c-x><c-f> to start completing a filename. You can use <c-n>/<c-p> just like you normally would after you have started completion to move between options. If the completion ends in a directory (e.g. /usr/bin/) then just execute <c-x><c-f> to start completion into that directory.
Whole line completion
If you are commonly using the same line, but it isn't worth making a snippet or an abbreviation, then type the start of the line you wish then <c-x><c-l> to start line completion. Then just use <c-n>/<c-p> as you normally would.
Multi-word completion
You can use <c-x><c-n>/<c-x><c-p> to complete another word that follows the current word. This one is sort of tough to explain without just trying it.
Let's say you have the following text:
self.logger.debug("foo")
Let's say you would like another self.logger.debug somewhere else.
So type: sel then use <c-p> to as you normally would complete to self
Then use <c-x><c-p> to complete to self.logger (may need to do some <c-p>/<c-n> to get to .logger).
Once self.logger is completed then use <c-x><c-p> again for the .debugger part.
Note: this does use iskeyword so it may not complete exactly as you want, but should be pretty close.
For more help
:h ins-completion
:h compl-whole-line
:h compl-current
:h compl-filename
:h 'complete'
IMO, snippets are the best way to proceed in your case -- as you certainly don't want to change 'iskeyword' option (it'd trigger too many undesired side-effects, and as you said you'd need to restore it afterward, which is not trivial if possible at all). You could use abbreviations or mappings, but then you'd loose the "completion" feeling/feature you'd get with snippet plugins.
There exist plenty different snippet plugins. I'm quite sure there are plenty answers here on SO, or on vi.SE which describe the existing plugins.
For pathnames, you have i_CTRL-X_CTRL-f, but indeed it stops at each directory. In that case you could may be override i_CTRL-X_CTRL-f to alter &isk (and key sequences that valid/abort completion), trigger the completion, and then restore &isk and the mappings when you validate/abort the completion. This restoration at the end of completion is what some snippet plugins do. That's what I do in the core functions used in mu-template to take care of the completion. (Explanations of how this works on vi.SE)
I have written a plugin that is powered by my CompleteHelper plugin that does just that:
The WORDComplete plugin finds matches for WORDs that start with the non-blank characters in front of the cursor and end at the next whitespace. By default, it is triggered in insert mode with <C-x><C-w>. Like the built-in completions, the source buffers it considers can be configured.

How do I customize three letter sequences in Vim Latex-Suite?

I installed Latex-Suite for Vim, and I like it very much, but I'd like to be able to customize the environment mappings that came by default, and add new ones. For example I want to edit the equation environment that appears typing EEQ and move around some elements, like the \label{} command. How can I do this? I've been scanning everything inside my /usr/share/vim/vimfiles/ftplugin but I can't find a way to do it (or I just don't understand what those files are).
You want to check out the documentation on Macro Customisation, specifically the Tex_Env_{name} bit.
In short, if you want your theorem snippet to look like
\begin{theorem}
<++>
\end{theorem}<++>
then you want a line like
let g:Tex_Env_theorem = "\\begin{theorem}\<CR><++>\<CR>\\end{theorem}"
in your vimrc.
Note the backslashes to escape carriage-return, and double-backslash for normal backslashes.
The <F5> functionality (press F5 after typing an environment name, i.e. figure<F5>) should work out of the box, but you may need to refresh the three-letter code. This is more hassle than it needs to be, but something like
autocmd BufNewFile,BufRead *.tex call IMAP('EFI', g:Tex_Env_figure,'tex')
will do the job.
The answer to the question you asked comes with a caveat, which is that Latex-Suite is an enormous amount of code that is very hard and annoying to modify, and which does not play nicely with other plugins. This falls into Latex-Suite's philosophy that it's the only plugin you need for editing latex within vim.
That said, you want to look in /path/to/ftplugin/latex-suite/envmacros.vim. Searching for EEQ will lead you on the path to understanding the set of calls that latex-suite performs. I would like to reiterate that many functions are deeply intertwined.
On the other hand, there is a very easy way to have very easily customizable environments, which are snippets. See the UltiSnips page for a good example of how this works. These are designed for customization and extremely easy to write.

vim command-line snippets possible?

Is there any way to define and use snippets on the vim command-line? For example, when I want to select a portion of text I want to replace a string of text within, excluding the rest of the line, I have to change:
:'<,'>
to
:%s\%VsPat/rPat/g
which once in awhile might be alright, but lately I find myself performing this kind of s/S/R/ often enough to make it a PITA; yet still more efficient than making each change in the selection manually.
Actually there are quite a few regular editing command I use in VIM that would increase my efficiency if I could tie them to a snippet somehow. So is there any way to use snippets at vim command-line?
What about just going on with your substitution without changing anything?
:'<,'>s/\%VsPat/rPat/g
Or using a visual mode mapping?
xnoremap <key> :s/\%V/g<left><left>
There is build-in feature cnoreabbrev it is simple replacement, so if you define it for example
:cnoreabbrev ss %s\%VsPat/rPat/g
then when you type :ss and press <space>, it will automatically replace ss with following
:%s\%VsPat/rPat/g
Check it out, it should solve at least half of your problems :-)

Table-of-contents with VIM folding

A long time ago there was an editor called MultiEdit. It has a feature which I can not find in all powerful VIM. In MultiEdit I could press some hot key and it would show something like table-of-contents (aka, condensed-mode, aka outline) were I could see only 1st line of all functions (let it be C source) in current file. I could then move cursor to function that I need and after pressing enter, mode will switch to normal and I would be in function that I need. Very useful for those who likes to put many functions in one file. This feature was extremely simple to use: one config option to enter regex for selecting title-lines and one hotkey for mode toggle.
VIM has folding. But this is different. Folding hides parts of files and displays folded-lines-indicator. It is much more difficult to specify what to hide in folds for table-of-content-display: you need to start fold at title-line and end before next title line. This is more complex than simple regex to select titles.
I so much wanted this feature, I even wrote VIM macro to emulate this MultiEdit behavior, even though I don't know VIM that much. I've wrote it in part because it was easier to to learn a new language and write a macro than to figure out VIM folding module complexity.
Unfortunately, after upgrading VIM, this macro now does not work (infinite loop?). I've wrote it long time ago, and what little I did know about VIM is all forgotten and I could not fix it now. (EDIT: I've fixed my script. Thanks to #romainl for the link).
My question is how to get this table-of-content like display in VIM?
This recent vimcast by Drew Neil explains the generalities of folding and this one goes through the process of creating the kind of folding you are (probably) after.
Depending on the language you work with and your coding style, something as simple as
set foldmethod=marker
set foldmarker={,}
and zM can get you a long way:
If you want to customize what information is displayed, the second link above is almost certainly just what you need.
Have a look at ctags and the vim plugin tagbar.
You also check out the vim plugin unite with the extension Unite-Ouline
it gives a behavior quite close to what you describe.
It's not great but have you tried setlocal foldmethod=syntax? It seems to do a decent job in 7.3 on Windows. ...although I just realized that our coding standard has the opening brace for a block at the end of the line rather than on a new line and if I change to having it on a new line it works substantially less well.

Vim: Making Auto-Completion Smarter

I use ctags, taglist, etc., to have auto completion in Vim. However, it is very limited compared to Visual Studio intellisense or Eclipse auto-completion. I am wondering whether it is possible to tune Vim to:
Show auto-completion whenever . or -> are typed. But only after some text that might be a variable (e.g. avoid showing auto completion after a number).
Show function parameters when ( is typed.
Stop removing the auto completion list when some delete all characters after . or ->: When I enter a variable name, then press . or -> to search for a certain member, I frequently have to delete all the characters I type after the . or ->, but this makes Vim hide the auto completion list. I would like to keep it visible unless I press Esc.
Showing related auto completion: When I type a variable and press ^X ^O, it usually shows me all the tags in the ctags file. I would like to have it showing only the tags related to the variable.
Thanks for the help.
EDIT: Some people are voting for this question, but no body seems to know the answer. So just wanted to mention that you don't have to provide a complete answer; partial answers to any of the mentioned points would be good also.
AutoComplPop is what you need.
For (1) when working with C++ or C clang complete is a really nice option
To make vim trigger a certain behavior when a key is pressed you need to map the key to a function.
For instance to map the key . to call some type of completion when in INSERT mode you would need to do:
:inoremap <expr> <buffer> . MyFunction()
and then the function would need to evaluate the context where it was called and present an appropriate answer to the user.
Edit: This is the basis of how clang complete mentioned by #honk works.
I'm not sure if you can customize the behavior of omnifunc to meet your needs but on my experience, I never went too far. As #Mikhail said, you would need to keep track of things which in practice means interpreting or even running the code to some extent.
I use vim every day, and I'm not aware of any existing script that may do this. This action would require understanding of classes and keeping track of variables. someObject-> means that VIM would know what class the variable someObject is, and then be able to search methods/variables within that class.
Writing scripts for vim is relatively easy, though like you've commented - no one has answered this yet. Up vote from me.
I would love to have that same functionality that you are looking for and just came across a promising plugin:
https://github.com/Shougo/neocomplcache looks like it could be the new autocomplpop, and seems to work quite well during my initial trials... now to configure the omni completion to work with scala~
I've recently discovered YouCompleteMe, it behaves similarly to the Visual Studio autocomplete tool. A demonstration can be seen here:
https://www.youtube.com/watch?v=YuMyHAHF0xs
In any case, I recommend YouCompleteMe (YCM). It provides (fuzzy) matching of identifiers of your current file, as well as path-completion, integration with external completion engines,...
ad 1)
If you like the semantic completion of eclipse, use eclim to integrate vim with eclipse. (alernatively use another semantic engine for YCM)
ad 2)
These 2 play nicely together btw.,: YCM can even provide the function definition (= parameter list) of the recently completed function!
ad 3)
that's what YCM does anyways
ad 4)
not quite sure, what you mean by that one. never used ctags!
P.S.: I strongly recommend using UltiSnips and Tagbar (and if you like UndoTree) additionally, what makes vim a perfect IDE for me.

Resources