Skip to content

Instantly share code, notes, and snippets.

@robin-a-meade
Last active February 24, 2023 01:18
Show Gist options
  • Save robin-a-meade/b83dd635076993c4c25b7115d0b5da32 to your computer and use it in GitHub Desktop.
Save robin-a-meade/b83dd635076993c4c25b7115d0b5da32 to your computer and use it in GitHub Desktop.
Minimal config for shell and vim

Quick minimal config for shell and vim

For when a full dotfiles setup is overkill.

Installation Instructions

curl https://gist.githubusercontent.com/robin-a-meade/b83dd635076993c4c25b7115d0b5da32/raw/install.sh | bash

Time-stamped backup files are made of all replaced files.

Once satisfied, you may interactively delete these backup files with:

cd
find . -regextype posix-extended -regex '^.*[0-9]{8}T[0-9]{6}$' -ok rm {} \;
# Compare to Fedora's baseline:
# https://src.fedoraproject.org/rpms/bash/blob/rawhide/f/dot-bash_profile
# Our changes:
# - We do our PATH customizations here instead of .bashrc.
# - - I disagree with Fedora's decision to move PATH customizations from ~/.bash_profile to ~/.bashrc
# https://src.fedoraproject.org/rpms/bash/c/739b272e5f5d10cf27a847a44d09eb7f4b6ec89b?branch=rawhide
# - - We utilize the pathmunge function from /etc/profile,
# https://pagure.io/setup/blob/master/f/profile,
# but refine it for bash:
# - - - Utilize modern test
# - - - Remove superfluous quoting
# - We guard the sourcing of .bashrc with a test for interactive shell. Login shells can
# be interactive or non-interactive, but ~/.bashrc is supposed to be for interactive
# shells only. Testing for interactive shell before sourcing ~/.bashrc from ~/.bash_profile is
# recommended here: https://superuser.com/a/183980
pathmunge () {
case :${PATH}: in
*:$1:*)
;;
*)
if [[ $2 == after ]]; then
PATH=$PATH:$1
else
PATH=$1:$PATH
fi
esac
}
pathmunge "$HOME"/.local/bin
pathmunge "$HOME"/bin
unset -f pathmunge
# Interactive login shells should source ~/.bashrc
if [[ $- == *i* && -r ~/.bashrc ]]; then
source ~/.bashrc
fi
# Return immediately if not an interactive shell
# ==============================================
#
# The ~/.bashrc startup file is supposed to be for interactive shells only.
#
# In this file, I call commands that assume we are in an interactive shell. These
# commands can cause errors if this condition is not met. For example, `stty -ixon`
# will cause the following error if called from a non-interactive shell.
#
# $ ssh myserver 'cat file.txt'
# stty: 'standard input': Inappropriate ioctl for device
#
# For some strange reason, bash will source ~/.bashrc,
# even though it is non-interactive, if it detects that its standard input is connected to a
# network connection.
#
# [Why is bash sourcing .bashrc in non-interactive mode when working via ssh?](
# https://unix.stackexchange.com/q/587207
# )
#
# That's why we added the following check for interactive shell.
#
# Update: Apparently many linux distributions provide `/etc/skel/.bashrc` that do this check.
#
# [Why does bashrc check whether the current shell is interactive?](
# https://unix.stackexchange.com/q/257571
# )
#
# Not Fedora/RedHat though. (Todo: file bug)
if [[ $- != *i* ]]; then return; fi
# Based on Fedora's default .bashrc
# =================================
# https://src.fedoraproject.org/rpms/bash/blob/rawhide/f/dot-bashrc
# Except I moved PATH customizations out of this file back to where they used to be in ~/.bash_profile
# I disagree with Fedora's move of PATH customizations from ~/.bash_profile to ~/.bashrc
# https://src.fedoraproject.org/rpms/bash/c/739b272e5f5d10cf27a847a44d09eb7f4b6ec89b?branch=rawhide
# Doing PATH customizations in ~/.bash_profile is the preferred best practice.
# https://unix.stackexchange.com/a/26059
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# Enable extended glob patterns
shopt -s extglob
# Disable History Expansion
# http://superuser.com/a/133782
# https://unix.stackexchange.com/q/436505
# Short equivalent: set +H
set +o histexpand
# Support multi-line history entries well
# https://stackoverflow.com/a/17194155
# https://unix.stackexchange.com/a/109035
shopt -s lithist
shopt -s cmdhist
# Disable XON/XOFF flow control to free up Ctrl-S for forward-history-search
#
# The default readline binding for forward-search-history is Ctrl+S:
#
# $ bind -P | grep -E '^forward-search-history'
# forward-search-history can be found on "\C-s".
#
# This, however, collides with the terminal's use of Ctrl+S for XON/XOFF flow control.
#
# Never have I had needed to hit Ctrl+S to stop the sender from transmitting,
# or Ctrl+Q to resume transmitting. These key strokes were useful in the age
# of teletypes, early terminals, and primitive terminal emulators with
# no scrollback buffer on slow modem connection. At today's 1Mbps+ network speeds,
# trying to control the sender's transmission flow by pressing Ctrl+S and Ctrl+Q
# is futile. Modern terminal emulators have large scrollback buffers anyway, so
# the need no longer exists. Or use a pager, like 'more' (or 'less').
#
# We therefore disable XOFF/XON flow control so that readline's keybinding
# for Ctrl+S will work. As a bonus, it frees up Ctrl+Q too. Feel free to bind
# that to something useful.
#
# There's talk in some linux distributions of disabling this by default.
# https://bugs.launchpad.net/ubuntu/+source/bash/+bug/80635/comments/12
#
# Note: Disabling XOFF/XON flow control can cause 'Inappropriate ioctl for device' error
# when set in a non-interactive shell. See https://stackoverflow.com/q/24623021 .
# We're good though because we follow the best practice of testing for interactive
# shell at the top of .bashrc. See https://superuser.com/a/183980
stty -ixon
# When you press TAB after a variable holding a directory, expand it.
# http://tiswww.case.edu/php/chet/bash/NEWS
# http://askubuntu.com/questions/70750/how-to-get-bash-to-stop-escaping-during-tab-completion
# http://stackoverflow.com/questions/6418493/bash-variable-expansion-on-tab-complete
# https://bugs.launchpad.net/ubuntu/+source/bash/+bug/778627
# http://lists.gnu.org/archive/html/bug-bash/2011-02/msg00274.html
# http://nelsonslog.wordpress.com/2012/01/29/bash-4-2-variable-expansion-bug/
# https://unix.stackexchange.com/q/378625
shopt -s direxpand
# Make cd smarter
# So you never regret that you didn't use pushd
cd() {
if [[ $# == 0 ]]; then
pushd "$HOME" >/dev/null
elif [[ $1 == - ]]; then
pushd >/dev/null
else
pushd "$@" >/dev/null
fi
}
alias bk='popd >/dev/null'
# Source user-specific bash completion scripts
# ============================================
# Needed only on older systems. Modern bash-completion does this for us.
if [[ ! $BASH_COMPLETION_VERSINFO ]]; then
# We must be on an older system
# We'll need to source our user-specific bash completion scripts ourselves
if [[ -r ~/.local/share/bash-completion/completions ]]; then
for rc in ~/.local/share/bash-completion/completions/*; do
if [[ -f $rc ]]; then
. "$rc"
fi
done
fi
fi
# Disable beeping during TAB completion
# https://unix.stackexchange.com/a/593495
bind 'set bell-style none'
# It's better to put these keybindings in .inputrc so that they will apply to all
# programs that use the readline library, not just bash.
# I'm putting them here, too, in case you decide not to edit .inputrc.
bind 'TAB:menu-complete'
bind '"\e[A": history-search-backward'
bind '"\e[B": history-search-forward'
# Include system-wide settings
$include /etc/inputrc
# Enable prefix history search using UP and DOWN arrow keys
"\e[A": history-search-backward
"\e[B": history-search-forward
# Configure TAB key to cycle through completion candidates
# https://lists.gnu.org/archive/html/help-bash/2014-06/msg00002.html
TAB: menu-complete
" Source the example vimrc file
" - It has sensible defaults
" - It, in turn, sources $VIMRUNTIME/defaults.vim, which contains "defaults that most users want".
" This approach is inline with the default behavior on Windows: vim on Windows will
" source $VIMRUNTIME/vimrc_example.vim if the user did not define their own vimrc, as
" explained here: https://github.com/vim/vim/issues/1468
source $VIMRUNTIME/vimrc_example.vim
" Indent by two spaces
set expandtab
set shiftwidth=2
set softtabstop=-1 " Make 'softtabstop' follow 'shiftwidth'
set autoindent
" When pasting, it is necessary to temporarily disable autoindent
" Assign F2 to toggle autoindent
" Alternatively, you could use the ex commands:
" :set paste
" :set nopaste
" http://vim.wikia.com/wiki/Toggle_auto-indenting_for_code_paste
set pastetoggle=<F2>
if has('mouse')
set mouse=a
endif
" Disable beep
" https://vim.fandom.com/wiki/Disable_beeping
set noerrorbells visualbell t_vb=
autocmd GUIEnter * set visualbell t_vb=
" Set the directory to use for swap files
" (This must be a pre-existing directory. Our 'install.sh' script ensures this is the case.)
" The double trailing slashes (//) at the end tells vim to use the absolute path of the file
" when forming the swap file name so that there's no chance collisions between files of the
" same name from different directories.
" https://vi.stackexchange.com/questions/177/what-is-the-purpose-of-swap-files
set directory=~/.vimswp//
" Set a central directory to use for backup files
" This is much better than littering
" (This must be a pre-existing directory. Our 'install.sh' script ensures this is the case.)
" The double trailing slashes (//) at the end tells vim to use the absolute path of the file
" when forming the backup file name so that there's no chance collisions between files of the
" same name from different directories.
" Support for this was committed on Aug 7, 2018
" https://github.com/vim/vim/commit/b782ba475a3f8f2b0be99dda164ba4545347f60f
" (Patch 8.1.0251)
" Associated issue: https://github.com/vim/vim/issues/179
set backupdir=~/.vimbackup//
" If we don't have that patch, use Victor Schröder's workound:
" https://stackoverflow.com/a/38479550
if ! has('patch-8.1-0251')
" This is a copy and paste of Victor Schröder's workound, except I already set backupdir above
" === BACKUP SETTINGS ===
" turn backup OFF
" Normally we would want to have it turned on. See bug and workaround below.
" OBS: It's a known-bug that backupdir is not supporting
" the correct double slash filename expansion
" see: https://code.google.com/p/vim/issues/detail?id=179
set nobackup
" set a centralized backup directory
"set backupdir=~/.vim/backup// <== I already set this above -Robin
" This is the workaround for the backup filename expansion problem.
autocmd BufWritePre * :call SaveBackups()
function! SaveBackups()
if expand('%:p') =~ &backupskip | return | endif
" If this is a newly created file, don't try to create a backup
if !filereadable(@%) | return | endif
for l:backupdir in split(&backupdir, ',')
:call SaveBackup(l:backupdir)
endfor
endfunction
function! SaveBackup(backupdir)
let l:filename = expand('%:p')
if a:backupdir =~ '//$'
let l:backup = escape(substitute(l:filename, '/', '%', 'g') . &backupext, '%')
else
let l:backup = escape(expand('%') . &backupext, '%')
endif
let l:backup_path = a:backupdir . l:backup
:silent! execute '!cp ' . resolve(l:filename) . ' ' . l:backup_path
endfunction
endif
" Write with sudo
" This variation works smoother than others I tried.
" Reportedly works in nvim too.
" https://stackoverflow.com/q/2600783#comment123636916_2600783
command Wsudo :execute ':silent w !sudo tee > /dev/null "%"' | :edit!
" Persistent undo
"
" Keep undo history across sessions by storing it in a file
" http://stackoverflow.com/questions/5700389/using-vims-persistent-undo
if has('persistent_undo')
set undodir=~/.vim/undodir
set undofile
endif
" Set a colorscheme, if desired
"colorscheme desert
"colorscheme darkblue
"colorscheme elflord
"colorscheme murphy
"colorscheme ron
"colorscheme slate
"colorscheme torte
" Make search more forgiving by ignoring case
set ignorecase
# Save the current working directory
saved_pwd=$(pwd)
cd # Ensure we are in home directory
# Create the directories needed by vim
# The -p option ensures there is no error for case of the directory already existing
mkdir -p ~/.vimswp
mkdir -p ~/.vimbackup
files=( .bash_profile .bashrc .vimrc .inputrc )
for f in "${files[@]}"; do
echo "Processing $f..."
if [[ -r "$f" ]]; then
cp -p "$f" "$f.$(date +'%Y%m%dT%H%M%S')"
if [[ $? != 0 ]]; then
echo "An error occurred while backing up $f" >&2
return
fi
fi
done
PRE=https://gist.githubusercontent.com/robin-a-meade/b83dd635076993c4c25b7115d0b5da32/raw
for f in "${files[@]}"; do
escaped="${f//\//:}" # Replace / with :
if ! mkdir -p ./"$(dirname "$f")"; then
echo "An error occurred while creating directory $(dirname "$f")" >&2
return
fi
# Cache-Control to bust the cache. I haven't tested yet. Seen here:
# https://gist.github.com/atenni/5604615#gistcomment-3063801
# Others recommend adding a fake query string parameter to bust the cache.
echo curl -sS -o "$f" -H 'Cache-Control: no-cache' "$PRE/$escaped"
if ! curl -sS -o "$f" -H 'Cache-Control: no-cache' "$PRE/$escaped"; then
echo "An error occurred while downloading $PRE/$escaped" >&2
return
fi
cd # Return to home directory
done
# Bash history won't persist to disk if the file referenced by $HISTFILE
# does not actually exist. Bash won't automatically create it.
if [[ $HISTFILE && ! -e $HISTFILE ]]; then
echo "History file '$HISTFILE' didn't exist. Creating it."
touch "$HISTFILE"
fi
# Return to the saved working directory
cd "$saved_pwd"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment