diff --git a/modules/home-manager/bash.nix b/modules/home-manager/bash.nix index 75fb205..6dc6cfc 100644 --- a/modules/home-manager/bash.nix +++ b/modules/home-manager/bash.nix @@ -5,285 +5,285 @@ enable = true; enableCompletion = false; initExtra = '' -if [[ ! -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 + if [[ ! -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 ###################### -if [ -d ~/.bashrc.d ]; then - for rc in ~/.bashrc.d/*; do - bn=''${rc##*/} - if [ -f "''$rc" ] && [ -r "''$rc" ] && [ ! "''${bn::1}" = '.' ]; then - \. "''$rc" - fi - done -fi -unset rc bn + #-##################### user specific aliases and functions ###################### + if [ -d ~/.bashrc.d ]; then + for rc in ~/.bashrc.d/*; do + bn=''${rc##*/} + if [ -f "''$rc" ] && [ -r "''$rc" ] && [ ! "''${bn::1}" = '.' ]; then + \. "''$rc" + fi + done + fi + unset rc bn -#-########################### shell settings & options ########################### -set -E -set -o pipefail + #-########################### shell settings & options ########################### + set -E + set -o pipefail -shopt -s nullglob dotglob globstar extglob -shopt -s autocd cdable_vars cdspell -shopt -s checkwinsize -shopt -s lastpipe -shopt -s inherit_errexit -shopt -s no_empty_cmd_completion -shopt -s histreedit -shopt -s lithist -shopt -u histverify -_have bash_abbr && shopt -u expand_aliases + shopt -s nullglob dotglob globstar extglob + shopt -s autocd cdable_vars cdspell + shopt -s checkwinsize + shopt -s lastpipe + shopt -s inherit_errexit + shopt -s no_empty_cmd_completion + shopt -s histreedit + shopt -s lithist + shopt -u histverify + _have bash_abbr && shopt -u expand_aliases -#-############################### shell variables ################################ -FIGNORE='.o' -# Warning -HISTCONTROL=ignoreboth:erasedups -HISTTIMEFORMAT='%y-%m-%d %H:%M:%S ' -HISTSIZE=-1 -HISTFILESIZE=-1 -HISTFILE=''$HOME/.''${USER:-default}_bash_history + #-############################### shell variables ################################ + FIGNORE='.o' + # Warning + HISTCONTROL=ignoreboth:erasedups + HISTTIMEFORMAT='%y-%m-%d %H:%M:%S ' + HISTSIZE=-1 + HISTFILESIZE=-1 + HISTFILE=''$HOME/.''${USER:-default}_bash_history -#-############################ environment variables ############################# -export PYTHON_BASIC_REPL=1 # I'm good at readline so I'm gonna use readline whereever possible! -export LESS='-SRFX' -export PAGER='less' GIT_PAGER='less' MANPAGER='less' SYSTEMD_PAGER='less' -export BAT_PAGER=''' -export EDITOR='vim' VISUAL='vim' FCEDIT='vim' SYSTEMD_EDITOR='vim' -export PATH + #-############################ environment variables ############################# + export PYTHON_BASIC_REPL=1 # I'm good at readline so I'm gonna use readline whereever possible! + export LESS='-SRFX' + export PAGER='less' GIT_PAGER='less' MANPAGER='less' SYSTEMD_PAGER='less' + export BAT_PAGER=''' + export EDITOR='vim' VISUAL='vim' FCEDIT='vim' SYSTEMD_EDITOR='vim' + export PATH -#-########################## generally useful functions ########################## -take () { - : 'Idempotently create directory recursively and cd into it' - local out - out=''$(set -o pipefail && mkdir -vp "''$@" | tail -1) || return - printf '%s\n' "''$out" - eval "out=''${out#"mkdir: created directory "}" - CDPATH= cd "''${out:-''${@: -1}}" -} + #-########################## generally useful functions ########################## + take () { + : 'Idempotently create directory recursively and cd into it' + local out + out=''$(set -o pipefail && mkdir -vp "''$@" | tail -1) || return + printf '%s\n' "''$out" + eval "out=''${out#"mkdir: created directory "}" + CDPATH= cd "''${out:-''${@: -1}}" + } -safe_ls () { - command ls --color=always --quoting-style=shell-escape -lArth 2>/dev/null || \ - command ls --color=always -q -lArth 2>/dev/null || \ - command ls --color=always -lArth 2>/dev/null || \ - command ls --color -lArth 2>/dev/null || \ - command ls -lArth 2>/dev/null || \ - command ls -lArt 2>/dev/null || \ - command ls -lAr 2>/dev/null || \ - command ls -lar 2>/dev/null || \ - command ls -la 2>/dev/null || \ - command ls -l 2>/dev/null || \ - command ls -1 2>/dev/null || \ - command printf '%q\n' * 2>/dev/null || \ - command printf '%s\n' * 2>/dev/null -} + safe_ls () { + command ls --color=always --quoting-style=shell-escape -lArth 2>/dev/null || \ + command ls --color=always -q -lArth 2>/dev/null || \ + command ls --color=always -lArth 2>/dev/null || \ + command ls --color -lArth 2>/dev/null || \ + command ls -lArth 2>/dev/null || \ + command ls -lArt 2>/dev/null || \ + command ls -lAr 2>/dev/null || \ + command ls -lar 2>/dev/null || \ + command ls -la 2>/dev/null || \ + command ls -l 2>/dev/null || \ + command ls -1 2>/dev/null || \ + command printf '%q\n' * 2>/dev/null || \ + command printf '%s\n' * 2>/dev/null + } -cd () { - : 'Run cd; on success in a terminal, show the 4 newest entries (with a count of hidden ones)' + cd () { + : 'Run cd; on success in a terminal, show the 4 newest entries (with a count of hidden ones)' - builtin cd "''$@" || return - [[ -t 1 ]] || return 0 - command -v ls &>/dev/null || return 0 + builtin cd "''$@" || return + [[ -t 1 ]] || return 0 + command -v ls &>/dev/null || return 0 - local -a lines - mapfile -t lines < <(safe_ls) - if (( ''${#lines[@]} > 10 )); then - printf '\033[7m... %d more entries ...\033[27m\n' "$(( ''${#lines[@]} - 10 ))"; - printf '%s\n' "''${lines[@]: -9}" - else - printf '%s\n' "''${lines[@]}" - fi -} + local -a lines + mapfile -t lines < <(safe_ls) + if (( ''${#lines[@]} > 10 )); then + printf '\033[7m... %d more entries ...\033[27m\n' "$(( ''${#lines[@]} - 10 ))"; + printf '%s\n' "''${lines[@]: -9}" + else + printf '%s\n' "''${lines[@]}" + fi + } -drop_caches () { - : 'Drop pagecache, dentries and inodes' - : 'https://unix.stackexchange.com/a/87909' - echo 3 | sudo tee /proc/sys/vm/drop_caches >/dev/null -} + drop_caches () { + : 'Drop pagecache, dentries and inodes' + : 'https://unix.stackexchange.com/a/87909' + echo 3 | sudo tee /proc/sys/vm/drop_caches >/dev/null + } -respawn_shell () { - : 'Intelligently respawn shell' - : 'pure posix sh without forking' - if [ "''${BASH_VERSINFO-}" ] && command -v bash 1>/dev/null 2>&1; then - if _is_login_shell; then - exec bash -l - else - exec bash - fi - : 'TODO: Implement more detection mechanisms for various shells (zsh, etc.)' - elif [ -x /proc/self/exe ]; then - if _is_login_shell; then - exec -l /proc/self/exe - else - exec /proc/self/exe - fi - 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)' - printf 'Warning: replacing current shell with unreliable ''$0, which is: %s\n' "''$0" - if _is_login_shell; then - exec -l "''${0#-}" - else - exec "''${0#-}" - fi - else - 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' - return 1 - fi -} + respawn_shell () { + : 'Intelligently respawn shell' + : 'pure posix sh without forking' + if [ "''${BASH_VERSINFO-}" ] && command -v bash 1>/dev/null 2>&1; then + if _is_login_shell; then + exec bash -l + else + exec bash + fi + : 'TODO: Implement more detection mechanisms for various shells (zsh, etc.)' + elif [ -x /proc/self/exe ]; then + if _is_login_shell; then + exec -l /proc/self/exe + else + exec /proc/self/exe + fi + 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)' + printf 'Warning: replacing current shell with unreliable ''$0, which is: %s\n' "''$0" + if _is_login_shell; then + exec -l "''${0#-}" + else + exec "''${0#-}" + fi + else + 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' + return 1 + fi + } -export_bashrc () { - CDPATH= command cd ~/.bashrc.d/ || return - : 'Not using an associative array because those are not sorted!' - declare -ar plugins=(*) - [[ ''${#plugins[@]} -eq 0 ]] || [[ ''${#plugins} -eq 1 && ''${plugins[0]} = '*' ]] && return - local IFS=' ' - declare -Ai selected - declare plugin - for plugin in "''${plugins[@]}"; do - case "''$plugin" in - #-# Comment below case match if you don'\'''t want to have a pre-selection of plugins to export - #-# Requires `shopt -s extglob` - (+([0-9])-@(util|redact|prompt|docker-tools|funcs|init-and-complete|general-aliases|bash-abbr)) selected[''$plugin]=1 ;; - (*) selected[''$plugin]= - esac - done - declare -a plugins_with_selection - while :; do - local PS3='Which plugins do you want to export/not export (enter a single number)? ' - plugins_with_selection=() - for plugin in "''${plugins[@]}"; do - if [[ ''${selected[''$plugin]} -eq 0 ]]; then - plugins_with_selection+=(''$'\033[31m'''$plugin''$'\033[m') - else - plugins_with_selection+=(''$'\033[32m'''$plugin''$'\033[m') - fi - done - 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[m'} - [[ -z ''$REPLY || ''$plugin = QUIT || ''$plugin = DONE ]] && break 2 - [[ -z ''$plugin ]] && { echo "Please enter a number (1-''$((''${#plugins[@]}+2)))."; continue; } - selected[''$plugin]=1-''${selected[''$plugin]} - break - done - [[ -z ''$REPLY || ''$plugin = QUIT || ''$plugin = DONE ]] && break - done - [[ -z ''$REPLY || ''$plugin = QUIT ]] && { echo "Aborting"; return; } - declare -a exported_plugins=() - for plugin in "''${!selected[@]}"; do - if [[ ''${selected[''$plugin]} -eq 1 ]]; then - exported_plugins+=(".bashrc.d/''$plugin") - fi - done - command rm -vf "exported_bashrc.tar.gz" - CDPATH= command cd - >/dev/null - CDPATH= command cd ~ - as_base64=''$(command tar -cvhzf - ".bashrc" "''${exported_plugins[@]}" | base64 -w0) - CDPATH= command cd - >/dev/null - as_base64_wrapped=''$(printf %s "''$as_base64" | sed 's#.\{,70\}#'\'''&'\'''\\\n#g' | sed ''\'''$s#\\$##') - command install -m775 /dev/stdin ~/bashrc_installer.sh <<-EOF - #! /usr/bin/env bash + export_bashrc () { + CDPATH= command cd ~/.bashrc.d/ || return + : 'Not using an associative array because those are not sorted!' + declare -ar plugins=(*) + [[ ''${#plugins[@]} -eq 0 ]] || [[ ''${#plugins} -eq 1 && ''${plugins[0]} = '*' ]] && return + local IFS=' ' + declare -Ai selected + declare plugin + for plugin in "''${plugins[@]}"; do + case "''$plugin" in + #-# Comment below case match if you don'\'''t want to have a pre-selection of plugins to export + #-# Requires `shopt -s extglob` + (+([0-9])-@(util|redact|prompt|docker-tools|funcs|init-and-complete|general-aliases|bash-abbr)) selected[''$plugin]=1 ;; + (*) selected[''$plugin]= + esac + done + declare -a plugins_with_selection + while :; do + local PS3='Which plugins do you want to export/not export (enter a single number)? ' + plugins_with_selection=() + for plugin in "''${plugins[@]}"; do + if [[ ''${selected[''$plugin]} -eq 0 ]]; then + plugins_with_selection+=(''$'\033[31m'''$plugin''$'\033[m') + else + plugins_with_selection+=(''$'\033[32m'''$plugin''$'\033[m') + fi + done + 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[m'} + [[ -z ''$REPLY || ''$plugin = QUIT || ''$plugin = DONE ]] && break 2 + [[ -z ''$plugin ]] && { echo "Please enter a number (1-''$((''${#plugins[@]}+2)))."; continue; } + selected[''$plugin]=1-''${selected[''$plugin]} + break + done + [[ -z ''$REPLY || ''$plugin = QUIT || ''$plugin = DONE ]] && break + done + [[ -z ''$REPLY || ''$plugin = QUIT ]] && { echo "Aborting"; return; } + declare -a exported_plugins=() + for plugin in "''${!selected[@]}"; do + if [[ ''${selected[''$plugin]} -eq 1 ]]; then + exported_plugins+=(".bashrc.d/''$plugin") + fi + done + command rm -vf "exported_bashrc.tar.gz" + CDPATH= command cd - >/dev/null + CDPATH= command cd ~ + as_base64=''$(command tar -cvhzf - ".bashrc" "''${exported_plugins[@]}" | base64 -w0) + CDPATH= command cd - >/dev/null + as_base64_wrapped=''$(printf %s "''$as_base64" | sed 's#.\{,70\}#'\'''&'\'''\\\n#g' | sed ''\'''$s#\\$##') + command install -m775 /dev/stdin ~/bashrc_installer.sh <<-EOF + #! /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; } - command -v bash >/dev/null 2>&1 || { printf 'bash must be installed!\\n'; exit 2; } + [ "\''$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; } - as_base64=''$as_base64_wrapped - tempdir=\''$(mktemp -d) - trap 'rm -rf -- "\''$tempdir"' EXIT - cd -- "\''$tempdir" - base64 -d <<< "\''$as_base64" | tar xzf - - create_dir_and_move () { - src=\''$1 - dst=\''$2 - [ ! -f "\''$src" ] && { printf '%s\\n' "Source argument '\''$src' is not a regular file"; return 1; } - dst_dir=\''$(dirname -- "\''${dst//[^!-~]/-}") - [ ! -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" || : - } - ask_overwrite () { - file1=\''$1 - file2=\''$2 - if [[ ! -e \''$file2 ]]; then - create_dir_and_move "\''$file1" "\''$file2" - elif [[ -d \''$file2 ]]; then - printf 'WARNING: Destination file %s is a directory! Skipping this file\\n' "\''${file2@Q}" - return - elif [[ ! -f \''$file2 ]]; then - printf 'WARNING: Destination file %s is not a regular file! Skipping this file\\n' "\''${file2@Q}" - return - elif ! diff -q "\''$file1" "\''$file2"; then - printf 'File to be installed (%s) differs from already installed file (%s)\\n' "\''${file1@Q}" "\''${file2@Q}" - read -p 'Press enter to show diff. ' || : - diff --color -u "\''$file1" "\''$file2" || : - 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' - 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 || : - printf 'Destination file %s will be overwritten. Continue? ' "\''${file2@Q}" - read || : - create_dir_and_move "\''$file1" "\''$file2" - else - printf 'File %s was not changed\\n' "\''${file2@Q}" - fi - } - ask_overwrite .bashrc ~/.bashrc - set +f - shopt -s nullglob dotglob - for file in .bashrc.d/*; do - ask_overwrite "\''$file" ~/"\''$file" - done - cd - >/dev/null - 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'; } - EOF -} + as_base64=''$as_base64_wrapped + tempdir=\''$(mktemp -d) + trap 'rm -rf -- "\''$tempdir"' EXIT + cd -- "\''$tempdir" + base64 -d <<< "\''$as_base64" | tar xzf - + create_dir_and_move () { + src=\''$1 + dst=\''$2 + [ ! -f "\''$src" ] && { printf '%s\\n' "Source argument '\''$src' is not a regular file"; return 1; } + dst_dir=\''$(dirname -- "\''${dst//[^!-~]/-}") + [ ! -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" || : + } + ask_overwrite () { + file1=\''$1 + file2=\''$2 + if [[ ! -e \''$file2 ]]; then + create_dir_and_move "\''$file1" "\''$file2" + elif [[ -d \''$file2 ]]; then + printf 'WARNING: Destination file %s is a directory! Skipping this file\\n' "\''${file2@Q}" + return + elif [[ ! -f \''$file2 ]]; then + printf 'WARNING: Destination file %s is not a regular file! Skipping this file\\n' "\''${file2@Q}" + return + elif ! diff -q "\''$file1" "\''$file2"; then + printf 'File to be installed (%s) differs from already installed file (%s)\\n' "\''${file1@Q}" "\''${file2@Q}" + read -p 'Press enter to show diff. ' || : + diff --color -u "\''$file1" "\''$file2" || : + 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' + 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 || : + printf 'Destination file %s will be overwritten. Continue? ' "\''${file2@Q}" + read || : + create_dir_and_move "\''$file1" "\''$file2" + else + printf 'File %s was not changed\\n' "\''${file2@Q}" + fi + } + ask_overwrite .bashrc ~/.bashrc + set +f + shopt -s nullglob dotglob + for file in .bashrc.d/*; do + ask_overwrite "\''$file" ~/"\''$file" + done + cd - >/dev/null + 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'; } + EOF + } -#-#################################### binds ##################################### -bind '"\e\C-r": kill-region' \ - '"\C-x\C-k": kill-whole-line' \ - '"\e\C-p": history-search-backward' \ - '"\e\C-n": history-search-forward' \ - '"\eP": history-substring-search-backward' \ - '"\eN": history-substring-search-forward' \ - '"\C-x\C-d": "\e#\C-m exit\C-m"' \ - '"\ej": "\C-e |& tac | \\cat -n | tac | \\cat -n | less -SFXR\C-m"' \ - '"\eX": ">/dev/null "' \ - '"\t": menu-complete' \ - '"\e[Z": menu-complete-backward' \ - '"\C-x\C-r": forward-search-history' \ - 'set show-all-if-ambiguous on' \ - 'set completion-query-items 0' \ - 'set menu-complete-display-prefix on' \ - 'set colored-completion-prefix on' \ - 'set colored-stats on' \ - 'set mark-modified-lines on' \ - 'set revert-all-at-newline on' \ - 'set blink-matching-paren on' \ - 'set history-preserve-point on' + #-#################################### binds ##################################### + bind '"\e\C-r": kill-region' \ + '"\C-x\C-k": kill-whole-line' \ + '"\e\C-p": history-search-backward' \ + '"\e\C-n": history-search-forward' \ + '"\eP": history-substring-search-backward' \ + '"\eN": history-substring-search-forward' \ + '"\C-x\C-d": "\e#\C-m exit\C-m"' \ + '"\ej": "\C-e |& tac | \\cat -n | tac | \\cat -n | less -SFXR\C-m"' \ + '"\eX": ">/dev/null "' \ + '"\t": menu-complete' \ + '"\e[Z": menu-complete-backward' \ + '"\C-x\C-r": forward-search-history' \ + 'set show-all-if-ambiguous on' \ + 'set completion-query-items 0' \ + 'set menu-complete-display-prefix on' \ + 'set colored-completion-prefix on' \ + 'set colored-stats on' \ + 'set mark-modified-lines on' \ + 'set revert-all-at-newline on' \ + 'set blink-matching-paren on' \ + 'set history-preserve-point on' -#-################################## autoclear ################################### -#-# TODO + #-################################## autoclear ################################### + #-# TODO -#-# prank () { -#-# line_up_until_cursor=''${READLINE_LINE::READLINE_POINT} -#-# line_after_cursor=''${READLINE_LINE:READLINE_POINT} -#-# if [[ ''$((RANDOM % 5)) -eq 0 ]]; then -#-# READLINE_LINE="''$line_up_until_cursor''$line_after_cursor" -#-# #READLINE_LINE="''$line_up_until_cursor''${1^}''$line_after_cursor" -#-# READLINE_POINT=''$((READLINE_POINT+1)) -#-# else -#-# READLINE_LINE="''$line_up_until_cursor''$1''$line_after_cursor" -#-# READLINE_POINT=''$((READLINE_POINT+1)) -#-# fi -#-# } -#-# bind -x '" ": prank " "' -#-# bind -x '"a": prank "a"' + #-# prank () { + #-# line_up_until_cursor=''${READLINE_LINE::READLINE_POINT} + #-# line_after_cursor=''${READLINE_LINE:READLINE_POINT} + #-# if [[ ''$((RANDOM % 5)) -eq 0 ]]; then + #-# READLINE_LINE="''$line_up_until_cursor''$line_after_cursor" + #-# #READLINE_LINE="''$line_up_until_cursor''${1^}''$line_after_cursor" + #-# READLINE_POINT=''$((READLINE_POINT+1)) + #-# else + #-# READLINE_LINE="''$line_up_until_cursor''$1''$line_after_cursor" + #-# READLINE_POINT=''$((READLINE_POINT+1)) + #-# fi + #-# } + #-# bind -x '" ": prank " "' + #-# bind -x '"a": prank "a"' ''; }; }