How to switch between multiple vim configurations with a command or local vimrc files?

后端 未结 12 1348
花落未央
花落未央 2020-12-04 05:43

I work in several groups, each of which has its own tab/indentation/spacing standards in C.

Is there a way to have separate selectable VIM configurations for each so

12条回答
  •  北荒
    北荒 (楼主)
    2020-12-04 06:05

    In Summary

    There are a few ways to do this, of which most have been suggested, but I thought I'd summarise them with two extra ones:

    • Per-directory vimrc - has the disadvantage that Vim must be started in the right directory: if your project is in ~/project1 and you have ~/project1/.vim.custom and do cd ~ ; vim project1/file.c, the custom settings won't be found.
    • Modelines - very effective, but has the disadvantage of needing to add them to all files (and remember to add them to new files)
    • Directory specific autocommands - this is very effective
    • Scan for a specific header in the file (see below) - this is the one I've used most in the past where working for different companies or on clearly named projects
    • Per-directory vimrc that's checked when the file is opened (see below). Another fairly easy one to implement, especially if your project code is all in one place.

    Scanning for a Header

    In a lot of organisations, there's a standard header (with a copyright notice and project name etc) at the top of every source file. If this is the case, you can get Vim to automatically scan the first (e.g.) 10 lines of the file looking for a keyword. If it finds it, it can change your settings. I've modified this to make it simpler than the form I use (which does lots of other things), but create a ~/.vim/after/filetype.vim (if you don't have one yet) and add something like this:

    au FileType * call ConfigureFiletypes(expand(""))
    
    " List of file types to customise
    let s:GROUPNAMETypes = ['c', 'cpp', 'vhdl', 'c.doxygen']
    
    func! CheckForGROUPNAMECode()
        " Check if any of the first ten lines contain "GROUPNAME".
    
        " Read the first ten lines into a variable
        let header = getline(1)
        for i in range(2, 10)
            let header = header . getline(i)
        endfor
    
        if header =~ '\'
            " Change the status line to make it clear which
            " group we're using
            setlocal statusline=%<%f\ (GROUPNAME)\ %h%m%r%=%-14.(%l,%c%V%)\ %P
            " Do other customisation here
            setlocal et
            " etc
        endif
    endfunc
    
    func! ConfigureFiletypes(filetype)
        if index(s:GROUPNAMETypes, a:filetype) != -1
            call CheckForGROUPNAMECode()
        endif
    endfunc
    

    Whenever a file of any type is opened and the file type is set (the au FileType * line), the ConfigureFiletypes function is called. This checks whether the file type is in the list of file types associated with the current group (GROUPNAME), in this case 'c', 'cpp', 'vhdl' or 'c.doxygen'. If it is, it calls CheckForGROUPNAMECode(), which reads the first 10 lines of the file and if they contain GROUPNAME, it does some customisation. As well as setting expandtabs or whatever, this also changes the status bar to show the group name clearly so you know it's worked at a glance.

    Checking for Configuration When Opening

    Much like JS Bangs' suggestion, having a custom configuration file can be useful. However, instead of loading it in vimrc, consider something like this, which will check when a .c file is opened for a .vim.custom in the same directory as the .c file.

    au BufNewFile,BufRead *.c call CheckForCustomConfiguration()
    
    function! CheckForCustomConfiguration()
        " Check for .vim.custom in the directory containing the newly opened file
        let custom_config_file = expand('%:p:h') . '/.vim.custom'
        if filereadable(custom_config_file)
            exe 'source' custom_config_file
        endif
    endfunction
    

提交回复
热议问题