Giter VIP home page Giter VIP logo

direnv.vim's Introduction

direnv -- unclutter your .profile

Built with Nix Packaging status latest packaged version(s) Support room on Matrix

direnv is an extension for your shell. It augments existing shells with a new feature that can load and unload environment variables depending on the current directory.

Use cases

  • Load 12factor apps environment variables
  • Create per-project isolated development environments
  • Load secrets for deployment

How it works

Before each prompt, direnv checks for the existence of a .envrc file (and optionally a .env file) in the current and parent directories. If the file exists (and is authorized), it is loaded into a bash sub-shell and all exported variables are then captured by direnv and then made available to the current shell.

It supports hooks for all the common shells like bash, zsh, tcsh and fish. This allows project-specific environment variables without cluttering the ~/.profile file.

Because direnv is compiled into a single static executable, it is fast enough to be unnoticeable on each prompt. It is also language-agnostic and can be used to build solutions similar to rbenv, pyenv and phpenv.

Getting Started

Prerequisites

  • Unix-like operating system (macOS, Linux, ...)
  • A supported shell (bash, zsh, tcsh, fish, elvish, powershell, murex, nushell)

Basic Installation

  1. direnv is packaged in most distributions already. See the installation documentation for details.
  2. hook direnv into your shell.

Now restart your shell.

Quick demo

To follow along in your shell once direnv is installed.

# Create a new folder for demo purposes.
$ mkdir ~/my-project
$ cd ~/my-project

# Show that the FOO environment variable is not loaded.
$ echo ${FOO-nope}
nope

# Create a new .envrc. This file is bash code that is going to be loaded by
# direnv.
$ echo export FOO=foo > .envrc
.envrc is not allowed

# The security mechanism didn't allow to load the .envrc. Since we trust it,
# let's allow its execution.
$ direnv allow .
direnv: reloading
direnv: loading .envrc
direnv export: +FOO

# Show that the FOO environment variable is loaded.
$ echo ${FOO-nope}
foo

# Exit the project
$ cd ..
direnv: unloading

# And now FOO is unset again
$ echo ${FOO-nope}
nope

The stdlib

Exporting variables by hand is a bit repetitive so direnv provides a set of utility functions that are made available in the context of the .envrc file.

As an example, the PATH_add function is used to expand and prepend a path to the $PATH environment variable. Instead of export PATH=$PWD/bin:$PATH you can write PATH_add bin. It's shorter and avoids a common mistake where $PATH=bin.

To find the documentation for all available functions check the direnv-stdlib(1) man page.

It's also possible to create your own extensions by creating a bash file at ~/.config/direnv/direnvrc or ~/.config/direnv/lib/*.sh. This file is loaded before your .envrc and thus allows you to make your own extensions to direnv.

Note that this functionality is not supported in .env files. If the coexistence of both is needed, one can use .envrc for leveraging stdlib and append dotenv at the end of it to instruct direnv to also read the .env file next.

Docs

Make sure to take a look at the wiki! It contains all sorts of useful information such as common recipes, editor integration, tips-and-tricks.

Man pages

FAQ

Based on GitHub issues interactions, here are the top things that have been confusing for users:

  1. direnv has a standard library of functions, a collection of utilities that I found useful to have and accumulated over the years. You can find it here: https://github.com/direnv/direnv/blob/master/stdlib.sh

  2. It's possible to override the stdlib with your own set of function by adding a bash file to ~/.config/direnv/direnvrc. This file is loaded and its content made available to any .envrc file.

  3. direnv is not loading the .envrc into the current shell. It's creating a new bash sub-process to load the stdlib, direnvrc and .envrc, and only exports the environment diff back to the original shell. This allows direnv to record the environment changes accurately and also work with all sorts of shells. It also means that aliases and functions are not exportable right now.

Contributing

Bug reports, contributions and forks are welcome. All bugs or other forms of discussion happen on http://github.com/direnv/direnv/issues .

Or drop by on Matrix to have a chat. If you ask a question make sure to stay around as not everyone is active all day.

Testing

To run our tests, use these commands: (you may need to install homebrew)

brew bundle
make test

Complementary projects

Here is a list of projects you might want to look into if you are using direnv.

Related projects

Here is a list of other projects found in the same design space. Feel free to submit new ones.

  • Environment Modules - one of the oldest (in a good way) environment-loading systems
  • autoenv - older, popular, and lightweight.
  • zsh-autoenv - a feature-rich mixture of autoenv and smartcd: enter/leave events, nesting, stashing (Zsh-only).
  • asdf - a pure bash solution that has a plugin system. The asdf-direnv plugin allows using asdf managed tools with direnv.
  • ondir - OnDir is a small program to automate tasks specific to certain directories
  • shadowenv - uses an s-expression format to define environment changes that should be executed
  • quickenv - an alternative loader for .envrc files that does not hook into your shell and favors speed over convenience.

Commercial support

Looking for help or customization?

Get in touch with Numtide to get a quote. We make it easy for companies to work with Open Source projects: https://numtide.com/contact

COPYRIGHT

MIT licence - Copyright (C) 2019 @zimbatm and contributors

direnv.vim's People

Contributors

agraven avatar delphinus avatar halostatue avatar hauleth avatar kalekseev avatar kyoh86 avatar midchildan avatar p0deje avatar rpdelaney avatar zimbatm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

direnv.vim's Issues

Allow for `:DirenvAllow` command

Similar to how :DirenvExport works, being able to do :DirenvAllow after editing a .envrc file would be handy for those of us not eager to spin up a little terminal window each time configuration is changed.

Invalid argument: stderr

I get this at startup when running 1ad05d9 direnv.vim in Vim 8.0.1257:

Error detected while processing function direnv#export:
line 14:
E475: Invalid argument: stderr

It looks like Vim is executing code intended only for NeoVim.

No matching autocommands

Whenever I start gvim I'm greeted with the following:

No matching autocommands: User DirenvLoaded

This is due to this line in direnv.vim:
https://github.com/direnv/direnv.vim/blob/master/autoload/direnv.vim#L23

I can make this warning go away in my own vimrc by defining that autocmd to do nothing:

autocmd User DirenvLoaded echo

Another idea would be to silence the doautocmd with silent!. But I'm unsure what problems that might cause, if a user wants to echo something out in their autocmd.

Ideas on how we should tackle this?

`:!echo $PATH` and `:echo $PATH` are different

Thank you for this great plugin!

I specify my settings by asdf-direnv.

It edits my $PATH correctly in my zsh, however, :!echo $PATH and :echo $PATH are different on vim with direnv/direnv.vim and this leads to different paths to executables.

my dotfiles

Could this issue be resolved by some settings?

Thank you.

envrc filetype

It would be nice to register .envrc as a custom filetype (envrc), so you can hook into autocmd FileType envrc, etc.

 autocmd BufNewFile,BufRead .envrc set filetype=envrc

Loading problem neovim

I am using direnv with a setup like this https://juliu.is/ditch-your-version-manager/
I have a Ruby On Rails project and I think that somethink not loading correctly in neovim, while with vim is working properly.

I am running the following commands to demonstrate the problem

