Code Monkey home page Code Monkey logo

environ's Introduction

MELPA

environ

An Emacs package that provides some helpful functions for working with environment variables and env files.

This package uses a bash subprocess to fully expand variables, which means you can leverage the power of bash to define variables.

Table of Contents

Example Usage

Create an env file with the following contents at ~/.env/foo:

FOO=~/foo
BAR=$FOO/bar
BAZ=$(pwd)

Now, run M-x environ-set-file, which will prompt for a file. Navigate to ~/.env/foo and press Enter. Voilà, you have three new environment variables set in Emacs. Verify you can retrieve them with M-x getenv. Unset them with M-x environ-unset-file (this will again prompt for a file).

Besides setting (and unsetting) environment variables from env files, this package provides an API for common operations with environment variables. Examples below.

API

environ-set-file (file-path)

[interactive] Set environment variables defined in the file at FILE-PATH.

When used interactively, prompts for the file to load. The prompt begins in environ-dir. When used from elisp, FILE-PATH can either be absolute or relative to default-directory.

(environ-set-file (expand-file-name "~/.env/foo"))

environ-unset-file (file-path)

[interactive] Unset the environment variables defined in FILE-PATH.

See the documentation for environ-set-file.

(environ-unset-file (expand-file-name "~/.env/foo"))

environ-set-str (str)

Set environment variables defined in the given string STR.

Parse STR like an env file. STR is split into newline-delimited lines, where each line is a key/value pair.

(environ-set-str "A=foo\nB=$A-bar")
(getenv "A") ;; => "foo"
(getenv "B") ;; => "foo-bar"

environ-unset-str (str)

Unset environment variables defined in string STR.

Parse STR like an env file. STR is split into newline-delimited pairs, where the key of each pair is the environment variable name. The value of each pair is discarded, as the environment variable will be unset regardless of its value.

(environ-unset-str "A=foo\nB=$A-bar")
(getenv "FOO") ;; => nil
(getenv "BAR") ;; => nil

environ-get-pairs

Return all current environment variables as a list of pairs.

(environ-get-pairs)
;; => (("LANG" "en_US.UTF-8")
;;     ("HOME" "/Users/cfclrk")
;;     ...)

environ-set-pairs (pairs)

Set the environment variables defined by the given PAIRS.

PAIRS is a list of pairs, where each pair is an environment variable name and value.

(environ-set-pairs '(("A" "foo")
                     ("B" "$A-bar")))
(getenv "A") ;; => "foo"
(getenv "B") ;; => "foo-bar"

;; Prevent interpolation using single quotes
(environ-set-pairs '(("A" "foo")
                     ("B" "'$A-bar'")))
(getenv "A") ;; => "foo"
(getenv "B") ;; => "$A-bar"

environ-unset-pairs (pairs)

Unset the environment variables defined in the given PAIRS.

PAIRS is a list of pairs, where each pair is an environment variable name and value. The value in each pair doesn't matter; each environment variable will be unset regardless of its value.

(getenv "A") ;; => "foo"
(environ-unset-pairs '(("A" "foo")
                       ("B" "bar")))
(getenv "A") ;; => nil

environ-get-names

Return a list of all current environment variable names.

(environ-get-names)
;; => ("HOME" "FOO" "BAR" ...)

environ-unset-names (names)

Unset environment variables with the given NAMES.

NAMES is a list of environment variable names which may or may not be currently set. This function removes each name from process-environment if it is set.

(getenv "A") ;; => "foo"
(environ-unset-names '("A" "B"))
(getenv "A") ;; => nil

environ-unset-name (name)

[interactive] Unset the environment variable NAME.

Unset the given environment variable by removing it from process-environment if it is there. Note that calling setenv with a prefix argument can unset a variable by setting its value to nil, but the variable remains in process-environment. This function completely removes the variable from process-environment.

Configuration

environ-dir

Directory to prompt for env files.

This variable is only used by environ-set-file and environ-unset-file when they are run interactively. Defaults to (expand-file-name "~/").

(setq environ-dir (expand-file-name "~/.env"))

environ-pre-eval-functions

A list of functions to run before shell evaluation.

Each function takes a list of pairs and returns an updated list of pairs. Defaults to nil.

(setq environ-pre-eval-functions
      '((lambda (pairs)
          (cons '("A" "a") pairs))
        (lambda (pairs)
          (cons '("B" "b") pairs))))

environ-post-eval-functions

A list of functions to run after shell evaluation.

Each function takes a list of pairs and returns an updated list of pairs. Defaults to '(environ-ignore-bash-vars).

(setq environ-post-eval-functions
      '((lambda (pairs)
          (cons '("A" "a") pairs))
        (lambda (pairs)
          (cons '("B" "b") pairs))))

File Format

Each line in an env file must be in a KEY=VALUE format, with one entry per line. This package invokes an bash shell to interpret the file, so shellisms should work (like ~ expansion or using single quotes to prevent variable interpolation).

For example:

A=foo
B="bar"
C='R$%!$KP$'
D=$A-bar
E=~/cats

Usage from org-mode

This example shows one way to set environment variables in an org document using a table:

#+NAME: env
| Var  | Value           |
|------+-----------------|
| FOO  | ~/foo           |
| BAR  | $FOO/bar        |
| BAZ  | '$FOO/bar'      |

#+begin_src emacs-lisp :var env=env
  (environ-set-pairs env)
#+end_src

How it Works

This package works by evaluating the provided input in a bash subprocess, and then returning the difference between current environment and the subprocess environment.

You can think of each function in terms of two phases: the way in, and the way out. On the way in, input is parsed into a list of pairs (the IR) if it isn't already in that form. Then, all pre-eval-functions (if any) are run, which may update the IR. The IR is then assembled into a bash script, executed, and then the result of running printenv in the bash subprocess is returned.

flowchart LR
    env-file[env file] -- parse --> IR
    IR -- pre-eval-functions --> IR
    IR -- build script --> script[bash script]
    script -- run script --> stdout

On the way out, we start with two things: the stdout that was produced by running printenv in the bash process, and the current process-environment in Emacs. The bash stdout is parsed back into a list of pairs (IR_1) and all post-eval functions (if any) are run, which may update IR_1. Emacs' current process-environment is parsed into a separate list of pairs (IR_2). Then, the two IRs are compared, and only elements in IR_1 that are not in IR_2 are kept (IR_3). Finally, each pair in IR_3 is set in the current process-environment.

flowchart LR
  stdout -- parse --> IR_1
  IR_1 -- post-eval-functions --> IR_1
  cur[current environment] -- parse --> IR_2
  IR_1 -- diff --> IR_3
  IR_2 -- diff --> IR_3
  IR_3 -- setenv each pair --> done

See Also

environ's People

Contributors

cfclrk avatar syohex avatar

Stargazers

D.K. avatar Bryce avatar Koji Matsuda avatar Juan A. Ruz avatar stardiviner avatar Daniel Mahler avatar Sandy avatar

Watchers

 avatar

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.