Skip to content

Instantly share code, notes, and snippets.

@SteveBenner
Last active April 28, 2023 22:14
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save SteveBenner/588fff3e54636f3d8297 to your computer and use it in GitHub Desktop.
Save SteveBenner/588fff3e54636f3d8297 to your computer and use it in GitHub Desktop.
Define Environment variables in your shell using a YAML config file
#!/usr/bin/env ruby
#
# This bit of code lets you define Environment variables in your shell via a YAML file.
# It works by composing Bash commands from the parsed data, meant to be executed within
# a Bash environment, which will export the variables just as in a regular Bash profile.
# This is accomplished by executing this script via the Bash substitution syntax $(...)
# which returns the output of evaluating whatever is inside the parenthesis, which in
# the case of this script would be appropriate 'export' commands that are run by Bash.
#
# This version is designed to parse aliases organized under named groups in the YAML
# file, so the first level of mappings are purely semantic, and are used to keep the
# data organized and well-documented.
#
require 'yaml'
require 'pathname'
$stdout.sync = true
DATA_FILE = '~/.env' # a YAML file of your choice
# Use of Pathname is optional, but I think it makes for particularly clean, efficient code
VARS = YAML.load_file(Pathname(DATA_FILE).expand_path.realpath)
.group_by { |key, val| val.class } # this underrated `Enumerable` method is a neat way to sort data
# The two lines of code below are great examples of how Ruby excels at data manipulation!
# This might look kludgy, but all this line does is separate keys from the first-level mappings
# that are aliases (not named groups), and then puts them into their own group for parsing.
variable_groups = VARS[Hash] << ['_ungrouped', Hash[VARS[String] + VARS[Array]]]
# While the previous line was very dense and focused on brevity, from the result we can
# obtain a radically transformed collection simply by chaining several mutators together
# and running it through the closest thing Ruby comes to having for list comprehension. Elegant!
variable_groups.transpose.last.reduce({}, &:merge).each do |varname, value|
val = case value
# Regular values are just aliased 'as-is'
when String, Integer then value
# Arrays are used to represent PATH-type variables, whose value is composed of multiple items
when Array then value.join(File::PATH_SEPARATOR)
# Changing nil values to an empty String allows empty keys in the data file to be tolerated
when nil then ''
else nil
end
puts val.nil? ? # check for values whose data type is unsupported
"WARNING: Bad value given for environment variable #{varname}: #{value}" :
"export #{varname}=#{val}" unless val.to_s.empty? # empty values are ignored
end
#!/usr/bin/env ruby
#
# This bit of code lets you define Environment variables in your shell via a YAML file.
# It works by composing Bash commands from the parsed data, meant to be executed within
# a Bash environment, which will export the variables just as in a regular Bash profile.
# This is accomplished by executing this script via the Bash substitution syntax $(...)
# which returns the output of evaluating whatever is inside the parenthesis, which in
# the case of this script would be appropriate 'export' commands that are run by Bash.
#
require 'yaml'
require 'pathname'
$stdout.sync = true
DATA_FILE = '~/.env' # a YAML file of your choice
# Use of Pathname is optional, but I think it makes for particularly clean, efficient code
VARS = YAML.load_file Pathname(DATA_FILE).expand_path.realpath # use absolute path, follow symlinks
# Parse the data file and export variables to the shell environment
VARS.each do |varname, value|
val = case value
# Regular values are just aliased 'as-is'
when String, Integer then value
# Arrays are used to represent PATH-type variables, whose value is composed of multiple items
when Array then value.join(File::PATH_SEPARATOR)
# Changing nil values to an empty String allows empty keys in the data file to be tolerated
when nil then ''
else nil
end
puts val.nil? ? # check for values whose data type is unsupported
"WARNING: Bad value given for environment variable #{varname}: #{value}" :
"export #{varname}=#{val}" unless val.to_s.empty? # empty values are ignored
end
# These are some examples of how one would store Environment variables in YAML
EDITOR: /usr/bin/nano
PREFIX: /usr/local
CC: gcc
# Sass
SASS_PATH: [~/.sasslib]
# Node.js load paths
NODE_PATH: # using an alternate installation due to problem with Homebrew on Mavericks
- ~/.node/lib
- ~/.node/lib/node_modules
# Directories to add to the $LOAD_PATH variable for all Ruby interpreters
RUBYLIB:
- ~/.rubylib
@SteveBenner
Copy link
Author

I execute this script by loading it into my Bash profile as follows:

# Load ENV vars
$(~/.yaml-env-vars-groups.rb)

Alternatively, you could omit the ‘shebang’ (the first line of the script) and just use the Ruby interpreter directly

$(ruby ~/.yaml-env-vars-groups.rb)

Don’t forget that the script needs execution permission!

chmod u+x ~/.yaml-env-vars-groups.rb

If you like this approach, be sure to check out how I use the same technique to define Bash aliases

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment