18

I'm trying to split my vimrc up into multiple files - init.vim, keybindings.vim, ui.vim, etc. - but I can't get Vim to source files relative to init.vim (it instead sources relative to where I launch Vim from.

This is what I've got at the top of init.vim:

source keybindings.vim
source ui.vim

If I run vim from the same directory as those files, it works fine; if I run it from any other directory, I get the following errors:

Error detected while processing /path/to/vimrc:
line 1:
E484: Can't open file keybindings.vim
line 2:
E484: Can't open file ui.vim
Press ENTER or type command to continue

Edit: It's worth noting that I'm using NixOS, so I don't know what the absolute paths will be, nor if they would be constant if I found out.

jdhao
  • 24,001
  • 18
  • 134
  • 273
dontexist
  • 5,252
  • 4
  • 27
  • 51
  • You know, you can split your .vimrc into plugins (i.e. files dropped into your `~/.vim/plugin/` directory. However, there is no way to control their relative loading order. – Luc Hermitte Oct 26 '17 at 23:17

7 Answers7

14

I think you can use

runtime keybindings.vim
dave
  • 62,300
  • 5
  • 72
  • 93
  • I tried this, but I couldn't get it to work. I'll try to dig deeper into why the particular directory I'm using isn't in the `runtimepath` or if I can put it there somehow. – dontexist Oct 27 '17 at 07:32
12

Source needs the full path, you can however simplify it using something like this :

let path = expand('%:p:h')
exec 'source' path . '/keybindings.vim'

You can have a look at mine here - https://github.com/dhruvasagar/dotfiles/blob/master/vim/vimrc for reference.

Dhruva Sagar
  • 7,089
  • 1
  • 25
  • 34
6

If the order is not important, you can just put your scripts into ~/.vim/plugin/, and they will be sourced after ~/.vimrc. You can check :scriptnames output to see what gets sourced when.

You can influence the ordering somewhat via the plugin filenames. For example, I have a ~/.vim/plugin/00plugin-configuration.vim that configures Vim plugins; the 00... ensures this is sourced first.

To get finer control, I would instead put the scripts into ~/.vim/. Vim will ignore them there, but they can easily be addressed via :runtime, which looks in all runtimepaths, and ~/.vim/ typically is included in 'runtimepath':

# .vimrc
runtime init.vim
runtime keybindings.vim
...

Relevant help pages: :help .vimrc and :help load-plugins.

Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324
4

I have met exactly the same issue with you in Neovim. I split my large init.vim file into several small vim scripts and I want to source them inside init.vim. This is what I get finally based on @Dhruva Sagar's links:

let g:nvim_config_root = stdpath('config')
let g:config_file_list = ['variables.vim',
    \ 'options.vim',
    \ 'autocommands.vim',
    \ 'mappings.vim',
    \ 'plugins.vim',
    \ 'ui.vim'
    \ ]

for f in g:config_file_list
    execute 'source ' . g:nvim_config_root . '/' . f
endfor
jdhao
  • 24,001
  • 18
  • 134
  • 273
3

Building on Dhruva's answer, you can make a function to help out with this

function! SourceLocal(relativePath)
  let root = expand('%:p:h')
  let fullPath = root . '/'. a:relativePath
  exec 'source ' . fullPath
endfunction

You then use it like

call SourceLocal ("yourScript.vim")
JonnyRaa
  • 7,559
  • 6
  • 45
  • 49
0

As none of the solutions works as a real substitute for source working globally (on any script, even sourced from vimrc), I ended up with this solution and decided to share here, which can be used as a substitute for source with relative support, as simple as:

Rsource /home/me/.vim/your/file/path
Rsource $HOME/.vim/your/file/path
Rsource your/file/path
Rsource ../your/file/path

To use it, this must be defined on your vimrc or any file sourced by it before you can use Rsource:

if !exists('g:RelativeSource')
    function! g:RelativeSource(file)
        let file = expand(a:file)

        " if file is a root path, just source it
        if stridx(file, '/') == 0
            exec 'source ' . file
            return
        endif

        let sfile = expand('<sfile>:p:h')

        " If this is called outside this script, it will contains this script
        " name, this function name, a script_marker then the executing script name
        " In this case we extract just the last part, the script name which called
        " the this function
        let script_marker = '..script '
        let path_index = strridx(sfile, script_marker)

        if path_index == -1
            let path_index = 0
        else
            let path_index += len(script_marker)
        endif

        let path = strpart(sfile,path_index)
        let absolute_path = resolve(path . '/'. file)

        exec 'source ' . absolute_path
    endfunction

    command! -nargs=1 Rsource :call g:RelativeSource(<q-args>)
endif

This is safe to be used in any script or plugin.

sergiogarciadev
  • 2,061
  • 1
  • 21
  • 35
-2

These are all great solutions, and this is what I ended up using.

let home = expand('~')
exec 'source' home . '/.config/nvim/prettierConfig.vim'
fliptopbox
  • 123
  • 2