Last active
April 28, 2023 22:14
-
-
Save SteveBenner/588fff3e54636f3d8297 to your computer and use it in GitHub Desktop.
Define Environment variables in your shell using a YAML config file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I execute this script by loading it into my Bash profile as follows:
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