2026-06-11 18:28:00 +02:00
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
# `bash`-specific configurations
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Prevent running this file twice, as a non-login `bash` enters here,
|
|
|
|
|
# sources ~/.profile, and ~/.profile sources this file again
|
|
|
|
|
[ -n "$BASHRC_LOADED" ] && return
|
|
|
|
|
BASHRC_LOADED=1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Load configuration files common to all kinds of shells,
|
|
|
|
|
# if not already done by a `bash` login shell
|
|
|
|
|
[ -z "$PROFILE_LOADED" ] && [ -f "$HOME/.profile" ] && . "$HOME/.profile"
|
2026-06-11 18:28:02 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
# Ensure `bash` is running interactively
|
|
|
|
|
case $- in
|
|
|
|
|
*i*) ;;
|
|
|
|
|
*) return;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Configure the `history`
|
|
|
|
|
|
|
|
|
|
# Set these environment variables here
|
|
|
|
|
# to avoid conflict/overlap with `zsh`
|
|
|
|
|
|
|
|
|
|
export HISTFILE="$XDG_STATE_HOME/bash/history"
|
|
|
|
|
|
|
|
|
|
export HISTSIZE=999999 # Number of lines kept in memory
|
|
|
|
|
export HISTFILESIZE=999999 # Number of lines kept in the `$HISTFILE`
|
|
|
|
|
|
|
|
|
|
# Ignore commands prefixed with a space
|
|
|
|
|
# and ones entered identically just before
|
|
|
|
|
export HISTCONTROL=ignoreboth
|
|
|
|
|
|
|
|
|
|
shopt -s cmdhist # Remember multi-line commands as just one line
|
|
|
|
|
shopt -s histappend # Do not overwrite the `$HISTFILE`
|
|
|
|
|
shopt -s histreedit # Allow editing failed history substitutions
|
|
|
|
|
shopt -s lithist # Store multi-line commands in history without `;`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Make `bash` feel a bit more like `zsh`
|
|
|
|
|
|
|
|
|
|
shopt -s autocd # Just type the directory to `cd` into it
|
|
|
|
|
shopt -s cdspell # Correct minor spelling mistakes with `cd`
|
|
|
|
|
|
|
|
|
|
shopt -s checkjobs # Show number of running jobs when exiting `bash`
|
|
|
|
|
|
|
|
|
|
shopt -s checkwinsize # Update `$LINES` and `$COLUMNS` after commands
|
|
|
|
|
|
|
|
|
|
shopt -s globstar # Expand ** into recursive directories
|
|
|
|
|
shopt -s extglob # Advanced glob patterns (like `EXTENDED_GLOB` in `zsh`)
|
|
|
|
|
shopt -s failglob # Abort when a glob matches nothing (like `NO_MATCH` in `zsh`)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stty -ixon # Prevent <Control>s from freezing `bash`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Make `bash` show `chroot`s in the prompt
|
|
|
|
|
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
|
|
|
|
|
debian_chroot=$(cat /etc/debian_chroot)
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
2026-06-11 18:28:02 +02:00
|
|
|
# Align `bash` and `zsh` for prompts (see `$PS1` in ~/.zshrc)
|
2026-06-11 18:28:02 +02:00
|
|
|
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Enable tab completion
|
|
|
|
|
if ! shopt -oq posix; then
|
|
|
|
|
if [ -f /usr/share/bash-completion/bash_completion ]; then
|
|
|
|
|
. /usr/share/bash-completion/bash_completion
|
|
|
|
|
elif [ -f /etc/bash_completion ]; then
|
|
|
|
|
. /etc/bash_completion
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Jump to frequently used directories with `z <fragment>`
|
|
|
|
|
if _command_exists zoxide; then
|
|
|
|
|
eval "$(zoxide init bash)"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Suggest the `apt` package providing an unknown command
|
|
|
|
|
if [ -r /etc/bash_command_not_found ]; then
|
|
|
|
|
. /etc/bash_command_not_found
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Fuzzy finding for
|
|
|
|
|
# - `history`: <Control>r
|
|
|
|
|
# - files: <Control>t
|
|
|
|
|
# - `cd`: <Alt>c
|
|
|
|
|
if [ -r /usr/share/doc/fzf/examples/key-bindings.bash ]; then
|
|
|
|
|
. /usr/share/doc/fzf/examples/key-bindings.bash
|
|
|
|
|
fi
|
|
|
|
|
|
2026-10-06 13:01:48 +02:00
|
|
|
# Fuzzy completion with the `**` trigger (e.g., `vi **<Tab>`, `ssh **<Tab>`)
|
|
|
|
|
# is set up in ~/.bash_completion, so that it is loaded before `complete_alias`
|