How to perform File Extension based Actions in VIM? - vim

I want to perform rubyf action in VIM when I press F5 if the file is of .rb extension.
Right now I just have
map <F5> :rubyf % <CR>.
But I also want to interpret scheme files if its .scm or compile tex etc using the same F5. How do I check the file extension and perform the correct binding? How do you guys compile different files in G/VIM?

You could create a different autocmd for each file extension. eg:
au BufEnter,BufNew *.rb map <F5> :rubyf % <CR>.
See :help autocmd for info about autocmds.
A better approach for your specific problem would be to map <F5> to always invoke :make % and then have a autocmd that set the makeprg option for each file type (use setlocal when you do this for best results). This wouldn't be for loading ruby into Vim (as you seem to be doing) but instead for invoking an external compiler/interpreter/linter. This is essentially what I do. The nice thing about doing it this way is that Vim can interpret the errors and warnings and automatically jump to the problems in your code. You can also bring up a list of the errors/warnings. See :help quickfix for info about this, as well as the help topics for 'makeprg', :make, :copen and 'errorformat'.
A slight variation on this would be to not use autocmds at all, but instead to have an external script that when given a source filename figures out what to run (ruby, your scheme compiler, pychecker, your C compiler, whatever). Then just set makeprg to always run that script.

Use filetype plugins.
Create a file ~/.vim/ftplugin/ruby/custom.vim
In that file, put any commands you want included only when the filetype of the current buffer is ruby. They'll be sourced appropriately.
If you want to do the same thing from scheme, create another file ~/.vim/ftplugin/scheme/custom.vim`` and do the same thing.
Each time you load a file in vim, it will detect the filetype, and load all the plugins corresponding to your filetype.

Autocommands is your friend.
it is defined as followed:
:au[tocmd] [group] {event} {pat} [nested] {cmd}
in your case the following line in .vimrc will do what you want.
autocmd BufRead,BufNewFile *.rb map <F5> :rubyf % <CR>.
for more information se:
http://www.ph.unimelb.edu.au/~ssk/vim/autocmd.html

This is answered fairly well in the answers for this question.

Related

Vim load buffer depending on file type

I am using vim for a lot of languages and I am hoping to improve the ctrl + p/n autocomplete. When I am going to work with a specific one I load a file in the buffer containing the substet of language specific functions I am using like so:
:badd perl.txt
This loads the functions inside that file to the auto-complete buffer
I have one .txt file for each language I am using. I wish to automate this process by having a particular buffer loaded depending on the file type. I tried searching but cloudn't find a good answer. The only lead I have is that I might need to use filetype plugins thought not sure how. Bonus points (though not important) if the solution is just in the rc file (since it will be easy to set up new work places that way)
One possible solution:
autocmd BufNewFile,BufRead *`<extention>` badd `<dir to file>`
Example:
autocmd BufNewFile,BufRead *pl badd /home/vim_autocomplete/perl.txt
To answer the question you asked, I think that
:au FileType * badd path/to/<amatch>.txt
(untested) will work. Instead of using :badd, I would modify the 'complete' option:
:au FileType * setl complete+=k/path/to/<amatch>.txt
Either way, you can wrap the command in a test:
:au FileType * if filereadable("path/to/<amatch>.txt") | ... | endif
(equally untested). Of course, if you want a single autocommand, then (whichever approach you use) you will have to name the files after the file types.
:help :au
:help FileType
:help <amatch>
:help 'complete'

How to automatically run a command after saving a file

I want vim to run g++ after saving a .cpp file to compile it. How can I achieve this? I know how to map an external command to keys, but I want to know how to map a command to another command.
You use :autocmd for that. After a :write, the BufWritePost event is fired. See :h autocmd-events for what's available.
:autocmd BufWritePost <buffer> !g++ %
The % represents the current file (that is written).
A better alternative might be to invoke :make instead; this can also handle more than single file compiles.
To install that for all C++ files, you could just replace <buffer> with *.cpp, but then you're duplication the filetype detection built into Vim. Better put the above :autocmd into e.g. ~/.vim/ftplugin/cpp_autocompile.vim. (This requires that you have :filetype plugin on. Alternatively, you could define an :autocmd FileType cpp autocmd BufWritePost... directly in your ~/.vimrc, but this tends to become unwieldy once you have many customizations.
I wouldn't do that. Most of the time we save files that are not fully compilable (because we want to update tags database, make sure the file is saved before going home). Moreover most of the projects are not made of single files.
But anyway. You are looking for BufWritePost autocommands. For instance,
aug AutoCompileCppFiles
au!
au BufWritePost *.cpp,*.c make
aug END
BTW, :make shall do the work as it'll call gnumake on most systems, and gnumake already knows how to compile single isolated files. If you want to parametrize the compilation, just set $LDFLAGS and $CXXFLAGS ; e.g.:
:let $CXXFLAGS='-std=c++0x -Wall -pedantic'

