updated shell config

This commit is contained in:
Ezri Brimhall 2025-12-17 11:06:06 -07:00
parent 61b96b3f38
commit 79b9ddf5f6
Signed by: ezri
GPG Key ID: 058A78E5680C6F24
22 changed files with 828 additions and 367 deletions

3
.config/git/ignore Normal file
View File

@ -0,0 +1,3 @@
# Never include pycache directories or pyc files
__pycache__
*.pyc

View File

@ -1,127 +0,0 @@
# Move shell into its own systemd scope if possible
if ! hash busctl &>/dev/null; then
return
fi
if [[ $_scope_loaded == 1 ]]; then
# shell reload, ignore
return
fi
_scope_loaded=1
# Load new scope unit
busctl -q --user call org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager StartTransientUnit 'ssa(sv)a(sa(sv))' \
"zsh-$$.scope" \
replace \
2 \
PIDs au 1 $$ \
Slice s app-shell.slice \
0 \
&>/dev/null # this call fails on a shell re-exec, but we don't really care since the scope will already exist in that case, so forward to dave null
# Set and unset variables
export INVOCATION_ID=$(systemctl --user show "zsh-$$.scope" | awk -F= '/InvocationID=/{ print $2 }')
export SYSTEMD_UNIT="zsh-$$.scope"
unset SYSTEMD_EXEC_PID
unset JOURNAL_STREAM
unset MEMORY_PRESSURE_WATCH
unset MEMORY_PRESSURE_WRITE
function lift-constraints() {
# Don't lift the PID constraint since there's really no reason a shell should have more than 100 active PIDs. Reap what you sow!
env systemctl --user set-property zsh-$$.scope CPUQuota=
env systemctl --user set-property zsh-$$.scope MemoryHigh=
env systemctl --user set-property zsh-$$.scope MemoryMax=
}
function detach() {
local args slice type unit passed_envs
passed_envs=(SUDO_PROMPT EDITOR SUDO_EDITOR VISUAL)
args=(--user --same-dir -q --collect)
slice="app-shell.slice"
type="scope"
while true; do
case $1 in
--help)
cat <<EOF
Usage: detach [OPTIONS] <COMMAND> [ARGS...]
Invoke a command outside of the shell's execution context, detaching it from any resource
constraints on the shell itself.
It will be run by the user service manager using systemd-run. By default, the command
is invoked in the app-shells slice, so is still subject to any restrictions placed
on the set of all user shells.
This is intended to simplify the act of intentionally launching resource-intensive programs
(such as compilers) while still limiting most programs in terms of how much they are allowed
to consume.
Some environment variables are inherited by default, which can be disabled with --clean-env:
$passed_envs
OPTIONS:
--help - display this help message and exit
--app - launch in the main app slice rather than the app-shell slice. Equivalent to --slice app.slice
--background - launch in the background slice. Equivalent to --slice background.slice
--slice <SLICE> - launch in the specified user slice.
--service - create a service unit, rather than a scope, producing a truly clean environment. This separates
the program from the shell's process tree, preventing the shell's job management from managing it.
--env <VAR>[=VALUE] - inherit the given environment variable from the shell, or set it if a value is given.
--clean-env - disable the default set of inherited environment variables
--unit <UNIT> - set the unit name. Defaults to "invoke-<shell PID>@<random>" for services,
"invoke-<shell PID>-<random>" for scopes.
EOF
return 0
;;
--app)
slice="app.slice"
;;
--background)
slice="background.slice"
;;
--slice)
slice=$2
shift
;;
--service)
type="service"
;;
--env)
args+="-E"
args+=$2
shift
;;
--clean-env)
passed_envs=()
;;
*)
break
;;
esac
shift
done
for env in $passed_envs; do
args+="--setenv=$env"
done
case $type in
service)
unit="invoke-$$@$RANDOM.service"
args+=(--service-type=exec --pty --pipe --wait)
;;
scope)
unit="invoke-$$-$RANDOM.scope"
args+="--scope"
;;
esac
systemd-run $args --slice=${slice} --unit=${unit} -- "$@"
}
for cmd in $always_detach; do
eval $(echo alias $cmd=\"detach $cmd\")
done
for cmd in $always_detach_as_service; do
eval $(echo alias $cmd=\"detach --service $cmd\")
done

244
.config/zsh/00-systemd.zsh Normal file
View File

@ -0,0 +1,244 @@
# Move shell into its own systemd scope if possible
if ! hash busctl &>/dev/null; then
return
fi
if [[ $_scope_loaded == 1 ]]; then
# shell reload, ignore
return
fi
_scope_loaded=1
# Load new scope unit
busctl -q --user call org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager StartTransientUnit 'ssa(sv)a(sa(sv))' \
"zsh-$$.scope" \
replace \
2 \
PIDs au 1 $$ \
Slice s ${SHELL_SLICE:-app-shell.slice} \
0 \
&>/dev/null # this call fails on a shell re-exec, but we don't really care since the scope will already exist in that case, so forward to dave null
# Environment variable possibly passed by parent, but we don't want it to be inherited, so unset it
unset SHELL_SLICE
function env_merge {
# usage: env_merge <ENVIRON> <VALUE>
# If ENVIRON is not already set, set it to VALUE. Then export ENVIRON.
: "${(P)1=$2}"
export $1
}
# import environment from systemd user daemon.
# this is necessary when running in a context not descended from the user manager (e.g. tty login, ssh login, etc.)
# use the "env_merge" function defined above to not override existing environment (e.g. SSH-forwarded SSH_AUTH_SOCK or DISPLAY)
eval $(systemctl --user show-environment | awk 'match($0, /^([a-zA-Z_]+)=(.*)$/, ary) { print "env_merge " ary[1] " " ary[2] }')
# discard the env_merge function
unset -f env_merge
# Set and unset variables
export INVOCATION_ID=$(systemctl --user show "zsh-$$.scope" | awk -F= '/InvocationID=/{ print $2 }')
export SYSTEMD_UNIT="zsh-$$.scope"
unset SYSTEMD_EXEC_PID
unset JOURNAL_STREAM
unset MEMORY_PRESSURE_WATCH
unset MEMORY_PRESSURE_WRITE
function lift-constraints() {
# Don't lift the PID constraint since there's really no reason a shell should have more than 100 active PIDs. Reap what you sow!
env systemctl --user set-property zsh-$$.scope CPUQuota=
env systemctl --user set-property zsh-$$.scope MemoryHigh=
env systemctl --user set-property zsh-$$.scope MemoryMax=
}
function run() {
local args slice type unit passed_envs
passed_envs=(SUDO_PROMPT EDITOR SUDO_EDITOR VISUAL)
args=(--user --same-dir -q --collect)
slice="app-shell.slice"
type="scope"
while true; do
case $1 in
--help)
cat <<EOF
Usage: $0 [OPTIONS] <COMMAND> [ARGS...]
Invoke a command outside of the shell's execution context, detaching it from any resource
constraints on the shell itself.
It will be run by the user service manager using systemd-run. By default, the command
is invoked in the app-shells slice, so is still subject to any restrictions placed
on the set of all user shells.
This is intended to simplify the act of intentionally launching resource-intensive programs
(such as compilers) while still limiting most programs in terms of how much they are allowed
to consume.
Some environment variables are inherited by default, which can be disabled with --clean-env:
$passed_envs
OPTIONS:
--help - display this help message and exit
--app - launch in the main app slice rather than the app-shell slice. Equivalent to --slice app.slice
--background - launch in the background slice. Equivalent to --slice background.slice
--slice <SLICE> - launch in the specified user slice.
--service - create a service unit, rather than a scope, producing a truly clean environment. This separates
the program from the shell's process tree, preventing the shell's job management from managing it.
--env <VAR>[=VALUE] - inherit the given environment variable from the shell, or set it if a value is given.
--clean-env - disable the default set of inherited environment variables
--unit <UNIT> - set the unit name. Defaults to "invoke-<shell PID>@<random>" for services,
"invoke-<shell PID>-<random>" for scopes.
EOF
return 0
;;
--app)
slice="app.slice"
;;
--background)
slice="background.slice"
;;
--slice)
slice=$2
shift
;;
--service)
type="service"
;;
--env)
args+="-E"
args+=$2
shift
;;
--clean-env)
passed_envs=()
;;
--unit)
unit=$2
shift
;;
*)
break
;;
esac
shift
done
for env in $passed_envs; do
args+="--setenv=$env"
done
case $type in
service)
if [[ $unit == '' ]]; then
unit="invoke-$$@$RANDOM.service"
fi
args+=(--service-type=exec --pty --pipe --wait)
;;
scope)
if [[ $unit == '' ]]; then
unit="invoke-$$-$RANDOM.scope"
fi
args+="--scope"
;;
esac
if [[ $unit != *.$type ]]; then
echo "Unit suffix does not match unit type! Should end in .$type!"
return 1
fi
systemd-run $args --slice=${slice} --unit=${unit} -- "$@"
}
function with-group {
local args slice unit passed_envs user passed_envs_when_user_is_us
passed_envs=(EDITOR VISUAL)
passed_envs_when_user_is_us=(DBUS_SESSION_BUS_ADDRESS DISPLAY WAYLAND_DISPLAY XDG_RUNTIME_DIR)
args=(--same-dir -q --collect)
slice="system.slice"
user=$USER
groups=${1//,/ }
shift
while true; do
case $1 in
--help)
cat <<EOF
Usage: with-group [OPTIONS] <GROUPS> [<COMMAND> [ARGS...]]
Invoke a command as the current user with additional supplementary groups. Provides a convenient
way to temporarily gain permissions afforded to groups the user does not have, while still retaining
regular user permissions (i.e. without switching to another user or fully elevating to root).
Multiple groups may be specified in a comma-separated list (similar to the -G flag of useradd and usermod).
It will be run by the system service manager using systemd-run as a transient service. As it has to be
invoked by the service manager to gain the additional permissions, there is no way to run it as a scope.
If no command is specified, the current shell will be launched instead.
Some environment variables are inherited by default, which can be disabled with --clean-env:
$passed_envs
OPTIONS:
--help - display this help message and exit.
--slice <SLICE> - launch in the specified system slice.
--env <VAR>[=VALUE] - inherit the given environment variable from the shell, or set it if a value is given.
--clean-env - disable the default set of inherited environment variables.
--unit <UNIT> - set the unit name.
--user <USER> - run as the given user rather than the current user.
EOF
return 0
;;
--slice)
slice=$2
shift
;;
--env)
args+="-E"
args+=$2
shift
;;
--clean-env)
passed_envs=()
;;
--unit)
unit=$2
shift
;;
--user)
user=$2
shift
;;
*)
break
;;
esac
shift
done
for env in $passed_envs; do
args+="--setenv=$env"
done
if [[ $user == $USER ]]; then
for env in $passed_envs_when_user_is_us; do
args+="--setenv=$env"
done
fi
args+=(--service-type=exec --pty --pipe --wait -p "User=$user" -p "SupplementaryGroups=$groups" -p "PAMName=login")
if [[ $unit != "" ]]; then
args+=("--unit=$unit")
fi
if [[ $1 == '' ]]; then
systemd-run $args --slice=${slice} -- $SHELL
else
systemd-run $args --slice=${slice} -- "$@"
fi
}
for cmd in $always_detach; do
eval $(echo alias $cmd=\"run $cmd\")
done
for cmd in $always_detach_as_service; do
eval $(echo alias $cmd=\"run --service $cmd\")
done
alias ssh='run --slice app-ssh.slice --unit ssh-client-$RANDOM.scope ssh'

View File

@ -0,0 +1,108 @@
#
# System introspection script which defines variables for use in later dropins.
#
# Exposes system data as the SYSTEM_INFO associative array. Primarily pulls information via
# systemd-hostnamed if available; falls back to reading /etc/machine-info and /etc/hostname,
# or retrieving the system hostname with `uname`. Keys will always be the names of the D-Bus
# properties, not their corresponding fields in /etc/machine-info.
#
# Exposes OS release data as the OS_RELEASE associative array. Data is read directly from
# /etc/os-release if available, otherwise it is not provided.
#
# Exposes all /etc/machine-info fields, including those not defined by the spec, under MACHINE_INFO.
# Keys are the field names with no transforms applied.
_introspection--generate-file-parser() {
awk 'match($0, /^([A-Za-z_][A-Za-z0-9_]*)=(.*)/, ary) { print "'"$1"'[" ary[1] "]='\''" ary[2] "'\''"}'
}
_introspection--parse-file() {
local varname=$1
while read line; do
key=${${(LC)line%%=*}//_/}
val=${line#*=}
eval "${varname}[${key}]=\"${${val%\"}#\"}\""
done
}
declare -A SYSTEM_INFO
declare -A OS_RELEASE
declare -A MACHINE_INFO
declare -A INTRO_STATE
refresh-system-info() {
INTRO_STATE[SYSTEM_INFO]=none
INTRO_STATE[OS_RELEASE]=none
INTRO_STATE[MACHINE_INFO]=none
INTRO_STATE[hostname]=none
if [ -f /etc/machine-info ]; then
# Populate MACHINE_INFO array
_introspection--parse-file MACHINE_INFO </etc/machine-info
INTRO_STATE[MACHINE_INFO]=present
fi
# Parse OS release info, trying first from the new os-release file, then from the LSB standard. Variables should have more or less the same names between the two files.
if [ -f /etc/os-release ]; then
_introspection--parse-file OS_RELEASE </etc/os-release
INTRO_STATE[OS_RELEASE]=present
elif [ -f /etc/lsb_release ]; then
_introspection--parse-file OS_RELEASE </etc/lsb_release
INTRO_STATE[OS_RELEASE]=legacy_lsb_release
fi
# Parse detailed system info from hostnamectl, or synthesize what we can from /etc/machine-info and static and transient hostnames.
if type hostnamectl &>/dev/null; then
# We can get all relevant data from hostnamectl, so lets do that.
eval $(hostnamectl --json=short | jq -r 'to_entries | .[] | select((.value | type) != "array" and (.value | type) != "object" and (.value | type) != "null") | "SYSTEM_INFO[\(.key)]=\(.value | @sh)"')
INTRO_STATE[SYSTEM_INFO]=full
INTRO_STATE[hostname]=full
else
# Parse machine info if available
if [ -f /etc/machine-info ]; then
# Populate SYSTEM_INFO array as best as possible (this will be missing a _lot_ of fields that hostnamed calculates)
while read line; do
case $line in
PRETTY_HOSTNAME=*)
eval "${line/PRETTY_HOSTNAME/SYSTEM_INFO[PrettyHostname]}"
;;
ICON_NAME=*)
eval "${line/ICON_NAME/SYSTEM_INFO[IconName]}"
;;
CHASSIS=*)
eval "${line/CHASSIS/SYSTEM_INFO[Chassis]}"
;;
DEPLOYMENT=*)
eval "${line/DEPLOYMENT/SYSTEM_INFO[Deployment]}"
;;
LOCATION=*)
eval "${line/LOCATION/SYSTEM_INFO[Location]}"
;;
HARDWARE_VENDOR=*)
eval "${line/HARDWARE_VENDOR/SYSTEM_INFO[HardwareVendor]}"
;;
HARDWARE_MODEL=*)
eval "${line/HARDWARE_MODEL/SYSTEM_INFO[HardwareModel]}"
;;
HARDWARE_SKU=*)
eval "${line/HARDWARE_SKU/SYSTEM_INFO[HardwareSKU]}"
;;
HARDWARE_VERSION=*)
eval "${line/HARDWARE_VERSION/SYSTEM_INFO{HardwareVersion]}"
;;
esac
done </etc/machine-info
INTRO_STATE[SYSTEM_INFO]=limited
fi
# Read current (transient) hostname
SYSTEM_INFO[Hostname]=$(uname -n)
INTRO_STATE[hostname]=transient
# Read static hostname if available
if [ -f /etc/hostname ]; then
SYSTEM_INFO[StaticHostname]=$(</etc/hostname)
INTRO_STATE[hostname]=full
fi
fi
}
refresh-system-info

