updated shell config
This commit is contained in:
parent
61b96b3f38
commit
79b9ddf5f6
3
.config/git/ignore
Normal file
3
.config/git/ignore
Normal file
@ -0,0 +1,3 @@
|
||||
# Never include pycache directories or pyc files
|
||||
__pycache__
|
||||
*.pyc
|
||||
@ -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
244
.config/zsh/00-systemd.zsh
Normal 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'
|
||||
|
||||
108
.config/zsh/01-introspection.zsh
Normal file
108
.config/zsh/01-introspection.zsh
Normal 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
65
.config/zsh/02-colors.zsh
Normal 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'
|
||||
178
.config/zsh/05-prompt-pre.zsh
Normal file
178
.config/zsh/05-prompt-pre.zsh
Normal 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
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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"
|
||||
|
||||
24
.config/zsh/60-options.zsh
Normal file
24
.config/zsh/60-options.zsh
Normal 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)
|
||||
|
||||
37
.config/zsh/80-emacs-vterm.zsh
Normal file
37
.config/zsh/80-emacs-vterm.zsh
Normal 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
105
.config/zsh/90-prompt.zsh
Normal 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
|
||||
19
.config/zsh/99-greeting.zsh
Normal file
19
.config/zsh/99-greeting.zsh
Normal 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
|
||||
@ -1,2 +0,0 @@
|
||||
hash -d cpp=$HOME/Documents/School/FA22/CS3460
|
||||
hash -d hpc=$HOME/Documents/School/FA22/CS5030
|
||||
@ -1,2 +0,0 @@
|
||||
hash -d webdev=$HOME/Documents/School/SP22/CS4610
|
||||
hash -d gamedev=$HOME/Documents/School/SP22/CS5410
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user