Vim change filetype after typing shebang line

I want Vim to change the filetype when I type a shebang line (eg. #!/bin/bash) on the first line of a new buffer.
Currently I'm using vim-shebang plugin for changing filetype, but it only works when opening a new buffer.
Clarification: I'm interested in achieving the desired result by mapping <CR> in insert mode. What I want is when I type #!/bin/bash<CR> on the first line of a buffer to automatically execute :filetype detect and return to editing.
You can use
:filetype detect
to re-trigger the filetype detection after you've written the shebang line.
This can be automated with :autocmd, e.g. on the BufWritePost when &filetype is still empty.
I'd recommend to read the (always great) documentation of Vim (which I'm quoting bellow):
:help new-filetype-scripts
This might help you.
If your filetype can only be detected by inspecting the contents of
the file.
Create your user runtime directory. You would normally use the first
item of the 'runtimepath' option. Example for Unix: :!mkdir ~/.vim
Create a vim script file for doing this. Example:
if did_filetype() " filetype already set..
finish " ..don't do these checks
endif
if getline(1) =~ '^#!.*\<mine\>'
setfiletype mine
elseif getline(1) =~? '\<drawing\>'
setfiletype drawing
endif
See $VIMRUNTIME/scripts.vim for more examples.
Write this file as "scripts.vim" in your user runtime directory. For
example, for Unix:
:w ~/.vim/scripts.vim
Update (after the edit of the original question): I'd recommend against the mapping of , but you can do it with
:inoremap <CR> YOUR_SPECIAL_FUNCTION_WHICH_DETECS_THE_CURRENT_LINE_AND_RUNS_FILETYPE_DETECT
The above code snippet (if getline(1)... is enough to get you started. We are not the writethecodeformeforfree.com community.

how to make a vim filetype plugin

I want to make a filetype plugin(in fact asm) of vim. After Searching for a while on the Internet, i found that i should add a asm.vim in ~/.vim/ftplugin folder. So I added that new file asm.vim in that folder and wrote the following codes:
map <F7> oTest<CR><Esc>
a very simple vim script, only output the Test string in the next line. but i failed, when i opened an xxx.asm file and pressed <F7> button, nothing happened. Anything wrong with the code? any help appreciated!
You need to ensure that Vim actually detects the filetype; asm is defined in $VIMRUNTIME/filetype.vim, and there is a syntax, but no filetype plugin yet. Check that
:set filetype?
outputs asm. If not, you need to work on the detection.
You also need to have :filetype plugin on (in your ~/.vimrc); otherwise, no filetype plugin scripts aren't loaded. Check with :scriptnames.
Also note that you should not define global mappings or commands in a filetype plugin. Use :noremap <buffer> <F7> ....
You can check your mapping exists with :verbose map <F7>.

colorcolum only in certain files (e.g. *.cpp, *.h) in VIM

I would like to have a marker at column 80 in VIM, but only in file like *.cpp, *.h. but not in *.txt
For now I have this in my .vimrc
set cc=120
Cheers
Solution:
autocmd FileType cpp,c,cxx,h,hpp,python,sh setlocal cc=120
Vim doesn't directly use the file extension, it has an indirection called filetype, which is then used for syntax highlighting and specific settings.
Put your :set command (as :setlocal, so that it only affects the current buffer [1]) in a new file ~/.vim/after/ftplugin/cpp.vim. (You could also use :autocmd FileType cpp setlocal cc=120 directly in your .vimrc, but the separation is cleaner once you do a lot of that customization.)
[1] Note that 'colorcolumn' is window-local, not buffer-local, so the approach isn't perfect, but usually good enough. It can be perfected with additional BufWinEnter/Leave autocmds.

Resources