65
.config/zsh/02-colors.zsh Normal file
View File

@ -0,0 +1,65 @@
#
# Color control code variables
#
declare -A fg
declare -A bg
declare -A ctrl
fg[black]=$'\033[30m'
fg[blue]=$'\033[34m'
fg[red]=$'\033[31m'
fg[green]=$'\033[32m'
fg[magenta]=$'\033[35m'
fg[cyan]=$'\033[36m'
fg[yellow]=$'\033[33m'
fg[white]=$'\033[37m'
fg[bright_black]=$'\033[90m'
fg[bright_blue]=$'\033[94m'
fg[bright_red]=$'\033[91m'
fg[bright_green]=$'\033[92m'
fg[bright_magenta]=$'\033[95m'
fg[bright_cyan]=$'\033[96m'
fg[bright_yellow]=$'\033[93m'
fg[bright_white]=$'\033[97m'
fg[reset]=$'\033[39m'
bg[black]=$'\033[40m'
bg[blue]=$'\033[44m'
bg[red]=$'\033[41m'
bg[green]=$'\033[42m'
bg[magenta]=$'\033[45m'
bg[cyan]=$'\033[46m'
bg[yellow]=$'\033[43m'
bg[white]=$'\033[47m'
bg[bright_black]=$'\033[100m'
bg[bright_blue]=$'\033[104m'
bg[bright_red]=$'\033[101m'
bg[bright_green]=$'\033[102m'
bg[bright_magenta]=$'\033[105m'
bg[bright_cyan]=$'\033[106m'
bg[bright_yellow]=$'\033[103m'
bg[bright_white]=$'\033[107m'
bg[reset]=$'\033[49m'
ctrl[reset]=$'\033[0m'
ctrl[bold]=$'\033[1m'
ctrl[faint]=$'\033[2m'
ctrl[italic]=$'\033[3m'
ctrl[underline]=$'\033[4m'
ctrl[slowblink]=$'\033[5m'
ctrl[fastblink]=$'\033[6m'
ctrl[invert]=$'\033[7m'
ctrl[hide]=$'\033[8m'
ctrl[strike]=$'\033[9m'
ctrl[nobold]=$'\033[22m'
ctrl[noitalic]=$'\033[23m'
ctrl[nounderline]=$'\033[24m'
ctrl[noblink]=$'\033[25m'
ctrl[noinvert]=$'\033[27m'
ctrl[nohide]=$'\033[28m'
ctrl[nostrike]=$'\033[29m'

