From 9232cf030bd37566a62641e2cccc0fff2a24798e Mon Sep 17 00:00:00 2001 From: Matthew Binning Date: Sat, 29 Mar 2025 14:02:53 -0700 Subject: [PATCH] init: Start dotfiles with a test container to verify installation. --- .config/aliasrc | 18 ++++ .config/inputrc | 47 ++++++++++ .containerignore | 7 ++ .gitconfig | 18 ++++ .gitignore | 12 +++ .profile | 24 +++++ Dockerfile | 14 +++ Makefile | 86 ++++++++++++++++++ README.md | 20 +++++ gitignore.template | 219 +++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 465 insertions(+) create mode 100644 .config/aliasrc create mode 100644 .config/inputrc create mode 100644 .containerignore create mode 100644 .gitconfig create mode 100644 .gitignore create mode 100644 .profile create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 README.md create mode 100644 gitignore.template diff --git a/.config/aliasrc b/.config/aliasrc new file mode 100644 index 0000000..c31bc41 --- /dev/null +++ b/.config/aliasrc @@ -0,0 +1,18 @@ +#!/bin/sh + +# Typical verbosity and settings. +alias \ + mkd='mkdir -pv' \ + ffmepg='ffmpeg -hidebanner' + +# Colorize when possible. +alias \ + ls='ls -h -N -G --group-directories-first' \ + grep='grep --color=auto' + +# Shortenings +alias \ + d='docker' \ + h='history' \ + l='less' \ + s='sudo' diff --git a/.config/inputrc b/.config/inputrc new file mode 100644 index 0000000..5c96822 --- /dev/null +++ b/.config/inputrc @@ -0,0 +1,47 @@ +$include /etc/inputrc + +set colored-stats On +set completion-prefix-display-length 6 +set mark-symlinked-directories On + +set bell-style none +set completion-ignore-case off +set show-all-if-ambiguous on +set menu-complete-display-prefix on + +"\e[Z": menu-complete +"\e[A": history-search-backward +"\e[B": history-search-forward + +# "\eOd": backward-word +# "\eOc": forward-word +# +# # for linux console +# "\e[1~": beginning-of-line +# "\e[4~": end-of-line +# "\e[5~": beginning-of-history +# "\e[6~": end-of-history +# "\e[3~": delete-char +# "\e[2~": quoted-insert +# +# # for xterm +# "\eOH": beginning-of-line +# "\eOF": end-of-line + +set editing-mode vi +$if mode=vi + +set show-mode-in-prompt on +set vi-ins-mode-string \1\e\[6 q\2 +set vi-cmd-mode-string \1\e\[2 q\2 + +set keymap vi-command +Control-l: clear-screen +Control-a: beginning-of-line + +set keymap vi-insert +Control-l: clear-screen +Control-a: beginning-of-line +"\C-i": menu-complete + +$endif diff --git a/.containerignore b/.containerignore new file mode 100644 index 0000000..01cb1dc --- /dev/null +++ b/.containerignore @@ -0,0 +1,7 @@ +CHANGELOG.md +Containerfile +.containerignore +.dockerignore +.git +.gitignore +README.md diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 0000000..aec4966 --- /dev/null +++ b/.gitconfig @@ -0,0 +1,18 @@ +[user] + email = matthew@binning.dev + name = Matthew Binning +[diff] + tool = vimdiff +[difftool] + prompt = false +[difftool "sdiff"] + cmd = cmddiff $LOCAL $REMOTE +[merge] + tool = fugitive +[alias] + df = difftool + sdiff = difftool --ignore-submodules --tool=sdiff +[mergetool] + prompt = false +[mergetool "fugitive"] + cmd = vim -f -c \"Gvdiff\" \"$MERGED\" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..be78379 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +.cache +.config/shell/histfile +.config/sfeed/feeds +.config/sfeed/urls +.config/when/calendar +.*history +.local/share/nvim/site/pack/gitmodules/start/er.vim/* +.local/share/nvim/site/pack/gitmodules/start/indentLine/* +.local/share/nvim/site/pack/gitmodules/start/lspconfig/* +.local/share/nvim/site/pack/gitmodules/start/lspconfig/.* +.local/share/nvim/site/pack/gitmodules/start/todo.txt-vim/* +.kube/ diff --git a/.profile b/.profile new file mode 100644 index 0000000..c60808c --- /dev/null +++ b/.profile @@ -0,0 +1,24 @@ +#!/usr/bin/env sh +# PS1='[\u@\h \W]\$ ' + +export XDG_CONFIG_HOME="$HOME/.config" +export XDG_DATA_HOME="$HOME/.local/share" +export XDG_CACHE_HOME="$HOME/.cache" + +export INPUTRC="${XDG_CONFIG_HOME:-$HOME/.config}/inputrc" +export ALIASRC="${XDG_CONFIG_HOME:-$HOME/.config}/aliasrc" + +if docker --version > /dev/null 2>&1; then + PS1="\[\033[38;5;34m\]\u@\h \W]\\$\[$(tput sgr0)\] " + export PS1 +else + PS1="\[\033[38;5;44m\]\u@\h \W]\\$\[$(tput sgr0)\] " + export PS1 +fi + +# Git should ask for a password through the command line. +unset GIT_ASKPASS +unset SSH_ASKPASS + +# shellcheck source=./.config/aliasrc +[ -f "$ALIASRC" ] && . ./"$ALIASRC" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7ce0d8b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +ARG BASE_REGISTRY=docker.io +ARG BASE_IMAGE=alpine +ARG BASE_TAG=latest +FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} AS base +RUN apk update && \ + apk upgrade && \ + apk add make + +FROM base as test +RUN adduser -D user +USER user +WORKDIR /home/user/dotfiles +COPY --chown=user ./ ./ +ENTRYPOINT [ "make" ] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1eb4f3f --- /dev/null +++ b/Makefile @@ -0,0 +1,86 @@ +.POSIX: +.SUFFIXES: + +COLOR_BLUE:=\033[36m +COLOR_AUTO:=\033[0m +SRC=.config/aliasrc .config/inputrc .gitconfig .*profile +TGT=$(addprefix $$HOME/, $(SRC)) + +.PHONY: help ## Show this help menu. +help: + @printf 'make \n\nsubcommand:\n' + @awk -F '(: | ## )' '/^\.PHONY:.*?## .*$$/ {\ + printf("\t$(COLOR_BLUE)%s\t\t$(COLOR_AUTO)%s\n",$$2, $$3)\ + }' $(MAKEFILE_LIST) + +.PHONY: installcheck ## Check if the dotfiles are properly linked to home. +installcheck: + # Assert link sources match link destinations. + for link in $(SRC); do \ + dst_link=$$(stat -c "%N" ~/"$$link" | cut -d ' ' -f 3); \ + src_link="$$PWD/$$link"; \ + if [ ! "$$dst_link" = \'"$$src_link"\' ]; then \ + printf 'Destination link matches not the source link!\n'; \ + fi; \ + done + +# RFE: Use the single suffix inference rule to enhance iteration semantics +# to actual Makefile semantics. This could probably be done by suffixing source +# links with .ln. +.PHONY: install ## Actually symlink the dotfiles to home. +install: $(SRC) + mkdir -p $(dir $(TGT)) + for file in $(SRC); do $(RM) -r ~/$$file; ln -s $$PWD/$$file ~/$$file; done + +.PHONY: uninstallcheck ## Check if dotfiles' symlinks were properly removed. +uninstallcheck: + # Assert destination links were removed. + for link in $(TGT); do \ + [ ! -e ~/"$$link" ] || \ + printf '%s%s\n' "$$link" "survived teardown!"; \ + done + +.PHONY: uninstall ## Remove the symlinks to dotfiles. +uninstall: + $(RM) -r $(TGT) + for file in $(TGT); do if [ -e "$$file~" ]; then mv "$$file~" "$$file"; fi; done + +.PHONY: clean ## Purge cruft (not the dotfiles payload). +clean: + -docker rm check_dotfiles + -docker rmi dotfiles + +# ---------------------------------------------------------------------------- +# Make is not really a good system for this. +# It works with files, but this works with containers. +# Write a deployment for the test container? + +.PHONY: all ## lint -> build -> check +all: lint build check + +.PHONY: lint ## Lint the source repository. +lint: + docker run --rm \ + -u "$(shell id -u):$(shell id -g)" \ + -v "$(shell pwd):/mnt" \ + -w /mnt \ + mvdan/shfmt:latest -d -sr -i 4 .config/aliasrc .*profile + docker run --rm \ + -u "$(shell id -u):$(shell id -g)" \ + -v "$(shell pwd):/mnt" \ + -w /mnt \ + koalaman/shellcheck -x .config/aliasrc .*profile + +.PHONY: build ## Build a container to system-test the dotfiles. +build: + docker build --target test --tag dotfiles . + +.PHONY: check ## Check if (un)install works in the test container. +check: build + docker run --name="check_dotfiles" --tty -d --entrypoint sh dotfiles + docker exec check_dotfiles make install + docker exec check_dotfiles make installcheck + docker exec check_dotfiles make uninstall + docker exec check_dotfiles make uninstallcheck + docker stop check_dotfiles +# ---------------------------------------------------------------------------- diff --git a/README.md b/README.md new file mode 100644 index 0000000..64e7723 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# dotfiles + +This source repository contains configuration for common Unix systems. + +Influences include: + +- [Luke Smith's voidrice](https://github.com/lukesmithxyz/voidrice) +- [Whynothugo's dotfiles](https://git.sr.ht/~whynothugo/dotfiles) + +## Install + +This uses `make`. + +## Test + +To create a container, install the dotfiles there, check the installation, and then destroy the container, run: + +``` +make check +``` diff --git a/gitignore.template b/gitignore.template new file mode 100644 index 0000000..3cdc6bb --- /dev/null +++ b/gitignore.template @@ -0,0 +1,219 @@ +### Project specific +.gen/**/*_pb2*.py + +*_output.mpg +test-results.xml + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ +