Skip to content

Personal dotfiles and shell scripts

Notifications You must be signed in to change notification settings

Notgnoshi/dotfiles

Repository files navigation

dotfiles

My personal dotfiles and shell scripts

Customizes a vanilla Fedora or Ubuntu system to my preferences.


Prerequisites

  • SSH keys should already be created and configured in GitHub user settings

    ssh-keygen -b 4096
  • Prerequisite packages

    sudo dnf install vim-enhanced stow git curl
    sudo apt install vim-gtk stow git curl

Installation

git clone --recurse-submodules git@github.com:Notgnoshi/dotfiles.git ~/.config/dotfiles
cd ~/.config/dotfiles
./setup

Setting up and maintaining a new system

How it works

Dotfiles are managed with GNU Stow. Anything in the ./stowdir/ is symlinked into my home directory. Stow can somehow detect script renames, and delete the stale symlinks.

I highly recommend Stow, especially over doing it yourself.

Installed applications and system preferences are listed in various scriptlets in ./setup.d/.

All of this is managed through the setup script, which handles Ubuntu/Fedora differences using the -fedora.sh or -ubuntu.sh suffix on the ./setup.d/*.sh scriptlets when there's differences to account for.

Shell scripts

I have lots of shell scripts in ~/.local/bin/. Some I use very often, some are just one-offs.

Here's some of the highlights:

  • git-gl - A better git log with an unforunate name that's now embedded in my muscle memory
  • clip - Pipe to/from your Wayland/X11 clipboard.
  • docker-cwd - Get an interactive shell in the current directory for the given Docker image. Has Bash completion for available Docker images
  • filter-wkt and wkt2csv - Helpers for working with WKT geometry data
  • qgis-project - Generate a QGIS project from a (nested) directory of CSV layer files
  • date2unix and unix2date - Helpers to convert UTC timestamps between Unix timestamps and ISO-8061 timestamps. Useful for correlating between logs files in different formats
  • randpass - Generate random passphrases that use alliteration
  • csvdelta - calculate interrow deltas for a column in a CSV file
  • csvstats - calculate summary statistics for a column in a CSV file
  • emoticon - copy different emoticons to the clipboard
  • xldd - A version of ldd that tries to be cross-compilation and Yocto SDK aware

Shell customizations

bashrc

Keeping myself organized

As my bashrc and setup scripts have grown, I've found the need to break them apart. My ~/.bashrc nowadays is essentially

DOTFILES_DIR=# Resolve the symlink for this file

##################################################################################################
# Source each of components in alphabetical order.
##################################################################################################
for rcfile in "${DOTFILES_DIR}/bashrc.d/"*.sh; do
    [ -f "$rcfile" ] && source "$rcfile"
done

with some extra bookkeeping.

My PS1 is fairly dynamic and gives several useful at-a-glance status indicators:

  • Color the trailing $ red if the previous command failed
  • Utilize the excellent __git_ps1 if it exists
  • List the number of background jobs, if there are any
  • Indicate whether I'm connected to the current device over SSH or a serial connection (requires this PS1 to be configured on the remote device)
  • Indicate whether this shell's environment has been polluted by a Yocto SDK, and which SDK, if it has been
  • Indicate if my work VPN is running, and if it is, whether or not it has a route to the gateway
    • Requires VPN_GATEWAY be set, which I do with bashrc.d/100-work.sh, which is .gitignored

I highly recommend using __git_ps1. I frequently see coworkers getting confused because they weren't aware of the state their worktree was in before or after some Git incantation.

  • Keep an infinite history
  • Keep track of the date and time each command was run on
  • Share the same history between every shell

IMPORTANT: Don't mount your home directory in a Docker container - that's asking to get your history wiped out.

Environment variables - bashrc.d/070-environment.sh

I refuse to run sudo make install.

So I use environment variables to make ~/.local/ act just like /usr/local/.

i <3 fzf

fzf has had a profound impact on my perceived usability of the terminal.

A better reverse history search

Pressing ctrl-r will start a reverse history search. The one provided by GNU Readline is perfectly useable, but FZF's is just better. It shows me the closest matches to my query, and I don't have to spell something perfectly.

This combines nicely with a permanent Bash history.

Finding files

Outside of Vim, I use ctrl-t to open a fuzzy file-finder.

Navigating in Vim

Inside of Vim, I use :GFiles and sometimes just :Files to do exactly the same thing. I use this often enough that I have keybinds for it.

I also use :Buffers to switch between open buffers, and :Rg [pattern] to use ripgrep to recursively grep a codebase. Using tab to select results loads them into the quickfix list.

:Rg is a much more powerful :vimgrep.

Browsing Git commits

Within Vim, there's also :BCommits and :Commits to view the Git commits for the current buffer, or the whole project respectively.

I tend not to use this, because it's been difficult to customize, so I built git-gl to do the same thing. It's effectively a console version of gitk that's optimized for my workflow.

It accept any argument that git log accepts, and also has Bash completion to tab-complete, because that's just plain nice.

  • Press enter to open git show for the selected commit, using delta as the pager, which provides word diffs, and side-by-side diffs if the terminal is wide enough.
  • Press ctrl-y to git checkout the selected commit
  • Press ctrl-h to copy the selected commit's hash to my clipboard (useful for git commit --fixup=<hash> commits)
  • Press ctrl-p to git cherry-pick the selected commit onto your current branch (you probably only want to do this if you run git gl on a branch other than your current one).
  • Press ctrl-r to perform an interactive rebase targetting the selected commit

Grooming a Git branch's history is like combing hair. Never start at the root and yank all the way to the tip. Instead, start at the root and make tiny short strokes, working your way to the tip.

(I don't have long hair, so maybe I have the direction backwards; it seems like working your way from the tip to the root would be less painful?)

I don't run git log or git rebase by hand anymore.

tmux

I used to use Tilix as my terminal emulator, but it's unmaintained, and sometimes crashes. The primary reason I used to use it was to get side-by-side terminal panes.

I now use tmux for this, and have found I quite like it.

I use vim-tmux-navigator to use the same keybinds ctrl-{h,j,k,l} to seamlessly navigate between Vim splits and tmux panes.

Vim customizations

ALE

I use ALE to provide completion, code formatting, and linting in Vim. It supports any language I care to use, and provides enough configuration hooks for me to use whatever formatter / linter / LSP a project requires.

I mostly use

  • rust-analyzer
  • clangd
  • clang-format
  • clang-tidy
  • black
  • isort
  • pydocstyle
  • gitlint

ALE provides the IDE experience I want:

  • Jump to definition
  • Find references
  • Rename
  • Completion
  • Static-analysis lints
  • Compilation warnings and errors

I don't want a "big green 'go' button", because my experience has shown me that

  • You get IDE lock-in to sub-par IDEs when a work project requires an IDE just to build a project
  • Understanding how the build works is important!
  • Not understanding how the build works results in developers that don't know how to troubleshoot CI/CD pipelines
  • Building a project at your terminal and the CI/CD pipeline should be the same experience - or else developers won't trust the pipeline

The rest

I won't list each plugin, but here's the important ones: