In this post, I will explain how to load custom variables by reading a JSON file, this will be done every time we open a Terminal. I will also improve the shortcuts we create in the previous posts.
Template ready to use!
The cangulo-templates/linux-terminal-profile repository contains a ready-to-use template based on this article.
Requirements
- Linux (I'm using Elementary OS, a Ubuntu-based distro, try it!)
- VS Code. If you don't want to use it, change all the
code
commands in the bash code for your text editor. Alternatives: gedit or gnome-text-editor. - fzf command-line fuzzy finder
Notes
- Remember to add execution permissions to the scripts through
chmod +x
- Profile script:
$HOME/.bashrc
for bash terminal and$HOME/.zshrc
for zsh
Problem
Simplify, as much as possible, the process to set up my shortcuts every time I migrate to a new computer, personal or work. This process is: download and setups all my scripts in the Bash profile.
Idea
Remember the concept Behavior vs Configuration I explained in my previous post? We are going to continue using it ๐. Let me list down the main points:
- Variables are stored in a JSON file. We want those variables to be available during all the terminal sessions.
- Functions depend on those variables, values that could change depending on the PC your use, for example paths, shouldn't be hard-coded.
- Both, variables and functions are added in the Bash Profile.
Nice, now that we have the main points, let me show the implementation.
Implementation
First, we have the JSON file containing the variables:
{
"LOCAL_REPOS": "/home/cangulo/repos",
"LOCAL_DOCUMENTS": "/home/cangulo/Documents",
"SCRIPTS_FOLDER": "/home/cangulo/repos/cangulo-blog/cangulo.github.io/blog/posts/bash/4-create-config-repo/code/scripts",
"BOOKMARKS_FILE": "/home/cangulo/repos/cangulo-blog/cangulo.github.io/blog/posts/bash/4-create-config-repo/code/2-bookmarks.json"
}
Each JSON key will be an environment variable, I prefer to define them in upper case to differentiate them from other variables we define during the terminal session.
Then, in the bash profile we only have to do the next actions:
- Export the path to the JSON settings. My convention is to call this variable as
SETTINGS_FILE
. - Call a script to load all the variables and functions using the previous settings. Let's call this script
load-custom-profile.sh
.
Next is the code for that. Please append it in your profile.
# Update FULL_PATH_TO_JSON_SETTINGS with yours
export SETTINGS_FILE="FULL_PATH_TO_JSON_SETTINGS"
source FULL_PATH/load-custom-profile.sh
Please note we use the export
keyword, which sets SETTINGS_FILE
as an environment variable. In that way, it will be available for other scripts. Please check this link for more details.
load-custom-profile.sh
This script should perform the next actions:
- Verify
$SETTINGS_FILE
is defined and valid:- String is not empty
- Path provided exists
- Read the JSON file and export the variables. The command is based on
jq
andeval
as explained in my previous post for more details. The main difference now is the use of theexport
command, following the pattern:export KEY='VALUE'
#!/bin/bash
# verify $SETTINGS_FILE is empty
if [[ -z "$SETTINGS_FILE" ]]; then
echo "no SETTINGS_FILE provided"
return -1
fi
# verify the path at $SETTINGS_FILE exists
if [ ! -f $SETTINGS_FILE ]; then
echo "SETTINGS_FILE path does not exists"
return -1
fi
# export variables
for command in "$(jq -r 'to_entries | .[] | "export " + .key + "=" + (.value | @sh) ' <$SETTINGS_FILE)"; do
eval $command
done
# source functions and aliases
for i in $SCRIPTS_FOLDER/*.sh; do source "$i"; done
# List the bookmarks when opening the terminal
listBookmarks
Next are the scripts stored in $SCRIPTS_FOLDER
:
- aliases:
- bash
- zsh
#!/bin/bash
alias tf="terraform"
alias goToRepos="cd $LOCAL_REPOS"
alias goToDocs="cd $LOCAL_DOCUMENTS"
alias editAwsCredentials="code $HOME/.aws"
alias editBashProfile="code $HOME/.bashrc"
aliases-bash.sh
#!/bin/bash
alias tf="terraform"
alias goToRepos="cd $LOCAL_REPOS"
alias goToDocs="cd $LOCAL_DOCUMENTS"
alias editAwsCredentials="code $HOME/.aws"
alias editZshProfile="code $HOME/.zshrc"
aliases-zsh.sh
- functions:
#!/bin/bash
listBookmarks() {
local pathSelected=$(cat $BOOKMARKS_FILE |
jq -r '.[]' |
fzf)
if [[ -n "$pathSelected" ]]; then
cd $pathSelected
else
echo "no bookmark selected"
fi
}
openRepoUrl() {
local gitUrl=$(git remote get-url --all origin)
local repoUrl="${gitUrl%".git"}" # Removing .git prefix
if [[ -n "$repoUrl" ]]; then
echo "repoUrl:$repoUrl"
xdg-open $repoUrl
fi
}
# REQUIRES fzf, this list the current folder interactively
lsf() {
local chosenDir=$(ls | fzf)
if [[ -n "$chosenDir" ]]; then
cd $chosenDir
fi
}
- Bookmarks file referenced in the variable
BOOKMARKS_FILE
, and used in thelistBookmarks
function:
[
"/home/cangulo/repos/cangulo-tf",
"/home/cangulo/repos/cangulo-nuke"
]
Demo
Repository
If we store the settings and the implementations in a repository (e.g. GitHub) , we just need to reference them in the profile script the same way we have done so far:
# Update LOCAL_REPO_FULL_PATH with yours
export SETTINGS_FILE="LOCAL_REPO_FULL_PATH/settings.local.json"
source LOCAL_REPO_FULL_PATH/load-custom-profile.sh
I recommend you to have a settings.template.json
with the empty variables as next:
{
"LOCAL_REPOS": "",
"LOCAL_DOCUMENTS": "",
"SCRIPTS_FOLDER": "",
"BOOKMARKS_FILE": ""
}
In that way, when you clone the repo locally, you duplicate it, rename copy to settings.local.json
, and fill the values. Add it to your gitignore
to avoid pushing it.
Final Notes
wow, this post is the longest one I have done so far! Do you have another approach for importing scripts or settings? How would you do it? Let me know in the comments below.
About me
I'm a Software Engineer with experience as Developer and DevOps. The technologies I have worked with are DotNet, Terraform and AWS. For the last one, I have the Developer Associate certification. I define myself as a challenge-seeker person and team player. I simply give it all to deliver high-quality solutions. On the other hand, I like to analyze and improve processes, promote productivity and document implementations (yes, I'm a developer that likes to document ๐งโ๐ป).
You can check my experience here.
Personal Blog - cangulo.github.io
GitHub - Carlos Angulo Mascarell - cangulo
LinkedIn - Carlos Angulo Mascarell
Twitter - @AnguloMascarell