View File

@ -0,0 +1,178 @@
#
# Initial setup for prompt generation.
#
# Defines the arrays for prompt elements ($prompt_list), rprompt elements ($rprompt_list), and history prompt elements ($history_prompt, the prompt is rewritten using this when a command is submitted).
#
# Prompt elements are strings. Some special prefixes are understood:
# - Strings prefixed with 'func:' will run the function given, using the contents of ${prompt_element_contents} as the element. Argument splitting is performed, but variable interpolation is not (you should be able to do that yourself).
# - Strings prefixed with 'var:' will expand the given variable specifier when the prompt is generated, within curly braces. This allows specifying that the given variable be evaluated at generation time.
# - Strings prefixed with 'literal:' will use the remaining string literally. This allows a static component which starts with "func:" or "var:" if you want to for whatever reason.
#
# We set the prompt_subst option, so variables can be included in prompt elements (e.g. in single quotes), and changes to them will be reflected the next time the prompt renders.
#
# We also set precmd_functions to an empty array in this file, so it should be extended.
declare -a prompt_list
declare -a rprompt_list
declare -a history_prompt
declare -A prompt_elements
setopt prompt_subst
precmd_functions=()
prompt_elements[privilege]='%B%0(#.%F{red} as root.%(!.%F{red} with privileges.))%b'
prompt-element-host() {
# Adds host info to the prompt.
if [[ ${SYSTEM_INFO[Chassis]} == "container" ]] || [[ ${SYSTEM_INFO[Chassis]} == "vm" ]]; then
prompt_element_contents='%F{blue}%B${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}}%b%f'
elif [[ -v SSH_CLIENT ]]; then
prompt_element_contents='%F{blue}%BRemote Console%b%f @ %F{magenta}%B${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}}%b%f'
elif [[ -o login ]]; then
prompt_element_contents='%F{green}%BLogin Console%b%f @ %F{magenta}%B${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}}%b%f'
else
prompt_element_contents='%F{magenta}%B${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}}%f%b'
fi
}
prompt_elements[host]="func:prompt-element-host"
prompt-element-console() {
if [[ ${TTY} =~ "tty" ]]; then
prompt_element_contents=" %F{red}%y%f"
else
prompt_element_contents=""
fi
}
prompt_elements[console]="func:prompt-element-console"
prompt-element-deployment() {
if [[ ${SYSTEM_INFO[Deployment]+yes} == "yes" ]]; then
case ${(L)SYSTEM_INFO[Deployment]} in
*prod|production)
prompt_element_contents='%F{red}%BPROD%b%f '
;;
*devl|dev|devel|development)
prompt_element_contents='%F{green}%BDEV%b%f '
;;
*pprd|preprod|preproduction)
prompt_element_contents='%F{cyan}%BPRE-PROD%b%f '
;;
*)
prompt_element_contents='%F{blue}%B${(U)SYSTEM_INFO[Deployment]}%b%f '
;;
esac
fi
}
prompt_elements[deployment]="func:prompt-element-deployment"
prompt_elements[retcode]="%(?..%F{red}  %?%f)"
prompt_elements[prompt]="%(?..%F{red}%f) "
prompt_elements[pwd]="%B%F{blue}%3~%f%b"
prompt_elements[pyenv]='$pyenv_info_msg_0_'
prompt_elements[vcs]='$vcs_info_msg_0_'
prompt_elements[clock]='%F{yellow}%T%f'
prompt-element-groups() {
# Produces newlines at start and end.
local ambient_groups defined_groups ambient_map defined_map
declare -A ambient_map
declare -A defined_map
ambient_groups=($(id -Gn))
defined_groups=($(id -Gn ${USER}))
prompt_element_contents=$'\n'
# yay 3 loops :/
for group in "${ambient_groups[@]}"; do
ambient_map[$group]=1
done
for group in "${defined_groups[@]}"; do
defined_map[$group]=1
if [ ${ambient_map[$group]:-0} -eq 0 ]; then
prompt_element_contents+=" %F{red}$group%f"$'\n'
fi
done
for group in "${ambient_groups[@]}"; do
if [ ${defined_map[${group}]:-0} -eq 0 ]; then
prompt_element_contents+=" %F{green}$group%f"$'\n'
fi
done
}
prompt_elements[groups]='func:prompt-element-groups'
_build-prompt() {
PROMPT=""
for el in "${prompt_list[@]}"; do
case $el in
func:*)
# Clear the variable
prompt_element_contents=''
# Run the function
${=el/func:/}
# Add the variable to the prompt
PROMPT+="${prompt_element_contents}"
;;
var:*)
# eval the variable.
eval "PROMPT+=\"\${${el/var:/}}\""
;;
literal:*)
# strip the leading 'literal:' and add the string to the prompt
PROMPT+="${el/literal:/}"
;;
*)
# not a known prefix, so just add it as a string
PROMPT+="${el}"
;;
esac
done
RPROMPT=""
for el in "${rprompt_list[@]}"; do
case $el in
func:*)
# Clear the variable
prompt_element_contents=''
# Run the function
${=el/func:/}
# Add the variable to the prompt
RPROMPT+="${prompt_element_contents}"
;;
var:*)
# eval the variable.
eval "RPROMPT+=\"\${${el/var:/}}\""
;;
literal:*)
# strip the leading 'literal:' and add the string to the prompt
RPROMPT+="${el/literal:/}"
;;
*)
# not a known prefix, so just add it as a string
RPROMPT+="${el}"
;;
esac
done
HISTORY_UNPROMPT=""
for el in "${history_prompt[@]}"; do
case $el in
func:*)
# Clear the variable
prompt_element_contents=''
# Run the function
${=el/func:/}
# Add the variable to the prompt
HISTORY_UNPROMPT+="${prompt_element_contents}"
;;
var:*)
# eval the variable.
eval "HISTORY_UNPROMPT+=\"\${${el/var:/}}\""
;;
literal:*)
# strip the leading 'literal:' and add the string to the prompt
HISTORY_UNPROMPT+="${el/literal:/}"
;;
*)
# not a known prefix, so just add it as a string
HISTORY_UNPROMPT+="${el}"
;;
esac
done
}

