These are my personal dotfiles.
This setup is designed to support ad-hoc management of modular packages, where a package may consist of multiple dependencies, configurations, and shell extensions.
This design has a couple of benefits over a traditional dotfile setup:
-
Portability: A single package can be used by others without needing to install all of the dotfiles. For example, try out my neovim setup with
./install nvim. -
Composability: Different sets of packages can be configured for various environments. For example, you may want to have just your neovim setup on a remote server without installing all of your language packages used in your development environment.
Packages are identified by their directory name within packages.
To install one or more packages manually, include the name(s) as arguments to the install script:
./install <package1> <package2> ...To configure which packages are automatically installed, update the install script to detect your environment and specify a list of packages:
packages=()
if [ ! $# -eq 0 ]; then
# Manually selected packages
packages=$*
elif [[ -n "${GITPOD_WORKSPACE_ID}" ]]; then
# Gitpod packages
packages=(
homebrew
zsh
)
elif [[ $(uname) == "Darwin" ]]; then
# MacOS packages
packages=(
elixir
git
macos
mutagen
nvim
ruby
tmux
wezterm
)
fiThough there are a number of packages already included in this setup, you may want to add your own package(s) or start fresh and just use the package management portion of these dotfiles. To that end, I'll walk through what a package consists of and how to set up a new one. You can also just review the package.sh library if you want to skip the exposition.
For our example, we'll be creating a new package called acme:
mkdir packages/acmeSystem dependencies are currently handled by homebrew since it's semi cross-platform.
To specify homebrew dependencies, create a Brewfile in the package root:
touch packages/acme/BrewfileThe Brewfile.lock.json will automatically be ignored by the included .gitignore.
Note
If a Brewfile is detected during package installation, the homebrew package will be automatically installed before continuing. For this reason, it's not required to include homebrew in your list of environment packages unless none of the other packages require homebrew and you would still like it installed.
Many dependencies have added support for XDG Base Directory Specification. In short, this means that they will look for their configuration in the $XDG_CONFIG_HOME which defaults to ~/.config.
To add XDG-compliant configuration, create a config folder in the package root. This directory will be symlinked into the $XDG_CONFIG_HOME with the package name as the target.
mkdir packages/acme/config # symlinked to ~/.config/acmeFor files and directories that need to go into directly into your home directory, you can just add a dot- prefix to their name. These will be symlinked to your home directory with the dot- prefix replaced by a .:
touch packages/acme/dot-file # symlinked to ~/.file
mkdir packages/acme/dot-directory # symlinked to ~/.directoryImportant
These dotfiles are very dependent on zsh at the moment. I plan to loosen this dependency in the future, but this section won't really apply unless you're also using my zsh package.
If your package needs to add autoloaded zsh extensions (aliases, autocompletes, etc.), you can add a zsh directory in the package root. This directory will be symlinked into the plugins directory that my zsh package is configured to autoload:
mkdir packages/acme/zsh # symlinked to ~/.config/zsh/plugins/_acmeAnd finally, if you need to run some installation logic, you can create an install executable in the package root. This will be executed at the very end, after dependencies and symlinks have been created:
touch packages/acme/install
chmod +x packages/acme/installThere are several bash variables that are available to your script:
$name: the name of the package (e.g.acme)$package: the full path of the package directory (e.g.packages/acme)$tmp: the full path of a temporary directory that can be used for package artifacts (e.g..tmp/acme)
Any artifacts from package installation will remain in the .tmp directory and ignored by git.
Some ideas for future improvements:
- Better cross-platform dependency management instead of homebrew.
- Less dependency on zsh as the specific shell for extensions.
- Smarter shell reloading (it currently reloads zsh even if the plugin symlink already exists)
- A top-level
dotcommand to be used in place of executing./installdirectly - A set of subcommands to be used with
dot(e.g.install,uninstall,package new, etc.) - A complete separation of the
dotpackage manager with a way to install external packages
Code is under the BSD 2-clause "Simplified" License. Documentation is under the Creative Commons Attribution license.