Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/Shopify/shadowenv
reversible directory-local environment variable manipulations
https://github.com/Shopify/shadowenv
Last synced: about 2 months ago
JSON representation
reversible directory-local environment variable manipulations
- Host: GitHub
- URL: https://github.com/Shopify/shadowenv
- Owner: Shopify
- License: mit
- Created: 2019-01-03T19:04:03.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2024-03-01T18:31:08.000Z (7 months ago)
- Last Synced: 2024-04-14T09:45:33.080Z (5 months ago)
- Language: Rust
- Homepage: https://shopify.github.io/shadowenv/
- Size: 604 KB
- Stars: 375
- Watchers: 375
- Forks: 18
- Open Issues: 16
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
# Shadowenv
Shadowenv provides a way to perform a set of manipulations to the process environment upon entering
a directory in a shell. These manipulations are reversed when leaving the directory, and there is
some limited ability to make the manipulations dynamic.![shadowenv in action](https://burkelibbey.s3.amazonaws.com/shadowenv.gif)
In order to use shadowenv, add a line to your shell profile (`.zshrc`, `.bash_profile`, or
`config.fish`) reading:```bash
eval "$(shadowenv init bash)" # for bash
eval "$(shadowenv init zsh)" # for zsh
shadowenv init fish | source # for fish
```With this code loaded, upon entering a directory containing a `.shadowenv.d` directory,
any `*.lisp` files in that directory will be executed and you will see "activated shadowenv." in your
shell.The syntax for the `.shadowenv.d/*.lisp` files is [Shadowlisp](https://shopify.github.io/shadowenv/),
a minimal [Scheme-like](https://en.wikipedia.org/wiki/Scheme_(programming_language)) language.
Unlike other tools like [direnv](https://direnv.net/), this has the interesting property of allowing
us to do things like simulate `chruby reset` upon entry into a directory without the user having
`chruby` installed (and undo these changes to the environment when `cd`'ing back out):```scheme
(provide "ruby")(when-let ((ruby-root (env/get "RUBY_ROOT")))
(env/remove-from-pathlist "PATH" (path-concat ruby-root "bin"))
(when-let ((gem-root (env/get "GEM_ROOT")))
(env/remove-from-pathlist "PATH" (path-concat gem-root "bin"))
(env/remove-from-pathlist "GEM_PATH" gem-root))
(when-let ((gem-home (env/get "GEM_HOME")))
(env/remove-from-pathlist "PATH" (path-concat gem-home "bin"))
(env/remove-from-pathlist "GEM_PATH" gem-home)))
```The intention isn't really for users to write these files directly, nor to commit them to
repositories , but for other tool authors to generate configuration on the user's machine. Here's
an example of a generated Shadowlisp file for activating ruby 2.7.1:```scheme
(provide "ruby" "2.7.1")(when-let ((ruby-root (env/get "RUBY_ROOT")))
(env/remove-from-pathlist "PATH" (path-concat ruby-root "bin"))
(when-let ((gem-root (env/get "GEM_ROOT")))
(env/remove-from-pathlist "PATH" (path-concat gem-root "bin")))
(when-let ((gem-home (env/get "GEM_HOME")))
(env/remove-from-pathlist "PATH" (path-concat gem-home "bin"))))(env/set "GEM_PATH" ())
(env/set "GEM_HOME" ())
(env/set "RUBYOPT" ())(env/set "RUBY_ROOT" "/opt/rubies/2.7.1")
(env/prepend-to-pathlist "PATH" "/opt/rubies/2.7.1/bin")
(env/set "RUBY_ENGINE" "ruby")
(env/set "RUBY_VERSION" "2.7.1")
(env/set "GEM_ROOT" "/opt/rubies/2.7.1/lib/ruby/gems/2.7.0")(when-let ((gem-root (env/get "GEM_ROOT")))
(env/prepend-to-pathlist "GEM_PATH" gem-root)
(env/prepend-to-pathlist "PATH" (path-concat gem-root "bin")))(let ((gem-home
(path-concat (env/get "HOME") ".gem" (env/get "RUBY_ENGINE") (env/get "RUBY_VERSION"))))
(do
(env/set "GEM_HOME" gem-home)
(env/prepend-to-pathlist "GEM_PATH" gem-home)
(env/prepend-to-pathlist "PATH" (path-concat gem-home "bin"))))
```## `.shadowenv.d`
The `.shadowenv.d` directory will generally exist at the root of your repository (in the same
directory as `.git`.We *strongly* recommend creating `gitignore`'ing everything under `.shadowenv.d` (`echo '*' > .shadowenv.d/.gitignore`).
A `.shadowenv.d` will contain any number of `*.lisp` files. These are evaluated in the order in which
the OS returns when reading the directory: generally alphabetically. We *strongly* recommend using
a prefix like `090_something.lisp` to make it easy to maintain ordering.`.shadowenv.d` will also contain a `.trust-` file if it has been marked as trusted. (see
the trust section).## Language
See https://shopify.github.io/shadowenv/ for Shadowlisp documentation.
## Integrations
Shadowenv has plugins for multiple editors and/or IDEs:
* [shadowenv.vim](https://github.com/Shopify/shadowenv.vim)
* [shadowenv.el](https://github.com/Shopify/shadowenv.el)
* [vscode-shadowenv](https://github.com/Shopify/vscode-shadowenv)
* [atom-shadowenv](https://github.com/Shopify/atom-shadowenv)
* [sublime-shadowenv](https://github.com/Shopify/sublime-shadowenv)
* [intellij-shadowenv](https://github.com/Shopify/intellij-shadowenv)## Trust
If you `cd` into a directory containing `.shadowenv.d/*.lisp` files, they will not be run and you
will see a message indicating so. This is for security reasons: we don't want to enable random
stuff downloaded from the internet to modify your `PATH`, for example.You can run `shadowenv trust` to mark a directory as trusted.
Technically, running `shadowenv trust` will create a file at `.shadowenv.d/.trust-`,
indicating that it's okay for `shadowenv` to run this code. The `.shadowenv.d/.trust-*` file contains
a cryptographic signature of the directory path. The key is generated the first time `shadowenv` is
run, and the fingerprint is an identifier for the key.