~/.zshrc
My personal zsh configuration, now available in literate form.
Zim setup
At the time of writing, I'm using zim as my zsh framework of choice.
Here is some general setup of it before doing wider zsh fiddling.
# Set editor default keymap to vi (`-v`) rather than emacs (`-e`)
bindkey -v
# Remove path separator from WORDCHARS.
WORDCHARS=${WORDCHARS//[\/]}
zsh-autosuggestions
# Disable automatic widget re-binding on each precmd. This can be set when
# zsh-users/zsh-autosuggestions is the last module in your ~/.zimrc.
ZSH_AUTOSUGGEST_MANUAL_REBIND=1
zsh-syntax-highlighting
# Set what highlighters will be used.
# See https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/docs/highlighters.md
ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets)
Module setup + zimfw install
If we don't have zimfw already installed, let's automatically install it before attempting setup.
ZIM_HOME=${ZDOTDIR:-${HOME}}/.zim
# Download zimfw plugin manager if missing.
if [[ ! -e ${ZIM_HOME}/zimfw.zsh ]]; then
if (( ${+commands[curl]} )); then
curl -fsSL --create-dirs -o ${ZIM_HOME}/zimfw.zsh \
https://github.com/zimfw/zimfw/releases/latest/download/zimfw.zsh
else
mkdir -p ${ZIM_HOME} && wget -nv -O ${ZIM_HOME}/zimfw.zsh \
https://github.com/zimfw/zimfw/releases/latest/download/zimfw.zsh
fi
fi
# Install missing modules, and update ${ZIM_HOME}/init.zsh if missing or outdated.
if [[ ! ${ZIM_HOME}/init.zsh -nt ${ZDOTDIR:-${HOME}}/.zimrc ]]; then
source ${ZIM_HOME}/zimfw.zsh init -q
fi
# Initialize modules.
source ${ZIM_HOME}/init.zsh
Post-setup configuration
zsh-history-substring-search
zmodload -F zsh/terminfo +p:terminfo
# Bind ^[[A/^[[B manually so up/down works both before and after zle-line-init
for key ('^[[A' '^P' ${terminfo[kcuu1]}) bindkey ${key} history-substring-search-up
for key ('^[[B' '^N' ${terminfo[kcud1]}) bindkey ${key} history-substring-search-down
for key ('k') bindkey -M vicmd ${key} history-substring-search-up
for key ('j') bindkey -M vicmd ${key} history-substring-search-down
unset key
Initialisation
This section consists of helpers functions and global variables used by various applications.
A few of the helper functions are intended to make sure my configuration acts mostly identical across all machines and OSes without any extra configuration.
Whether that statement holds true is... debatable 😃
Setting up PATH
These paths generally exist on most every system so we'll set them seperately from other PATH additions.
path=(
$HOME/.local/share/mise/shims
/opt/homebrew/opt/emacs-mac/bin
/opt/homebrew/opt/openjdk/bin
/opt/homebrew/opt/mtr/sbin
/nix/var/nix/profiles/default/bin
/home/linuxbrew/.linuxbrew/bin
$HOME/.bin
/opt/homebrew/bin
/bin
/sbin
/usr/local/bin
/usr/bin
/usr/sbin
/usr/local/sbin
/usr/libexec
/opt/X11/bin
$HOME/.nix-profile/bin
$HOME/.config/emacs/bin
$HOME/.local/bin
$HOME/.opam/default/bin
$HOME/scripts
/usr/local/MacGPG2/bin
/usr/local/opt/postgresql@10/bin
/Applications/Postgres.app/Contents/Versions/latest/bin
"/Applications/Sublime Text.app/Contents/SharedSupport/bin"
)
export PATH
- If we're using Nix, we want Nix installed binaries to always resolve first no matter what
- While this could cause trouble, this path should only ever resolve on Linux so it'll do for now
- We want to make sure that our Homebrew binaries are picked up earlier than system binaries that tend to be older
- Enables quickly opening Sublime Text via terminal by using the
subl
command
TODO: Why is Homebrew on Linux installed as its own user
Homebrew
Some homebrew setup that is needed on Linux
{{ if eq .chezmoi.os "darwin" -}}
eval "$(brew shellenv)"
{{ end -}}
fzf setup
This is requested by the fzf plugin so we need to do it before we load things
{{- if eq .chezmoi.os "darwin" -}}
export FZF_BASE=$(brew --prefix)/opt/fzf
{{ end -}}
- Updates are handled by chezmoi so we disable automatic zsh updating
Handy credentials
export GITHUB_TOKEN={{ onepasswordRead "op://Personal/Chezmoi Github Token/password" "my" }} # (1)!
- I use this with the Github CLI among other places so it's useful to just have it always set in my shell
History
The following options were borrowed from this HN comment
SHARE_HISTORY will cause zsh to write to the history file after every command which means that two shells running in parallel won't override changes of each other and it will write a timestamp to the file too in order to have the history in chronological order even in light of multiple instances.
HIST_IGNORE_DUPS (or HIST_IGNORE_ALL_DUPS) will cause duplicated commands to not be written to the history file which helps with
Ctrl-R
ing
setopt SHARE_HISTORY HIST_IGNORE_ALL_DUPS
Also, just for my sanity across platforms, here are the macOS history defaults explicitly defined
HISTFILE=${ZDOTDIR:-$HOME}/.zsh_history
HISTSIZE=2000
SAVEHIST=1000
Setting up build flags
Compiling some things can end in failure on macOS when using a version of OpenSSL installed using Homebrew.
This ensures that the right folders are scanned for development libraries.
Pretty boring stuff.
Crystal on macOS Silicon fails with an architecture error for me without this PKG_CONFIG_PATH
as an example
{{ if eq .chezmoi.os "darwin" -}}
export LDFLAGS="-L$(brew --prefix)/opt/[email protected]/lib"
export CPPFLAGS="-I$(brew --prefix)/opt/[email protected]/include"
export PKG_CONFIG_PATH="$(brew --prefix)/opt/[email protected]/lib/pkgconfig"
{{ end -}}
Setting up WSL Shims
In order to support WSL, there are a bunch of scripts that live in dot_wslshims
containing wrapper scripts.
These are just dumb files that translate eg; op
into op.exe
which is the equivalent executable in Windows land
{{ if .wsl }}
export PATH="~/.wslshims:$PATH"
{{ end }}
Setting my workspace
All of my development occurs in $HOME/Code
regardless of what machine I'm on. One day I might change it though hence the variable.
export WORKSPACE="$HOME/Code"
Setting various global constants
export CONFIG_FILE="$HOME/.zshrc"
export CONFIG_SRC="$(chezmoi source-path)/zshrc.md"
export EDITOR="nvim"
export GPG_TTY=$(tty)
export LANGUAGE="en_NZ:en"
export LAST_MODIFIED="$(date)"
REPORTTIME=5
Applications
Atuin
if [[ $(command -v atuin) ]]; then
eval "$(atuin init zsh)"
fi
Emacs
Given that I use chezmoi, I can't have Doom Emacs editing the default config in $HOME
so we need to overwrite that.
export DOOMDIR=$(chezmoi source-path)/dot_doom.d # (1)!
- If I make updates to my Emacs config, I want to make sure that I'm editing the source and not the version in
$HOME
which will get overwritten on the nextchezmoi apply
fzf
A fuzzy finder which comes with some autocompletions
if [[ $(command -v fzf) ]]; then
[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
fi
Homebrew
It can take quite some time if Homebrew decides to automatically update everything so let's turn that off
export HOMEBREW_NO_AUTO_UPDATE=1
less
Less is great by default but it'd be even nicer with syntax highlighting!
if [[ $(which src-hilite-lesspipe.sh) ]]; then
LESSPIPE=`which src-hilite-lesspipe.sh`
export LESSOPEN="| ${LESSPIPE} %s"
export LESS=' -R -X -F '
fi
mise
eval "$(mise activate zsh)"
nix
I don't use it yet but Home Manager is promising
Setup is:
sh <(curl -L https://nixos.org/nix/install) --darwin-use-unencrypted-nix-store-volume
nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
nix-channel --update
nix-shell '<home-manager>' -A install
export NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt
if [[ $(command -v nix) ]]; then
export NIX_PATH=$HOME/.nix-defexpr/channels${NIX_PATH:+:}$NIX_PATH
fi
if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then
. '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh'
fi
opam
The package manager for OCaml
[[ ! -r /Users/marcus/.opam/opam-init/init.zsh ]] || source /Users/marcus/.opam/opam-init/init.zsh > /dev/null 2> /dev/null
pnpm
export PNPM_HOME="$HOME/Library/pnpm"
export PATH="$PNPM_HOME:$PATH"
Languages
Erlang
Whenever I compile erlang
, I always use the same flags so it's easier to just set them within my shell
export ERL_AFLAGS="-kernel shell_history enabled"
export KERL_CONFIGURE_OPTIONS="--disable-debug --without-javac"
export KERL_BUILD_DOCS="yes"
go
I don't explicitly set GOROOT
as it is defined by mise
generally.
export GOPATH="$WORKSPACE/go"
export PATH="$PATH:$GOPATH/bin"
Shortcuts
Admittedly most of the git related stuff could live inside of a .gitconfig
file but I never get around to moving it
That and I figure this will all eventually be superseded by nix
anyway
You know... when I get around to doing that...
alias ae="deactivate &> /dev/null; source ./venv/bin/activate"
alias alphaenv="env -0 | sort -z | tr '\0' '\n'"
alias assume="source assume"
alias ccd="chezmoi cd"
alias cce="chezmoi edit"
alias crush="pngcrush -ow"
alias de="deactivate &> /dev/null"
alias ec="emacsclient -na $(which code)"
alias edit="$EDITOR $CONFIG_SRC"
alias gb="git branch -v"
alias gbm="git checkout master"
alias gcm="git commit -Ssi"
alias gr="git remote -v"
# Taken from https://twitter.com/flakpaket/status/1445751410331586568
alias grip='grep -oE "([0-9]{1,3}[.]){3}[0-9]{1,3}"'
alias gs="git status"
alias gst="git status"
alias ipv4="dig @resolver4.opendns.com myip.opendns.com +short -4"
alias ipv6="dig @resolver1.ipv6-sandbox.opendns.com AAAA myip.opendns.com +short -6"
alias lidclosed="ioreg -r -k AppleClamshellState -d 4 | grep AppleClamshellState | awk '{ print $4 }'"
alias lvim="nvim"
alias rebrew="brew bundle --file=$(chezmoi source-path)/Brewfile"
alias refresh="chezmoi git pull && chezmoi apply && exec zsh && echo '~ refreshed shell config'"
alias rmuntracked="git status -su --no-ahead-behind | awk '{ print $2 }' | xargs rm"
alias rtx="echo 'Reminder that rtx is now called mise!'"
alias tabcheck="/bin/cat -e -t -v"
alias tsc="transmission-remote netocean"
alias utd="cd ~/utf9k && yarn start"
alias venv="python3 -m venv venv && ae"
alias vi="$EDITOR"
alias view="less $CONFIG_FILE"
alias vim="$EDITOR"
alias ws="cd $WORKSPACE"
alias wsd="chezmoi cd"
alias youtube-dl="yt-dlp --add-metadata --dateafter 20081004 -i -o '%(uploader)s [%(channel_id)s]/%(title)s [%(id)s].%(ext)s' -ci --format 'bestvideo[height<=?1080]+bestaudio[ext=m4a]/bestvideo+bestaudio/best' --merge-output-format mp4"
Functions
These are some handy functions I use from time to time
What application is listening on any given port?
function whomport() { lsof -nP -i4TCP:$1 | grep LISTEN }
Example
> lsof -nP -i4TCP:1313 | grep LISTEN hugo 64740 marcus 466u IPv4 0x76ace186a77b90b9 0t0 TCP 127.0.0.1:1313 (LISTEN)
I'd like to tangle a markdown file please
I have my own little Markdown tangling tool which you can read about here
function tangle-md() {
if [[ $(command -v lugh) ]]; then
lugh -f "$1"
else
echo "lugh isn't installed. You can find it at https://github.com/marcus-crane/lugh"
fi
}
I'd like to tangle an org file please
function tangle-file() {
emacs --batch -l org $@ -f org-babel-tangle
}
What's inside that JWT?
This function is used to display both encrypted and regular JWT tokens, as opposed to using an online service like https://jwt.io
It's taken almost verbatim from this post except the original exit 0
would cause my terminal session to exit so I swapped it for a break
instead.
To pretty print a JWT line, just use it like so: jwt <token>
If you'd like to use a JWT stored as a file, you can do that pretty easily too: jwt $(cat a_saved_jwt)
function jwt() {
for part in 1 2; do
b64="$(cut -f$part -d. <<< "$1" | tr '_-' '/+')"
len=${#b64}
n=$((len % 4))
if [[ 2 -eq n ]]; then
b64="${b64}=="
elif [[ 3 -eq n ]]; then
b64="${b64}="
fi
d="$(openssl enc -base64 -d -A <<< "$b64")"
python -mjson.tool <<< "$d"
# don't decode further if this is an encrypted JWT (JWE)
if [[ 1 -eq part ]] && grep '"enc":' <<< "$d" >/dev/null ; then
break
fi
done
}
Example
> jwt eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c { "alg": "HS256", "typ": "JWT" } { "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
What functions have I defined?
Often I'll forget what little shortcut functions I've made so here's a quick cheatsheet
There is a built-in functions
but it shows the actual source code rather than a list of names
function funcs() {
functions | grep "()" | grep -v '"'
}
Example
> funcs kumamon () { massunset () { master2main () { mkd () {
How's that for disorientation? Enough "functions" for ya?
The extra grep
is a bit of a hack because without it, the actual function body will match the search for grep "()"
It's quite interesting in a way, that it would recursively search itself so I added in a second grep to remove any lines that feature a double quote.
Technically speaking, the second grep would potentially be filtering itself out recursively which I think is pretty interesting
It also makes my head hurt a little bit for what you'd think would be a pretty basic function!
What is the definition of a given shell function?
Sometimes I like to take a copy of an existing shell function and poke around the internals to debug/fix it.
I can read through my shell config but I'm lazy so instead here is a function to search other functions.
function fsearch () {
functions | sed -n "/$1/,/^}$/p"
}
What's a quick way to archive backups?
In order to save on cloud storage space, while still keeping a home for rarely used backups, I like to store things in Backblaze B2
While I could use the web UI, it's often just as fast to use rclone which is what this script is a wrapper around
function archive() {
rclone copy "$(pwd)/$1" b2:long-term-backups --progress
}
Quick convert screen recording to a more suitable format
Often times, I find myself making screen recording with Quicktime but they export as .mov
files. I much prefer having an mp4
file as it's more universally accepted so this is a quick function to perform that convertion with ffmpeg.
function demov() {
if [[ $(command -v "ffmpeg") ]]; then
ffmpeg -i $1 -vcodec libx264 -acodec aac $(echo "$1" | rev | cut -f 2- -d '.' | rev).mp4
else
print "It doesn't look like you have ffmpeg installed."
fi
}
Quick convert h265 to 8 bit 264
function de265() {
if [[ $(command -v "ffmpeg") ]]; then
ffmpeg -i $1 -map 0 -c:v libx264 -crf 18 -vf format=yuv420p -c:a copy $(echo "$1" | rev | cut -f 2- -d '.' | rev).mp4
else
print "It doesn't look like you have ffmpeg installed."
fi
}
Calculating nines
Often times, it can be useful to put service uptime into minutes and hours. Thankfully uptime.is is a handy tool for this plus it reserves JSON too!
function nines() {
curl -s https://uptime.is/$1 | jq
}
Example
> nines 99.95 { "SLA": 99.95, "dailyDown": "43s", "dailyDownSecs": 43, "weeklyDown": "5m 2s", "weeklyDownSecs": 302, "monthlyDown": "21m 54s", "monthlyDownSecs": 1314, "quarterlyDown": "1h 5m 44s", "quarterlyDownSecs": 3944, "yearlyDown": "4h 22m 58s", "yearlyDownSecs": 15778, "uptimeURL": "https://uptime.is/99.95", "runtimeSecs": 0.001 }
Delete Git branches interactively with fzf
This function was quite shamelessly taken from this very good post by Sebastian Jambor.
It opens an interactive fzf window which shows a list of git branches, with their relevant history on the side as a preview pane.
You can press TAB to select multiple branches and ENTER to delete them.
If you decide to back out, you can press ESC to cancel.
function gbd() {
git branch |
grep --invert-match $(git branch --show-current) |
cut -c 3- |
fzf --multi --preview="git log {} --" |
xargs git branch --delete --force
}
View homebrew casks
I find that the Homebrew cask search doesn't provide enough information to make an informed decision so I'm using fzf instead to help
function casks() {
curl "https://formulae.brew.sh/api/cask.json" |
jq '.[].token' |
tr -d '"' |
fzf --multi --preview="curl https://formulae.brew.sh/api/cask/{}.json | jq '.'" |
xargs brew install --cask
}
Regenerate a secret key that has the same length as the input
Something I commonly do is regenerate secret keys between environments when deploying software. These keys aren't necessarily secret in themselves so much as they are just used to provide extra entropy.
I can never remember which keys require a specific length so this is a short function to take a key and regenerate a key that is the exact same length.
function secretregen() {
local SECRET_LENGTH=$(echo -n $1 | wc -m | awk '{$1=$1};1')
LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c $SECRET_LENGTH ; echo ''
}
Example
> secretregen ABC123 0qbTGG > secretregen 0qbTGG LUhxAp > secretregen LUhxAp S5VkqQ
Decode URLs with percentage decoded values
Often times, it can be more useful to inspect the API calls made by a web application, than using the API documentation supplies but this can get a little annoying when you need to decode HTML entities.
As a result, this little function will decode a URL parameter like team_ids%5B%5D=ABC123
into team_ids[]=ABC123
.
There are other types of HTML encoding of course but I only ever seem to run into percentage decoding on a day to day basis.
Remember to quote your input so that &
symbols and the like aren't interpreted as shell commands.
function percentdecode() {
echo $1 | python3 -c 'import sys,urllib.parse as ul; print(ul.unquote_plus(sys.stdin.read()),end="")'
}
Example
> percentdecode "https://example.com?repo=marcus%2Dcrane%2Fdotfiles" https://example.com?repo=marcus-crane/dotfiles
Envy
A small helper function for sourcing the contents of .env
files into my shell
envy() {
if [ -f ".env" ]; then
set -o allexport
source .env
set +o allexport
else
echo "No env file located"
return 1
fi
}
Pretty print PATH
path() {
echo -e "${PATH//:/\\n}"
}
Kumamon on demand
I like Kumamon but I don't watch Kumamon videos enough so this is a small function that opens a random Kumamon YouTube video using mpv
kumamon() {
channels=(
https://www.youtube.com/c/KumamonTV/videos
https://www.youtube.com/channel/UCHZQHTjxwQ5fa9Fiosp6orw/videos
https://www.youtube.com/channel/UCZ4jjYAi4BI1-aU7Tg4HliQ/videos
https://www.youtube.com/channel/UCrw3-jkioIlt7JtvtrrbPFg/videos
)
channel=${channels[$(( $RANDOM % ${#channels[@]} +1 ))]}
mpv $channel --shuffle --geometry=100%:0% --autofit=20% --ytdl-format="bestvideo[height<=480]+bestaudio/best[height<=480]" --ontop
}
defaults plist viewer
This is probably my weightiest command to date
viewdefaults() {
defaults domains |
sed 's/$/, NSGlobalDomain/' |
tr -d ',' |
tr ' ' '\n' |
fzf --preview="defaults export {} - | python3 -c \"import sys,plistlib,pprint; pprint.pprint(plistlib.loads(sys.stdin.read().encode('utf-8')))\"" |
xargs -n1 -I{} sh -c 'defaults export $1 - > $1.plist' -- {}
}
Pretty print URL params
Using the previously defined percentdecode
function, this makes it easy to visualise request params in a URL
params() {
percentdecode $1 |
tr "?" "\n" |
tr "&" "\n"
}
Example
> params "http://localhost:1313?test=hi&nice=cool&wow=great" http://localhost:1313 test=hi nice=cool wow=great
master to main
From time to time, I'll update a repo's branch for consistency and forget the steps to update my local
master2main() {
git branch -m master main
git fetch origin
git branch -u origin/main main
git remote set-head origin -a
}
Sign in with 1Password CLI
At this point, my work config is intertwined with my 1Password installation and shortly the same will probably be true of my work config.
It's a hassle manually entering in my password each time so instead, here's a shortcut to automatically log me in to the op
cli tool
It requires your password being stored in at $HOME/.op
Also note that if you have a printf
formatting symbol such as %
in your master password, you'll need to escape it so eg; abc12%
becomes abc12%%
Does this mean my master password is stored on my machine? Yes but realistically, it isn't much of a threat.
You still need to a) unlock my laptop and b) have my security key to access my vault on a new machine
You could physically access my machine of course but that's no less of a threat than it is at present so always remember to lock your devices!
opauth() {
eval $(op signin --account $1.1password.com)
echo "~ Signed in to $1 vault"
}
mkd
It's often handy to change into a folder you've just created so this is a handy way to do that.
mkd() {
mkdir -p $1 && cd $_
}
Pull an image from ECR and recurse
ecrrecurse() {
REPOSITORY_NAME=$1
IMAGE_TAG=$2
if [[ $REPOSITORY_NAME == "" || $IMAGE_TAG == "" ]]; then
echo "Please enter both a repository name and an image tag"
echo "Usage: ecrrecurse myservice abc1234"
exit 1
fi
MANIFEST=$(aws ecr batch-get-image --repository-name=$REPOSITORY_NAME --image-id imageTag=$IMAGE_TAG --region=us-west-2 --output json | jq -r '.images[].imageManifest')
if [[ $MANIFEST == "" ]]; then
echo "No results found for that Docker manifest"
exit 1
fi
MEDIA_TYPE=$(jq '.mediaType' <<< "${MANIFEST}")
if [[ $MEDIA_TYPE == '"application/vnd.docker.distribution.manifest.list.v2+json"' ]]; then
INNER_DIGEST=$(jq '.manifests[0].digest' <<< "${MANIFEST}")
MANIFEST=$(aws ecr batch-get-image --repository-name=$REPOSITORY_NAME --image-id imageDigest=$INNER_DIGEST | jq -r '.images[].imageManifest')
fi
CONFIG_DIGEST=$(jq '.config.digest' <<< "${MANIFEST}")
DOWNLOAD_URL=$(xargs -I{} aws ecr get-download-url-for-layer --repository-name=$REPOSITORY_NAME --layer-digest={} <<< "${CONFIG_DIGEST}" | jq '.downloadUrl')
CONTENT=$(xargs curl -s <<< "${DOWNLOAD_URL}")
echo $CONTENT | jq '.config.Labels'
}
Show env with values redacted
Sometimes it's useful to illustrate some env values but you don't actually want to show the content
redactenv() {
sed -E 's/=.*/=•••/g;t' <<< $(env | grep "$1")
}
Example
> env | grep SHELL SHELL=/bin/zsh > redactenv SHELL SHELL=•••
Mass unset environment items
massunset() {
name=$(env | fzf --multi | tr "=" " " | awk '{ print $1 }')
spacedName=$(echo $name | tr "\n" " ")
unset $spacedName
}
Remotely remove torrents
Sometimes it's nice to be able to remove Linux distro ISO torrents from across the room
tsd() {
tsc -l |
awk 'NR>2 {print last} {last=$0}' |
awk '{ $2=$3=$4=$5=$6=$7=$8=$9=""; print $0 }' |
sed 's/ //g' |
fzf --multi --preview="awk '{ print $1 }' | transmission-remote netocean -t {} -i" | awk '{ print $1 }' |
xargs -I{} transmission-remote netocean -t {} -r
}
Format Terraform plans for Github
At work, I occasionally paste Terraform plans into Github pull requests where they aren't otherwise automated.
In order to make use of screen real estate, these are put inside of an HTML details
block that can be expanded.
txtplan() {
gsed '1 i <details><summary>Plan</summary>||```terraform' txt.plan | gsed -E '$ a ```||</details>' | tr '|' '\n' | pbcopy
}
Quick convert unix timestamps to ISO-8601 timestamps
Often times, when using the jwt
shell function (earlier in this file), the timestamps for expiry will be provided as unix timestamps.
I always end up going to some website to convert these and never remember that date
exists so this shell function is a quick way to convert these locally.
Note that gdate
is needed for macOS (brew install coreutils
) but you can probably just use plain date
on Linux.
TODO: Update this to use date
by default but gdate
if platform is darwin
deunix() {
gdate --iso-8601=seconds -d '@$1'
}
1Password CLI for WSL
When using WSL, it's more ideal to use an instance of the OP CLI installed on the Windows host as that will enable the use of biometric unlock from within WSL
As my dotfiles use both my personal and work accounts for various things, this is basically required due to having to switch accounts partway through the dotfile installation process.
It's also just a lot nicer not having to deal with long passwords.
By default, op.exe
is installed at C:/Program Files/1Password CLI
In order to make this switch transparent to any calling scripts, there is a wrapper script that can be found in the dot_wslshims
folder
{{ if .wsl }}
export PATH="/mnt/c/Program Files/1Password CLI:$PATH"
{{- end }}
Work configuration
Usually most people maintain a separate configuration between their personal and work lives.
I've opted to maintain mine in public to show that it's possible to have the best of both worlds without leaking credentials.
In the case of my employer, not only are the referenced tools the usual suspects but you can easily verify on Github that we use them internally in the form of public repos so this can't be considered as leaking metadata in that sense.
{{ if .workmode }}
source $HOME/Code/work/home/aliases.sh
source $HOME/Code/work/home/functions.sh
source $HOME/Code/work/home/variables.sh
export PATH=$PATH:$HOME/Code/work/home/bin
export TF_VAR_datadog_api_key={{ onepasswordRead "op://Private/Datadog API Key/username" "lightspeedhq" }}
export TF_VAR_datadog_app_key={{ onepasswordRead "op://Private/Datadog API Key/password" "lightspeedhq" }}
{{- end }}
iTerm 2 integration
I used iTerm 2 on my various devices as a terminal and so, there are some shell integrations that are handy to use
if [[ -f "$HOME/.iterm2_shell_integration.zsh" ]]; then
. $HOME/.iterm2_shell_integration.zsh
fi