View File

@ -12,12 +12,12 @@ function getkernelpkg() {
fi
}
function docker() {
# Wrapper for docker command that executes it inside the systemd-nspawn docker container
# This container has our home directory bound, so we should cd to the current directory before running this command
# function docker() {
# # Wrapper for docker command that executes it inside the systemd-nspawn docker container
# # This container has our home directory bound, so we should cd to the current directory before running this command
ssh -t dockerbox "env ORIGINALWD=\"$(pwd)\" ~/.local/bin/dockerbox.sh $*"
}
# ssh -t dockerbox "env ORIGINALWD=\"$(pwd)\" ~/.local/bin/dockerbox.sh $*"
#}
function random-xkcd() {
blocklist=(
@ -25,7 +25,7 @@ function random-xkcd() {
"631" # "Anatomy Text", don't want that coming up in public thanks
)
link="https://xkcd.com/404/"
while (( $blocklist[(Ie)$(basename $link)] )); do
while (( ${blocklist[(Ie)$(basename $link)]} )); do
link=$(curl https://c.xkcd.com/random/comic/ -v |& grep location | cut -d' ' -f3 | sed 's/\r//')
done
html=$(curl -L ${link/http:/https:} 2>/dev/null)
@ -38,11 +38,11 @@ function random-xkcd() {
}
if [[ $(hostnamectl chassis) == "container" ]]; then
DEFAULT_WINDOW_NAME="Container Connection: [ $os_icon $hostname Console ]"
DEFAULT_WINDOW_NAME="Container Connection: [ ${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}} Console ]"
elif [[ -z "${SSH_CONNECTION+x}" ]]; then
DEFAULT_WINDOW_NAME="$os_icon $hostname Console"
DEFAULT_WINDOW_NAME="${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}} Console"
else
DEFAULT_WINDOW_NAME="Remote Connection: [ $os_icon $hostname Console ]"
DEFAULT_WINDOW_NAME="Remote Connection: [ ${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}} Console ]"
fi
function _rename_window() {
@ -172,3 +172,38 @@ function urlencode {
echo -n $@ | jq -sRr '@uri'
fi
}
function ssh-copy-shell {
# Copy shell config to the given SSH host
local port=22 host
while [ $# -gt 0 ]; do
case $1 in
-p|--port)
port=$2
shift
;;
--port=*)
port=${1/--port=/}
;;
*:*)
host=${1/:*/}
port=${1/*:/}
;;
*)
host=$1
;;
esac
shift
done
if [[ ${host+x} != x ]]; then
echo "Target host is required!"
return 1
fi
ssh -p ${port} ${host} mkdir -p .config .local/lib
# Deploy files
sftp -P ${port} ${host} <<SFTP
put -R .config/zsh .config
put -R .local/lib/zsh .local/lib
put .zshrc
SFTP
}

View File

@ -2,8 +2,7 @@
alias emacs="TERM=screen-256color emacsclient -t"
alias systemctl="sudo systemctl"
alias userctl="\systemctl --user"
alias userctl="systemctl --user"
alias ujournalctl="\journalctl --user"

View File

@ -0,0 +1,24 @@
# CD to directory when you type it, without having to type cd
setopt auto_cd
# Use directory stack
setopt auto_pushd
# resolve links when CDing
setopt chase_links
# Completion
setopt auto_list
# History
setopt hist_ignore_dups
setopt hist_ignore_space
setopt hist_expire_dups_first
setopt extended_history # adds timestamps and command durations to history file
setopt hist_reduce_blanks
unsetopt hist_save_by_copy # we have compression enabled on history file, we don't want to lose that attribute, so truncate and rewrite rather than making a new file and moving.
setopt hist_save_no_dups # no reason to save old dups
setopt hist_verify # hitting enter on history search will pull it into the current line editor, not execute directly
setopt inc_append_history_time
# I/O
unsetopt clobber # disallow clobbering of files with > (require >! or >| instead)

View File

@ -0,0 +1,37 @@
#
# Shell-side support for Emacs libvterm terminal
#
# This file returns immediately if we are not running in an Emacs vterm.
if [[ ${INSIDE_EMACS} != "vterm" ]]; then
return
fi
vterm_printf() {
# Function definition pulled from emacs-libvterm README
if [ -n "$TMUX" ] && { [ "${TERM%%-*}" = "tmux" ] || [ "${TERM%%-*}" = "screen" ]; }; then
# Tell tmux to pass the escape sequences through
printf "\ePtmux;\e\e]%s\007\e\\" "$1"
elif [ "${TERM%%-*}" = "screen" ]; then
# GNU screen (screen, screen-256color, screen-256color-bce)
printf "\eP\e]%s\007\e\\" "$1"
else
printf "\e]%s\e\\" "$1"
fi
}
vterm_prompt_end() {
vterm_printf "51;A${USER}@${SYSTEM_INFO[Hostname]}:${PWD}"
}
prompt_elements[prompt]="${prompt_elements[prompt]}"'%{$(vterm_prompt_end)%}'
emacsctl() {
local vterm_elisp
vterm_elisp=""
while [ $# -gt 0 ]; do
vterm_elisp="$vterm_elisp""$(printf '"%s" ' "$(printf "%s" "$1" | sed -e 's|\\|\\\\|g' -e 's|"|\\"|g')")"
shift
done
vterm_printf "51;E${vterm_elisp}"
}

105
.config/zsh/90-prompt.zsh Normal file
View File

@ -0,0 +1,105 @@
autoload -Uz vcs_info
# Show active python virtualenv in prompt
precmd_pyenv_info() {
# use nerd fonts for icons
_pyenv_icon=""
# Only update if we've changed directory, since pyenv can be slow
if [[ "$PWD" == "$_pyenv_old_pwd" ]]; then
return
else
_pyenv_old_pwd="$PWD"
fi
_pyenv_version=$(pyenv version-name 2>/dev/null)
if [[ $? -eq 0 ]] && [[ ${_pyenv_version} != "system" ]] && [[ ${_pyenv_version} != "personal" ]]; then
pyenv_info_msg_0_="%F{yellow} ${_pyenv_icon} ${_pyenv_version}%f"
elif [[ ${_pyenv_version} == "system" ]]; then
pyenv_info_msg_0_="%F{red} ${_pyenv_icon} ${_pyenv_version}%f"
else
pyenv_info_msg_0_=""
fi
}
precmd_kernel_info() {
# check to see if a kernel update has been installed
# since we need to reboot to use it
# if message has been set, don't check again, since a reboot
# is required to clear the message
if [[ -n ${kernel_info_msg_0_} ]]; then
return
fi
if [[ ${OS_RELEASE[Id]} == "arch" ]] || [[ ${OS_RELEASE[IdLike]} == "arch" ]]; then
# Arch Linux removes the old kernel when updating, so we can
# just check to see if /usr/lib/modules/$(uname -r)/vmlinuz exists
if ! [[ -f /usr/lib/modules/$(uname -r)/vmlinuz ]]; then
# kernel update available
kernel_info_msg_0_="%F{red} reboot required %f"
fi
fi
}
precmd_vcs_info() {
vcs_info
}
if [[ ${TERM} == "alacritty" ]]; then
precmd_functions+=(precmd_vcs_info precmd_pyenv_info _reset_window_name)
elif ! [[ ${TERM} == "dumb" ]]; then
precmd_functions+=(precmd_vcs_info precmd_pyenv_info)
fi
if [[ ${SYSTEM_INFO[Chassis]} != "container" ]] && [[ ${OS_RELEASE[IdLike]:-${OS_RELEASE[Id]}} == "arch" ]]; then
# Only check if a reboot is necessary if we're not in a container, and we're arch-based (the check we're using only works for arch-based distros)
precmd_functions+=(precmd_kernel_info)
fi
prompt_list=(
'$kernel_info_msg_0_' $'\n'
"%F{cyan}[%f " ${prompt_elements[deployment]} ${prompt_elements[host]} ${prompt_elements[privilege]} " %F{cyan}]%f" ${prompt_elements[console]} ${prompt_elements[pyenv]} ' ' ${prompt_elements[pwd]} ${prompt_elements[groups]}
" " ${prompt_elements[prompt]}
)
rprompt_list=(
${prompt_elements[vcs]} ${prompt_elements[retcode]}
)
history_prompt=(
"%F{cyan}[%f " ${prompt_elements[host]} ${prompt_elements[privilege]} " %F{cyan}]%f" ${prompt_elements[console]} ' ' ${prompt_elements[clock]} ' ' ${prompt_elements[pwd]} ' ' ${prompt_elements[prompt]}
)
set-prompt() {
if [[ ${TERM} == "dumb" ]]; then
# Dumb terminal needs a dumb prompt, otherwise things like
# emacs TRAMP break
PROMPT='[%~] $ '
PROMPT2='> '
else
_build-prompt
PROMPT2=" %F{yellow}%_ %f "
fi
}
set-prompt
rewrite-prompt-and-accept() {
local oldprompt
if [[ ${TERM} == "dumb" ]]; then
return
fi
oldprompt="${PROMPT}"
PROMPT="${HISTORY_UNPROMPT}"
# Clear any suggestions; we've committed to this command
zle autosuggest-clear
zle reset-prompt
PROMPT="${oldprompt}"
zle accept-line
}
zle -N rewrite-prompt-and-accept
bindkey '^M' rewrite-prompt-and-accept
zstyle ':vcs_info:git:*' formats '%c %F{magenta} 󰊢 %B%r%%b %F{cyan} %b%f'
zstyle ':vcs_info:git:*' actionformats '%c%F{magenta} 󰊢 %B%r%%b %F{cyan} %b %F{red} %a%f'
zstyle ':vcs_info:git:*' stagedstr "%F{green}%f"
zstyle ':vcs_info:git:*' check-for-staged-changes true
zstyle ':vcs_info:*' enable git

View File

@ -0,0 +1,19 @@
#
# Print a greeting
#
echo -n "Greetings, ${fg[cyan]}${ctrl[bold]}${USER}${ctrl[reset]}. The time is "
date +"${fg[yellow]}%H:%M${fg[reset]} on ${fg[blue]}%A, %B %d, %Y${fg[reset]}."
local os_name=${SYSTEM_INFO[OperatingSystemPrettyName]:-${OS_RELEASE[PrettyName]:-${OS_RELEASE[Id]:-an unknown operating system}}}
if [ ${+OS_RELEASE[AnsiColor]} -eq 1 ]; then
os_name=${ctrl[bold]}$'\033['"${OS_RELEASE[AnsiColor]}m${os_name}${ctrl[reset]}"
fi
echo "
This is ${fg[magenta]}${ctrl[bold]}${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}}${ctrl[reset]}${SYSTEM_INFO[Chassis]+, a ${SYSTEM_INFO[HardwareVendor]+${SYSTEM_INFO[HardwareVendor]} }${SYSTEM_INFO[Chassis]}} running ${os_name}."
if [[ ${(L)SYSTEM_INFO[Deployment]} == *prod* ]]; then
echo "
${fg[red]}${ctrl[bold]}This is a production system.${ctrl[reset]}"
fi

View File

@ -1,2 +0,0 @@
hash -d cpp=$HOME/Documents/School/FA22/CS3460
hash -d hpc=$HOME/Documents/School/FA22/CS5030

View File

@ -1,2 +0,0 @@
hash -d webdev=$HOME/Documents/School/SP22/CS4610
hash -d gamedev=$HOME/Documents/School/SP22/CS5410

View File

@ -1,8 +0,0 @@
# CD to directory when you type it, without having to type cd
setopt auto_cd
# Use directory stack
setopt auto_pushd
# Ignore duplicate commands and commands starting with space
setopt hist_ignore_dups
setopt hist_ignore_space

View File

@ -1,151 +0,0 @@
autoload -Uz vcs_info
pwd="%B%F{blue}%3~%f%b"
# Show active python virtualenv in prompt
precmd_pyenv_info() {
# use nerd fonts for icons
_pyenv_icon=""
# Only update if we've changed directory, since pyenv can be slow
if [[ "$PWD" == "$_pyenv_old_pwd" ]]; then
return
else
_pyenv_old_pwd="$PWD"
fi
_pyenv_version=$(pyenv version-name 2>/dev/null)
if [[ $? -eq 0 ]] && [[ ${_pyenv_version} != "system" ]] && [[ ${_pyenv_version} != "personal" ]]; then
pyenv_info_msg_0_="%F{yellow} ${_pyenv_icon} ${_pyenv_version}%f"
elif [[ ${_pyenv_version} == "system" ]]; then
pyenv_info_msg_0_="%F{red} ${_pyenv_icon} ${_pyenv_version}%f"
else
pyenv_info_msg_0_=""
fi
}
precmd_kernel_info() {
# check to see if a kernel update has been installed
# since we need to reboot to use it
# if message has been set, don't check again, since a reboot
# is required to clear the message
if [[ -n ${kernel_info_msg_0_} ]]; then
return
fi
if [[ ${OS_ID} == "arch" ]] || [[ ${OS_ID_LIKE} == "arch" ]]; then
# Arch Linux removes the old kernel when updating, so we can
# just check to see if /usr/lib/modules/$(uname -r)/vmlinuz exists
if ! [[ -f /usr/lib/modules/$(uname -r)/vmlinuz ]]; then
# kernel update available
kernel_info_msg_0_="%F{red} reboot required %f"
fi
fi
}
precmd_vcs_info() {
vcs_info
}
# Reset precmd_functions, then add our functions. This way, regardless of
# whether this file is sourced multiple times, we don't end up with duplicate
# entries which will slow down the prompt.
precmd_functions=()
if [[ ${TERM} == "alacritty" ]]; then
precmd_functions+=(precmd_vcs_info precmd_pyenv_info _reset_window_name)
setopt prompt_subst
elif ! [[ ${TERM} == "dumb" ]]; then
precmd_functions+=(precmd_vcs_info precmd_pyenv_info)
setopt prompt_subst
fi
eval $(awk '{print "OS_" $0}' /etc/os-release)
eval $(awk '{print "MACHINE_" $0}' /etc/machine-info)
eval $(awk '{print "PERSONAL_" $0}' ${HOME}/.personal-info 2>/dev/null)
if [[ -z ${MACHINE_CHASSIS} ]]; then MACHINE_CHASSIS=$(hostnamectl chassis 2>/dev/null); fi
if [[ -z ${MACHINE_CHASSIS} ]]; then MACHINE_CHASSIS="desktop"; fi
if [[ ${MACHINE_CHASSIS} != "container" ]] && [[ ${OS_ID} == "arch" ]]; then
# Only check if a reboot is necessary if we're not in a container
precmd_functions+=(precmd_kernel_info)
fi
hostname=$PERSONAL_HOSTNAME
if [[ -z ${hostname} ]]; then # No personal hostname set
if [[ -n ${MACHINE_PRETTY_HOSTNAME} ]]; then
# Use MACHINE_PRETTY_HOSTNAME if set
hostname=${MACHINE_PRETTY_HOSTNAME}
elif [[ -f /etc/hostname ]]; then
# Fall back to system hostname
hostname=$(</etc/hostname)
else
# Ask the kernel for the hostname
hostname=$(uname -n)
fi
fi
prompt_char="%(?..%F{red}%f)"
ssh_host="%F{cyan}[ %F{blue}%BRemote Console%b%f @ %F{magenta}%B${hostname}%(!.%F{red} as root.)%b%F{cyan} ]%f"
localhost="%F{cyan}[ %F{magenta}%B${hostname}%(!.%F{red} as root.)%b %F{cyan}]%f"
login_shell="%F{cyan}[ %F{green}%BLogin Console%b%f @ %F{magenta}%B${hostname}%(!.%F{red} as root.)%b%F{cyan} ]%f"
serial_host="%F{cyan}[ %F{magenta}${hostname}%(!.%F{red} as root.) %F{cyan}] %F{red}%y%f"
container_host="%F{cyan}[ %F{blue}%B${hostname}%(!.%F{red} as root.)%b %F{cyan}]%f"
returncode="%(?..%F{red}  %?%f)"
prompt_line1='$kernel_info_msg_0_'
prompt_line3=" $prompt_char"
# Create conditional prompt line 2
if [[ ${TTY} =~ "tty" ]]; then
prompt_line2='${serial_host}$pyenv_info_msg_0_ ${pwd}'
history_line="${serial_host}"
elif [[ ${MACHINE_CHASSIS} == "container" ]] || [[ ${MACHINE_CHASSIS} == "vm" ]]; then
prompt_line2='${container_host}$pyenv_info_msg_0_ ${pwd}'
history_line="${container_host}"
elif [[ -v SSH_CLIENT ]]; then
prompt_line2='${ssh_host}$pyenv_info_msg_0_ ${pwd}'
history_line="${ssh_host}"
elif [[ -o login ]]; then
prompt_line2='${login_shell}$pyenv_info_msg_0_ ${pwd}'
history_line="${localhost}"
else
prompt_line2='${localhost}$pyenv_info_msg_0_ ${pwd}'
history_line="${localhost}"
fi
set-prompt() {
if [[ ${TERM} == "dumb" ]]; then
# Dumb terminal needs a dumb prompt, otherwise things like
# emacs TRAMP break
PROMPT='[%~] $ '
PROMPT2='> '
else
PROMPT="${prompt_line1}
${prompt_line2}
${prompt_line3} "
PROMPT2=" %F{yellow}%_ %f "
fi
}
set-prompt
rewrite-prompt-and-accept() {
if [[ ${TERM} == "dumb" ]]; then
return
fi
PROMPT='${history_line} %F{yellow}%T%f ${pwd}$pyenv_info_msg_0_ %F{green}${prompt_char}%f '
# Clear any suggestions; we've committed to this command
zle autosuggest-clear
zle reset-prompt
set-prompt
zle accept-line
}
zle -N rewrite-prompt-and-accept
bindkey '^M' rewrite-prompt-and-accept
RPROMPT='$vcs_info_msg_0_$returncode'
zstyle ':vcs_info:git:*' formats '%c %F{magenta} 󰊢 %B%r%%b %F{cyan} %b%f'
zstyle ':vcs_info:git:*' actionformats '%c%F{magenta} 󰊢 %B%r%%b %F{cyan} %b %F{red} %a%f'
zstyle ':vcs_info:git:*' stagedstr "%F{green}%f"
zstyle ':vcs_info:git:*' check-for-staged-changes true
zstyle ':vcs_info:*' enable git

View File

@ -1,43 +0,0 @@
#
# ROS stuff for ZSH
#
function ros-version {
if [[ $1 == '' ]]; then
if [[ $ROS_DISTRO == '' ]]; then
echo 'Error: no ROS distribution active' >&2
return 1
else
echo ROS Distribution: $ROS_DISTRO
echo ROS Version: $ROS_VERSION
fi
else
source /opt/ros/$1/setup.zsh
fi
}
function ros-load-workspace {
if [[ $1 == '' ]]; then
echo 'Error: No workspace directory given' >&2
return 1
elif [[ ! -d $1 ]]; then
echo 'Error: workspace directory does not exist' >&2
return 2
elif [[ $ROS_VERSION != '2' ]] && ([[ ! -d $1/devel ]] || [[ ! -f $1/devel/setup.zsh ]]); then
echo 'Error: directory is not a ROS workspace' >&2
return 3
elif [[ $ROS_VERSION == '2' ]] && ([[ ! -d $1/install ]] || [[ ! -f $1/install/local_setup.zsh ]]); then
echo 'Error: directory is not a ROS workspace' >&2
return 3
else
if [[ $ROS_VERSION == '2' ]]; then
source $1/install/local_setup.zsh
else
source $1/devel/setup.zsh
fi
ROS_WORKSPACES=$ROS_WORKSPACES:$(readlink -f $1)
fi
}
export ROS_DOMAIN_ID=37

View File

@ -1,23 +0,0 @@
if [[ $SSH_CLIENT != "" ]]; then
mkfifo "/tmp/ssh_test.$$"
exec 3<> "/tmp/ssh_test.$$"
unlink "/tmp/ssh_test.$$"
ps -o ppid= -p $$ | sed 's/ //g' 1>&3
read -u3 ppid
if ls /tmp | grep ssh- 1> /dev/null 2>&1; then
for dir in /tmp/ssh-*; do
if [[ -e $dir/agent.$ppid ]]; then
export SSH_AUTH_SOCK=$dir/agent.$ppid
fi
done
fi
else
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
fi