2019-02-27 18:07:19 +01:00
|
|
|
#!/usr/bin/env zsh
|
|
|
|
|
|
|
|
# Docker
|
|
|
|
dsh() {
|
|
|
|
# Drop into a Docker shell. Shell defaults to /bin/bash.
|
|
|
|
container=$1
|
|
|
|
cmd=${2-/bin/bash}
|
|
|
|
|
|
|
|
docker exec -it "${container}" "${cmd}"
|
|
|
|
}
|
|
|
|
|
2019-03-08 19:15:27 +01:00
|
|
|
# Emacs
|
|
|
|
dired() {
|
|
|
|
# Opens either the `$(pwd)` or `$1` in Emacs's `dired`.
|
|
|
|
# Uses i3 to focus Emacs.
|
|
|
|
directory=${1:-$(pwd)}
|
|
|
|
echo $directory
|
|
|
|
emacsclient --eval "(dired \"$directory\")" && focus Emacs
|
|
|
|
}
|
|
|
|
|
|
|
|
org_capture() {
|
|
|
|
# Spawns an Emacs frame running org-capture.
|
|
|
|
echo called
|
|
|
|
emacsclient --create-frame \
|
|
|
|
--frame-parameters '(quote (name . "org-protocol-capture"))' \
|
|
|
|
--eval '(org-capture)'
|
|
|
|
}
|
|
|
|
|
2019-02-27 18:07:19 +01:00
|
|
|
# Git
|
|
|
|
conflicts() {
|
|
|
|
# Edit git conflicts one-by-one in your favorite editor.
|
|
|
|
${EDITOR} "$(git status --porcelain | awk '/^UU/ { print $2 }')"
|
|
|
|
}
|
|
|
|
|
|
|
|
# GPG
|
|
|
|
gpg_encrypt() {
|
|
|
|
# Convenience function around encryping files and directories.
|
|
|
|
# Appends a .gpg extension and deletes the unencrypted source.
|
|
|
|
local file=${1}
|
|
|
|
|
|
|
|
echo "Encrypting..."
|
|
|
|
|
|
|
|
if [ -f "${file}" ]; then
|
|
|
|
gpg --symmetric "${file}" && \
|
|
|
|
rm "${file}"
|
|
|
|
|
|
|
|
elif [ -d "${file}" ]; then
|
|
|
|
tar -cz "${file}" | gpg --symmetric --output "${file}.tar.gz.gpg"
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "Done."
|
|
|
|
}
|
|
|
|
|
|
|
|
gpg_decrypt() {
|
|
|
|
# Convenience function around decrypting .gpg files and directories.
|
|
|
|
# Deletes the original encrypted file with the .gpg extension.
|
|
|
|
local file=$1
|
|
|
|
|
|
|
|
echo "Decrypting..."
|
|
|
|
|
|
|
|
if [ -f "${file}" ]; then
|
|
|
|
gpg --decrypt "${file}" >"${file%.gpg}" && \
|
|
|
|
rm "${file}"
|
|
|
|
|
|
|
|
elif [ -d "${file}" ]; then
|
|
|
|
local outdir="${dirname%.tar.gz.gpg}"
|
|
|
|
|
|
|
|
if [ -d "${outdir}" ]; then
|
|
|
|
echo "Output directory, ${outdir}, already exists and will be overwritten by this command. Aborting..."
|
|
|
|
return 1
|
|
|
|
else
|
|
|
|
gpg --decrypt "${dirname}" | tar -xv
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "Done."
|
|
|
|
}
|
|
|
|
|
|
|
|
# Python
|
|
|
|
python_sandbox() {
|
|
|
|
# Creates a nix-shell with the specified arguments as Python packages
|
|
|
|
nix-shell -p "python36.withPackages(p: with p; [$@])"
|
|
|
|
}
|
|
|
|
|
|
|
|
# Haskell
|
|
|
|
cabal_unhell() {
|
|
|
|
# Run this function to save yourself from Cabal hell.
|
|
|
|
# Note: this will require that you reinstall packages for your projects again.
|
|
|
|
find ~/.ghc -maxdepth 1 -type d -exec rm -rf {} \;
|
|
|
|
rm -rf ~/.cabal/{lib,packages,share}
|
|
|
|
}
|
|
|
|
|
|
|
|
haskell_sandbox() {
|
|
|
|
# Creates a nix-shell with the specified arguments as Haskell packages
|
|
|
|
nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [$@])"
|
|
|
|
}
|
|
|
|
|
|
|
|
_haskell_test_watch_path() {
|
|
|
|
# Runs and watches the tests for a provided file path.
|
|
|
|
ghcid -c "stack ghci grid:lib grid:grid-test --ghci-options=-fobject-code" \
|
|
|
|
--height="$(tput lines)" --width="$(tput cols)" --warnings --test "$1"
|
|
|
|
}
|
|
|
|
|
|
|
|
_haskell_test_watch_pattern() {
|
|
|
|
# Runs and watches the tests that match a provided pattern.
|
|
|
|
stack test --file-watch grid:grid-test --ta "-p \"${1}\""
|
|
|
|
}
|
|
|
|
|
|
|
|
haskell_test_watch() {
|
|
|
|
# Accepts either a filepath or a pattern and runs a test-watcher for either.
|
|
|
|
if [ -f "$1" ]; then
|
|
|
|
_haskell_test_watch_path "$1"
|
|
|
|
else
|
|
|
|
_haskell_test_watch_pattern "$1"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
# Kubernetes
|
|
|
|
kush() {
|
|
|
|
# Drop into a shell via Kubernetes. Shell defaults to /bin/bash.
|
|
|
|
local name=$1
|
|
|
|
local cmd=${2-/bin/bash}
|
|
|
|
|
|
|
|
kubectl exec -it "${name}" -- "${cmd}"
|
|
|
|
}
|
|
|
|
|
|
|
|
# Misc
|
2019-03-06 18:00:40 +01:00
|
|
|
all_users() {
|
|
|
|
# Lists all of the known users in the Linux system
|
|
|
|
# Useful because when you type `~art` in a prompt and tab-complete, ZSH looks
|
|
|
|
# up all users whose names start with "art". It's also just interesting to
|
|
|
|
# have access to this information.
|
|
|
|
#
|
|
|
|
# NOTE: this is not as simple as `cat /etc/passwd` for reasons of which I'm
|
|
|
|
# not entirely sure.
|
|
|
|
getent passwd
|
|
|
|
}
|
|
|
|
|
|
|
|
test_true_color() {
|
|
|
|
# Run this to test if your terminal emulator supports True Color
|
|
|
|
curl --silent https://raw.githubusercontent.com/JohnMorales/dotfiles/master/colors/24-bit-color.sh | bash
|
|
|
|
}
|
|
|
|
|
2019-02-27 18:07:19 +01:00
|
|
|
path() {
|
|
|
|
# Pretty-print the $PATH variable
|
|
|
|
echo "$PATH" | tr : '\n'
|
|
|
|
}
|
|
|
|
|
2019-03-07 17:47:14 +01:00
|
|
|
nix_installed() {
|
|
|
|
# Lists the packages installed with `nix-env`
|
|
|
|
nix-env -q
|
|
|
|
}
|
|
|
|
|
2019-02-27 18:07:19 +01:00
|
|
|
nix_store() {
|
|
|
|
# Print the packages in /nix/store without the preceding hash
|
|
|
|
ls /nix/store | sed 's/[a-z0-9]*-//'
|
|
|
|
}
|
|
|
|
|
|
|
|
browse() {
|
|
|
|
# Open a URL in $BROWSER. Friendly for terminal input and output.
|
|
|
|
nohup "$BROWSER" $@ &
|
|
|
|
}
|
|
|
|
|
2019-03-08 19:17:41 +01:00
|
|
|
lh() {
|
|
|
|
# Opens http://localhost:<port> in your $BROWSER.
|
|
|
|
# Usage: `lh 8080`
|
|
|
|
# Here, in case it wasn't obvious, `lh` stands for "localhost".
|
|
|
|
browse "http://localhost:$1"
|
|
|
|
}
|
|
|
|
|
2019-02-27 18:07:19 +01:00
|
|
|
essids() {
|
|
|
|
# Returns a list of all ESSIDs the network card detects
|
|
|
|
local interface=${1-wlp4s0}
|
|
|
|
sudo iwlist "${interface}" scan | awk -F \" '{print $2}' | sed '/^\s*$/d'
|
|
|
|
}
|
|
|
|
|
|
|
|
mkdir_cd() {
|
|
|
|
# Make and cd into a directory or path
|
|
|
|
mkdir -p "$1" && cd "$1"
|
|
|
|
}
|
|
|
|
|
|
|
|
swap() {
|
|
|
|
# Swaps the names of files and directories.
|
|
|
|
local file_a="${1}"
|
|
|
|
local file_b="${2}"
|
|
|
|
|
|
|
|
if [ -d "${file_a}" ] && [ -d "${file_b}" ]; then
|
|
|
|
local backup=$(mktemp -d backup.XXX)
|
|
|
|
|
|
|
|
mv "${file_a}" "${backup}"
|
|
|
|
mv "${file_b}" "${file_a}"
|
|
|
|
mv "${backup}/${file_a}" "${file_b}"
|
|
|
|
rm -rf "${backup}"
|
|
|
|
elif [ -f "${file_a}" ] && [ -f "${file_b}" ]; then
|
|
|
|
local backup=$(mktemp backup.XXX)
|
|
|
|
|
|
|
|
mv "${file_a}" "${backup}"
|
|
|
|
mv "${file_b}" "${file_a}"
|
|
|
|
mv "${backup}" "${file_b}"
|
|
|
|
rm "${backup}"
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "Swapped: ${file_a} <-> ${file_b}"
|
|
|
|
}
|
|
|
|
|
|
|
|
bak() {
|
|
|
|
# Backup a file or a directory by appending a .bak extension to it.
|
|
|
|
mv "$1" "$1.bak"
|
|
|
|
}
|
|
|
|
|
|
|
|
unbak() {
|
|
|
|
# Restore a file by removing the .bak extension from it.
|
|
|
|
mv "$1.bak" "$1"
|
|
|
|
}
|
|
|
|
|
|
|
|
is_online() {
|
|
|
|
# Pings google.com and echos "Online" or "Offline" and returns the appropriate
|
|
|
|
# exit code. Could be useful in the ${PS1} variable.
|
|
|
|
wget -q --spider "http://google.com"
|
|
|
|
|
|
|
|
if [ $? -eq 0 ]; then
|
|
|
|
echo "Online"
|
|
|
|
return 0
|
|
|
|
else
|
|
|
|
echo "Offline"
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
du_it_live() {
|
|
|
|
# Outputs and refreshes the size of a directory's content.
|
|
|
|
# Useful for watching a directory as large amounts of data are
|
|
|
|
# downloaded into it.
|
|
|
|
local directory="${1}"
|
|
|
|
|
|
|
|
while true; do
|
|
|
|
du -hc "${directory}" | tail -n 1 | tr -d '\n' && echo -n ' ' && sleep 0.5
|
|
|
|
|
|
|
|
# elipsis
|
|
|
|
echo -n '.' && sleep 0.5 &&
|
|
|
|
echo -n '.' && sleep 0.5 &&
|
|
|
|
echo -n '.' && sleep 0.5 &&
|
|
|
|
|
|
|
|
# clear the three-dots
|
|
|
|
echo -n '\b\b\b' && echo -n ' ' && echo -n '\r'
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
router() {
|
|
|
|
# Returns the IP address of the network's router.
|
|
|
|
# Useful in a call like `ping $(router)` to diagnose an internet problem.
|
|
|
|
netstat -nr | grep default | head -n 1 | awk '{ print $2 }'
|
|
|
|
}
|
|
|
|
|
2019-03-04 18:53:49 +01:00
|
|
|
monitor_dimensions() {
|
|
|
|
# Outputs the dimensions of your computer monitor
|
|
|
|
xdpyinfo | awk '/dimensions/{ print $2 }'
|
|
|
|
}
|
|
|
|
|
2019-03-06 18:00:40 +01:00
|
|
|
list_sinks() {
|
|
|
|
# Lists the available output sources (speakers?)
|
|
|
|
pacmd list-sinks | grep -e 'name:' -e 'index:'
|
|
|
|
}
|
|
|
|
|
|
|
|
list_sources() {
|
|
|
|
# List available input sources (microphones?)
|
|
|
|
pacmd list-sources | grep -e 'index:' -e device.string -e 'name:'
|
|
|
|
}
|
|
|
|
|
2019-02-27 18:07:19 +01:00
|
|
|
lt() {
|
|
|
|
# Convenience wrapper around `exa --tree`.
|
|
|
|
# Optionally accepts a number for the max-depth and a directory to list.
|
|
|
|
# $ lt 2 ./scripts
|
|
|
|
|
|
|
|
# lt
|
|
|
|
if [ -z ${1} ]; then
|
|
|
|
exa --tree --all
|
|
|
|
|
|
|
|
# lt 2
|
|
|
|
elif [[ "${1}" =~ '^[0-9]+$' ]] && [ -z ${2} ]; then
|
|
|
|
local depth="${1}"
|
|
|
|
|
|
|
|
exa --tree -all --level "${depth}"
|
|
|
|
|
|
|
|
# lt ./scripts
|
|
|
|
elif [ -z ${2} ]; then
|
|
|
|
local directory="${1}"
|
|
|
|
|
|
|
|
exa --tree --all "${directory}"
|
|
|
|
|
|
|
|
# lt 2 ./scripts
|
|
|
|
else
|
|
|
|
local depth=${1}
|
|
|
|
local directory="${2}"
|
|
|
|
|
|
|
|
exa --tree --all --level ${depth} "${directory}"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
gql() {
|
|
|
|
# Convenience wrapper around `http POST` that allows you write GQL queries in
|
|
|
|
# Vim before posting them to the server.
|
|
|
|
local endpoint="${1}"
|
|
|
|
local query="/tmp/http-query.gql"
|
|
|
|
|
|
|
|
vim "${query}" && \
|
|
|
|
echo "{\"query\":\"$(cat ${query})\"}" | \
|
|
|
|
http --body POST "${endpoint}"
|
|
|
|
}
|
|
|
|
|
|
|
|
# Nix
|
|
|
|
nix_introspect() {
|
|
|
|
# Greps through my local nixpkgs repo for
|
|
|
|
rg --after-context 5 "\\b$1\\b\\s*=" "$(nix-instantiate --find-file nixpkgs)"
|
|
|
|
}
|
|
|
|
|
|
|
|
# Tmux
|
|
|
|
t() {
|
|
|
|
# Find or create a Tmux session.
|
|
|
|
local session_name="${1}"
|
|
|
|
if ! tmux has-session -t "${session_name}" 2> /dev/null; then
|
|
|
|
local oldTMUX="${TMUX}"
|
|
|
|
unset TMUX
|
|
|
|
tmux new -d -s "${session_name}" -n "${session_name}"
|
|
|
|
export TMUX="${oldTMUX}"
|
|
|
|
unset oldTMUX
|
|
|
|
|
|
|
|
if command -v j >/dev/null; then
|
|
|
|
tmux send-keys -t "${session_name}" "j ${session_name}; clear" "C-m"
|
|
|
|
else
|
|
|
|
tmux send-keys -t "${session_name}"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
if [[ -n "${TMUX}" ]]; then
|
|
|
|
tmux switch-client -t "${session_name}"
|
|
|
|
else
|
|
|
|
tmux attach -t "${session_name}"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
tk() {
|
|
|
|
# `tk`: "tmux kill". Kills a tmux session by name.
|
|
|
|
# If no arguments are provided, kills the current session after jumping to the previous session.
|
|
|
|
session_name="${1}"
|
|
|
|
if [ ! -z "${session_name}" ]; then
|
|
|
|
tmux kill-session -t "${session_name}"
|
|
|
|
else
|
|
|
|
session_name=tmux ls -f '#{?session_attached,#{session_name},}' | xargs
|
|
|
|
tmux switch-client -l
|
|
|
|
tmux kill-session -t "${session_name}"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2019-03-06 18:00:40 +01:00
|
|
|
tmux_is_running() {
|
|
|
|
# Returns zero if tmux is running
|
|
|
|
# Although this is a simple function body, it's useful to encode esoteric
|
|
|
|
# knowledge that I will easily forget.
|
|
|
|
test -n "$TMUX"
|
|
|
|
}
|
|
|
|
|
|
|
|
tmux_focused_pane() {
|
|
|
|
# Returns the ID of the focused tmux pane.
|
|
|
|
# WIP
|
|
|
|
# tmux list-panes -F '#{pane_active} #{pane_tty}' | awk /1/{ print $1 }
|
|
|
|
echo 'Not implemented'
|
|
|
|
}
|
|
|
|
|
2019-03-08 19:17:41 +01:00
|
|
|
# Google3
|
|
|
|
g3_root() {
|
|
|
|
# Outputs the root of the CitC client in g3
|
|
|
|
# NOTE: there is probably a function already supported by g4 to cd to the
|
|
|
|
# root, so support for this function may be dropped shortly.
|
|
|
|
echo "${PWD%%/google3/*}/google3"
|
|
|
|
}
|
|
|
|
|
|
|
|
# i3
|
|
|
|
focus() {
|
|
|
|
# Focuses an i3 window by application name.
|
|
|
|
i3-msg "[class=\"$1\"] focus" >/dev/null
|
|
|
|
}
|
|
|
|
|
2019-02-27 18:07:19 +01:00
|
|
|
# zsh
|
2019-03-06 18:00:40 +01:00
|
|
|
fns() {
|
|
|
|
# Outputs all available functions.
|
|
|
|
# `fns` was chosen instead of `functions`, since `functions` was already
|
|
|
|
# taken.
|
|
|
|
compgen -A function
|
|
|
|
}
|
|
|
|
|
|
|
|
aliases() {
|
|
|
|
# Outputs all available aliases.
|
|
|
|
compgen -a
|
|
|
|
}
|
|
|
|
|
|
|
|
keywords() {
|
|
|
|
# Outputs all of the shell's reserved keywords.
|
|
|
|
compgen -k
|
|
|
|
}
|
|
|
|
|
|
|
|
builtins() {
|
|
|
|
# Outputs all of the shell's builtin commands.
|
|
|
|
compgen -b
|
|
|
|
}
|
|
|
|
|
2019-02-27 18:07:19 +01:00
|
|
|
zle_insert_subshell() {
|
|
|
|
LBUFFER+='$(' ; RBUFFER=")$RBUFFER"
|
|
|
|
}
|
|
|
|
zle -N zle_insert_subshell
|
|
|
|
bindkey '^j' zle_insert_subshell
|
|
|
|
|
|
|
|
zle_insert_variable() {
|
|
|
|
LBUFFER+='${' ; RBUFFER="}$RBUFFER"
|
|
|
|
}
|
|
|
|
zle -N zle_insert_variable
|
|
|
|
bindkey '^v' zle_insert_variable
|
|
|
|
|
|
|
|
zle_insert_2x_dash() {
|
|
|
|
LBUFFER+=' --'
|
|
|
|
}
|
|
|
|
zle -N zle_insert_2x_dash
|
|
|
|
bindkey '^[^f' zle_insert_2x_dash
|
|
|
|
|
|
|
|
zle_insert_2x_quote() {
|
|
|
|
LBUFFER+=' "' ; RBUFFER="\"$RBUFFER"
|
|
|
|
}
|
|
|
|
zle -N zle_insert_2x_quote
|
|
|
|
bindkey '^["' zle_insert_2x_quote
|
|
|
|
|
|
|
|
zle_insert_quote() {
|
|
|
|
LBUFFER+=" '" ; RBUFFER="'$RBUFFER"
|
|
|
|
}
|
|
|
|
zle -N zle_insert_quote
|
|
|
|
bindkey "^['" zle_insert_quote
|