Compare commits

..

No commits in common. "10c415c3e5d90f462d31a669ce719b0a091001b9" and "70f4f215c07ee582329c96e33c31d02e90f5e3af" have entirely different histories.

View file

@ -1,268 +1,264 @@
{ pkgs, ... }: { ... }:
{ {
programs.bash = { programs.bash = {
enable = true; enable = true;
enableCompletion = false;
initExtra = '' initExtra = ''
if [[ ! -v BASH_COMPLETION_VERSINFO ]] && [ "''${BASH_COMPLETION_VERSINFO-}" ] || unset -v BASH_COMPLETION_VERSINFO
[[ -f "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh" ]]; then
source "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh"
fi
[ "$DISPLAY" ] && xset r rate 300 60 [ "$DISPLAY" ] && xset r rate 300 60
#-##################### user specific aliases and functions ###################### #-##################### user specific aliases and functions ######################
if [ -d ~/.bashrc.d ]; then if [ -d ~/.bashrc.d ]; then
for rc in ~/.bashrc.d/*; do for rc in ~/.bashrc.d/*; do
bn=''${rc##*/} bn=''${rc##*/}
if [ -f "''$rc" ] && [ -r "''$rc" ] && [ ! "''${bn::1}" = '.' ]; then if [ -f "''$rc" ] && [ -r "''$rc" ] && [ ! "''${bn::1}" = '.' ]; then
\. "''$rc" \. "''$rc"
fi fi
done done
fi fi
unset rc bn unset rc bn
#-########################### shell settings & options ########################### #-########################### shell settings & options ###########################
set -E set -E
set -o pipefail set -o pipefail
shopt -s nullglob dotglob globstar extglob shopt -s nullglob dotglob globstar extglob
shopt -s autocd cdable_vars cdspell shopt -s autocd cdable_vars cdspell
shopt -s checkwinsize shopt -s checkwinsize
shopt -s lastpipe shopt -s lastpipe
shopt -s inherit_errexit shopt -s inherit_errexit
shopt -s no_empty_cmd_completion shopt -s no_empty_cmd_completion
shopt -s histreedit shopt -s histreedit
shopt -s lithist shopt -s lithist
shopt -u histverify shopt -u histverify
_have bash_abbr && shopt -u expand_aliases _have bash_abbr && shopt -u expand_aliases
#-############################### shell variables ################################ #-############################### shell variables ################################
FIGNORE='.o' FIGNORE='.o'
HISTCONTROL=ignoreboth:erasedups HISTCONTROL=ignoreboth:erasedups
HISTTIMEFORMAT='%y-%m-%d %H:%M:%S ' HISTTIMEFORMAT='%y-%m-%d %H:%M:%S '
HISTSIZE=-1 HISTSIZE=-1
HISTFILESIZE=-1 HISTFILESIZE=-1
HISTFILE=''$HOME/.''${USER:-default}_bash_history HISTFILE=''$HOME/.''${USER:-default}_bash_history
#-############################ environment variables ############################# #-############################ environment variables #############################
export PYTHON_BASIC_REPL=1 # I'm good at readline so I'm gonna use readline whereever possible! export PYTHON_BASIC_REPL=1 # I'm good at readline so I'm gonna use readline whereever possible!
export LESS='-SRFX' export LESS='-SRFX'
export PAGER='less' GIT_PAGER='less' MANPAGER='less' SYSTEMD_PAGER='less' export PAGER='less' GIT_PAGER='less' MANPAGER='less' SYSTEMD_PAGER='less'
export BAT_PAGER=''' export BAT_PAGER='''
export EDITOR='vim' VISUAL='vim' FCEDIT='vim' SYSTEMD_EDITOR='vim' export EDITOR='vim' VISUAL='vim' FCEDIT='vim' SYSTEMD_EDITOR='vim'
export PATH export PATH
#-########################## generally useful functions ########################## #-########################## generally useful functions ##########################
take () { take () {
: 'Idempotently create directory recursively and cd into it' : 'Idempotently create directory recursively and cd into it'
local out local out
out=''$(set -o pipefail && mkdir -vp "''$@" | tail -1) || return out=''$(set -o pipefail && mkdir -vp "''$@" | tail -1) || return
printf '%s\n' "''$out" printf '%s\n' "''$out"
eval "out=''${out#"mkdir: created directory "}" eval "out=''${out#"mkdir: created directory "}"
CDPATH= cd "''${out:-''${@: -1}}" CDPATH= cd "''${out:-''${@: -1}}"
} }
cd () { cd () {
: 'Run cd; on success in a terminal, show the 4 newest entries (with a count of hidden ones)' : 'Run cd; on success in a terminal, show the 4 newest entries (with a count of hidden ones)'
builtin cd "''$@" || return builtin cd "''$@" || return
[[ -t 1 ]] || return 0 [[ -t 1 ]] || return 0
command -v ls &>/dev/null || return 0 command -v ls &>/dev/null || return 0
local -a lines local -a lines
mapfile -t lines < <(command ls --color=always --quoting-style=shell-escape -lArth) mapfile -t lines < <(command ls --color=always --quoting-style=shell-escape -lArth)
if (( ''${#lines[@]} > 10 )); then if (( ''${#lines[@]} > 10 )); then
printf '\033[7m... %d more entries ...\033[27m\n' "$(( ''${#lines[@]} - 10 ))"; printf '\033[7m... %d more entries ...\033[27m\n' "$(( ''${#lines[@]} - 10 ))";
printf '%s\n' "''${lines[@]: -9}" printf '%s\n' "''${lines[@]: -4}"
else else
printf '%s\n' "''${lines[@]}" printf '%s\n' "''${lines[@]}"
fi fi
} }
drop_caches () { drop_caches () {
: 'Drop pagecache, dentries and inodes' : 'Drop pagecache, dentries and inodes'
: 'https://unix.stackexchange.com/a/87909' : 'https://unix.stackexchange.com/a/87909'
echo 3 | sudo tee /proc/sys/vm/drop_caches >/dev/null echo 3 | sudo tee /proc/sys/vm/drop_caches >/dev/null
} }
respawn_shell () { respawn_shell () {
: 'Intelligently respawn shell' : 'Intelligently respawn shell'
: 'pure posix sh without forking' : 'pure posix sh without forking'
if [ "''${BASH_VERSINFO-}" ] && command -v bash 1>/dev/null 2>&1; then if [ "''${BASH_VERSINFO-}" ] && command -v bash 1>/dev/null 2>&1; then
if _is_login_shell; then if _is_login_shell; then
exec bash -l exec bash -l
else else
exec bash exec bash
fi fi
: 'TODO: Implement more detection mechanisms for various shells (zsh, etc.)' : 'TODO: Implement more detection mechanisms for various shells (zsh, etc.)'
elif [ -x /proc/self/exe ]; then elif [ -x /proc/self/exe ]; then
if _is_login_shell; then if _is_login_shell; then
exec -l /proc/self/exe exec -l /proc/self/exe
else else
exec /proc/self/exe exec /proc/self/exe
fi fi
elif command -v "''${0#-}" 1>/dev/null 2>&1; then elif command -v "''${0#-}" 1>/dev/null 2>&1; then
: 'TODO: Make it work with shells that actually start with a dash (unlikely, but possible)' : 'TODO: Make it work with shells that actually start with a dash (unlikely, but possible)'
printf 'Warning: replacing current shell with unreliable ''$0, which is: %s\n' "''$0" printf 'Warning: replacing current shell with unreliable ''$0, which is: %s\n' "''$0"
if _is_login_shell; then if _is_login_shell; then
exec -l "''${0#-}" exec -l "''${0#-}"
else else
exec "''${0#-}" exec "''${0#-}"
fi fi
else else
printf 'Error: Don'\'''t know how to reliably replace this shell, not exec'\'''ing and not exiting\n' printf 'Error: Don'\'''t know how to reliably replace this shell, not exec'\'''ing and not exiting\n'
printf 'You might want to manually run `exec [-l] "''$SHELL"`, however, `''$SHELL` might not be the shell you are currently running' printf 'You might want to manually run `exec [-l] "''$SHELL"`, however, `''$SHELL` might not be the shell you are currently running'
return 1 return 1
fi fi
} }
export_bashrc () { export_bashrc () {
CDPATH= command cd ~/.bashrc.d/ || return CDPATH= command cd ~/.bashrc.d/ || return
: 'Not using an associative array because those are not sorted!' : 'Not using an associative array because those are not sorted!'
declare -ar plugins=(*) declare -ar plugins=(*)
[[ ''${#plugins[@]} -eq 0 ]] || [[ ''${#plugins} -eq 1 && ''${plugins[0]} = '*' ]] && return [[ ''${#plugins[@]} -eq 0 ]] || [[ ''${#plugins} -eq 1 && ''${plugins[0]} = '*' ]] && return
local IFS=' ' local IFS=' '
declare -Ai selected declare -Ai selected
declare plugin declare plugin
for plugin in "''${plugins[@]}"; do for plugin in "''${plugins[@]}"; do
case "''$plugin" in case "''$plugin" in
#-# Comment below case match if you don'\'''t want to have a pre-selection of plugins to export #-# Comment below case match if you don'\'''t want to have a pre-selection of plugins to export
#-# Requires `shopt -s extglob` #-# Requires `shopt -s extglob`
(+([0-9])-@(util|redact|prompt|docker-tools|funcs|init-and-complete|general-aliases|bash-abbr)) selected[''$plugin]=1 ;; (+([0-9])-@(util|redact|prompt|docker-tools|funcs|init-and-complete|general-aliases|bash-abbr)) selected[''$plugin]=1 ;;
(*) selected[''$plugin]= (*) selected[''$plugin]=
esac esac
done done
declare -a plugins_with_selection declare -a plugins_with_selection
while :; do while :; do
local PS3='Which plugins do you want to export/not export (enter a single number)? ' local PS3='Which plugins do you want to export/not export (enter a single number)? '
plugins_with_selection=() plugins_with_selection=()
for plugin in "''${plugins[@]}"; do for plugin in "''${plugins[@]}"; do
if [[ ''${selected[''$plugin]} -eq 0 ]]; then if [[ ''${selected[''$plugin]} -eq 0 ]]; then
plugins_with_selection+=(''$'\033[31m'''$plugin''$'\033[m') plugins_with_selection+=(''$'\033[31m'''$plugin''$'\033[m')
else else
plugins_with_selection+=(''$'\033[32m'''$plugin''$'\033[m') plugins_with_selection+=(''$'\033[32m'''$plugin''$'\033[m')
fi fi
done done
select plugin in ''$'\033[31mQUIT\033[m' ''$'\033[34mDONE\033[m' "''${plugins_with_selection[@]}"; do select plugin in ''$'\033[31mQUIT\033[m' ''$'\033[34mDONE\033[m' "''${plugins_with_selection[@]}"; do
plugin=''${plugin#''$'\033[3'[0-7]m} plugin=''${plugin#''$'\033[3'[0-7]m}
plugin=''${plugin%''$'\033[m'} plugin=''${plugin%''$'\033[m'}
[[ -z ''$REPLY || ''$plugin = QUIT || ''$plugin = DONE ]] && break 2 [[ -z ''$REPLY || ''$plugin = QUIT || ''$plugin = DONE ]] && break 2
[[ -z ''$plugin ]] && { echo "Please enter a number (1-''$((''${#plugins[@]}+2)))."; continue; } [[ -z ''$plugin ]] && { echo "Please enter a number (1-''$((''${#plugins[@]}+2)))."; continue; }
selected[''$plugin]=1-''${selected[''$plugin]} selected[''$plugin]=1-''${selected[''$plugin]}
break break
done done
[[ -z ''$REPLY || ''$plugin = QUIT || ''$plugin = DONE ]] && break [[ -z ''$REPLY || ''$plugin = QUIT || ''$plugin = DONE ]] && break
done done
[[ -z ''$REPLY || ''$plugin = QUIT ]] && { echo "Aborting"; return; } [[ -z ''$REPLY || ''$plugin = QUIT ]] && { echo "Aborting"; return; }
declare -a exported_plugins=() declare -a exported_plugins=()
for plugin in "''${!selected[@]}"; do for plugin in "''${!selected[@]}"; do
if [[ ''${selected[''$plugin]} -eq 1 ]]; then if [[ ''${selected[''$plugin]} -eq 1 ]]; then
exported_plugins+=(".bashrc.d/''$plugin") exported_plugins+=(".bashrc.d/''$plugin")
fi fi
done done
command rm -vf "exported_bashrc.tar.gz" command rm -vf "exported_bashrc.tar.gz"
CDPATH= command cd - >/dev/null CDPATH= command cd - >/dev/null
CDPATH= command cd ~ CDPATH= command cd ~
as_base64=''$(command tar -cvhzf - ".bashrc" "''${exported_plugins[@]}" | base64 -w0) as_base64=''$(command tar -cvhzf - ".bashrc" "''${exported_plugins[@]}" | base64 -w0)
CDPATH= command cd - >/dev/null CDPATH= command cd - >/dev/null
as_base64_wrapped=''$(printf %s "''$as_base64" | sed 's#.\{,70\}#'\'''&'\'''\\\n#g' | sed ''\'''$s#\\$##') as_base64_wrapped=''$(printf %s "''$as_base64" | sed 's#.\{,70\}#'\'''&'\'''\\\n#g' | sed ''\'''$s#\\$##')
command install -m775 /dev/stdin ~/bashrc_installer.sh <<-EOF command install -m775 /dev/stdin ~/bashrc_installer.sh <<-EOF
#! /usr/bin/env bash #! /usr/bin/env bash
set -e set -e
[ "\''$BASH_VERSINFO" ] && command -v declare >/dev/null 2>&1 && command declare -p BASH_VERSINFO | { IFS=' ' read -r _ flags _; case "\''$flags" in (*r*) ;; (*) false; esac; } || { printf 'This installer must be run with bash!\\n'; exit 1; } [ "\''$BASH_VERSINFO" ] && command -v declare >/dev/null 2>&1 && command declare -p BASH_VERSINFO | { IFS=' ' read -r _ flags _; case "\''$flags" in (*r*) ;; (*) false; esac; } || { printf 'This installer must be run with bash!\\n'; exit 1; }
command -v bash >/dev/null 2>&1 || { printf 'bash must be installed!\\n'; exit 2; } command -v bash >/dev/null 2>&1 || { printf 'bash must be installed!\\n'; exit 2; }
as_base64=''$as_base64_wrapped as_base64=''$as_base64_wrapped
tempdir=\''$(mktemp -d) tempdir=\''$(mktemp -d)
trap 'rm -rf -- "\''$tempdir"' EXIT trap 'rm -rf -- "\''$tempdir"' EXIT
cd -- "\''$tempdir" cd -- "\''$tempdir"
base64 -d <<< "\''$as_base64" | tar xzf - base64 -d <<< "\''$as_base64" | tar xzf -
create_dir_and_move () { create_dir_and_move () {
src=\''$1 src=\''$1
dst=\''$2 dst=\''$2
[ ! -f "\''$src" ] && { printf '%s\\n' "Source argument '\''$src' is not a regular file"; return 1; } [ ! -f "\''$src" ] && { printf '%s\\n' "Source argument '\''$src' is not a regular file"; return 1; }
dst_dir=\''$(dirname -- "\''${dst//[^!-~]/-}") dst_dir=\''$(dirname -- "\''${dst//[^!-~]/-}")
[ ! -d "\''$dst_dir" ] && { printf '%s\\n' "Trying to create destination directory '\''$dst_dir'"; mkdir -p -- "\''$dst_dir"; } || : [ ! -d "\''$dst_dir" ] && { printf '%s\\n' "Trying to create destination directory '\''$dst_dir'"; mkdir -p -- "\''$dst_dir"; } || :
[ -d "\''$dst_dir" ] && mv -v -t "\''$dst_dir" -- "\''$src" || : [ -d "\''$dst_dir" ] && mv -v -t "\''$dst_dir" -- "\''$src" || :
} }
ask_overwrite () { ask_overwrite () {
file1=\''$1 file1=\''$1
file2=\''$2 file2=\''$2
if [[ ! -e \''$file2 ]]; then if [[ ! -e \''$file2 ]]; then
create_dir_and_move "\''$file1" "\''$file2" create_dir_and_move "\''$file1" "\''$file2"
elif [[ -d \''$file2 ]]; then elif [[ -d \''$file2 ]]; then
printf 'WARNING: Destination file %s is a directory! Skipping this file\\n' "\''${file2@Q}" printf 'WARNING: Destination file %s is a directory! Skipping this file\\n' "\''${file2@Q}"
return return
elif [[ ! -f \''$file2 ]]; then elif [[ ! -f \''$file2 ]]; then
printf 'WARNING: Destination file %s is not a regular file! Skipping this file\\n' "\''${file2@Q}" printf 'WARNING: Destination file %s is not a regular file! Skipping this file\\n' "\''${file2@Q}"
return return
elif ! diff -q "\''$file1" "\''$file2"; then elif ! diff -q "\''$file1" "\''$file2"; then
printf 'File to be installed (%s) differs from already installed file (%s)\\n' "\''${file1@Q}" "\''${file2@Q}" printf 'File to be installed (%s) differs from already installed file (%s)\\n' "\''${file1@Q}" "\''${file2@Q}"
read -p 'Press enter to show diff. ' || : read -p 'Press enter to show diff. ' || :
diff --color -u "\''$file1" "\''$file2" || : diff --color -u "\''$file1" "\''$file2" || :
printf 'Giving you a plain bash shell to resolve the situation. Once done, just exit.\\n' printf 'Giving you a plain bash shell to resolve the situation. Once done, just exit.\\n'
printf 'After you exit, the destination file WILL BE FORCEFULLY OVERWRITTEN!!!\n' printf 'After you exit, the destination file WILL BE FORCEFULLY OVERWRITTEN!!!\n'
read -p 'Press enter to continue in the shell. ' || : read -p 'Press enter to continue in the shell. ' || :
bash --rcfile <(printf 'cd; printf "You are running bash version \''$BASH_VERSION. Your CWD is \''$PWD. Your HOME is \''$HOME. You are \''$USER and HOSTNAME is \''$HOSTNAME.\\nUse this bash shell to make changes, backups, etc.\\nThen just exit.\\n"') --noprofile || : bash --rcfile <(printf 'cd; printf "You are running bash version \''$BASH_VERSION. Your CWD is \''$PWD. Your HOME is \''$HOME. You are \''$USER and HOSTNAME is \''$HOSTNAME.\\nUse this bash shell to make changes, backups, etc.\\nThen just exit.\\n"') --noprofile || :
printf 'Destination file %s will be overwritten. Continue? ' "\''${file2@Q}" printf 'Destination file %s will be overwritten. Continue? ' "\''${file2@Q}"
read || : read || :
create_dir_and_move "\''$file1" "\''$file2" create_dir_and_move "\''$file1" "\''$file2"
else else
printf 'File %s was not changed\\n' "\''${file2@Q}" printf 'File %s was not changed\\n' "\''${file2@Q}"
fi fi
} }
ask_overwrite .bashrc ~/.bashrc ask_overwrite .bashrc ~/.bashrc
set +f set +f
shopt -s nullglob dotglob shopt -s nullglob dotglob
for file in .bashrc.d/*; do for file in .bashrc.d/*; do
ask_overwrite "\''$file" ~/"\''$file" ask_overwrite "\''$file" ~/"\''$file"
done done
cd - >/dev/null cd - >/dev/null
read -p 'Self destruct (y/N)? ' choice || : read -p 'Self destruct (y/N)? ' choice || :
[[ \''$choice = y ]] && { printf 'Trying to rm myself (%s)\\n' "\''${0@Q}"; rm -- "\''$0" && printf 'Success\\n' || printf 'Failed. Not trying further\\n'; } [[ \''$choice = y ]] && { printf 'Trying to rm myself (%s)\\n' "\''${0@Q}"; rm -- "\''$0" && printf 'Success\\n' || printf 'Failed. Not trying further\\n'; }
EOF EOF
} }
#-#################################### binds ##################################### #-#################################### binds #####################################
bind '"\e\C-r": kill-region' \ bind '"\e\C-r": kill-region' \
'"\C-x\C-k": kill-whole-line' \ '"\C-x\C-k": kill-whole-line' \
'"\e\C-p": history-search-backward' \ '"\e\C-p": history-search-backward' \
'"\e\C-n": history-search-forward' \ '"\e\C-n": history-search-forward' \
'"\eP": history-substring-search-backward' \ '"\eP": history-substring-search-backward' \
'"\eN": history-substring-search-forward' \ '"\eN": history-substring-search-forward' \
'"\C-x\C-d": "\e#\C-m exit\C-m"' \ '"\C-x\C-d": "\e#\C-m exit\C-m"' \
'"\ej": "\C-e |& tac | \\cat -n | tac | \\cat -n | less -SFXR\C-m"' \ '"\ej": "\C-e |& tac | \\cat -n | tac | \\cat -n | less -SFXR\C-m"' \
'"\eX": ">/dev/null "' \ '"\eX": ">/dev/null "' \
'"\t": menu-complete' \ '"\t": menu-complete' \
'"\e[Z": menu-complete-backward' \ '"\e[Z": menu-complete-backward' \
'"\C-x\C-r": forward-search-history' \ '"\C-x\C-r": forward-search-history' \
'set show-all-if-ambiguous on' \ 'set show-all-if-ambiguous on' \
'set completion-query-items 0' \ 'set completion-query-items 0' \
'set menu-complete-display-prefix on' \ 'set menu-complete-display-prefix on' \
'set colored-completion-prefix on' \ 'set colored-completion-prefix on' \
'set colored-stats on' 'set colored-stats on'
#-################################## autoclear ################################### #-################################## autoclear ###################################
#-# TODO #-# TODO
#-# prank () { #-# prank () {
#-# line_up_until_cursor=''${READLINE_LINE::READLINE_POINT} #-# line_up_until_cursor=''${READLINE_LINE::READLINE_POINT}
#-# line_after_cursor=''${READLINE_LINE:READLINE_POINT} #-# line_after_cursor=''${READLINE_LINE:READLINE_POINT}
#-# if [[ ''$((RANDOM % 5)) -eq 0 ]]; then #-# if [[ ''$((RANDOM % 5)) -eq 0 ]]; then
#-# READLINE_LINE="''$line_up_until_cursor''$line_after_cursor" #-# READLINE_LINE="''$line_up_until_cursor''$line_after_cursor"
#-# #READLINE_LINE="''$line_up_until_cursor''${1^}''$line_after_cursor" #-# #READLINE_LINE="''$line_up_until_cursor''${1^}''$line_after_cursor"
#-# READLINE_POINT=''$((READLINE_POINT+1)) #-# READLINE_POINT=''$((READLINE_POINT+1))
#-# else #-# else
#-# READLINE_LINE="''$line_up_until_cursor''$1''$line_after_cursor" #-# READLINE_LINE="''$line_up_until_cursor''$1''$line_after_cursor"
#-# READLINE_POINT=''$((READLINE_POINT+1)) #-# READLINE_POINT=''$((READLINE_POINT+1))
#-# fi #-# fi
#-# } #-# }
#-# bind -x '" ": prank " "' #-# bind -x '" ": prank " "'
#-# bind -x '"a": prank "a"' #-# bind -x '"a": prank "a"'
''; '';
}; };
} }