diff --git a/base/.bashrc b/base/.bashrc new file mode 100755 index 00000000..63ef744f --- /dev/null +++ b/base/.bashrc @@ -0,0 +1,14 @@ +#!/bin/bash +# +# ~/.bashrc +# + +# If not running interactively, don't do anything +[[ $- != *i* ]] && return + +# Source .profile +if [ -r ~/.profile ]; then + # shellcheck disable=1090 + source ~/.profile +fi + diff --git a/base/.config/dircolors b/base/.config/dircolors new file mode 100644 index 00000000..f802612f --- /dev/null +++ b/base/.config/dircolors @@ -0,0 +1,252 @@ +# Copyright (c) 2017-present Arctic Ice Studio +# Copyright (c) 2017-present Sven Greb + +# Project: Nord dircolors +# Repository: https://github.com/arcticicestudio/nord-dircolors +# License: MIT + +COLOR tty + +TERM ansi +TERM *color* +TERM con[0-9]*x[0-9]* +TERM cons25 +TERM console +TERM cygwin +TERM dtterm +TERM dvtm +TERM dvtm-256color +TERM Eterm +TERM eterm-color +TERM fbterm +TERM gnome +TERM gnome-256color +TERM hurd +TERM jfbterm +TERM konsole +TERM konsole-256color +TERM kterm +TERM linux +TERM linux-c +TERM mlterm +TERM putty +TERM putty-256color +TERM rxvt* +TERM rxvt-unicode +TERM rxvt-256color +TERM rxvt-unicode256 +TERM screen* +TERM screen-256color +TERM st +TERM st-256color +TERM terminator +TERM tmux* +TERM tmux-256color +TERM vt100 +TERM xterm* +TERM xterm-color +TERM xterm-88color +TERM xterm-256color + +#+-----------------+ +#+ Global Defaults + +#+-----------------+ +NORMAL 00 +RESET 0 + +FILE 00 +DIR 01;34 +LINK 36 +MULTIHARDLINK 04;36 + +FIFO 04;01;36 +SOCK 04;33 +DOOR 04;01;36 +BLK 01;33 +CHR 33 + +ORPHAN 31 +MISSING 01;37;41 + +EXEC 01;36 + +SETUID 01;04;37 +SETGID 01;04;37 +CAPABILITY 01;37 + +STICKY_OTHER_WRITABLE 01;37;44 +OTHER_WRITABLE 01;04;34 +STICKY 04;37;44 + +#+-------------------+ +#+ Extension Pattern + +#+-------------------+ +#+--- Archives ---+ +.7z 01;32 +.ace 01;32 +.alz 01;32 +.arc 01;32 +.arj 01;32 +.bz 01;32 +.bz2 01;32 +.cab 01;32 +.cpio 01;32 +.deb 01;32 +.dz 01;32 +.ear 01;32 +.gz 01;32 +.jar 01;32 +.lha 01;32 +.lrz 01;32 +.lz 01;32 +.lz4 01;32 +.lzh 01;32 +.lzma 01;32 +.lzo 01;32 +.rar 01;32 +.rpm 01;32 +.rz 01;32 +.sar 01;32 +.t7z 01;32 +.tar 01;32 +.taz 01;32 +.tbz 01;32 +.tbz2 01;32 +.tgz 01;32 +.tlz 01;32 +.txz 01;32 +.tz 01;32 +.tzo 01;32 +.tzst 01;32 +.war 01;32 +.xz 01;32 +.z 01;32 +.Z 01;32 +.zip 01;32 +.zoo 01;32 +.zst 01;32 + +#+--- Audio ---+ +.aac 32 +.au 32 +.flac 32 +.m4a 32 +.mid 32 +.midi 32 +.mka 32 +.mp3 32 +.mpa 32 +.mpeg 32 +.mpg 32 +.ogg 32 +.opus 32 +.ra 32 +.wav 32 + +#+--- Customs ---+ +.3des 01;35 +.aes 01;35 +.gpg 01;35 +.pgp 01;35 + +#+--- Documents ---+ +.doc 32 +.docx 32 +.dot 32 +.odg 32 +.odp 32 +.ods 32 +.odt 32 +.otg 32 +.otp 32 +.ots 32 +.ott 32 +.pdf 32 +.ppt 32 +.pptx 32 +.xls 32 +.xlsx 32 + +#+--- Executables ---+ +.app 01;36 +.bat 01;36 +.btm 01;36 +.cmd 01;36 +.com 01;36 +.exe 01;36 +.reg 01;36 + +#+--- Ignores ---+ +*~ 02;37 +.bak 02;37 +.BAK 02;37 +.log 02;37 +.log 02;37 +.old 02;37 +.OLD 02;37 +.orig 02;37 +.ORIG 02;37 +.swo 02;37 +.swp 02;37 + +#+--- Images ---+ +.bmp 32 +.cgm 32 +.dl 32 +.dvi 32 +.emf 32 +.eps 32 +.gif 32 +.jpeg 32 +.jpg 32 +.JPG 32 +.mng 32 +.pbm 32 +.pcx 32 +.pgm 32 +.png 32 +.PNG 32 +.ppm 32 +.pps 32 +.ppsx 32 +.ps 32 +.svg 32 +.svgz 32 +.tga 32 +.tif 32 +.tiff 32 +.xbm 32 +.xcf 32 +.xpm 32 +.xwd 32 +.xwd 32 +.yuv 32 + +#+--- Video ---+ +.anx 32 +.asf 32 +.avi 32 +.axv 32 +.flc 32 +.fli 32 +.flv 32 +.gl 32 +.m2v 32 +.m4v 32 +.mkv 32 +.mov 32 +.MOV 32 +.mp4 32 +.mpeg 32 +.mpg 32 +.nuv 32 +.ogm 32 +.ogv 32 +.ogx 32 +.qt 32 +.rm 32 +.rmvb 32 +.swf 32 +.vob 32 +.webm 32 +.wmv 32 diff --git a/base/.config/htop/htoprc b/base/.config/htop/htoprc new file mode 100644 index 00000000..96c93fcc --- /dev/null +++ b/base/.config/htop/htoprc @@ -0,0 +1,26 @@ +# Beware! This file is rewritten by htop when settings are changed in the interface. +# The parser is also very primitive, and not human-friendly. +fields=0 5 48 17 18 38 39 2 46 47 49 1 +sort_key=46 +sort_direction=1 +hide_threads=0 +hide_kernel_threads=1 +hide_userland_threads=1 +shadow_other_users=1 +show_thread_names=1 +show_program_path=1 +highlight_base_name=0 +highlight_megabytes=1 +highlight_threads=1 +tree_view=1 +header_margin=1 +detailed_cpu_time=0 +cpu_count_from_zero=0 +update_process_names=0 +account_guest_in_cpu_meter=0 +color_scheme=0 +delay=15 +left_meters=AllCPUs2 Memory Swap +left_meter_modes=1 1 1 +right_meters=Tasks LoadAverage Uptime +right_meter_modes=2 2 2 diff --git a/base/.config/systemd/user/dot-fetch.service b/base/.config/systemd/user/dot-fetch.service new file mode 100644 index 00000000..fbb9a461 --- /dev/null +++ b/base/.config/systemd/user/dot-fetch.service @@ -0,0 +1,9 @@ +# vim:ft=systemd: +[Unit] +Description=Dotfile fetch service + +[Service] +ExecStart=git --git-dir=%h/.dotfiles/ --work-tree=%h fetch + +[Install] +WantedBy=default.target diff --git a/base/.config/systemd/user/dot-fetch.timer b/base/.config/systemd/user/dot-fetch.timer new file mode 100644 index 00000000..09ae63ef --- /dev/null +++ b/base/.config/systemd/user/dot-fetch.timer @@ -0,0 +1,11 @@ +# vim:ft=systemd: +[Unit] +Description=Dot fetch timer + +[Timer] +Persistent=true +OnBootSec=15min +OnCalendar=*-*-* 22:00:00 + +[Install] +WantedBy=default.target diff --git a/base/.config/systemd/user/proj-fetch.service b/base/.config/systemd/user/proj-fetch.service new file mode 100644 index 00000000..a3cb35d6 --- /dev/null +++ b/base/.config/systemd/user/proj-fetch.service @@ -0,0 +1,9 @@ +# vim:ft=systemd: +[Unit] +Description=Project fetch service + +[Service] +ExecStart=find %h/Projects -type d -iname .git -execdir git fetch \; + +[Install] +WantedBy=default.target diff --git a/base/.config/systemd/user/proj-fetch.timer b/base/.config/systemd/user/proj-fetch.timer new file mode 100644 index 00000000..fc5a4fea --- /dev/null +++ b/base/.config/systemd/user/proj-fetch.timer @@ -0,0 +1,11 @@ +# vim:ft=systemd: +[Unit] +Description=Project fetch timer + +[Timer] +Persistent=true +OnBootSec=15min +OnCalendar=*-*-* 23:00:00 + +[Install] +WantedBy=default.target diff --git a/base/.functions b/base/.functions new file mode 100644 index 00000000..731d491f --- /dev/null +++ b/base/.functions @@ -0,0 +1,70 @@ +#! /bin/sh +# +# .functions +# Functions for interactive shells +# + +proj() { + # Ensure we have an argument + if [ -z ${1+x} ]; then + echo "proj: requires argument" + return 1 + fi + # POSIX mandates this external call to sed + projname="$(echo "$1" | sed -re 's/[^ a-zA-Z0-9.-]//g')" + projdir="$HOME/Projects/$projname" + # Ensure we have a ~/Projects directory + mkdir -p "$HOME/Projects" > /dev/null 2>&1 + # cd into the project or make it if necessary + if [ -d "$projdir" ]; then + # It exists + cd "$projdir" || return 50 + else + # It does not exist + echo "Creating new project \"$projname\"" + mkdir -p "$projdir" + cd "$projdir" || return 51 + if command -v git > /dev/null 2>&1; then + # Initialize git + echo "Initializing git with .gitignore" + git init > /dev/null 2>&1 + echo '*.swp' > .gitignore + git add .gitignore > /dev/null 2>&1 + git commit -am "Create gitignore" > /dev/null 2>&1 + git status + fi + fi +} +# Autocompletion for bash +# A note on the shellcheck disable: that's fine, because this is also a test +# If it fails, we don't even define a completion function +# shellcheck disable=2039 +complete -F _proj proj > /dev/null 2>&1 && \ +_proj() { + [ "${#COMP_WORDS[@]}" != "2" ] && return 0 + for dir in "$HOME"/Projects/*; do + reply="$(basename "$dir")" + reply="${reply//[^ \-a-zA-Z0-9.]/}" + # shellcheck disable=2179 + COMPREPLY+=" $reply" + done + unset reply + # shellcheck disable=2178 + COMPREPLY=($(compgen -W "$COMPREPLY" "${COMP_WORDS[COMP_CWORD]}")) + return 0 +} +# Autocompletion for zsh +compdef _proj proj > /dev/null 2>&1 && \ +_proj() { + #! /usr/bin/env zsh + # It's okay, shellcheck + # We zsh now + # shellcheck disable=2039 + for dir in "$HOME"/Projects/*; do + temp="$(basename "$dir")" + temp="${reply//[^ a-zA-Z0-9.]/}" + reply+=" $temp" + done + return 0 +} + diff --git a/base/.inputrc b/base/.inputrc new file mode 100644 index 00000000..d614f92e --- /dev/null +++ b/base/.inputrc @@ -0,0 +1,17 @@ +## COMPLETION +set colored-stats on +set completion-ignore-case on +# Only need a single tab press to show results +set show-all-if-ambiguous on +# You ever do that thing where you put your cursorright in the middle of a word, +# like you're at the "e" in "Makefile", and hit tab, and bash oh-so-helpfully +# inserts the latter half of the word right in the middle of it -- so you've +# got "Makefilefile" sitting in your terminal? +# Yeah fuck that +set skip-completed-text on + +## KEYBINDINGS +# History searching +"\e[A": history-search-backward +"\e[B": history-search-forward + diff --git a/base/.profile b/base/.profile new file mode 100755 index 00000000..0e1bb204 --- /dev/null +++ b/base/.profile @@ -0,0 +1,405 @@ +#!/bin/sh + +# Copyright (c) 2017 rehashedsalt/vintagesalt +# Licensed under the terms of the MIT license + +## POSIX NOTICE +# This script, or at least the parts expected to be run by a standard sh +# implementation, should be fully POSIX-compliant. If it is not, open a bug +# report at git.9iron.club/salt/home and I'll take care of it. + +## SHELLCHECK +# Not finding these sources is none of my concern; they're out of scope +# shellcheck disable=1091 +# shellcheck disable=1090 +# I'm well aware of when functions are defined vs used +# Those choices are deliberate +# shellcheck disable=2139 +# shellcheck disable=2016 +# Some variables will not be used here, but in the shell +# shellcheck disable=2034 +# Quit being pedantic +# shellcheck disable=1117 + +# Environment variables +_baseshell="$(basename -- "$0")" + +# Patch PATH +for dir in \ + "$HOME/.bin" \ + "$HOME/.local/bin" \ + "$HOME/.firestarter" \ + "/usr/local/opt/coreutils/libexec/gnubin" \ + "/usr/local/opt/gnu-sed/libexec/gnubin" \ + "/usr/local/opt/grep/libexec/gnubin" \ + "/usr/local/opt/util-linux/bin" \ + "/usr/local/opt/util-linux/sbin" +do + if [ -d "$dir" ]; then + PATH="$dir:$PATH" + fi +done + +# Grab bash_completion, if it exists +[ -f "/etc/profile.d/bash_completion.sh" ] && . "/etc/profile.d/bash_completion.sh" + +# Source ~/.functions, if it exists +[ -r "$HOME/.functions" ] \ + && [ "$_baseshell" != "sh" ] \ + && [ "$_baseshell" != "dash" ] \ + && . "$HOME/.functions" + +# Define a require function +has() { + [ -z "$1" ] && return 1 + command -v "$1" > /dev/null 2>&1 +} + +# Doot +if ! has doot; then + alias doot="echo Doot doot." +fi + +# Grab pip completion, if it exists +if has pip; then + case "$_baseshell" in + *bash) + if ! [ -f "$HOME/.pip-completion-bash" ]; then + pip completion --bash > "$HOME/.pip-completion-bash" + echo ".profile: Created pip completion for bash" + fi + . "$HOME/.pip-completion-bash" + ;; + zsh) + if ! [ -f "$HOME/.pip-completion-zsh" ]; then + pip completion --zsh > "$HOME/.pip-completion-zsh" + echo ".profile: Created pip completion for zsh" + fi + . "$HOME/.pip-completion-zsh" + ;; + *) + ;; + esac +fi + +# Set up go, if we have it +if has go; then + export GOPATH="$HOME/.local/go" + [ "${PATH#*$GOPATH}" = "$PATH" ] && export PATH="$PATH:$GOPATH/bin" +fi + +# Grab dircolors, if it exists +if has dircolors; then + dircolorsfile="$HOME/.config/dircolors" + if [ -r "$dircolorsfile" ]; then + eval "$(dircolors "$dircolorsfile")" + else + eval "$(dircolors -b)" + fi +fi + +# Set up our text editor +for editor in vim vi nano; do + if has "$editor"; then + export EDITOR="$editor" + break + fi +done +alias e='$EDITOR' + +# Now for a shitton of aliases +if ! has define; then + if has mate-dictionary; then + alias define='mate-dictionary -n --look-up' + fi +fi +if ! has helpme; then + # https://breanneboland.com/blog/2020/02/28/you-can-put-what-in-dns-txt-records-a-blog-post-for-con-west-2020/ + alias helpme='dig +short txt "$(( RANDOM % 50 )).maybethiscould.work"' +fi +if has emerge; then + alias e-depclean='sudo emerge -a --depclean' + alias e-inst='sudo emerge -a --jobs --tree --quiet-build y' + alias e-upgrade='sudo emerge -DNUua --jobs --tree --quiet-build y --with-bdeps=y --keep-going --backtrack=1000 @world' + alias e-newuse='sudo emerge -Uva --jobs --tree --quiet-build y @world' + alias e-search='emerge -s' + alias e-sync='sudo emerge --sync' + if has eclean; then + alias e-cleanup='sudo eclean -d distfiles && sudo eclean -d packages' + fi +fi +if has firestarter and ! has fs; then + alias fs="firestarter" +fi +if has fork; then + alias dup="fork $TERMINAL $PWD" +fi +if has git; then + # Thanks Bash-it! + alias g='git' + alias ga='git add' + alias gall='git add -A' + alias gap='git add -p' + alias gb='git branch' + alias gbD='git branch -D' + alias gba='git branch -a' + alias gbd='git branch -d' + alias gbm='git branch -m' + alias gbt='git branch --track' + alias gc='git commit -v' + alias gca='git commit -v -a' + alias gcam="git commit -v -am" + alias gcb='git checkout -b' + alias gci='git commit --interactive' + alias gcl='git clone' + alias gclean='git clean -fd' + alias gcm='git commit -v -m' + alias gco='git checkout' + alias gcob='git checkout -b' + alias gcom='git checkout master' + alias gcount='git shortlog -sn' + alias gcp='git cherry-pick' + alias gcpd='git checkout master; git pull; git branch -D' + alias gcpx='git cherry-pick -x' + alias gcsam="git commit -S -am" + alias gct='git checkout --track' + alias gd='git diff' + alias gdel='git branch -D' + alias gds='git diff --staged' + alias gdv='git diff -w "$@" | vim -R -' + alias get='git' + alias gexport='git archive --format zip --output' + alias gf='git fetch --all --prune' + alias gft='git fetch --all --prune --tags' + alias gftv='git fetch --all --prune --tags --verbose' + alias gfv='git fetch --all --prune --verbose' + alias ggs="gg --stat" + alias ggui="git gui" + alias gh='cd "$(git rev-parse --show-toplevel)"' + alias gl='git pull' + alias gll='git log --graph --pretty=oneline --abbrev-commit' + alias glum='git pull upstream master' + alias gm="git merge" + alias gmu='git fetch origin -v; git fetch upstream -v; git merge upstream/master' + alias gmv='git mv' + alias gp='git push' + alias gpatch="git format-patch -1" + alias gpo='git push origin' + alias gpom='git push origin master' + alias gpp='git pull && git push' + alias gpr='git pull --rebase' + alias gpristine='git reset --hard && git clean -dfx' + alias gpu='git push --set-upstream' + alias gpuo='git push --set-upstream origin' + alias gpuoc='git push --set-upstream origin $(git symbolic-ref --short HEAD)' + alias gr='git remote' + alias gra='git remote add' + alias grm='git rm' + alias grv='git remote -v' + alias gs='git status' + alias gsl="git shortlog -sn" + alias gss='git status -s' + alias gst="git stash" + alias gstb="git stash branch" + alias gstd="git stash drop" + alias gstl="git stash list" + alias gstp="git stash pop" + alias gsu='git submodule update --init --recursive' + alias gt="git tag" + alias gta="git tag -a" + alias gtd="git tag -d" + alias gtl="git tag -l" + alias gtls='git tag -l | sort -V' + alias gup='git fetch && git rebase' + alias gus='git reset HEAD' + alias gwc="git whatchanged" + # Add uncommitted and unstaged changes to the last commit + alias gcaa="git commit -a --amend -C HEAD" + # From http://blogs.atlassian.com/2014/10/advanced-git-aliases/ + # Show commits since last pull + alias gnew="git log HEAD@{1}..HEAD@{0}" + # Show untracked files + alias gu='git ls-files . --exclude-standard --others' +fi +if has nc; then + # I'm not sorry + alias blinkenlights='nc -v towel.blinkenlights.nl 23' +fi +if has ptgdp; then + song() { + if [ -z "$*" ]; then + echo "song: Requires an argument" + return 1 + fi + echo "$*" | ptgdp -p + } +fi +if has sed && has find; then + replace() { + if [ $# -ne 2 ]; then + echo "replace: Requires two arguments" + return 1 + fi + find . -type f -exec sed -i "s/$1/$2/g" {} \; + } +fi +if has sudo; then + case $_baseshell in + *bash|*zsh) + export SUDO_PROMPT=$'[\e[34msudo\e[0m as %U]: Password for %p: ' + ;; + *) + export SUDO_PROMPT='[sudo as %U]: Password for %p: ' + esac +fi +if has tree; then + treeargs='-qF --dirsfirst' + alias tree="tree $treeargs" + alias t="tree $treeargs -L 2" + alias tl="tree $treeargs -pughL 2" + alias tp="tree $treeargs -pL 2" + alias ts="tree $treeargs -hL 2" + unset treeargs +fi +if has vault; then + alias vlogin="vault login -method=ldap username=$(whoami)" + alias vls="vault list" + alias vr="vault read" +fi + +# Dotfile management aliases +if [ -d "$HOME/.dotfiles" ]; then + dotcmd='git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME' + alias dot="$dotcmd" + if [ -f "/usr/share/bash-completion/completions/git" ] && [ "$_baseshell" == "bash" ]; then + . "/usr/share/bash-completion/completions/git" + __git_complete dot _git + fi + alias dotupdate="\ + printf 'Pulling...\n' + $dotcmd pull + printf 'Updating submodules...\n' + $dotcmd submodule update --init --recursive --remote + $dotcmd status" + alias dotupgrade="\ + printf 'Pulling...\n' + $dotcmd pull + printf 'Updating submodules...\n' + $dotcmd submodule update --init + printf 'Checking out masters...\n' + $dotcmd submodule -q foreach --recursive 'git checkout -q master && git pull' && \ + $dotcmd status" + unset dotcmd +fi + +# Aliases for common utilities +if [ "$(uname)" = "Linux" ] || has brew; then + # Assume we have GNU coreutils + lsarguments='-Fh --color=auto --group-directories-first' + alias l="ls -l --file-type $lsarguments" + alias la="ls -A --file-type $lsarguments" + alias ls="ls $lsarguments" + alias ll="ls -Al --file-type $lsarguments" + unset lsarguments + + alias rm='rm -I' +else + # Else only assume POSIX/BSD + lsarguments='-F' + alias l="ls -$lsarguments" + alias la="ls -A $lsarguments" + alias ls="ls $lsarguments" + alias ll="ls -Ahl $lsarguments" +fi +alias cp='cp -i' +alias d='du -hs' + +# Set up a default PS1 for bash +_ps1bash() { + exitcode="$?" + r="\[\e[0m\]" + bg_red="\[\e[41m\]" + bg_yellow="\[\e[43m\]" + bg_blue="\[\e[44m\]" + fg_black="\[\e[30m\]" + fg_red="\[\e[31m\]" + fg_green="\[\e[32m\]" + fg_yellow="\[\e[33m\]" + fg_blue="\[\e[34m\]" + fg_magenta="\[\e[35m\]" + fg_grey="\[\e[37m\]" + fg_bold="\[\e[1m\]" + + # Add hostname prefix in SSH sessions + unset _prefix + # Alert if in an SSH session + if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then + _prefix="${fg_bold}${fg_red}$(hostname -s)${r}${fg_red}:${r}${_prefix}" + elif [ "$USER" != "salt" ]; then + _prefix="${fg_bold}${fg_yellow}$USER${r}${fg_yellow}:${r}${_prefix}" + fi + # Color PWD + _prefix="${_prefix}${fg_blue}" + # Show the tilde instead of $HOME + _cpwd='\w' + # Show read-only status in certain directories + if [ "$UID" = 0 ]; then + # Root gets the usual "#" prompt + _prompt="${fg_red}#${r}" + elif ! [ -d "$PWD" ]; then + # Something very bad has happened to our PWD, probably got deleted + _prompt="${bg_red}${fg_black}!${r}" + elif ! [ -r "$PWD" ]; then + # Guess we lost privileges + _prompt="${fg_red}"'$'"${r}" + elif ! [ -x "$PWD" ]; then + # Missing execution perms + if [ -w "$PWD" ]; then + # Fixable + _prompt="${bg_blue}${fg_black}"'$'"${r}" + else + # Unfixable + _prompt="${bg_yellow}${fg_black}"'$'"${r}" + fi + elif ! [ -w "$PWD" ]; then + # Can't write is really common but also good to know + _prompt="${fg_magenta}"'~'"${r}" + else + # Otherwise we should be fine + _prompt="${fg_green}"'$'"${r}" + fi + # Alert us if the last command failed + unset _fail + if ! [ "$exitcode" = "0" ]; then + _fail="${fg_bold}${fg_red}?" + fi + # shellcheck disable=2059 + PS1="[${_prefix}${_cpwd}${r}]${_fail}${r}${_prompt}${r} " +} + +# And export our PS1 +case "$_baseshell" in + zsh) + # Don't do this on ZSH + # I have a custom theme for that + ;; + *bash) + export PS1="" + export PROMPT_COMMAND=_ps1bash + ;; + *) + export PS1='[\e[31m\w\e[0m]\e[32m\$\e[0m ' + ;; +esac + +# Clean up +unset gnubin +unset -v _baseshell +unset -f has + +# Source in a site-specific profile +localprofile="$HOME/.local/profile" +if [ -f "$localprofile" ]; then + . "$localprofile" +fi +