diff --git a/.gitignore b/.gitignore
index d869ee2..f54ce28 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,2 @@
-config/git/config/*
-!config/git/config/.gitkeep
-!config/git/config/README.md
+managed/*
+!managed/.gitkeep
diff --git a/.helpers/X11/generate-x11-config b/.helpers/X11/generate-x11-config
deleted file mode 100755
index fe796fd..0000000
--- a/.helpers/X11/generate-x11-config
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-GIT_ROOT_DIR="$( cd "$( dirname $0 )/../.." && pwd )"
-X11_DOTFILES_SOURCE_DIR="${GIT_ROOT_DIR}/config/X11"
-X11_DOTFILES_DESTINATION_DIR="${XDG_CONFIG_HOME}/X11"
-
-if ! [ -d ${X11_DOTFILES_DESTINATION_DIR} ]; then
- echo "INFO: Creating directory ${X11_DOTFILES_DESTINATION_DIR}"
- mkdir ${X11_DOTFILES_DESTINATION_DIR}
-fi
-
-rsync -avh ${X11_DOTFILES_SOURCE_DIR}/xinitrc ${X11_DOTFILES_DESTINATION_DIR}/xinitrc && chmod a-rwx,u+rw $_
diff --git a/.helpers/amfora/generate-amfora-config b/.helpers/amfora/generate-amfora-config
deleted file mode 100755
index 4b33a72..0000000
--- a/.helpers/amfora/generate-amfora-config
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-GIT_ROOT_DIR="$( cd "$( dirname $0 )/../.." && pwd )"
-AMFORA_CONFIG_SOURCE_DIR="${GIT_ROOT_DIR}/config/amfora"
-AMFORA_CONFIG_DESTINATION_DIR="${XDG_CONFIG_HOME}/amfora"
-
-if ! [ -d ${AMFORA_CONFIG_DESTINATION_DIR} ]; then
- echo "INFO: Creating directory ${AMFORA_CONFIG_DESTINATION_DIR}"
- mkdir ${AMFORA_CONFIG_DESTINATION_DIR}
-fi
-
-rsync -avh ${AMFORA_CONFIG_SOURCE_DIR}/ ${AMFORA_CONFIG_DESTINATION_DIR}
-chmod a-rwx,u+rw ${AMFORA_CONFIG_DESTINATION_DIR}/*
diff --git a/.helpers/ansible/generate-ansible-config b/.helpers/ansible/generate-ansible-config
deleted file mode 100755
index 0a68ef9..0000000
--- a/.helpers/ansible/generate-ansible-config
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-GIT_ROOT_DIR="$( cd "$( dirname $0 )/../.." && pwd )"
-ANSIBLE_DOTFILES_DIR="${GIT_ROOT_DIR}/config/ansible"
-ANSIBLE_CONFIG_DIR=${XDG_CONFIG_HOME}/ansible
-ANSIBLE_DATA_DIR=${XDG_DATA_HOME}/ansible
-ANSIBLE_CACHE_DIR=${XDG_CACHE_HOME}/ansible
-
-for d in ${ANSIBLE_CONFIG_DIR} ${ANSIBLE_DATA_DIR} ${ANSIBLE_CACHE_DIR}; do
- if ! [ -d ${d} ]; then
- echo "INFO: Creating directory ${d}"
- mkdir ${d}
- fi
-done
-
-for f in $( find ${ANSIBLE_DOTFILES_DIR} -type f -exec basename {} \; ); do
- echo "INFO: Installing ${f}"
- rsync -avh ${ANSIBLE_DOTFILES_DIR}/${f} ${ANSIBLE_CONFIG_DIR}/${f} && chmod a-rwx,u+rw $_
-done
diff --git a/.helpers/bash/generate-bash-config b/.helpers/bash/generate-bash-config
deleted file mode 100755
index ad97fc8..0000000
--- a/.helpers/bash/generate-bash-config
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-GIT_ROOT_DIR="$( cd "$( dirname $0 )/../.." && pwd )"
-BASH_DOTFILES_DIR="${GIT_ROOT_DIR}/config/bash"
-BASHRC_DIRNAME="bashrc.d"
-BASHRC_CONFIG_DIR=${XDG_CONFIG_HOME}/bash/${BASHRC_DIRNAME}
-BASH_DATA_DIR=${XDG_DATA_HOME}/bash
-
-source ${GIT_ROOT_DIR}/helpers/lib/install-config
-
-for d in ${BASHRC_CONFIG_DIR} ${BASH_DATA_DIR}; do
- if ! [ -d ${d} ]; then
- mkdir -p ${d}
- fi
-done
-
-for f in $(find ${BASH_DOTFILES_DIR}/${BASHRC_DIRNAME} -mindepth 1 -maxdepth 1 -type f -exec basename {} \;); do
- configFilename=${f}
-
- if [ -f ${BASHRC_CONFIG_DIR}/${f}.disabled ]; then
- configFilename=${f}.disabled
- fi
-
- install_config ${BASH_DOTFILES_DIR}/${BASHRC_DIRNAME}/${f} ${BASHRC_CONFIG_DIR}/${configFilename}
-done
-
-for f in "bashrc" "bash_profile"; do
- install_config ${BASH_DOTFILES_DIR}/${f} ${HOME}/.${f}
-done
diff --git a/.helpers/dunst/generate-dunst-config b/.helpers/dunst/generate-dunst-config
deleted file mode 100755
index b8399b1..0000000
--- a/.helpers/dunst/generate-dunst-config
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-GIT_ROOT_DIR="$( cd "$( dirname $0 )/../.." && pwd )"
-DUNST_DOTFILES_SOURCE_DIR="${GIT_ROOT_DIR}/config/dunst"
-DUNST_DOTFILES_DESTINATION_DIR="${XDG_CONFIG_HOME}/dunst"
-
-if ! [ -d ${DUNST_DOTFILES_DESTINATION_DIR} ]; then
- echo "INFO: Creating directory ${DUNST_DOTFILES_DESTINATION_DIR}"
- mkdir ${DUNST_DOTFILES_DESTINATION_DIR}
-fi
-
-rsync -avh ${DUNST_DOTFILES_SOURCE_DIR}/dunstrc ${DUNST_DOTFILES_DESTINATION_DIR}/dunstrc && chmod a-rwx,u+rw $_
diff --git a/.helpers/git/generate-git-config b/.helpers/git/generate-git-config
deleted file mode 100755
index e9be8d5..0000000
--- a/.helpers/git/generate-git-config
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-GIT_ROOT_DIR="$( cd "$( dirname $0 )/../.." && pwd )"
-GIT_DOTFILES_DIR="${GIT_ROOT_DIR}/config/git"
-PARAMETER_FILE="${GIT_DOTFILES_DIR}/config/gitconfig-parameters"
-
-GITCONFIG_FILE="${GIT_DOTFILES_DIR}/gitconfig"
-GITIGNORE_FILE="${GIT_DOTFILES_DIR}/gitignore"
-GITMESSAGE_FILE="${GIT_DOTFILES_DIR}/gitmessage"
-
-GIT_OUTPUT_ROOT_DIR="${XDG_CONFIG_HOME}/git"
-GITCONFIG_OUTPUT="${GIT_OUTPUT_ROOT_DIR}/config"
-GITIGNORE_OUTPUT="${GIT_OUTPUT_ROOT_DIR}/ignore"
-GITMESSAGE_OUTPUT="${GIT_OUTPUT_ROOT_DIR}/message"
-
-validate_params() {
- if [ -z ${GIT_USER_NAME+x} ]; then
- echo "ERROR: 'GIT_USER_NAME' is not set or is empty in ${PARAMETER_FILE}"
- return 1
- fi
-
- if [ -z ${GIT_USER_EMAIL+x} ]; then
- echo "ERROR: 'GIT_USER_EMAIL' is not set or is empty in ${PARAMETER_FILE}"
- return 1
- fi
-
- if [ -z ${GIT_USER_SIGNINGKEY+x} ]; then
- echo "ERROR: 'GIT_USER_SIGNINGKEY' is not set or is empty in ${PARAMETER_FILE}"
- return 1
- fi
-
- return 0
-}
-
-echo "INFO: Attempting to source parameters from ${PARAMETER_FILE}."
-test -f ${PARAMETER_FILE} && source ${PARAMETER_FILE}
-
-echo "INFO: Validating parameters."
-validate_params || exit 1
-
-if ! [ -d ${GIT_OUTPUT_ROOT_DIR} ]; then
- echo "INFO: Creating directory ${GIT_OUTPUT_ROOT_DIR}"
- mkdir ${GIT_OUTPUT_ROOT_DIR}
-fi
-
-echo "INFO: Generating the gitconfig file and installing it to ${GITCONFIG_OUTPUT}."
-
-gitmessage_output=${GITMESSAGE_OUTPUT} \
-gitignore_output=${GITIGNORE_OUTPUT} \
-git_user_name=${GIT_USER_NAME} \
-git_user_email=${GIT_USER_EMAIL} \
-git_user_signingkey=${GIT_USER_SIGNINGKEY} \
-envsubst < ${GITCONFIG_FILE} > ${GITCONFIG_OUTPUT}
-
-chmod a-rwx,u+rw ${GITCONFIG_OUTPUT}
-
-echo "INFO: Installing ${GITIGNORE_OUTPUT}."
-rsync -avh ${GITIGNORE_FILE} ${GITIGNORE_OUTPUT} && chmod a-rwx,u+rw $_
-
-echo "INFO: Installing ${GITMESSAGE_OUTPUT}."
-rsync -avh ${GITMESSAGE_FILE} ${GITMESSAGE_OUTPUT} && chmod a-rwx,u+rw $_
diff --git a/.helpers/lf/generate-lf-config b/.helpers/lf/generate-lf-config
deleted file mode 100755
index 12f10d9..0000000
--- a/.helpers/lf/generate-lf-config
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-GIT_ROOT_DIR="$( cd "$( dirname $0 )/../.." && pwd )"
-LF_DOTFILES_SOURCE_DIR="${GIT_ROOT_DIR}/config/lf"
-LF_DOTFILES_DESTINATION_DIR="${XDG_CONFIG_HOME}/lf"
-
-if ! [ -d ${LF_DOTFILES_DESTINATION_DIR} ]; then
- echo "INFO: Creating directory ${LF_DOTFILES_DESTINATION_DIR}"
- mkdir ${LF_DOTFILES_DESTINATION_DIR}
-fi
-
-rsync -avh ${LF_DOTFILES_SOURCE_DIR}/lfrc ${LF_DOTFILES_DESTINATION_DIR}/lfrc && chmod a-rwx,u+rw $_
diff --git a/.helpers/lib/install-config b/.helpers/lib/install-config
deleted file mode 100755
index 2350614..0000000
--- a/.helpers/lib/install-config
+++ /dev/null
@@ -1,8 +0,0 @@
-# vi: set ft=bash :
-
-install_config() {
- [ -f ${2} ] && rm -rf ${2}
- echo "INFO: Installing ${1} to ${2}"
- cp ${1} ${2}
- chmod -R a-rwx,u+rw ${2}
-}
diff --git a/.helpers/logrotate/generate-logrotate-config b/.helpers/logrotate/generate-logrotate-config
deleted file mode 100755
index bb4250f..0000000
--- a/.helpers/logrotate/generate-logrotate-config
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-GIT_ROOT_DIR="$( cd "$( dirname $0 )/../.." && pwd )"
-LF_DOTFILES_SOURCE_DIR="${GIT_ROOT_DIR}/config/logrotate"
-LF_DOTFILES_DESTINATION_DIR="${XDG_CONFIG_HOME}/logrotate"
-
-if ! [ -d ${LF_DOTFILES_DESTINATION_DIR} ]; then
- echo "INFO: Creating directory ${LF_DOTFILES_DESTINATION_DIR}"
- mkdir ${LF_DOTFILES_DESTINATION_DIR}
-fi
-
-envsubst < ${LF_DOTFILES_SOURCE_DIR}/logrotate.conf > ${LF_DOTFILES_DESTINATION_DIR}/logrotate.conf
-chmod a-rwx,u+rw ${LF_DOTFILES_DESTINATION_DIR}/logrotate.conf
diff --git a/.helpers/scripts/install-scripts b/.helpers/scripts/install-scripts
deleted file mode 100755
index cdcedb5..0000000
--- a/.helpers/scripts/install-scripts
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-GIT_ROOT_DIR="$( cd "$( dirname $0 )/../.." && pwd )"
-SCRIPTS_SOURCE_DIR="${GIT_ROOT_DIR}/scripts"
-SCRIPTS_DESTINATION_DIR="${HOME}/.local/scripts"
-
-if ! [ -d ${SCRIPTS_DESTINATION_DIR} ]; then
- echo "INFO: Creating directory ${SCRIPTS_DESTINATION_DIR}"
- mkdir ${SCRIPTS_DESTINATION_DIR}
-fi
-
-rsync -avh ${SCRIPTS_SOURCE_DIR}/ ${SCRIPTS_DESTINATION_DIR}
-chmod -R 0700 ${SCRIPTS_DESTINATION_DIR}
diff --git a/.helpers/tmux/generate-tmux-config b/.helpers/tmux/generate-tmux-config
deleted file mode 100755
index 4243d11..0000000
--- a/.helpers/tmux/generate-tmux-config
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-GIT_ROOT_DIR="$( cd "$( dirname $0 )/../.." && pwd )"
-TMUX_DOTFILES_SOURCE_DIR="${GIT_ROOT_DIR}/config/tmux"
-TMUX_DOTFILES_DESTINATION_DIR="${XDG_CONFIG_HOME}/tmux"
-
-if ! [ -d ${TMUX_DOTFILES_DESTINATION_DIR} ]; then
- echo "INFO: Creating directory ${TMUX_DOTFILES_DESTINATION_DIR}"
- mkdir ${TMUX_DOTFILES_DESTINATION_DIR}
-fi
-
-rsync -avh ${TMUX_DOTFILES_SOURCE_DIR}/tmux.conf ${TMUX_DOTFILES_DESTINATION_DIR}/tmux.conf && chmod a-rwx,u+rw $_
diff --git a/.helpers/vim/generate-vim-config b/.helpers/vim/generate-vim-config
deleted file mode 100755
index b804185..0000000
--- a/.helpers/vim/generate-vim-config
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-GIT_ROOT_DIR="$( cd "$( dirname $0 )/../.." && pwd )"
-VIM_CONFIG_SOURCE_DIR="${GIT_ROOT_DIR}/config/vim"
-VIM_CONFIG_DESTINATION_DIR="${XDG_CONFIG_HOME}/vim"
-
-MINPAC_SOURCE="https://github.com/k-takata/minpac.git"
-MINPAC_DESTINATION="${XDG_DATA_HOME}/vim/pack/bundle/opt/minpac"
-
-GOTAGS_SOURCE="github.com/jstemmer/gotags"
-
-# Creating essential vim directories
-mkdir -p ${VIM_CONFIG_DESTINATION_DIR}
-mkdir -p ${XDG_CACHE_HOME}/vim/{backup,swap,undo,view} && chmod 0700 ${XDG_CACHE_HOME}/vim/{backup,swap,undo,view}
-mkdir -p ${XDG_DATA_HOME}/vim/spell && chmod 0700 ${XDG_DATA_HOME}/vim/spell
-
-# Syncing the vim configuration files
-echo "INFO: syncing ${VIM_CONFIG_SOURCE_DIR} to ${VIM_CONFIG_DESTINATION_DIR}"
-rsync -avh --exclude=*.gitkeep ${VIM_CONFIG_SOURCE_DIR}/ ${VIM_CONFIG_DESTINATION_DIR}
-chmod a-rwx,u+rwx ${VIM_CONFIG_DESTINATION_DIR}
-find ${VIM_CONFIG_DESTINATION_DIR} -type d -not -wholename */pack/bundle/opt/* -not -wholename */pack/bundle/start/* \
- | xargs chmod a-rwx,u+rwx
-
-# Ensuring minpac and gotags are installed
-if ! [ -d ${MINPAC_DESTINATION}/.git ]; then
- echo "INFO: Cloning ${MINPAC_SOURCE} to ${MINPAC_DESTINATION}"
- git clone --depth=1 ${MINPAC_SOURCE} ${MINPAC_DESTINATION}
-fi
-
-if [ -x "$( command -v go )" ]; then
- if ! [ -x "$( command -v gotags )" ]; then
- echo "INFO: Installing gotags"
- go get -u ${GOTAGS_SOURCE}
- fi
-fi
diff --git a/.helpers/xdg/check-xdg-settings b/.helpers/xdg/check-xdg-settings
deleted file mode 100755
index 2bec192..0000000
--- a/.helpers/xdg/check-xdg-settings
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-if [ -z ${XDG_CONFIG_HOME+x} ]; then
- echo "ERROR: 'XDG_CONFIG_HOME' is not set."
- exit 1
-fi
-
-if [ -z ${XDG_DATA_HOME+x} ]; then
- echo "ERROR: 'XDG_DATA_HOME' is not set."
- exit 1
-fi
-
-if [ -z ${XDG_CACHE_HOME+x} ]; then
- echo "ERROR: 'XDG_CACHE_HOME' is not set."
- exit 1
-fi
-
-if [ -z ${XDG_STATE_HOME+x} ]; then
- echo "ERROR: 'XDG_STATE_HOME' is not set."
- exit 1
-fi
diff --git a/.helpers/xdg/generate-user-dirs-config b/.helpers/xdg/generate-user-dirs-config
deleted file mode 100755
index 2524d12..0000000
--- a/.helpers/xdg/generate-user-dirs-config
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-GIT_ROOT_DIR="$( cd "$( dirname $0 )/../.." && pwd )"
-XDG_DOTFILES_DIR="${GIT_ROOT_DIR}/config/xdg"
-
-for f in $( find ${XDG_DOTFILES_DIR} -type f -exec basename {} \; ); do
- echo "INFO: Installing ${f}"
- rsync -avh ${XDG_DOTFILES_DIR}/${f} ${XDG_CONFIG_HOME}/${f} && chmod a-rwx,u+rw $_
-done
diff --git a/Makefile b/Makefile
deleted file mode 100644
index c1b5c44..0000000
--- a/Makefile
+++ /dev/null
@@ -1,46 +0,0 @@
-check_xdg_settings:
- @./.helpers/xdg/check-xdg-settings
-
-.PHONY: scripts
-scripts:
- @./.helpers/scripts/install-scripts
-
-.PHONY: ansible_configs
-ansible_configs: check_xdg_settings
- @./.helpers/ansible/generate-ansible-config
-
-.PHONY: bash_configs
-bash_configs:
- @./.helpers/bash/generate-bash-config
-
-.PHONY: git_configs
-git_configs: check_xdg_settings
- @./.helpers/git/generate-git-config
-
-.PHONY: tmux_configs
-tmux_configs: check_xdg_settings
- @./.helpers/tmux/generate-tmux-config
-
-.PHONY: xdg_configs
-xdg_configs: check_xdg_settings
- @./.helpers/xdg/generate-user-dirs-config
-
-.PHONY: x11_configs
-x11_configs: check_xdg_settings
- @./.helpers/X11/generate-x11-config
-
-.PHONY: lf_configs
-lf_configs: check_xdg_settings
- @./.helpers/lf/generate-lf-config
-
-.PHONY: amfora_configs
-amfora_configs: check_xdg_settings
- @./.helpers/amfora/generate-amfora-config
-
-.PHONY: dunst_configs
-dunst_configs: check_xdg_settings
- @./.helpers/dunst/generate-dunst-config
-
-.PHONY: logrotate_configs
-logrotate_configs: check_xdg_settings
- @./.helpers/logrotate/generate-logrotate-config
diff --git a/bash/profile.gotmpl b/bash/profile.gotmpl
new file mode 100644
index 0000000..3ccdad0
--- /dev/null
+++ b/bash/profile.gotmpl
@@ -0,0 +1,58 @@
+# If not running interactively, don't do anything
+[[ $- != *i* ]] && return
+
+# Environment section
+
+## Session Paths - These will be added to PATH
+{{- range $sessionPath := .BashProfile.SessionPaths -}}
+{{- $fullPath := printf "%s/%s" (env "HOME") $sessionPath.Path -}}
+{{ print "" }}
+{{ print "" }}
+### Add {{ $sessionPath.Description }} to PATH
+if ! [[ "${PATH}" =~ {{ $fullPath }} ]]; then
+ export PATH={{ $fullPath}}:${PATH}
+fi
+{{- end -}}
+{{ print "" }}
+{{ print "" }}
+## XDG Directories
+{{ print "" }}
+{{- range $key, $value := .BashProfile.XdgDirectories -}}
+{{ print "" }}
+export {{ $key }}="{{ $value }}"
+{{- end -}}
+{{ print "" }}
+{{ print "" }}
+## Extra Environment variables
+{{ print "" }}
+{{- range $key, $value := .BashProfile.EnvironmentVariables -}}
+{{ print "" }}
+export {{ $key }}="{{ $value }}"
+{{- end -}}
+{{ print "" }}
+{{ print "" }}
+# Aliases
+{{ print "" }}
+{{- range $key, $value := .BashProfile.Aliases -}}
+{{ print "" }}
+alias {{ $key }}="{{ $value }}"
+{{- end -}}
+{{ print "" }}
+{{ print "" }}
+# Bash Prompt
+
+HOSTNAME_BG="$(tput setab 26)"
+GREY_BG="$(tput setab 240)"
+RESET="$(tput sgr0)"
+FILEPATH_TC="$(tput setaf 81)"
+WHITE_TC="$(tput setaf 255)"
+PS1='${HOSTNAME_BG}${WHITE_TC}\033[1m \H ${GREY_BG} \u • ${FILEPATH_TC}\w ${RESET}\n\$ '
+PS2=" -> "
+
+# Commands
+{{ print "" }}
+{{- range $command := .BashProfile.Commands -}}
+{{ print "" }}
+## {{ $command.Description }}
+{{ $command.Command }}
+{{- end -}}
diff --git a/config/X11/xinitrc b/config/X11/xinitrc
deleted file mode 100644
index e676d0f..0000000
--- a/config/X11/xinitrc
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env bash
-
-[[ -f "${HOME}/.bashrc" ]] && source "${HOME}/.bashrc"
-
-# Start dunst
-if [ -x "$( command -v dunst )" ]; then
- dunst &
-fi
-
-# Load the wallpaper
-xwallpaper --stretch ~/.local/config/wallpaper/wallpaper.png &
-
-# Rotate the home logs with logrotate
-logrotate \
- --state=${XDG_STATE_HOME}/logrotate/status \
- --log=${LOG_HOME}/logrotate.log \
- ${XDG_CONFIG_HOME}/logrotate/logrotate.conf \
- &
-
-exec startdwm
diff --git a/config/ansible/ansible.cfg b/config/ansible/ansible.cfg
deleted file mode 100644
index 5bc6cbe..0000000
--- a/config/ansible/ansible.cfg
+++ /dev/null
@@ -1,10 +0,0 @@
-[defaults]
-
-nocows = 1
-cow_selection = default
-interpreter_python = /usr/bin/python3
-
-[persistent_connection]
-
-connect_timeout = 30
-command_timeout = 60
diff --git a/config/ansible/hosts.yml b/config/ansible/hosts.yml
deleted file mode 100644
index 3840406..0000000
--- a/config/ansible/hosts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-all:
- hosts:
- localhost:
- ansible_connection: local
diff --git a/config/bash/bash_profile b/config/bash/bash_profile
deleted file mode 100644
index 3a27f3a..0000000
--- a/config/bash/bash_profile
+++ /dev/null
@@ -1,5 +0,0 @@
-[[ -f ~/.bashrc ]] && source ~/.bashrc
-
-if [[ ! $DISPLAY && $XDG_VTNR && $XDG_VTNR -le 3 ]]; then
- exec startx "$XINITRC"
-fi
diff --git a/config/bash/bashrc b/config/bash/bashrc
deleted file mode 100644
index 0ee79bf..0000000
--- a/config/bash/bashrc
+++ /dev/null
@@ -1,27 +0,0 @@
-# If not running interactively, don't do anything
-[[ $- != *i* ]] && return
-
-# == Add personal bin directory to PATH
-if ! [[ "${PATH}" =~ "${HOME}/.local/bin" ]]; then
- export PATH=${HOME}/.local/bin:${PATH}
-fi
-
-# == Add custom scripts directory to PATH
-if ! [[ "${PATH}" =~ "${HOME}/.local/scripts" ]]; then
- export PATH=${HOME}/.local/scripts:${PATH}
-fi
-
-export XDG_CONFIG_HOME=${HOME}/.local/config
-export XDG_DATA_HOME=${HOME}/.local/share
-export XDG_CACHE_HOME=${HOME}/.local/cache
-export XDG_STATE_HOME=${HOME}/.local/state
-export LOG_HOME="${XDG_STATE_HOME}/logs"
-
-# == load all enabled scripts in ~/.bashrc.d
-# == any scripts with the .disabled extension won't be loaded
-for f in $(find ${XDG_CONFIG_HOME}/bash/bashrc.d -mindepth 1 -maxdepth 1 -type f -not -iname *.disabled | sort); do source $f; done
-
-# == Run tmux in the default session whenever a terminal session starts
-if command -v tmux &> /dev/null && [ -n "$PS1" ] && [[ ! "$TERM" =~ screen ]] && [[ ! "$TERM" =~ tmux ]] && [ -z "$TMUX" ]; then
- exec tmux new-session -A -s main
-fi
diff --git a/config/bash/bashrc.d/X11 b/config/bash/bashrc.d/X11
deleted file mode 100644
index 1d8aa87..0000000
--- a/config/bash/bashrc.d/X11
+++ /dev/null
@@ -1,4 +0,0 @@
-## Description: Bash configuration for X11.
-## vim: ft=sh :
-
-export XINITRC=${XDG_CONFIG_HOME}/X11/xinitrc
diff --git a/config/bash/bashrc.d/aliases b/config/bash/bashrc.d/aliases
deleted file mode 100644
index e6fbc29..0000000
--- a/config/bash/bashrc.d/aliases
+++ /dev/null
@@ -1,31 +0,0 @@
-## Description: All aliases are defined here.
-## vim: ft=sh :
-
-alias ls='ls --color=auto'
-alias ll='ls -laF'
-alias la='ls -A'
-alias l='ls -CF'
-
-alias rm='rm -i'
-alias mv='mv -i'
-alias cp='cp -i'
-
-alias grep='grep --color=auto'
-alias fgrep='fgrep --color=auto'
-alias egrep='egrep --color=auto'
-
-alias systemctl='sudo systemctl'
-alias journalctl='sudo journalctl'
-
-# aliases for pacman
-if [[ -x $( command -v pacman ) ]]; then
- alias pacman='sudo pacman'
- alias pacupdate='sudo pacman -Syu --noconfirm'
-fi
-
-alias pwgen="pwgen -s -c -n"
-alias dc="docker-compose"
-
-alias vim="nvim"
-alias view="nvim -R"
-alias vimdiff="nvim -d"
diff --git a/config/bash/bashrc.d/ansible b/config/bash/bashrc.d/ansible
deleted file mode 100644
index 71e1b40..0000000
--- a/config/bash/bashrc.d/ansible
+++ /dev/null
@@ -1,7 +0,0 @@
-## Description: Bash configuration for Ansible.
-## vim: ft=sh :
-
-export ANSIBLE_CONFIG=${XDG_CONFIG_HOME}/ansible/ansible.cfg
-export ANSIBLE_INVENTORY=${XDG_CONFIG_HOME}/ansible/hosts.yml
-export ANSIBLE_LOCAL_TEMP=${XDG_CACHE_HOME}/ansible
-export ANSIBLE_COLLECTIONS_PATH=${XDG_DATA_HOME}/ansible/collections
diff --git a/config/bash/bashrc.d/docker b/config/bash/bashrc.d/docker
deleted file mode 100644
index ab8229d..0000000
--- a/config/bash/bashrc.d/docker
+++ /dev/null
@@ -1,3 +0,0 @@
-## vim: ft=sh :
-
-export DOCKER_CONFIG=${XDG_CONFIG_HOME}/docker
diff --git a/config/bash/bashrc.d/exercism b/config/bash/bashrc.d/exercism
deleted file mode 100644
index fe62a5a..0000000
--- a/config/bash/bashrc.d/exercism
+++ /dev/null
@@ -1,8 +0,0 @@
-## File: ~/.bashrc.d/exercism
-## Description: Bash completion for exercism
-## vim: ft=sh :
-
-# == Bash completion for exercism
-if [ -f ${HOME}/.config/exercism/exercism_completion.bash ]; then
- source ~/.config/exercism/exercism_completion.bash
-fi
diff --git a/config/bash/bashrc.d/functions b/config/bash/bashrc.d/functions
deleted file mode 100644
index 785f49c..0000000
--- a/config/bash/bashrc.d/functions
+++ /dev/null
@@ -1,29 +0,0 @@
-## Description: All aliases are defined here.
-## vim: ft=sh :
-
-# mkcd creates a new directory (including the parent directories if they don't exist)
-# and makes it the current directory.
-mkcd() {
- mkdir -p $1
- cd $1
-}
-
-# go_up() navigates up a specified number of parent directories.
-# Inspired from DT's up() function:
-# https://gitlab.com/dwt1/dotfiles/-/blob/80632c5cad56ac96955e0ca1d582a4b59741bace/.bashrc#L109
-go_up() {
- local d=""
- local steps="$1"
-
- if [ -z "$steps" ] || [ "$steps" -lt 1 ]; then
- steps=1
- fi
-
- for ((i=1; i<=steps; i++)); do
- d="../$d"
- done
-
- if ! cd "$d"; then
- echo "Unable to go up $steps directories."
- fi
-}
diff --git a/config/bash/bashrc.d/git b/config/bash/bashrc.d/git
deleted file mode 100644
index 55c8e42..0000000
--- a/config/bash/bashrc.d/git
+++ /dev/null
@@ -1,10 +0,0 @@
-## File: ~/.bashrc.d/git
-## Description: Bash configuration for Git
-## vim: ft=sh :
-
-if [ -f /usr/share/bash-completion/completions/git ]; then
- source /usr/share/bash-completion/completions/git
-fi
-
-alias g="git"
-complete -o bashdefault -o default -o nospace -F __git_wrap__git_main g
diff --git a/config/bash/bashrc.d/gnupg b/config/bash/bashrc.d/gnupg
deleted file mode 100644
index fdce781..0000000
--- a/config/bash/bashrc.d/gnupg
+++ /dev/null
@@ -1,4 +0,0 @@
-## vim: ft=sh :
-
-export GPG_TTY=$(tty)
-export GNUPGHOME=${XDG_DATA_HOME}/gnupg
diff --git a/config/bash/bashrc.d/go b/config/bash/bashrc.d/go
deleted file mode 100644
index 5d2740f..0000000
--- a/config/bash/bashrc.d/go
+++ /dev/null
@@ -1,30 +0,0 @@
-## Description: Bash configuration for the Go setup
-## vim: ft=sh :
-
-if [ -f "${HOME}/.local/software/go/bin/go" ]; then
- export GOPATH=${XDG_DATA_HOME}/go
- export GOROOT=${HOME}/.local/software/go
- export GOBIN=${HOME}/.local/goblin
-
- if ! [[ "${PATH}" =~ "${GOBIN}" ]]; then
- export PATH=${GOBIN}:${PATH}
- fi
-
- if ! [ -d "${GOPATH}" ]; then
- mkdir ${GOPATH}
- fi
-
- if ! [ -d "${GOBIN}" ]; then
- mkdir ${GOBIN}
- fi
-
- export GOOS=linux
- export GOARCH=amd64
- export CGO_ENABLED=0
-fi
-
-# Magefile stuff
-if [ -x "$( command -v mage )" ]; then
- export MAGEFILE_CACHE=${XDG_CACHE_HOME}/magefile
- export MAGEFILE_ENABLE_COLOR=true
-fi
diff --git a/config/bash/bashrc.d/history b/config/bash/bashrc.d/history
deleted file mode 100644
index 4104c9b..0000000
--- a/config/bash/bashrc.d/history
+++ /dev/null
@@ -1,21 +0,0 @@
-## File: ~/.bashrc.d/history
-## Description: Configuration for Bash history
-## vim: ft=sh :
-
-# The name of the history file.
-HISTFILE=${XDG_STATE_HOME}/bash/history
-
-# Don't put duplicate lines or lines starting with space in the history.
-HISTCONTROL=ignoreboth
-
-# The maximum number of lines in the history file.
-HISTFILESIZE=10000
-
-# The number of commands to remember in the command history.
-HISTSIZE=1000
-
-# Display the timestamp of each command in history using the below format.
-HISTTIMEFORMAT="%d/%m/%y %T: "
-
-# Append to the history file, don't overwrite it.
-shopt -s histappend
diff --git a/config/bash/bashrc.d/kubectl b/config/bash/bashrc.d/kubectl
deleted file mode 100644
index 60ec097..0000000
--- a/config/bash/bashrc.d/kubectl
+++ /dev/null
@@ -1,9 +0,0 @@
-## Description: Bash settings for kubectl
-## vim: ft=sh :
-export KUBECONFIG=${XDG_CONFIG_HOME}/kube/config
-
-if [ -x "$( command -v kubectl )" ]; then
- source <(kubectl completion bash)
- alias k='kubectl'
- complete -F __start_kubectl k
-fi
diff --git a/config/bash/bashrc.d/less b/config/bash/bashrc.d/less
deleted file mode 100644
index 2ba931d..0000000
--- a/config/bash/bashrc.d/less
+++ /dev/null
@@ -1,3 +0,0 @@
-## vim: ft=sh :
-
-export LESSHISTFILE=${XDG_STATE_HOME}/less/history
diff --git a/config/bash/bashrc.d/lf b/config/bash/bashrc.d/lf
deleted file mode 100644
index 4af8efc..0000000
--- a/config/bash/bashrc.d/lf
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-
-lf () {
- tmp="$(mktemp)"
-
- logpath="${LOG_HOME}/lf.log"
-
- command lf --last-dir-path="$tmp" --log="$logpath" "$@"
- if [ -f "$tmp" ]; then
- dir="$(cat "$tmp")"
- rm -f "$tmp"
- if [ -d "$dir" ]; then
- if [ "$dir" != "$(pwd)" ]; then
- cd "$dir"
- fi
- fi
- fi
-}
diff --git a/config/bash/bashrc.d/local_software b/config/bash/bashrc.d/local_software
deleted file mode 100644
index f6de046..0000000
--- a/config/bash/bashrc.d/local_software
+++ /dev/null
@@ -1,12 +0,0 @@
-if [[ -d "$HOME/.local/software" ]]; then
- for dir in ${HOME}/.local/software/*; do
- dir=${dir:A}
- if [[ -d "$dir/bin" ]]; then
- if ! [[ "${PATH}" =~ "$dir/bin" ]]; then
- export PATH="$dir/bin:$PATH"
- fi
- fi
- done
-fi
-
-unset dir
diff --git a/config/bash/bashrc.d/minikube b/config/bash/bashrc.d/minikube
deleted file mode 100644
index 84549e8..0000000
--- a/config/bash/bashrc.d/minikube
+++ /dev/null
@@ -1,3 +0,0 @@
-## vim: ft=sh :
-
-export MINIKUBE_HOME=${XDG_DATA_HOME}/minikube
diff --git a/config/bash/bashrc.d/misc b/config/bash/bashrc.d/misc
deleted file mode 100644
index 68af067..0000000
--- a/config/bash/bashrc.d/misc
+++ /dev/null
@@ -1,21 +0,0 @@
-## Description: Bash configuration where we can't categorize anywhere else.
-## vim: ft=sh :
-
-export BROWSER=firefox
-export EDITOR=nvim
-export TERMINAL=st
-export LANG=en_GB.UTF-8
-export MANPAGER="nvim +Man!"
-
-# == vi mode in Bash
-set -o vi
-
-# == make less more friendly for non-text input files, see lesspipe(1)
-[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
-
-# == ensure that programmable completion features are enabled.
-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
diff --git a/config/bash/bashrc.d/pass b/config/bash/bashrc.d/pass
deleted file mode 100644
index fbd244e..0000000
--- a/config/bash/bashrc.d/pass
+++ /dev/null
@@ -1,9 +0,0 @@
-## Description: Bash configuration for pass
-## vim: ft=sh :
-
-export PASSWORD_STORE_DIR=${XDG_DATA_HOME}/pass
-
-if ! [ -d "${PASSWORD_STORE_DIR}" ]; then
- mkdir ${PASSWORD_STORE_DIR}
- chmod 0700 ${PASSWORD_STORE_DIR}
-fi
diff --git a/config/bash/bashrc.d/prompt b/config/bash/bashrc.d/prompt
deleted file mode 100644
index 91d0d88..0000000
--- a/config/bash/bashrc.d/prompt
+++ /dev/null
@@ -1,32 +0,0 @@
-## File: ~/.bashrc.d/prompt
-## Description: Configuration for the Bash prompt
-## vim: ft=sh :
-
-get_date() {
- date '+%d.%m.%Y'
-}
-
-if [ -f /usr/share/git/completion/git-prompt.sh ]; then
- source /usr/share/git/completion/git-prompt.sh
-elif [ -f /usr/share/git/git-prompt.sh ]; then
- source /usr/share/git/git-prompt.sh
-elif [ -f /usr/lib/git-core/git-sh-prompt ]; then
- source /usr/lib/git-core/git-sh-prompt
-elif [ -f /etc/bash_completion.d/git-prompt ]; then
- source /etc/bash_completion.d/git-prompt
-elif [ -f ${HOME}/.git-prompt ]; then
- source ${HOME}/.git-prompt
-fi
-
-GIT_PS1_SHOWDIRTYSTATE="true"
-GIT_PS1_SHOWUPSTREAM="auto"
-GIT_PS1_STATESEPARATOR=": "
-
-DATE_BG="$(tput setab 68)"
-GREY_BG="$(tput setab 240)"
-RESET="$(tput sgr0)"
-FILEPATH_TC="$(tput setaf 81)"
-WHITE_TC="$(tput setaf 255)"
-GREEN_TC="$(tput setaf 2)"
-PS1='${DATE_BG}${WHITE_TC}$(get_date) ${GREY_BG} \u • ${FILEPATH_TC}\033[1m\w ${RESET} ${GREEN_TC}\033[3m$(__git_ps1 "git:(%s)")${RESET}\n\$ '
-PS2=" -> "
diff --git a/config/bash/bashrc.d/pulumi b/config/bash/bashrc.d/pulumi
deleted file mode 100644
index 9dfe08d..0000000
--- a/config/bash/bashrc.d/pulumi
+++ /dev/null
@@ -1,6 +0,0 @@
-## File: ~/.bashrc.d/pulumi
-## Description: Bash configuration for the pulumi setup
-## vim: ft=sh :
-
-export PULUMI_SKIP_UPDATE_CHECK="true"
-export PULUMI_HOME="${XDG_DATA_HOME}/pulumi"
diff --git a/config/bash/bashrc.d/terminfo b/config/bash/bashrc.d/terminfo
deleted file mode 100644
index bfeb17d..0000000
--- a/config/bash/bashrc.d/terminfo
+++ /dev/null
@@ -1,4 +0,0 @@
-## vim: ft=sh :
-
-export TERMINFO=${XDG_DATA_HOME}/terminfo
-export TERMINFO_DIRS=${TERMINFO}:/usr/share/terminfo
diff --git a/config/bash/bashrc.d/vagrant b/config/bash/bashrc.d/vagrant
deleted file mode 100644
index c8f609b..0000000
--- a/config/bash/bashrc.d/vagrant
+++ /dev/null
@@ -1,3 +0,0 @@
-## vim: ft=sh :
-
-export VAGRANT_HOME=${XDG_DATA_HOME}/vagrant
diff --git a/config/bash/bashrc.d/vault b/config/bash/bashrc.d/vault
deleted file mode 100644
index 38beb89..0000000
--- a/config/bash/bashrc.d/vault
+++ /dev/null
@@ -1,8 +0,0 @@
-## File: ~/.bashrc.d/vault
-## Description: Bash configuration for vault setup.
-## vim: ft=sh :
-
-# bash autocompletion for vault
-if [ -f "${HOME}/.local/bin/vault" ]; then
- complete -C /home/dananglin/.local/bin/vault vault
-fi
diff --git a/config/dunst/dunstrc b/config/dunst/dunstrc
deleted file mode 100644
index a6b10a6..0000000
--- a/config/dunst/dunstrc
+++ /dev/null
@@ -1,438 +0,0 @@
-# See dunst(5) for all configuration options
-
-[global]
- ### Display ###
-
- # Which monitor should the notifications be displayed on.
- monitor = 0
-
- # Display notification on focused monitor. Possible modes are:
- # mouse: follow mouse pointer
- # keyboard: follow window with keyboard focus
- # none: don't follow anything
- #
- # "keyboard" needs a window manager that exports the
- # _NET_ACTIVE_WINDOW property.
- # This should be the case for almost all modern window managers.
- #
- # If this option is set to mouse or keyboard, the monitor option
- # will be ignored.
- follow = keyboard
-
- ### Geometry ###
-
- # dynamic width from 0 to 300
- # width = (0, 300)
- # constant width of 300
- width = 300
-
- # The maximum height of a single notification, excluding the frame.
- height = 300
-
- # Position the notification in the top right corner
- origin = top-right
-
- # Offset from the origin
- offset = 20x40
-
- # Scale factor. It is auto-detected if value is 0.
- scale = 0
-
- # Maximum number of notification (0 means no limit)
- notification_limit = 3
-
- ### Progress bar ###
-
- # Turn on the progess bar. It appears when a progress hint is passed with
- # for example dunstify -h int:value:12
- progress_bar = true
-
- # Set the progress bar height. This includes the frame, so make sure
- # it's at least twice as big as the frame width.
- progress_bar_height = 10
-
- # Set the frame width of the progress bar
- progress_bar_frame_width = 1
-
- # Set the minimum width for the progress bar
- progress_bar_min_width = 150
-
- # Set the maximum width for the progress bar
- progress_bar_max_width = 300
-
-
- # Show how many messages are currently hidden (because of
- # notification_limit).
- indicate_hidden = yes
-
- # The transparency of the window. Range: [0; 100].
- # This option will only work if a compositing window manager is
- # present (e.g. xcompmgr, compiz, etc.). (X11 only)
- transparency = 0
-
- # Draw a line of "separator_height" pixel height between two
- # notifications.
- # Set to 0 to disable.
- separator_height = 2
-
- # Padding between text and separator.
- padding = 8
-
- # Horizontal padding.
- horizontal_padding = 8
-
- # Padding between text and icon.
- text_icon_padding = 0
-
- # Defines width in pixels of frame around the notification window.
- # Set to 0 to disable.
- frame_width = 2
-
- # Defines color of the frame around the notification window.
- frame_color = "#bb9af7"
-
- # Define a color for the separator.
- # possible values are:
- # * auto: dunst tries to find a color fitting to the background;
- # * foreground: use the same color as the foreground;
- # * frame: use the same color as the frame;
- # * anything else will be interpreted as a X color.
- separator_color = frame
-
- # Sort messages by urgency.
- sort = yes
-
- # Don't remove messages, if the user is idle (no mouse or keyboard input)
- # for longer than idle_threshold seconds.
- # Set to 0 to disable.
- # A client can set the 'transient' hint to bypass this. See the rules
- # section for how to disable this if necessary
- idle_threshold = 120
-
- ### Text ###
-
- font = Source Code Pro 12
-
- # The spacing between lines. If the height is smaller than the
- # font height, it will get raised to the font height.
- line_height = 0
-
- # Possible values are:
- # full: Allow a small subset of html markup in notifications:
- # bold
- # italic
- # strikethrough
- # underline
- #
- # For a complete reference see
- # .
- #
- # strip: This setting is provided for compatibility with some broken
- # clients that send markup even though it's not enabled on the
- # server. Dunst will try to strip the markup but the parsing is
- # simplistic so using this option outside of matching rules for
- # specific applications *IS GREATLY DISCOURAGED*.
- #
- # no: Disable markup parsing, incoming notifications will be treated as
- # plain text. Dunst will not advertise that it has the body-markup
- # capability if this is set as a global setting.
- #
- # It's important to note that markup inside the format option will be parsed
- # regardless of what this is set to.
- markup = full
-
- # The format of the message. Possible variables are:
- # %a appname
- # %s summary
- # %b body
- # %i iconname (including its path)
- # %I iconname (without its path)
- # %p progress value if set ([ 0%] to [100%]) or nothing
- # %n progress value if set without any extra characters
- # %% Literal %
- # Markup is allowed
- format = "%s\n%b"
-
- # Alignment of message text.
- # Possible values are "left", "center" and "right".
- alignment = left
-
- # Vertical alignment of message text and icon.
- # Possible values are "top", "center" and "bottom".
- vertical_alignment = center
-
- # Show age of message if message is older than show_age_threshold
- # seconds.
- # Set to -1 to disable.
- show_age_threshold = 60
-
- # Specify where to make an ellipsis in long lines.
- # Possible values are "start", "middle" and "end".
- ellipsize = middle
-
- # Ignore newlines '\n' in notifications.
- ignore_newline = no
-
- # Stack together notifications with the same content
- stack_duplicates = true
-
- # Hide the count of stacked notifications with the same content
- hide_duplicate_count = false
-
- # Display indicators for URLs (U) and actions (A).
- show_indicators = yes
-
- ### Icons ###
-
- # Align icons left/right/top/off
- icon_position = left
-
- # Scale small icons up to this size, set to 0 to disable. Helpful
- # for e.g. small files or high-dpi screens. In case of conflict,
- # max_icon_size takes precedence over this.
- min_icon_size = 0
-
- # Scale larger icons down to this size, set to 0 to disable
- max_icon_size = 32
-
- # Paths to default icons.
- icon_path = /usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/
-
- ### History ###
-
- # Should a notification popped up from history be sticky or timeout
- # as if it would normally do.
- sticky_history = yes
-
- # Maximum amount of notifications kept in history
- history_length = 20
-
- ### Misc/Advanced ###
-
- # dmenu path.
- dmenu = /usr/bin/dmenu -p dunst:
-
- # Browser for opening urls in context menu.
- browser = /usr/bin/xdg-open
-
- # Always run rule-defined scripts, even if the notification is suppressed
- always_run_script = true
-
- # Define the title of the windows spawned by dunst
- title = Dunst
-
- # Define the class of the windows spawned by dunst
- class = Dunst
-
- # Define the corner radius of the notification window
- # in pixel size. If the radius is 0, you have no rounded
- # corners.
- # The radius will be automatically lowered if it exceeds half of the
- # notification height to avoid clipping text and/or icons.
- corner_radius = 2
-
- # Ignore the dbus closeNotification message.
- # Useful to enforce the timeout set by dunst configuration. Without this
- # parameter, an application may close the notification sent before the
- # user defined timeout.
- ignore_dbusclose = false
-
- ### Wayland ###
- # These settings are Wayland-specific. They have no effect when using X11
-
- # Uncomment this if you want to let notications appear under fullscreen
- # applications (default: overlay)
- # layer = top
-
- # Set this to true to use X11 output on Wayland.
- force_xwayland = false
-
- ### Legacy
-
- # Use the Xinerama extension instead of RandR for multi-monitor support.
- # This setting is provided for compatibility with older nVidia drivers that
- # do not support RandR and using it on systems that support RandR is highly
- # discouraged.
- #
- # By enabling this setting dunst will not be able to detect when a monitor
- # is connected or disconnected which might break follow mode if the screen
- # layout changes.
- force_xinerama = false
-
- ### mouse
-
- # Defines list of actions for each mouse event
- # Possible values are:
- # * none: Don't do anything.
- # * do_action: Invoke the action determined by the action_name rule. If there is no
- # such action, open the context menu.
- # * open_url: If the notification has exactly one url, open it. If there are multiple
- # ones, open the context menu.
- # * close_current: Close current notification.
- # * close_all: Close all notifications.
- # * context: Open context menu for the notification.
- # * context_all: Open context menu for all notifications.
- # These values can be strung together for each mouse event, and
- # will be executed in sequence.
- mouse_left_click = close_current
- mouse_middle_click = do_action, close_current
- mouse_right_click = close_all
-
-# Experimental features that may or may not work correctly. Do not expect them
-# to have a consistent behaviour across releases.
-[experimental]
- # Calculate the dpi to use on a per-monitor basis.
- # If this setting is enabled the Xft.dpi value will be ignored and instead
- # dunst will attempt to calculate an appropriate dpi value for each monitor
- # using the resolution and physical size. This might be useful in setups
- # where there are multiple screens with very different dpi values.
- per_monitor_dpi = false
-
-
-[urgency_low]
- # IMPORTANT: colors have to be defined in quotation marks.
- # Otherwise the "#" and following would be interpreted as a comment.
- background = "#222222"
- foreground = "#888888"
- timeout = 10
- # Icon for notifications with low urgency, uncomment to enable
- #default_icon = /path/to/icon
-
-[urgency_normal]
- background = "#285577"
- foreground = "#ffffff"
- timeout = 10
- # Icon for notifications with normal urgency, uncomment to enable
- #default_icon = /path/to/icon
-
-[urgency_critical]
- background = "#900000"
- foreground = "#ffffff"
- frame_color = "#ff0000"
- timeout = 0
- # Icon for notifications with critical urgency, uncomment to enable
- #default_icon = /path/to/icon
-
-# Every section that isn't one of the above is interpreted as a rules to
-# override settings for certain messages.
-#
-# Messages can be matched by
-# appname (discouraged, see desktop_entry)
-# body
-# category
-# desktop_entry
-# icon
-# match_transient
-# msg_urgency
-# stack_tag
-# summary
-#
-# and you can override the
-# background
-# foreground
-# format
-# frame_color
-# fullscreen
-# new_icon
-# set_stack_tag
-# set_transient
-# set_category
-# timeout
-# urgency
-# icon_position
-# skip_display
-# history_ignore
-# action_name
-# word_wrap
-# ellipsize
-# alignment
-# hide_text
-#
-# Shell-like globbing will get expanded.
-#
-# Instead of the appname filter, it's recommended to use the desktop_entry filter.
-# GLib based applications export their desktop-entry name. In comparison to the appname,
-# the desktop-entry won't get localized.
-#
-# SCRIPTING
-# You can specify a script that gets run when the rule matches by
-# setting the "script" option.
-# The script will be called as follows:
-# script appname summary body icon urgency
-# where urgency can be "LOW", "NORMAL" or "CRITICAL".
-#
-# NOTE: It might be helpful to run dunst -print in a terminal in order
-# to find fitting options for rules.
-
-# Disable the transient hint so that idle_threshold cannot be bypassed from the
-# client
-#[transient_disable]
-# match_transient = yes
-# set_transient = no
-#
-# Make the handling of transient notifications more strict by making them not
-# be placed in history.
-#[transient_history_ignore]
-# match_transient = yes
-# history_ignore = yes
-
-# fullscreen values
-# show: show the notifications, regardless if there is a fullscreen window opened
-# delay: displays the new notification, if there is no fullscreen window active
-# If the notification is already drawn, it won't get undrawn.
-# pushback: same as delay, but when switching into fullscreen, the notification will get
-# withdrawn from screen again and will get delayed like a new notification
-#[fullscreen_delay_everything]
-# fullscreen = delay
-#[fullscreen_show_critical]
-# msg_urgency = critical
-# fullscreen = show
-
-#[espeak]
-# summary = "*"
-# script = dunst_espeak.sh
-
-#[script-test]
-# summary = "*script*"
-# script = dunst_test.sh
-
-#[ignore]
-# # This notification will not be displayed
-# summary = "foobar"
-# skip_display = true
-
-#[history-ignore]
-# # This notification will not be saved in history
-# summary = "foobar"
-# history_ignore = yes
-
-#[skip-display]
-# # This notification will not be displayed, but will be included in the history
-# summary = "foobar"
-# skip_display = yes
-
-#[signed_on]
-# appname = Pidgin
-# summary = "*signed on*"
-# urgency = low
-#
-#[signed_off]
-# appname = Pidgin
-# summary = *signed off*
-# urgency = low
-#
-#[says]
-# appname = Pidgin
-# summary = *says*
-# urgency = critical
-#
-#[twitter]
-# appname = Pidgin
-# summary = *twitter.com*
-# urgency = normal
-#
-#[stack-volumes]
-# appname = "some_volume_notifiers"
-# set_stack_tag = "volume"
-#
-# vim: ft=cfg
diff --git a/config/logrotate/logrotate.conf b/config/logrotate/logrotate.conf
deleted file mode 100644
index 61967c2..0000000
--- a/config/logrotate/logrotate.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-${LOG_HOME}/*.log ${LOG_HOME}/nvim/*.log {
- rotate 3
- size 10M
- nocompress
- notifempty
- copytruncate
-}
diff --git a/config/alacritty/alacritty.toml b/files/alacritty/alacritty.toml
similarity index 100%
rename from config/alacritty/alacritty.toml
rename to files/alacritty/alacritty.toml
diff --git a/config/amfora/config.toml b/files/amfora/config.toml
similarity index 86%
rename from config/amfora/config.toml
rename to files/amfora/config.toml
index bc0dc3d..bc71d32 100644
--- a/config/amfora/config.toml
+++ b/files/amfora/config.toml
@@ -269,60 +269,53 @@ entries_per_page = 20
[theme]
-# Atom One Dark theme ported to Amfora
-# by Serge Tymoshenko
-# Link: https://github.com/makeworld-the-better-one/amfora/blob/master/contrib/themes/one_dark.toml
+# Tokyo Night
-bg = "#282c34"
-fg = "#abb2bf"
-tab_num = "#abb2bf"
-tab_divider = "#abb2bf"
-bottombar_bg = "#abb2bf"
-bottombar_text = "#282c34"
-bottombar_label = "#282c34"
+bg = "#1a1b26"
+fg = "#a9b1d6"
+tab_num = "#565f89"
+tab_divider = "#3b4261"
+bottombar_label = "#7aa2f7"
+bottombar_text = "#7aa2f7"
+bottombar_bg = "#1f2335"
+scrollbar = "#565f89"
-hdg_1 = "#e06c75"
-hdg_2 = "#c678dd"
-hdg_3 = "#c678dd"
-amfora_link = "#61afef"
-foreign_link = "#56b6c2"
-link_number = "#abb2bf"
-regular_text = "#abb2bf"
-quote_text = "#98c379"
-preformatted_text = "#e5c07b"
-list_text = "#abb2bf"
+hdg_1 = "#f7768e"
+hdg_2 = "#7dcfff"
+hdg_3 = "#bb9af7"
+amfora_link = "#73daca"
+foreign_link = "#b4f9f8"
+link_number = "#ff9e64"
+regular_text = "#a9b1d6"
+quote_text = "#e0af68"
+preformatted_text = "#2ac3de"
+list_text = "#a9b1d6"
-btn_bg = "#282c34"
-btn_text = "#abb2bf"
+btn_bg = "#414868"
+btn_text = "#7aa2f7"
-dl_choice_modal_bg = "#98c379"
-dl_choice_modal_text = "#282c34"
+dl_choice_modal_bg = "#414868"
+dl_choice_modal_text = "#c0caf5"
+dl_modal_bg = "#414868"
+dl_modal_text = "#c0caf5"
+info_modal_bg = "#414868"
+info_modal_text = "#c0caf5"
+error_modal_bg = "#414868"
+error_modal_text = "#f7768e"
+yesno_modal_bg = "#414868"
+yesno_modal_text = "#e0af68"
+tofu_modal_bg = "#414868"
+tofu_modal_text = "#2ac3de"
+subscription_modal_bg = "#414868"
+subscription_modal_text = "#bb9af7"
-dl_modal_bg = "#98c379"
-dl_modal_text = "#282c34"
+input_modal_bg = "#414868"
+input_modal_text = "#c0caf5"
+input_modal_field_bg = "#33467c"
+input_modal_field_text = "#a9b1d6"
-info_modal_bg = "#98c379"
-info_modal_text = "#282c34"
-
-error_modal_bg = "#e06c75"
-error_modal_text = "#282c34"
-
-yesno_modal_bg = "#e5c07b"
-yesno_modal_text = "#282c34"
-
-tofu_modal_bg = "#e5c07b"
-tofu_modal_text = "#282c34"
-
-input_modal_bg = "#98c379"
-input_modal_text = "#282c34"
-input_modal_field_bg = "#282c34"
-input_modal_field_text = "#abb2bf"
-
-bkmk_modal_bg = "#98c379"
-bkmk_modal_text = "#282c34"
-bkmk_modal_label = "#282c34"
-bkmk_modal_field_bg = "#282c34"
-bkmk_modal_field_text = "#abb2bf"
-
-subscription_modal_bg = "#c678dd"
-subscription_modal_text = "#282c34"
+bkmk_modal_bg = "#414868"
+bkmk_modal_text = "#c0caf5"
+bkmk_modal_label = "#c0caf5"
+bkmk_modal_field_bg = "#33467c"
+bkmk_modal_field_text = "#a9b1d6"
diff --git a/files/foot/foot.ini b/files/foot/foot.ini
new file mode 100644
index 0000000..d605818
--- /dev/null
+++ b/files/foot/foot.ini
@@ -0,0 +1,239 @@
+# -*- conf -*-
+
+# shell=$SHELL (if set, otherwise user's default shell from /etc/passwd)
+term=foot
+login-shell=no
+app-id=foot
+title="Dan's Foot Terminal"
+locked-title=yes
+
+# Font configuration
+font=SauceCodePro Nerd Font Mono:size=10.50
+font-bold=SauceCodePro Nerd Font Mono:size=10.50:weight=bold
+font-italic=SauceCodePro Nerd Font Mono:size=10.50:slant=italic
+font-bold-italic=SauceCodePro Nerd Font Mono:size=10.50:weight=bold:slant=italic
+# font-size-adjustment=0.5
+# line-height=
+# letter-spacing=0
+# horizontal-letter-offset=0
+# vertical-letter-offset=0
+# underline-offset=
+# underline-thickness=
+# strikeout-thickness=
+# box-drawings-uses-font-glyphs=no
+# dpi-aware=no
+
+# initial-window-size-pixels=700x500 # Or,
+# initial-window-size-chars=
+# initial-window-mode=windowed
+# pad=0x0 # optionally append 'center'
+# resize-by-cells=yes
+# resize-keep-grid=yes
+# resize-delay-ms=100
+
+bold-text-in-bright=yes
+# word-delimiters=,│`|:"'()[]{}<>
+# selection-target=primary
+# workers=
+# utmp-helper=/usr/lib/utempter/utempter # When utmp backend is ‘libutempter’ (Linux)
+# utmp-helper=/usr/libexec/ulog-helper # When utmp backend is ‘ulog’ (FreeBSD)
+
+[environment]
+# name=value
+
+[bell]
+# urgent=no
+# notify=no
+# visual=no
+# command=
+# command-focused=no
+
+#[desktop-notifications]
+# command=notify-send --wait --app-name ${app-id} --icon ${app-id} --category ${category} --urgency ${urgency} --expire-time ${expire-time} --hint STRING:image-path:${icon} --hint BOOLEAN:suppress-sound:${muted} --hint STRING:sound-name:${sound-name} --replace-id ${replace-id} ${action-argument} --print-id -- ${title} ${body}
+# command-action-argument=--action ${action-name}=${action-label}
+# close=""
+# inhibit-when-focused=yes
+
+
+[scrollback]
+lines=10000
+multiplier=1.0
+# indicator-position=relative
+# indicator-format=""
+
+[url]
+launch=xdg-open ${url}
+# label-letters=sadfjklewcmpgh
+# osc8-underline=url-mode
+protocols=http, https, file
+# uri-characters=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.,~:;/?#@!$&%*+="'()[]
+
+[cursor]
+style=beam
+beam-thickness=1.5
+unfocused-style=hollow
+blink=no
+# blink-rate=500
+# color=
+# underline-thickness=
+
+[mouse]
+# hide-when-typing=no
+# alternate-scroll-mode=yes
+
+[touch]
+# long-press-delay=400
+
+[colors]
+alpha=1.0
+background=1a1b26
+foreground=c0caf5
+flash=7f7f00
+flash-alpha=0.5
+
+## Normal/regular colors (color palette 0-7)
+regular0=15161e # black
+regular1=f7768e # red
+regular2=9ece6a # green
+regular3=e0af68 # yellow
+regular4=7aa2f7 # blue
+regular5=bb9af7 # magenta
+regular6=7dcfff # cyan
+regular7=a9b1d6 # white
+
+## Bright colors (color palette 8-15)
+bright0=414868 # bright black
+bright1=f7768e # bright red
+bright2=9ece6a # bright green
+bright3=e0af68 # bright yellow
+bright4=7aa2f7 # bright blue
+bright5=bb9af7 # bright magenta
+bright6=7dcfff # bright cyan
+bright7=c0caf5 # bright white
+
+## dimmed colors (see foot.ini(5) man page)
+# dim0=
+# ...
+# dim7=
+
+## The remaining 256-color palette
+# 16 = <256-color palette #16>
+# ...
+# 255 = <256-color palette #255>
+
+## Misc colors
+# selection-foreground=
+# selection-background=
+# jump-labels= # black-on-yellow
+# scrollback-indicator= # black-on-bright-blue
+# search-box-no-match= # black-on-red
+# search-box-match= # black-on-yellow
+# urls=
+
+[csd]
+# preferred=server
+# size=26
+# font=
+# color=
+# hide-when-maximized=no
+# double-click-to-maximize=yes
+# border-width=0
+# border-color=
+# button-width=26
+# button-color=
+# button-minimize-color=
+# button-maximize-color=
+# button-close-color=
+
+[key-bindings]
+# scrollback-up-page=Shift+Page_Up
+# scrollback-up-half-page=none
+# scrollback-up-line=none
+# scrollback-down-page=Shift+Page_Down
+# scrollback-down-half-page=none
+# scrollback-down-line=none
+# scrollback-home=none
+# scrollback-end=none
+# clipboard-copy=Control+Shift+c XF86Copy
+# clipboard-paste=Control+Shift+v XF86Paste
+# primary-paste=Shift+Insert
+# search-start=Control+Shift+r
+# font-increase=Control+plus Control+equal Control+KP_Add
+# font-decrease=Control+minus Control+KP_Subtract
+# font-reset=Control+0 Control+KP_0
+# spawn-terminal=Control+Shift+n
+# minimize=none
+# maximize=none
+# fullscreen=none
+# pipe-visible=[sh -c "xurls | fuzzel | xargs -r firefox"] none
+# pipe-scrollback=[sh -c "xurls | fuzzel | xargs -r firefox"] none
+# pipe-selected=[xargs -r firefox] none
+# pipe-command-output=[wl-copy] none # Copy last command's output to the clipboard
+# show-urls-launch=Control+Shift+o
+# show-urls-copy=none
+# show-urls-persistent=none
+# prompt-prev=Control+Shift+z
+# prompt-next=Control+Shift+x
+# unicode-input=Control+Shift+u
+# noop=none
+
+[search-bindings]
+# cancel=Control+g Control+c Escape
+# commit=Return
+# find-prev=Control+r
+# find-next=Control+s
+# cursor-left=Left Control+b
+# cursor-left-word=Control+Left Mod1+b
+# cursor-right=Right Control+f
+# cursor-right-word=Control+Right Mod1+f
+# cursor-home=Home Control+a
+# cursor-end=End Control+e
+# delete-prev=BackSpace
+# delete-prev-word=Mod1+BackSpace Control+BackSpace
+# delete-next=Delete
+# delete-next-word=Mod1+d Control+Delete
+# extend-char=Shift+Right
+# extend-to-word-boundary=Control+w Control+Shift+Right
+# extend-to-next-whitespace=Control+Shift+w
+# extend-line-down=Shift+Down
+# extend-backward-char=Shift+Left
+# extend-backward-to-word-boundary=Control+Shift+Left
+# extend-backward-to-next-whitespace=none
+# extend-line-up=Shift+Up
+# clipboard-paste=Control+v Control+Shift+v Control+y XF86Paste
+# primary-paste=Shift+Insert
+# unicode-input=none
+# quit=none
+# scrollback-up-page=Shift+Page_Up
+# scrollback-up-half-page=none
+# scrollback-up-line=none
+# scrollback-down-page=Shift+Page_Down
+# scrollback-down-half-page=none
+# scrollback-down-line=none
+# scrollback-home=none
+# scrollback-end=none
+
+[url-bindings]
+# cancel=Control+g Control+c Control+d Escape
+# toggle-url-visible=t
+
+[text-bindings]
+# \x03=Mod4+c # Map Super+c -> Ctrl+c
+
+[mouse-bindings]
+# scrollback-up-mouse=BTN_WHEEL_BACK
+# scrollback-down-mouse=BTN_WHEEL_FORWARD
+# font-increase=Control+BTN_WHEEL_BACK
+# font-decrease=Control+BTN_WHEEL_FORWARD
+# selection-override-modifiers=Shift
+# primary-paste=BTN_MIDDLE
+# select-begin=BTN_LEFT
+# select-begin-block=Control+BTN_LEFT
+# select-extend=BTN_RIGHT
+# select-extend-character-wise=Control+BTN_RIGHT
+# select-word=BTN_LEFT-2
+# select-word-whitespace=Control+BTN_LEFT-2
+# select-quote = BTN_LEFT-3
+# select-row=BTN_LEFT-4
+
+# vim: ft=dosini
diff --git a/config/git/gitignore b/files/git/ignore
similarity index 57%
rename from config/git/gitignore
rename to files/git/ignore
index 5dca9c5..bf4d5c9 100644
--- a/config/git/gitignore
+++ b/files/git/ignore
@@ -1,6 +1,6 @@
-/tags
-/notes/*
-/tmp/*
+/.notes/*
+/.hack/*
+/.tmp/*
library/__pycache__/
library/*.pyc
diff --git a/config/git/gitmessage b/files/git/message
similarity index 100%
rename from config/git/gitmessage
rename to files/git/message
diff --git a/config/lf/lfrc b/files/lf/lfrc
similarity index 100%
rename from config/lf/lfrc
rename to files/lf/lfrc
diff --git a/files/river/init b/files/river/init
new file mode 100755
index 0000000..d1c9fba
--- /dev/null
+++ b/files/river/init
@@ -0,0 +1,77 @@
+#!/usr/bin/env bash
+
+# Set the background and border colours
+riverctl background-color 0x15161e
+riverctl border-color-focused 0xbb9af7 # Magenta
+riverctl border-color-unfocused 0x444444 # Grey
+
+# Super+Shift+T to spawn an instance of foot
+riverctl map normal Super+Shift T spawn foot
+
+# Super+Shift+B to spawn an instance of firefox
+riverctl map normal Super+Shift B spawn firefox
+
+# Super+Shift+Q to exit river
+riverctl map normal Super+Shift Q exit
+
+# Super+C to close the focused view
+riverctl map normal Super C close
+
+# Super+H to shift the focus to the previous view in the layout stack
+# Super+L to shift the focus to the next view in the layout stack
+riverctl map normal Super H focus-view previous
+riverctl map normal Super L focus-view next
+
+# Super+Shift+H to swap the focused view with the previous view in the layout stack
+# Super+Shift+L to swap the focused view with the next view in the layout stack
+riverctl map normal Super+Shift H swap previous
+riverctl map normal Super+Shift L swap next
+
+# Super+Period to focus the next output
+# Super+Comma to focus the previous output
+riverctl map normal Super Period focus-output next
+riverctl map normal Super Comma focus-output previous
+
+# Super+Shift+Period to send the focused view to the next output
+# Super+Shift+Comma to send the focused view to the previous output
+riverctl map normal Super+Shift Period send-to-output next
+riverctl map normal Super+Shift Comma send-to-output previous
+
+# Super+Return to bump the focused view to the top of the layout stack
+riverctl map normal Super Return zoom
+
+# Super+J to increase the main ratio of rivertile(1)
+# Super+K to decrease the main ratio of rivertile(1)
+riverctl map normal Super J send-layout-cmd rivertile "main-ratio +0.05"
+riverctl map normal Super K send-layout-cmd rivertile "main-ratio -0.05"
+
+# Super+Shift+J to increment the main count of rivertile(1)
+# Super+Shift+K to decrement the main count of rivertile(1)
+riverctl map normal Super+Shift J send-layout-cmd rivertile "main-count +1"
+riverctl map normal Super+Shift K send-layout-cmd rivertile "main-count -1"
+
+# Super+Alt+{H,J,K,L} to move views
+riverctl map normal Super+Alt H move left 100
+riverctl map normal Super+Alt J move down 100
+riverctl map normal Super+Alt K move up 100
+riverctl map normal Super+Alt L move right 100
+
+# Super+Alt+Control+{H,J,K,L} to snap views to screen edges
+riverctl map normal Super+Alt+Control H snap left
+riverctl map normal Super+Alt+Control J snap down
+riverctl map normal Super+Alt+Control K snap up
+riverctl map normal Super+Alt+Control L snap right
+
+# Super+Alt+Shift+{H,J,K,L} to resize views
+riverctl map normal Super+Alt+Shift H resize horizontal -100
+riverctl map normal Super+Alt+Shift J resize vertical 100
+riverctl map normal Super+Alt+Shift K resize vertical -100
+riverctl map normal Super+Alt+Shift L resize horizontal 100
+
+# Configure the keyboard layout
+riverctl keyboard-layout gb
+
+# Set the default layout generator to be rivertile and start it.
+# River will send the process group of the init executable SIGTERM on exit.
+riverctl default-layout rivertile
+rivertile -view-padding 6 -outer-padding 6 &
diff --git a/config/tmux/tmux.conf b/files/tmux/tmux.conf
similarity index 89%
rename from config/tmux/tmux.conf
rename to files/tmux/tmux.conf
index d73dba7..b61d929 100644
--- a/config/tmux/tmux.conf
+++ b/files/tmux/tmux.conf
@@ -1,6 +1,8 @@
+#set-option -g default-terminal "tmux-256color"
set-option -g default-terminal "$TERM"
set-option -ag terminal-overrides ",$TERM:Tc"
-set-option -g default-shell /usr/bin/bash
+# set-option -g default-shell /usr/bin/env bash
+set-option -g default-command "/usr/bin/env bash"
set-option -g mouse off
set-window-option -g status-keys vi
diff --git a/config/xdg/user-dirs.dirs b/files/user-dirs.dirs
similarity index 100%
rename from config/xdg/user-dirs.dirs
rename to files/user-dirs.dirs
diff --git a/config/xdg/user-dirs.locale b/files/user-dirs.locale
similarity index 100%
rename from config/xdg/user-dirs.locale
rename to files/user-dirs.locale
diff --git a/files/zk/config.toml b/files/zk/config.toml
new file mode 100644
index 0000000..2f24dc0
--- /dev/null
+++ b/files/zk/config.toml
@@ -0,0 +1,11 @@
+[note]
+default-title = "Note"
+extension = "md"
+filename = "{{date now '%Y%m%d%H%M%S'}}-{{slug title}}"
+language = "en"
+
+[extra]
+author = "dananglin"
+
+[tool]
+editor = "nvim"
diff --git a/hosts/falcon.json b/hosts/falcon.json
new file mode 100644
index 0000000..4166702
--- /dev/null
+++ b/hosts/falcon.json
@@ -0,0 +1,197 @@
+{
+ "bashProfile": {
+ "manage": true,
+ "filename": ".bashrc",
+ "sessionPaths": [
+ {
+ "path": ".local/software/element-desktop/bin",
+ "description": "Element"
+ },
+ {
+ "path": ".local/software/firefox/bin",
+ "description": "Firefox"
+ },
+ {
+ "path": ".local/software/go/bin",
+ "description": "Go"
+ },
+ {
+ "path": ".local/software/lua/bin",
+ "description": "Lua"
+ },
+ {
+ "path": ".local/software/lua-language-server/bin",
+ "description": "the Lua Language Server"
+ },
+ {
+ "path": ".local/software/luarocks/bin",
+ "description": "Luarocks"
+ },
+ {
+ "path": ".local/software/neovim/bin",
+ "description": "Neovim"
+ },
+ {
+ "path": ".local/software/node/bin",
+ "description": "Node"
+ },
+ {
+ "path": ".local/software/pulumi/bin",
+ "description": "Pulumi"
+ },
+ {
+ "path": ".local/software/radicle/bin",
+ "description": "Radicle"
+ },
+ {
+ "path": ".local/software/ruby/bin",
+ "description": "Ruby"
+ },
+ {
+ "path": ".local/bin",
+ "description": "the local bin directory"
+ },
+ {
+ "path": "Applications",
+ "description": "the AppImage directory"
+ },
+ {
+ "path": ".local/goblin",
+ "description": "the local gobin directory"
+ },
+ {
+ "path": ".local/scripts",
+ "description": "the directory of custom scripts"
+ }
+ ],
+ "xdgDirectories": {
+ "XDG_CACHE_HOME": "${HOME}/.local/cache",
+ "XDG_CONFIG_HOME": "${HOME}/.local/config",
+ "XDG_DATA_HOME": "${HOME}/.local/share",
+ "XDG_STATE_HOME": "${HOME}/.local/state"
+ },
+ "environmentVariables": {
+ "LOG_HOME": "${XDG_STATE_HOME}/logs",
+ "DOCKER_CONFIG": "${XDG_CONFIG_HOME}/docker",
+ "GPG_TTY": "$(tty)",
+ "GNUPGHOME": "${XDG_DATA_HOME}/gnupg",
+ "GOPATH": "${XDG_DATA_HOME}/go",
+ "GOROOT": "${HOME}/.local/software/go",
+ "GOBIN": "${HOME}/.local/goblin",
+ "GOOS": "linux",
+ "GOARCH": "amd64",
+ "CGO_ENABLED": "0",
+ "MAGEFILE_CACHE": "${XDG_CACHE_HOME}/magefile",
+ "MAGEFILE_ENABLE_COLOR": "true",
+ "HISTFILE": "${XDG_STATE_HOME}/bash/history",
+ "HISTCONTROL": "ignoreboth",
+ "HISTFILESIZE": "10000",
+ "HISTSIZE": "1000",
+ "HISTTIMEFORMAT": "%d/%m/%y %T: ",
+ "KUBECONFIG": "${XDG_CONFIG_HOME}/kube/config",
+ "LESSHISTFILE": "${XDG_STATE_HOME}/less/history",
+ "MINIKUBE_HOME": "${XDG_DATA_HOME}/minikube",
+ "BROWSER": "firefox",
+ "EDITOR": "nvim",
+ "TERMINAL": "st",
+ "LANG": "en_GB.UTF-8",
+ "MANPAGER": "nvim +Man!",
+ "PULUMI_SKIP_UPDATE_CHECK": "true",
+ "PULUMI_HOME": "${XDG_DATA_HOME}/pulumi",
+ "RAD_HOME": "${XDG_DATA_HOME}/radicle",
+ "TERMINFO": "${XDG_DATA_HOME}/terminfo",
+ "TERMINFO_DIRS": "${TERMINFO}:/usr/share/terminfo",
+ "VAGRANT_HOME": "${XDG_DATA_HOME}/vagrant"
+ },
+ "aliases": {
+ "ls": "ls --color=auto",
+ "ll": "ls -laF",
+ "la": "ls -A",
+ "l": "ls -CF",
+ "rm": "rm -i",
+ "mv": "mv -i",
+ "cp": "cp -i",
+ "grep": "grep --color=auto",
+ "fgrep": "fgrep --color=auto",
+ "egrep": "egrep --color=auto",
+ "systemctl": "sudo systemctl",
+ "journalctl": "sudo journalctl",
+ "pwgen": "pwgen -s -c -n",
+ "dc": "docker-compose",
+ "vim": "nvim",
+ "view": "nvim -R",
+ "vimdiff": "nvim -d",
+ "freeflow": "enbas --config-dir ${XDG_CONFIG_HOME}/enbas/free-flow",
+ "g": "git",
+ "k": "kubectl",
+ "pass": "PASSWORD_STORE_DIR=${XDG_DATA_HOME}/pass pass"
+ },
+ "commands": [
+ {
+ "command": "shopt -s histappend",
+ "description": "Append to the history file, don't overwrite it."
+ },
+ {
+ "command": "set -o vi",
+ "description": "Activate vi mode."
+ },
+ {
+ "command": ". /usr/share/bash-completion/bash_completion",
+ "description": "Ensure that programmable completion features are enabled."
+ },
+ {
+ "command": "source /usr/share/bash-completion/completions/git",
+ "description": "Enable bash completion for git"
+ },
+ {
+ "command": "complete -o bashdefault -o default -o nospace -F __git_wrap__git_main g",
+ "description": "Enable bash completion for the g alias"
+ },
+ {
+ "command": "source <(gopass completion bash)",
+ "description": "Enable bash completion for gopass"
+ },
+ {
+ "command": "eval \"$(SHELL=/bin/sh lesspipe)\"",
+ "description": "Make less more friendly for non-text input files"
+ }
+ ]
+ },
+ "directories": {
+ "useDefaultDirectories": true,
+ "includeXDGDirectories": true,
+ "additionalDirectories": [
+ ".local/goblin",
+ ".local/share/go",
+ ".local/software",
+ "Certificates",
+ "Docker",
+ "Installations",
+ "ISOs",
+ "Laboratory",
+ "Laboratory/Lab",
+ "Laboratory/Training",
+ "Notes",
+ "Projects"
+ ]
+ },
+ "git": {
+ "gpgSign": true,
+ "user": {
+ "email": "daangling@gmail.com",
+ "name": "Dan Anglin",
+ "signingKey": "0C1D44CFBEE68638"
+ }
+ },
+ "managedConfigurations": [
+ "alacritty",
+ "amfora",
+ "git",
+ "lf",
+ "logrotate",
+ "tmux",
+ "user-dirs.dirs",
+ "user-dirs.locale",
+ "zk"
+ ]
+}
diff --git a/hosts/sparrow.json b/hosts/sparrow.json
new file mode 100644
index 0000000..e7d7e99
--- /dev/null
+++ b/hosts/sparrow.json
@@ -0,0 +1,64 @@
+{
+ "bashProfile": {
+ "manage": true,
+ "filename": ".bash_profile",
+ "aliases": {},
+ "commands": [
+ {
+ "command": "shopt -s histappend",
+ "description": "Append to the history file, don't overwrite it."
+ },
+ {
+ "command": "set -o vi",
+ "description": "Activate vi mode."
+ }
+ ],
+ "environmentVariables": {},
+ "sessionPaths": [
+ {
+ "path": ".local/goblin",
+ "description": "the directory of go binaries"
+ },
+ {
+ "path": "Applications",
+ "description": "the AppImage directory"
+ }
+ ],
+ "xdgDirectories": {}
+ },
+ "directories": {
+ "useDefaultDirectories": true,
+ "includeXDGDirectories": true,
+ "additionalDirectories": [
+ ".local/bin",
+ ".local/data/gnupg",
+ ".local/data/go",
+ ".local/goblin",
+ ".local/opt",
+ ".local/state/bash",
+ ".local/state/less",
+ "Docker",
+ "Laboratory",
+ "Notes",
+ "Projects"
+ ]
+ },
+ "git": {
+ "gpgSign": false,
+ "user": {
+ "email": "daangling@gmail.com",
+ "name": "Dan Anglin",
+ "signingKey": ""
+ }
+ },
+ "managedConfigurations": [
+ "foot",
+ "git",
+ "lf",
+ "logrotate",
+ "river",
+ "tmux",
+ "user-dirs.dirs",
+ "user-dirs.locale"
+ ]
+}
diff --git a/magefiles/bash_profile.go b/magefiles/bash_profile.go
new file mode 100644
index 0000000..35c0fd9
--- /dev/null
+++ b/magefiles/bash_profile.go
@@ -0,0 +1,54 @@
+//go:build mage
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "text/template"
+)
+
+// BashProfile manages the user's Bash Profile using their configuration and the Bash Profile template.
+func BashProfile() error {
+ const (
+ bashProfileTemplateFile string = "bash/profile.gotmpl"
+ managedBashProfile string = "managed/bash_profile"
+ defaultFilename string = ".bash_profile"
+ )
+
+ homeDirectory, err := os.UserHomeDir()
+ if err != nil {
+ return fmt.Errorf("unable to get the user's home configuration directory: %w", err)
+ }
+
+ config, err := newConfig()
+ if err != nil {
+ return fmt.Errorf("unable to load the configuration: %w", err)
+ }
+
+ if !config.BashProfile.Manage {
+ return nil
+ }
+
+ funcMap := template.FuncMap{
+ "env": env,
+ }
+
+ if err := renderTemplate(config, bashProfileTemplateFile, managedBashProfile, funcMap); err != nil {
+ return fmt.Errorf("unable to generate the Bash Profile: %w", err)
+ }
+
+ filename := config.BashProfile.Filename
+ if filename == "" {
+ filename = defaultFilename
+ }
+
+ symlinkPath := filepath.Join(homeDirectory, filename)
+
+ if err := ensureSymlink(managedBashProfile, symlinkPath); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/magefiles/common.go b/magefiles/common.go
new file mode 100644
index 0000000..2490563
--- /dev/null
+++ b/magefiles/common.go
@@ -0,0 +1,132 @@
+//go:build mage
+
+package main
+
+import (
+ "errors"
+ "fmt"
+ "io/fs"
+ "os"
+ "path/filepath"
+ "slices"
+)
+
+const (
+ dirModePerm fs.FileMode = 0o700
+
+ configDir string = "hosts"
+ rootManagedDir string = "managed"
+ rootFilesDir string = "files"
+ rootTemplateDir string = "templates"
+)
+
+func ensureDirectory(path string) error {
+ info, err := os.Stat(path)
+ if err != nil {
+ if errors.Is(err, os.ErrNotExist) {
+ if err := os.Mkdir(path, dirModePerm); err != nil {
+ return fmt.Errorf("unable to create the directory: %w", err)
+ }
+
+ return nil
+ }
+
+ return fmt.Errorf(
+ "received an unexpected error after attempting to get the directory information: %w",
+ err,
+ )
+ }
+
+ if !info.IsDir() {
+ return errors.New("the path exists but it is not a directory")
+ }
+
+ if info.Mode().Perm() != dirModePerm {
+ if err := os.Chmod(path, dirModePerm); err != nil {
+ return fmt.Errorf("unable to update the directory's mode to %d: %w", dirModePerm, err)
+ }
+ }
+
+ return nil
+}
+
+func ensureSymlink(source, dest string) error {
+ absolutePathErrorMessageFormat := "unable to get the absolute path to %s: %w"
+
+ absoluteSourcePath, err := filepath.Abs(source)
+ if err != nil {
+ return fmt.Errorf(absolutePathErrorMessageFormat, source, err)
+ }
+
+ absoluteDestPath, err := filepath.Abs(dest)
+ if err != nil {
+ return fmt.Errorf(absolutePathErrorMessageFormat, dest, err)
+ }
+
+ destInfo, err := os.Lstat(absoluteDestPath)
+ if err != nil {
+ if errors.Is(err, os.ErrNotExist) {
+ fmt.Printf("Linking %s to %s\n", absoluteDestPath, absoluteSourcePath)
+
+ if err := os.Symlink(absoluteSourcePath, absoluteDestPath); err != nil {
+ return fmt.Errorf(
+ "unable to symlink %s to %s: %w",
+ absoluteDestPath,
+ absoluteSourcePath,
+ err,
+ )
+ }
+
+ return nil
+ }
+
+ return fmt.Errorf("unable to get the file info for %s: %w", absoluteDestPath, err)
+ }
+
+ if destInfo.Mode().Type() != fs.ModeSymlink {
+ return fmt.Errorf("the path %s exists but it is not a symlink", absoluteDestPath)
+ }
+
+ destLinksTo, err := filepath.EvalSymlinks(absoluteDestPath)
+ if err != nil {
+ return fmt.Errorf("unable to evaluate the symlink %s: %w", absoluteDestPath, err)
+ }
+
+ if destLinksTo == absoluteSourcePath {
+ return nil
+ }
+
+ fmt.Printf(
+ "%s should link back to %s but instead links back to %s\n",
+ absoluteDestPath,
+ absoluteSourcePath,
+ destLinksTo,
+ )
+
+ fmt.Println("Recreating:", absoluteDestPath)
+
+ if err := os.Remove(absoluteDestPath); err != nil {
+ return fmt.Errorf("unable to remove %s: %w", absoluteDestPath, err)
+ }
+
+ if err := os.Symlink(absoluteSourcePath, absoluteDestPath); err != nil {
+ return fmt.Errorf(
+ "unable to symlink %s to %s: %w",
+ absoluteDestPath,
+ absoluteSourcePath,
+ err,
+ )
+ }
+
+ return nil
+}
+
+func managedConfigSet(applicationConfigurationList []string) map[string]struct{} {
+ set := make(map[string]struct{})
+
+ for _, app := range slices.All(applicationConfigurationList) {
+ set[app] = struct{}{}
+ }
+
+ return set
+}
diff --git a/magefiles/config.go b/magefiles/config.go
new file mode 100644
index 0000000..f974bf2
--- /dev/null
+++ b/magefiles/config.go
@@ -0,0 +1,112 @@
+//go:build mage
+
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+type config struct {
+ ManagedConfigurations []string `json:"managedConfigurations"`
+ BashProfile configBashProfile `json:"bashProfile"`
+ Directories configDirectories `json:"directories"`
+ Git configGit `json:"git"`
+}
+
+type configDirectories struct {
+ UseDefaultDirectories bool `json:"useDefaultDirectories"`
+ IncludeXDGDirectories bool `json:"includeXDGDirectories"`
+ AdditionalDirectories []string `json:"additionalDirectories"`
+}
+
+type configGit struct {
+ GpgSign bool `json:"gpgSign"`
+ User configGitUser `json:"user"`
+}
+
+type configGitUser struct {
+ Email string `json:"email"`
+ Name string `json:"name"`
+ SigningKey string `json:"signingKey"`
+}
+
+type configBashProfile struct {
+ Manage bool `json:"manage"`
+ Filename string `json:"filename"`
+ SessionPaths []configBashProfileSessionPath `json:"sessionPaths"`
+ XdgDirectories map[string]string `json:"xdgDirectories"`
+ EnvironmentVariables map[string]string `json:"environmentVariables"`
+ Aliases map[string]string `json:"aliases"`
+ Commands []configBashProfileCommand `json:"commands"`
+}
+
+type configBashProfileSessionPath struct {
+ Path string `json:"path"`
+ Description string `json:"description"`
+}
+
+type configBashProfileCommand struct {
+ Command string `json:"command"`
+ Description string `json:"description"`
+}
+
+func newConfig() (config, error) {
+ cfg := defaultConfig()
+
+ path, err := configFilePath()
+ if err != nil {
+ return config{}, fmt.Errorf("unable to calculate the config file path: %w", err)
+ }
+
+ file, err := os.Open(path)
+ if err != nil {
+ return config{}, fmt.Errorf("unable to open the file: %w", err)
+ }
+ defer file.Close()
+
+ if err = json.NewDecoder(file).Decode(&cfg); err != nil {
+ return config{}, fmt.Errorf("unable to decode the JSON file: %w", err)
+ }
+
+ return cfg, nil
+}
+
+func configFilePath() (string, error) {
+ hostname, err := os.Hostname()
+ if err != nil {
+ return "", fmt.Errorf("unable to get the machine's hostname: %w", err)
+ }
+
+ hostnameParts := strings.SplitN(hostname, "-", 3)
+
+ if len(hostnameParts) != 3 {
+ return "", fmt.Errorf("unexpected hostname format")
+ }
+
+ identifier := hostnameParts[1]
+
+ return filepath.Join(configDir, identifier+".json"), nil
+}
+
+func defaultConfig() config {
+ return config{
+ Directories: configDirectories{
+ UseDefaultDirectories: true,
+ IncludeXDGDirectories: true,
+ AdditionalDirectories: []string{},
+ },
+ Git: configGit{
+ GpgSign: false,
+ User: configGitUser{
+ Email: "",
+ Name: "",
+ SigningKey: "",
+ },
+ },
+ ManagedConfigurations: []string{},
+ }
+}
diff --git a/magefiles/directories.go b/magefiles/directories.go
new file mode 100644
index 0000000..229e8e6
--- /dev/null
+++ b/magefiles/directories.go
@@ -0,0 +1,96 @@
+//go:build mage
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "slices"
+)
+
+// Directories ensure that the specified home directories are present.
+func Directories() error {
+ config, err := newConfig()
+ if err != nil {
+ return fmt.Errorf("unable to load the configuration: %w", err)
+ }
+
+ userHome, err := os.UserHomeDir()
+ if err != nil {
+ return fmt.Errorf("unable to get the user's home directory: %w", err)
+ }
+
+ directories := make([]string, 0)
+
+ if config.Directories.UseDefaultDirectories{
+ defaultHomeDirs := homeDirectories(userHome, defaultDirectories())
+ directories = append(directories, defaultHomeDirs...)
+ }
+
+ if config.Directories.IncludeXDGDirectories{
+ directories = append(directories, xdgDirectories()...)
+ }
+
+ if len(config.Directories.AdditionalDirectories) != 0 {
+ additionalHomeDirs := homeDirectories(userHome, config.Directories.AdditionalDirectories)
+ directories = append(directories, additionalHomeDirs...)
+ }
+
+ for _, dir := range slices.All(directories) {
+ if err := ensureDirectory(dir); err != nil {
+ return fmt.Errorf("unable to ensure that %s is present: %w", dir, err)
+ }
+
+ fmt.Printf("Successfully ensured %s is present.\n", dir)
+ }
+
+ return nil
+}
+
+func defaultDirectories() []string {
+ return []string{
+ ".local",
+ ".local/bin",
+ "Applications",
+ "Desktop",
+ "Documents",
+ "Downloads",
+ "Games",
+ "Git",
+ "Music",
+ "Pictures",
+ "Templates",
+ "Videos",
+ }
+}
+
+func homeDirectories(userHome string, directories []string) []string{
+ absolutePaths := make([]string, len(directories))
+
+ for ind := range slices.All(directories) {
+ absolutePaths[ind] = filepath.Join(userHome, directories[ind])
+ }
+
+ return absolutePaths
+}
+
+func xdgDirectories() []string {
+ xdgEnvVars := []string{
+ "XDG_DATA_HOME",
+ "XDG_CONFIG_HOME",
+ "XDG_CACHE_HOME",
+ "XDG_STATE_HOME",
+ }
+
+ directories := make([]string, 0)
+
+ for _, envVar := range slices.All(xdgEnvVars) {
+ directory := os.Getenv(envVar)
+ if directory != "" {
+ directories = append(directories, directory)
+ }
+ }
+
+ return directories
+}
diff --git a/magefiles/files.go b/magefiles/files.go
new file mode 100644
index 0000000..26b61f2
--- /dev/null
+++ b/magefiles/files.go
@@ -0,0 +1,84 @@
+//go:build mage
+
+package main
+
+import (
+ "fmt"
+ "io/fs"
+ "os"
+ "path/filepath"
+ "slices"
+ "strings"
+
+ "github.com/magefile/mage/sh"
+)
+
+// Files ensure that the configuration files in the managed directory is up to date and
+// ensures that they are symlinked correctly to the files in the user's home configuration
+// directory.
+func Files() error {
+ homeConfigDirectory, err := os.UserConfigDir()
+ if err != nil {
+ return fmt.Errorf("unable to get the user's home configuration directory: %w", err)
+ }
+
+ config, err := newConfig()
+ if err != nil {
+ return fmt.Errorf("unable to load the configuration: %w", err)
+ }
+
+ managedConfig := managedConfigSet(config.ManagedConfigurations)
+
+ if err = filepath.WalkDir(rootFilesDir, manageFilesFunc(homeConfigDirectory, managedConfig)); err != nil {
+ return fmt.Errorf("received an error while processing the files: %w", err)
+ }
+
+ return nil
+}
+
+func manageFilesFunc(homeConfigDirectory string, managedConfig map[string]struct{}) fs.WalkDirFunc {
+ return func(path string, d fs.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+
+ if path == rootFilesDir {
+ return nil
+ }
+
+ relativePath := strings.TrimPrefix(path, rootFilesDir+"/")
+
+ appConfigName := strings.SplitN(relativePath, "/", 2)[0]
+
+ if _, exists := managedConfig[appConfigName]; !exists {
+ return nil
+ }
+
+ managedPath := filepath.Join(rootManagedDir, relativePath)
+ configPath := filepath.Join(homeConfigDirectory, relativePath)
+
+ if d.IsDir() {
+ dirs := []string{managedPath, configPath}
+
+ for _, dir := range slices.All(dirs) {
+ if err := ensureDirectory(dir); err != nil {
+ return fmt.Errorf("unable to ensure the existence of the directory %q: %w", dir, err)
+ }
+ }
+
+ return nil
+ }
+
+ fmt.Println("Processing file:", relativePath)
+
+ if err := sh.Copy(managedPath, path); err != nil {
+ return fmt.Errorf("unable to copy %s to %s: %w", path, managedPath, err)
+ }
+
+ if err := ensureSymlink(managedPath, configPath); err != nil {
+ return err
+ }
+
+ return nil
+ }
+}
diff --git a/magefiles/go.mod b/magefiles/go.mod
new file mode 100644
index 0000000..93056e3
--- /dev/null
+++ b/magefiles/go.mod
@@ -0,0 +1,5 @@
+module codeflow.dananglin.me.uk/linux-home/manager/magefiles
+
+go 1.23.1
+
+require github.com/magefile/mage v1.15.0
diff --git a/magefiles/go.sum b/magefiles/go.sum
new file mode 100644
index 0000000..4ee1b87
--- /dev/null
+++ b/magefiles/go.sum
@@ -0,0 +1,2 @@
+github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
+github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
diff --git a/magefiles/main.go b/magefiles/main.go
new file mode 100644
index 0000000..8883df9
--- /dev/null
+++ b/magefiles/main.go
@@ -0,0 +1,13 @@
+//go:build ignore
+
+package main
+
+import (
+ "os"
+
+ "github.com/magefile/mage/mage"
+)
+
+func main() {
+ os.Exit(mage.Main())
+}
diff --git a/magefiles/manage.go b/magefiles/manage.go
new file mode 100644
index 0000000..27ee376
--- /dev/null
+++ b/magefiles/manage.go
@@ -0,0 +1,14 @@
+//go:build mage
+
+package main
+
+import "github.com/magefile/mage/mg"
+
+var Default = Manage
+
+// Manage runs all the management tasks.
+func Manage() error {
+ mg.Deps(Directories, Files, Templates)
+
+ return nil
+}
diff --git a/magefiles/templates.go b/magefiles/templates.go
new file mode 100644
index 0000000..6f1ec15
--- /dev/null
+++ b/magefiles/templates.go
@@ -0,0 +1,130 @@
+//go:build mage
+
+package main
+
+import (
+ "fmt"
+ "io/fs"
+ "os"
+ "path/filepath"
+ "slices"
+ "strings"
+ "text/template"
+)
+
+const templateExtension string = ".gotmpl"
+
+// Templates generates the configuration files in the managed directory from the templates and
+// ensures that they the generated files are symlinked correctly to the files in the user's home
+// configuration directory.
+func Templates() error {
+ homeConfigDirectory, err := os.UserConfigDir()
+ if err != nil {
+ return fmt.Errorf("unable to get the user's home configuration directory: %w", err)
+ }
+
+ config, err := newConfig()
+ if err != nil {
+ return fmt.Errorf("unable to load the configuration: %w", err)
+ }
+
+ managedConfig := managedConfigSet(config.ManagedConfigurations)
+
+ if err = filepath.WalkDir(rootTemplateDir, manageTemplatesFunc(homeConfigDirectory, config, managedConfig)); err != nil {
+ return fmt.Errorf("received an error while processing the templates: %w", err)
+ }
+
+ return nil
+}
+
+func manageTemplatesFunc(homeConfigDirectory string, config config, managedConfig map[string]struct{}) fs.WalkDirFunc {
+ funcMap := template.FuncMap{
+ "env": env,
+ }
+
+ return func(templatePath string, d fs.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+
+ if templatePath == rootTemplateDir {
+ return nil
+ }
+
+ relativePath := strings.TrimPrefix(templatePath, rootTemplateDir+"/")
+
+ appConfigName := strings.SplitN(relativePath, "/", 2)[0]
+
+ if _, exists := managedConfig[appConfigName]; !exists {
+ return nil
+ }
+
+ if d.IsDir() {
+ managedDir := filepath.Join(rootManagedDir, relativePath)
+ configDir := filepath.Join(homeConfigDirectory, relativePath)
+
+ dirs := []string{managedDir, configDir}
+
+ for _, dir := range slices.All(dirs) {
+ if err := ensureDirectory(dir); err != nil {
+ return fmt.Errorf("unable to ensure the existence of the directory %q: %w", dir, err)
+ }
+ }
+
+ return nil
+ }
+
+ if !strings.HasSuffix(templatePath, templateExtension) {
+ return fmt.Errorf(
+ "the template %s does not have the %q file extension",
+ templatePath,
+ templateExtension,
+ )
+ }
+
+ managedPath := filepath.Join(rootManagedDir, strings.TrimSuffix(relativePath, templateExtension))
+ configPath := filepath.Join(homeConfigDirectory, strings.TrimSuffix(relativePath, templateExtension))
+
+ fmt.Println("Processing template:", relativePath)
+
+ if err := renderTemplate(config, templatePath, managedPath, funcMap); err != nil {
+ return fmt.Errorf(
+ "unable to generate %s from template %s: %w",
+ managedPath,
+ templatePath,
+ err,
+ )
+ }
+
+ if err := ensureSymlink(managedPath, configPath); err != nil {
+ return err
+ }
+
+ return nil
+ }
+}
+
+func renderTemplate(config config, templatePath, managedPath string, funcMap template.FuncMap) error {
+ name := filepath.Base(templatePath)
+
+ tmpl, err := template.New(name).Funcs(funcMap).ParseFiles(templatePath)
+ if err != nil {
+ return fmt.Errorf("unable to create a new template value from %s: %w", templatePath, err)
+ }
+
+ output, err := os.Create(managedPath)
+ if err != nil {
+ return fmt.Errorf("unable to create %s: %w", managedPath, err)
+ }
+ defer output.Close()
+
+ if err := tmpl.Execute(output, config); err != nil {
+ return fmt.Errorf("unable to render the template to %s: %w", managedPath, err)
+ }
+
+ return nil
+}
+
+func env(value string) string {
+ return os.Getenv(value)
+}
diff --git a/managed/.gitkeep b/managed/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/config/git/gitconfig b/templates/git/config.gotmpl
similarity index 52%
rename from config/git/gitconfig
rename to templates/git/config.gotmpl
index 4ea6e79..5ede20e 100644
--- a/config/git/gitconfig
+++ b/templates/git/config.gotmpl
@@ -1,36 +1,41 @@
[alias]
br = branch
cm = commit
- co = checkout
df = diff
gr = log --all --graph --decorate --format=format:'%C(bold "#62ccff")%h%C(reset) %C(bold "#fa9c43")(%ai)%C(reset) %C(auto)%d%C(reset)%n%C(italic "#929292")%an:%C(reset) %C("#ffffff")%s%C(reset)%n'
- # mr allows you to checkout a merge request locally.
- # $1 is the name of the remote
- # $2 is the ID of the merge request
- # e.g. git mr origin 3
- # e.g. git mr upstream 5
- mr = !sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' -
pl = pull
ps = push
sr = reset --soft
st = status
up = !sh -c 'git checkout $(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@') && git fetch --all && git pull origin $(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')'
+ sw = switch
+ rb = rebase
+ fh = !sh -c 'git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main'
[commit]
- gpgsign = true
- template = $gitmessage_output
+ gpgsign = {{ .Git.GpgSign }}
+ template = {{ env "XDG_CONFIG_HOME" | printf "%s/git/message" }}
[core]
- excludesFile = $gitignore_output
+ excludesFile = {{ env "XDG_CONFIG_HOME" | printf "%s/git/ignore" }}
[diff]
tool = vimdiff
[fetch]
prune = true
[gpg]
- program = gpg2
+ program = gpg
[pull]
rebase = false
[user]
- email = $git_user_email
- name = $git_user_name
- signingkey = $git_user_signingkey
+ email = {{ .Git.User.Email }}
+ name = {{ .Git.User.Name }}
+ {{- if .Git.GpgSign -}}
+ {{ print "" }}
+ signingkey = {{ .Git.User.SigningKey }}
+ {{- end -}}
+{{ print "" }}
[init]
defaultBranch = main
+[filter "lfs"]
+ required = true
+ clean = git-lfs clean -- %f
+ smudge = git-lfs smudge -- %f
+ process = git-lfs filter-process
diff --git a/templates/logrotate/logrotate.conf.gotmpl b/templates/logrotate/logrotate.conf.gotmpl
new file mode 100644
index 0000000..604e9c1
--- /dev/null
+++ b/templates/logrotate/logrotate.conf.gotmpl
@@ -0,0 +1,15 @@
+{{ env "LOG_HOME" | printf "%s/*.log" }} {
+ rotate 3
+ size 3M
+ nocompress
+ notifempty
+ copytruncate
+}
+
+{{ env "XDG_STATE_HOME" | printf "%s/nvim/log" }} {{ env "XDG_STATE_HOME" | printf "%s/nvim/*.log" }} {
+ rotate 3
+ size 10M
+ nocompress
+ notifempty
+ copytruncate
+}