From 2402833b1a1f6a4e36509f1c6a33214c3140f025 Mon Sep 17 00:00:00 2001 From: Dan Anglin Date: Thu, 12 Sep 2024 16:35:06 +0100 Subject: [PATCH] feat: a new home manager This commit updates the scope of this project to manage the files and directories within my home directory. The Makefile and helper bash scripts are now replaced with mage targets so that the home directory is now managed with Mage. The state of the home directory is managed using a JSON configuration for each machine host. The manager is a set of mage targets to manage various aspects of the home directory. At the moment the manager can: - ensure specified directories are present within the home directory. - ensure application configuration files are up-to-date and have the correct symlinks within the user's home configuration directory. - manages the user's bash profile (a.k.a bashrc) file. Other notable changes: - The X11 xinitrc is removed because it is not currently used and won't be used for the forseeable future as we slowly move to Wayland. - All bashrc configurations are now defined in one file and is now fully managed by the manager. - The dunst configuration is currently removed but will make a comeback. - The ansible configuration is removed as it is no longer used. - The logrotate configuration is updated and now generated from a template. - Added configuration for the foot terminal. - Added configuration for the River window manager. --- .gitignore | 5 +- .helpers/X11/generate-x11-config | 14 - .helpers/amfora/generate-amfora-config | 15 - .helpers/ansible/generate-ansible-config | 21 - .helpers/bash/generate-bash-config | 31 -- .helpers/dunst/generate-dunst-config | 14 - .helpers/git/generate-git-config | 63 --- .helpers/lf/generate-lf-config | 14 - .helpers/lib/install-config | 8 - .helpers/logrotate/generate-logrotate-config | 15 - .helpers/scripts/install-scripts | 15 - .helpers/tmux/generate-tmux-config | 14 - .helpers/vim/generate-vim-config | 37 -- .helpers/xdg/check-xdg-settings | 23 - .helpers/xdg/generate-user-dirs-config | 11 - Makefile | 46 -- bash/profile.gotmpl | 58 +++ config/X11/xinitrc | 20 - config/ansible/ansible.cfg | 10 - config/ansible/hosts.yml | 5 - config/bash/bash_profile | 5 - config/bash/bashrc | 27 -- config/bash/bashrc.d/X11 | 4 - config/bash/bashrc.d/aliases | 31 -- config/bash/bashrc.d/ansible | 7 - config/bash/bashrc.d/docker | 3 - config/bash/bashrc.d/exercism | 8 - config/bash/bashrc.d/functions | 29 -- config/bash/bashrc.d/git | 10 - config/bash/bashrc.d/gnupg | 4 - config/bash/bashrc.d/go | 30 -- config/bash/bashrc.d/history | 21 - config/bash/bashrc.d/kubectl | 9 - config/bash/bashrc.d/less | 3 - config/bash/bashrc.d/lf | 18 - config/bash/bashrc.d/local_software | 12 - config/bash/bashrc.d/minikube | 3 - config/bash/bashrc.d/misc | 21 - config/bash/bashrc.d/pass | 9 - config/bash/bashrc.d/prompt | 32 -- config/bash/bashrc.d/pulumi | 6 - config/bash/bashrc.d/terminfo | 4 - config/bash/bashrc.d/vagrant | 3 - config/bash/bashrc.d/vault | 8 - config/dunst/dunstrc | 438 ------------------ config/logrotate/logrotate.conf | 7 - {config => files}/alacritty/alacritty.toml | 0 {config => files}/amfora/config.toml | 95 ++-- files/foot/foot.ini | 239 ++++++++++ config/git/gitignore => files/git/ignore | 6 +- config/git/gitmessage => files/git/message | 0 {config => files}/lf/lfrc | 0 files/river/init | 77 +++ {config => files}/tmux/tmux.conf | 4 +- {config/xdg => files}/user-dirs.dirs | 0 {config/xdg => files}/user-dirs.locale | 0 files/zk/config.toml | 11 + hosts/falcon.json | 197 ++++++++ hosts/sparrow.json | 64 +++ magefiles/bash_profile.go | 54 +++ magefiles/common.go | 132 ++++++ magefiles/config.go | 112 +++++ magefiles/directories.go | 96 ++++ magefiles/files.go | 84 ++++ magefiles/go.mod | 5 + magefiles/go.sum | 2 + magefiles/main.go | 13 + magefiles/manage.go | 14 + magefiles/templates.go | 130 ++++++ managed/.gitkeep | 0 .../gitconfig => templates/git/config.gotmpl | 33 +- templates/logrotate/logrotate.conf.gotmpl | 15 + 72 files changed, 1374 insertions(+), 1200 deletions(-) delete mode 100755 .helpers/X11/generate-x11-config delete mode 100755 .helpers/amfora/generate-amfora-config delete mode 100755 .helpers/ansible/generate-ansible-config delete mode 100755 .helpers/bash/generate-bash-config delete mode 100755 .helpers/dunst/generate-dunst-config delete mode 100755 .helpers/git/generate-git-config delete mode 100755 .helpers/lf/generate-lf-config delete mode 100755 .helpers/lib/install-config delete mode 100755 .helpers/logrotate/generate-logrotate-config delete mode 100755 .helpers/scripts/install-scripts delete mode 100755 .helpers/tmux/generate-tmux-config delete mode 100755 .helpers/vim/generate-vim-config delete mode 100755 .helpers/xdg/check-xdg-settings delete mode 100755 .helpers/xdg/generate-user-dirs-config delete mode 100644 Makefile create mode 100644 bash/profile.gotmpl delete mode 100644 config/X11/xinitrc delete mode 100644 config/ansible/ansible.cfg delete mode 100644 config/ansible/hosts.yml delete mode 100644 config/bash/bash_profile delete mode 100644 config/bash/bashrc delete mode 100644 config/bash/bashrc.d/X11 delete mode 100644 config/bash/bashrc.d/aliases delete mode 100644 config/bash/bashrc.d/ansible delete mode 100644 config/bash/bashrc.d/docker delete mode 100644 config/bash/bashrc.d/exercism delete mode 100644 config/bash/bashrc.d/functions delete mode 100644 config/bash/bashrc.d/git delete mode 100644 config/bash/bashrc.d/gnupg delete mode 100644 config/bash/bashrc.d/go delete mode 100644 config/bash/bashrc.d/history delete mode 100644 config/bash/bashrc.d/kubectl delete mode 100644 config/bash/bashrc.d/less delete mode 100644 config/bash/bashrc.d/lf delete mode 100644 config/bash/bashrc.d/local_software delete mode 100644 config/bash/bashrc.d/minikube delete mode 100644 config/bash/bashrc.d/misc delete mode 100644 config/bash/bashrc.d/pass delete mode 100644 config/bash/bashrc.d/prompt delete mode 100644 config/bash/bashrc.d/pulumi delete mode 100644 config/bash/bashrc.d/terminfo delete mode 100644 config/bash/bashrc.d/vagrant delete mode 100644 config/bash/bashrc.d/vault delete mode 100644 config/dunst/dunstrc delete mode 100644 config/logrotate/logrotate.conf rename {config => files}/alacritty/alacritty.toml (100%) rename {config => files}/amfora/config.toml (86%) create mode 100644 files/foot/foot.ini rename config/git/gitignore => files/git/ignore (57%) rename config/git/gitmessage => files/git/message (100%) rename {config => files}/lf/lfrc (100%) create mode 100755 files/river/init rename {config => files}/tmux/tmux.conf (89%) rename {config/xdg => files}/user-dirs.dirs (100%) rename {config/xdg => files}/user-dirs.locale (100%) create mode 100644 files/zk/config.toml create mode 100644 hosts/falcon.json create mode 100644 hosts/sparrow.json create mode 100644 magefiles/bash_profile.go create mode 100644 magefiles/common.go create mode 100644 magefiles/config.go create mode 100644 magefiles/directories.go create mode 100644 magefiles/files.go create mode 100644 magefiles/go.mod create mode 100644 magefiles/go.sum create mode 100644 magefiles/main.go create mode 100644 magefiles/manage.go create mode 100644 magefiles/templates.go create mode 100644 managed/.gitkeep rename config/git/gitconfig => templates/git/config.gotmpl (52%) create mode 100644 templates/logrotate/logrotate.conf.gotmpl 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 +}