!which ruby
/nix/store/fv8mr37kp374slp1b8dq231wqprb85fa-ruby-2.7.5/bin/ruby
:!which bundle
/nix/store/fv8mr37kp374slp1b8dq231wqprb85fa-ruby-2.7.5/bin/bundle
:!bundle exec rails
/nix/store/fv8mr37kp374slp1b8dq231wqprb85fa-ruby-2.7.5/lib/ruby/2.7.0/bundler/definition.rb:495:in `validate_ruby!': Your Ruby version is 2.6.8, but your Gemfile specified 2.7.5 (Bundler::RubyVersionMismatch)
        from /nix/store/fv8mr37kp374slp1b8dq231wqprb85fa-ruby-2.7.5/lib/ruby/2.7.0/bundler/definition.rb:470:in `validate_runtime!'
        from /nix/store/fv8mr37kp374slp1b8dq231wqprb85fa-ruby-2.7.5/lib/ruby/2.7.0/bundler.rb:143:in `setup'
        from /nix/store/fv8mr37kp374slp1b8dq231wqprb85fa-ruby-2.7.5/lib/ruby/2.7.0/bundler/setup.rb:20:in `block in <top (required)>'
        from /nix/store/fv8mr37kp374slp1b8dq231wqprb85fa-ruby-2.7.5/lib/ruby/2.7.0/bundler/ui/shell.rb:136:in `with_level'
        from /nix/store/fv8mr37kp374slp1b8dq231wqprb85fa-ruby-2.7.5/lib/ruby/2.7.0/bundler/ui/shell.rb:88:in `silence'
        from /nix/store/fv8mr37kp374slp1b8dq231wqprb85fa-ruby-2.7.5/lib/ruby/2.7.0/bundler/setup.rb:20:in `<top (required)>'
        from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'

shell returned 1

For some reason is trying to use system ruby

Support for direnv loading when accessing the file outside direnv folder through (neo)vim

Lets imagine this source tree:

$ tree -a
Python
├── nix-example
│   ├── .direnv
│   ├── **.envrc**
│   ├── script.py
│   ├── shell.nix
├── nix-example-2
│   ├── .envrc
│   ├── script.py
│   └── shell.nix
└── python
    ├── .envrc
    ├── Main.py
    └── shell.nix

The way I think this plugins works is by verifying if vim/neovim working directory have .envrc (Fix me if I'm wrong pls)
So if I try:

$ nvim nix-example

and then open script.py, it works flawlessly, since (neo)vim current working directory is nix-example which have .envrc.

However if we go back and try to open the script.py file directly without entering directory like:

$ nvim nix-example/script.py

the $PATH isnt updated and then other plugins like lsp doesnt work properly because it can't access the installed packages inside directory.

Is there anyway to this plugin verify if there is any .envrc in upper directories and load it automatically?

Clobbers vim-only environment variables modifications

I'm not sure how this happens, but direnv.vim appears to clobber environment variable values that are set only for the vim process (e.g. via env FOO=bar vim ... or vim being launched through a wrapper script).

From what I understand, direnv.vim just calls direnv to get the differing environment variables, which should be diffing against the environment it is launched in (and processes launched through :!{cmd} do inherit the vim environment, at least), and thus should return a set of environment variables that take into account values set only for the vim process... but it doesn't.

Instead, it is somehow returning a set of environment variables equivalent to what I get from running direnv in the parent shell of the vim process, rather than in the vim process itself. Any variables that are modified both by direnv and by some wrapper around vim will effectively have the vim-specific changes dropped (in my case, $PATH).

direnv breaks vim-black plugin when using layout_pipenv

I don't know if this is a bug with direnv or with vim-black:

$ cd pwstore/
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.
$ cat .envrc 
layout_pipenv
$ vim foo  # no problem
$ direnv allow
direnv: loading .envrc
direnv: export +PIPENV_ACTIVE +VIRTUAL_ENV -PS2 ~PATH
$ vim foo  # problem
Error detected while processing /home/ryan/.dotfiles/home/.vim/plug/black/plugin/black.vim:
line  135:
Traceback (most recent call last):
  File "<string>", line 63, in <module>
ModuleNotFoundError: No module named 'black'
Press ENTER or type command to continue
$ 

DirenvLoaded event seems bugged, or doesn't work as expected

I'm having an issue where my LSP servers can't find my project's dependencies, because direnv activates a Python virtualenv after my LSP servers have already started up.

To fix this, I thought I'd use the DirenvLoaded event to restart my LSP servers whenever the direnv environment is loaded:

local group = vim.api.nvim_create_augroup("DirenvLoaded", { clear = true })
vim.api.nvim_create_autocmd({ "User" }, {
  group = group,
  pattern = "DirenvLoaded",
  callback = function()
    vim.notify("Loaded environment from direnv")

    if vim.cmd.LspRestart ~= nil then
      vim.notify("Restarting LSP servers")
      vim.cmd.LspRestart()
    end
  end
})

Unexpected behavior:

  • Fires when I open nvim, no matter if the current directory has a .envrc or not
  • If I'm in a project that uses direnv, DirenvLoaded fires every time I change focus to a different buffer (changing focus between two windows with the same buffer doesn't trigger the event)

This behavior doesn't make any sense to me, so I'm assuming it's a bug.


$ nvim --version
NVIM v0.10.0-dev-2295+g672556525
Build type: RelWithDebInfo
LuaJIT 2.1.1707061634
Run "nvim -V1 -v" for more info

License?

I'd like to base another plugin on this one but there's no license. Is it intended to be MIT?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.