Can Vim's keyword completion be limited to only same filetype? - vim

I find Vim's keyword completion very useful when I only have files of the same filetype open. But as soon as I start editing more than one filetype, it becomes much less useful. If I'm editing a Python project and then open my vimrc in another tab, keyword completion from inside a Python file will now include keywords from my vimrc. Without disabling the options for complete to look in other buffers, is it possible to have keyword completion work only with buffers of the same filetype?

Good idea. I'm a huge fan of the Vim insert-mode completion, and have written a library that makes it easy to implement custom completions: CompleteHelper.
With a little enhancement to that library (which I've just implemented in version 1.30), it allows to limit the completion candidates to certain buffers. With this, I've implemented your suggestion as the SameFiletypeComplete plugin. Try it out; I hope it's useful to you.

You are using <C-n>/<C-p>, right?
The value of set complete determines the completion sources. The default value includes the content of other buffers and windows in the completion list.
See :help 'complete' for a list of options. This will probably solve your problem:
:set complete=.,t,i
Alternatively, you could use other completion shortcuts like <C-x><C-n>, <C-x><C-p> or <C-x><C-o>, depending on what you want to complete. See :help ins-completion.

Related

How to make Vim autocomplete a word based on words already found in the buffer?

How to make Vim autocomplete a word based on words already in the buffer?
How can I make Vim autocomplete words, based on words already found in the buffer, just like it is possible with Emacs (M-%)?
<C-n> and <C-p> will complete what is in all buffers. <C-x><C-n> and <C-x><C-p> will do exactly what you asked for and only give completion for tokens in the current buffer. However, there are a lot of completion options in Vim. To learn more about them, I would suggest reading the help section on them :help ins-completion (this is called insert mode completion).
A few other completion options in Vim are <C-x><C-f> to complete file paths and <C-x><C-l> to complete entire lines.
C-x C-n and C-x C-p do that in insert mode (next and previous)
Another solution is to use a plugin with an auto popup : neocomplcache plugin
It provides keyword completion system by maintaining a cache of keywords in the current buffer. neocomplcache could be customized easily and has a lot more features than the Vim's standard completion feature.

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.

Trigger command on buffer load and buffer save

I want to write a vim plugin that does certain text transformations to the text while in the editor, but I don't want these transformations visible inside the file.
As an example, consider the word Gnarly in a text file I want to edit. Upon load I would want my vim script change that to G, but when I save the buffer I want it to expanded back to Gnarly.
My scenario is a little bit more complex because it will involve an external script, but I want to see exactly how that would be invoked.
Also I'd want to be able to apply this change only to some files based on their extension.
See :h autocmd. The events you need are BufRead and BufWrite.
Maybe you will be interested by :h conceal.
First of all, define your own filetype, e.g. gnarly. Read :help new-filetype for the details, but basically it's this autocmd:
:autocmd BufRead,BufNewFile *.gnarly set filetype=gnarly
Then, the conceal feature introduced in Vim 7.3 is the way to go. Write a syntax script ~/.vim/syntax/gnarly.vim. For your example it would contain:
:syntax keyword gnarlyConceal Gnarly conceal cchar=G
But you can also use :syntax match for more complex patterns.
Finally, concealment is off by default. To turn it on, put the following command into ~/.vim/ftplugin/gnarly.vim (you could put it into the syntax file, too, but this separation is recommended and done by all full plugins that ship with Vim):
:setlocal conceallevel=1
You can customize the 'concealcursor' behavior, too. If you still need help, have a look at the help pages, or existing plugins that use concealment.

Is vim able to detect the natural language of a file, then load the correct dictionary?

I am using several languages, and currently I am obliged to indicate to vim with which of these the spell check must be done. Is there a way to set up vim so that it automatically detects the correct one? I vaguely remember that in a previous version of vim, when the spell check was not integrated, the vimspell script made this possible.
It would be even better if this could apply not only to a file but also to a portion of a file, since I frequently mix several languages in a single file. Of course, I would like to avoid to load several dictionaries simultaneously.
I don't know if there is a way to autodetect it, but if you put vim:spell:spelllang=foo,bar,baz at the bottom of the file, vim will set the spellchecking languages to foo, bar, and baz when the file is opened. Note that you must put at least one space before that text, or vim will think it's part of the file.
Since vim is missing this feature, I found it useful to define shortcuts like these in .vimrc:
command! Nb :set spelllang=nb
command! En :set spelllang=en

TextMate's Jump to Function in VIM?

Recently I've been trying my hand at using vim instead of TextMate and one of the features that I've missed most in VIM is TextMate's jump to method function (CMD + Shift + T for those who don't know). From looking around I havn't seen any particular way to emulate this functionality and was wondering if anyone here has had experience with this sort of functionality in VIM.
Thanks in advance for any answers
Patrick
You're looking for vim's 'tags' functionality ... I answered a similar question about tags here: How to implement own tag jump in VIM with CTRL-]?
This functionality has been implemented in fuzzyfinder using :FufBufferTag. See the ticket
I'd love to hear good suggestions as I use Vim all the time but haven't used TextMate. I do the following things which slightly overlap.
Search for d-e-f-space-<first few letters of function name>. So to go to function foo (in Python or Ruby, and within the same file of course), I type /def fo and I'm there. I also have incremental search enabled in Vim.
Use marks for functions which I visit often. So I'll ma at the function definition and then 'a back to it later. I know it's not function definitions but it is a crutch.
you can create a tags file with ctags http://ctags.sourceforge.net/
basically $ctags -R
Then once you're in vim :set tags=/path/to/tagsfile
this will also be any tag so not just class names, methods, etc. In normal mode ctrl-] on the method/class/ and it will jump to that position.
You can also use the taglist plugin which will display current tags in a side window. ctags
I had pretty much the same problem and I found a quick and dirty solution (paste this in your .vimrc and call by typing :LS)
function! s:ListFunctions()
vimgrep /function/j %
copen
endfunction
command! -bar -narg=0 LS call s:ListFunctions()
If you require more functionality then Exuberant Ctags will do better for you
I'm using CommandT for file searching, then / to search for a particular function. However, the real issue is with CSS. Cmd Shift T in Textmate enable quick jumps to a particular CSS class, and that is a huge time-saver.
CTags doesn't support CSS parsing, unless you re-compile with a patch (found via google), but I'm not even sure if we can do fuzzy searching for CSS classes like in Textmate. I really miss the Cmd Shift T feature.
I've written a TextMate Bundle command (you can easily assign it to Ctrl+] for example) that lookup for the definition of the class or method under the caret and displays it in a tooltip, along with the file name and the line where it was find.
Check it out: Add a shortcut to TextMate to lookup a class or method definition in a tooltip
Hope you'll find it useful!
The feature described in this question has many different names depending on the IDE/Editor:
In Resharper it's called "Goto File member"
In Sublime Text 2 it's called "Goto Symbol"
In PyCharm it's called "Goto Symbol"
The feature is essentially the same though in all of the above implementations (and I assume it's very similar in TextMate as well). The feature brings up an interactive list of methods/functions (and potentially also includes member variables/properties).
The list allows interactive filtering by typing the name of a methods/functions/etc. The list also usually allows the use of arrow keys to select a method/function/etc. Hitting the enter key with a method/function/etc selected navigates to the line in the current file where the selected method/function/etc is defined.
Of all the existing answers in this question the only one that I see which seems to provide a reasonably similar implementation of this feature is to use the command:
:FufBufferTag
in vim's FuzzyFinder plugin.
The answer which suggests using the taglist plugin is not a good solution, because the functionality offered by the taglist plugin is quite different from the feature. The taglist plugin offers similar functionality - the ability to view an outline of methods in the currently file, but it does not offer an interactive way to filter that list in realtime. The taglist plugin does allow you to search the tag buffer, but that's not nearly as convenient as the "Goto symbol" functionality offered in other editors.
I wanted to provide an alternative suggestion here, which is to use the command:
:CtrlPBufTag
in the excellent Ctrlp vim plugin. In my opinion this by far the best implementation of the "Goto Symbol" feature currently available in vim.

Resources