I have 3 languages and any can be a source or target so I need some flexibility. I am successfully loading a language translation specific setup with this:

let g:tr_source = 'dyu'    
let g:tr_target = 'fr'    
call system('export TR_SOURCE=dyu')    
call system('export TR_TARGET=fr')
autocmd BufNewFile $TR_SOURCE/*/*.adoc source ~/.config/nvim/$TR_SOURCE.vim
autocmd BufNewFile $TR_TARGET/*/*.adoc source ~/.config/nvim/$TR_TARGET.vim

I've tried a bunch of different ways to use g:tr_source etc. But with no success. I did go to :help pat, and that's what gave me the idea to use an environment variable. But what I'm doing although it's working seems a bit of a hack. And I don't want to set the variable twice. Is there a better 'vim' way?

  • I'm a bit puzzled at your mention that this approach worked... Environment variables don't usually work like that... Are you sure this worked? Do you by any chance also have them set in the shell where you launch Vim from? Or are you on Windows? (I think environment variables might work differently on Windows, not very sure about that...)
    – filbranden
    Commented Nov 21, 2020 at 22:32
  • vi.stackexchange.com/q/21392/10604
    – D. Ben Knoble
    Commented Nov 21, 2020 at 23:54

2 Answers 2


Setting environment variables with system() and export will not work. Environment variables set this way will only exist in the shell (or process) where they're defined and their descendents, so setting them in a shell spawned by system() will not make them available in Vim itself.

You can set environment variables directly in Vim, by using the :let command and using the $ prefix to refer to the variables (that indicates to Vim that you're accessing or setting environment variables.)

So this should work:

let $TR_SOURCE = 'dyu'

Or even:

let $TR_SOURCE = g:tr_source

That should allow you to refer to them from the :source command in your autocmd's. Note that these variables will also be accessible from any commands or shells you spawn from Vim, be it from the system() function or the :! command or some other command that takes an expression involving ! to run an external command.

Another possibility is to use Vim global variables directly, but in that case you'll need to use :execute, since the :source command doesn't interpret Vim variables directly (only environment variables.) You'll actually also need it for the whole autocmd since you need it in its pattern too.

You can refer to the Vim variables directly in your autocmd's with:

execute 'autocmd BufNewFile ' . g:tr_source . '/*/*.adoc source ~/.config/nvim/' . g:tr_source . '.vim'
execute 'autocmd BufNewFile ' . g:tr_target . '/*/*.adoc source ~/.config/nvim/' . g:tr_target . '.vim'

If you don't mind the small environment pollution from setting them as environment variables (which might even come useful as you can refer to them in interactive usage), it looks like the option of using environment variables, setting them with :let, is a much more convenient approach.

  • 1
    Thank you!. Yes as you pointed out I was probably trying so many things I had set that environment variable in my shell before launching vim and led myself to believe I had found something that worked.... So its 'execute' that is the solution I am looking for. Although I should investigate uc-hermitte 's suggestion to use a local vimrc per language directory. Thanks very much for the insight.
    – Boyd
    Commented Nov 22, 2020 at 17:46

You don't need environment variables for your use case. As filbranden said, you can directly use Vim variables, through :exe.

Using an environment variable would make sense only if you use a variable that is being set before starting Vim, or if you expect to execute (from Vim) an external program that relies on that environment variable. In that latter case :let $VARNAME = value is the (only vanilla) way that will work -- given how subprocesses works in programming. The global environment variable named $VARNAME would be set.

Now, your use case makes think about local-vimrcs actually, or any other project specific configuration. While we could hard-code pathnames in autocommands, we can also drop vimrc-like files that contain buffer specific settings (i.e. <buffer> mappings/abbreviations, :command-buffer, b:uffer-local variables, or even override specific snippets/templates if your snippet plugin/engine supports it, and so on) and use plugins to load them automatically.

Note: this approach can also be used to have a different values for an environment variable depending on the current buffer. BTW, I also provide another crazy approach on this topic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.