From 1f2ca90ca542064b133b46951c5c7a23974c5249 Mon Sep 17 00:00:00 2001 From: Ismo Vuorinen Date: Tue, 23 Jul 2024 03:43:12 +0300 Subject: [PATCH] feat!: refactor base, config, dfm and scripts --- base/bashrc | 6 +- base/zshenv | 17 +- base/zshrc | 163 +++++---- config/alias | 63 ---- config/exports | 457 +++++++++++++++++++++++-- config/exports-apps | 150 -------- config/exports-lakka | 14 +- config/exports-shell | 40 --- config/functions | 3 - config/shared.sh | 99 +++++- local/bin/dfm | 108 +++++- local/bin/x-load-configs | 115 ++++--- local/bin/x-path-append | 64 +++- local/bin/x-path-prepend | 48 ++- local/bin/x-path-remove | 44 ++- scripts/create-nvim-keymaps.sh | 30 +- scripts/create-omp-screenshot.sh | 21 +- scripts/install-asdf.sh | 54 +-- scripts/install-cargo-packages.sh | 61 ++-- scripts/install-cheat-purebashbible.sh | 109 +++--- scripts/install-composer.sh | 7 +- scripts/install-fonts.sh | 60 +++- scripts/install-fzf.sh | 24 +- scripts/install-gh-extensions.sh | 42 ++- scripts/install-git-crypt.sh | 11 +- scripts/install-go-packages.sh | 67 ++-- scripts/install-neofetch.sh | 56 ++- scripts/install-npm-packages.sh | 71 ++-- scripts/install-ntfy.sh | 50 ++- scripts/install-ohmybash.sh | 35 +- scripts/install-ohmyposh.sh | 28 +- scripts/install-pip-packages.sh | 36 +- scripts/install-xcode-cli-tools.sh | 65 ++-- scripts/install-z.sh | 28 +- scripts/set-macos-defaults.sh | 28 +- scripts/shared.sh | 166 +-------- 36 files changed, 1543 insertions(+), 897 deletions(-) delete mode 100755 config/exports-apps delete mode 100755 config/exports-shell delete mode 100755 config/functions diff --git a/base/bashrc b/base/bashrc index 550a600..355ef4a 100644 --- a/base/bashrc +++ b/base/bashrc @@ -1,9 +1,11 @@ # this is my bashrc config. there are many like it, but this one is mine. # shellcheck shell=bash -source "$HOME/.dotfiles/config/shared.sh" +export DOTFILES="$HOME/.dotfiles" +export PATH="$HOME/.local/bin:$DOTFILES/local/bin:$PATH" +export SHARED_SCRIPTS_SOURCED=0 -x-load-configs +source "$DOTFILES/config/shared.sh" # shellcheck source=../config/fzf/fzf.bash [ -f "${DOTFILES}/config/fzf/fzf.bash" ] && diff --git a/base/zshenv b/base/zshenv index 891367d..395a99b 100644 --- a/base/zshenv +++ b/base/zshenv @@ -1,19 +1,8 @@ # shellcheck shell=bash # vim: filetype=zsh -export PATH="$HOME/.local/bin:$HOME/.dotfiles/local/bin:$HOME/.local/go/bin:$PATH" - export DOTFILES="$HOME/.dotfiles" +export PATH="$HOME/.local/bin:$DOTFILES/local/bin:$PATH" +export SHARED_SCRIPTS_SOURCED=0 -# Explicitly set XDG folders -# https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html -export XDG_CONFIG_HOME="$HOME/.config" -export XDG_DATA_HOME="$HOME/.local/share" -export XDG_STATE_HOME="$HOME/.local/state" - -# custom variables -export XDG_BIN_HOME="$HOME/.local/bin" -export XDG_CACHE_HOME="$HOME/.cache" -export XDG_RUNTIME_DIR="$HOME/.local/run" - -eval "$DOTFILES/config/shared.sh" +source "$DOTFILES/config/shared.sh" diff --git a/base/zshrc b/base/zshrc index 033c65d..fbf9e94 100755 --- a/base/zshrc +++ b/base/zshrc @@ -1,87 +1,122 @@ # this is my zsh config. there are many like it, but this one is mine. # shellcheck shell=bash -eval "$HOME/.dotfiles/config/shared.sh" +# export VERBOSE=1 +# export DEBUG=1 + +x-path-prepend "/usr/local/bin" +x-path-prepend "/opt/homebrew/bin" +x-path-prepend "$HOME/.local/share/cargo/bin" +x-path-prepend "$HOME/.local/share/bob/nvim-bin" +x-path-prepend "$HOME/.local/bin" +x-path-prepend "$DOTFILES/local/bin" + x-load-configs -export PATH="$XDG_BIN_HOME:$DOTFILES/local/bin:$HOME/.local/go/bin:$XDG_DATA_HOME/bob/nvim-bin:$XDG_DATA_HOME/cargo/bin:/opt/homebrew/bin:/usr/local/bin:$PATH" +eval "$(oh-my-posh init zsh --config "$DOTFILES/config/omp/own.toml")" -x-have oh-my-posh && { - eval "$(oh-my-posh init zsh --config "$DOTFILES/config/omp/own.toml")" -} - -export COMPLETION_WAITING_DOTS=true - -if type brew &> /dev/null; then - eval "$(brew shellenv)" - FPATH="$HOMEBREW_PREFIX/share/zsh/site-functions:${FPATH}" +# Load asdf +export ASDF_DIR="$XDG_BIN_HOME/asdf" +if [[ -d $ASDF_DIR ]]; then + [[ -d $ASDF_DIR/bin ]] && x-path-prepend "$ASDF_DIR/bin" + [[ -d $ASDF_DIR/shims ]] && x-path-prepend "$ASDF_DIR/shims" + [[ -d $ASDF_DIR/completions ]] && fpath=("$ASDF_DIR/completions" $fpath) + [[ -d $ASDF_DIR/plugins ]] && fpath=("$ASDF_DIR/plugins" $fpath) + source "$ASDF_DIR/asdf.sh" fi -export ZSH_CUSTOM_COMPLETION_PATH="$XDG_CONFIG_HOME/zsh/completion" -x-dc "$ZSH_CUSTOM_COMPLETION_PATH" +# Function to load antigen if available +load_antigen() +{ + local antigen_zsh_path="$XDG_BIN_HOME/antigen.zsh" + # shellcheck source=../../.local/bin/antigen.zsh + if [[ -f "$antigen_zsh_path" ]]; then + source "$antigen_zsh_path" -# Add completion scripts to zsh path -FPATH="$ZSH_CUSTOM_COMPLETION_PATH:$FPATH" + antigen use oh-my-zsh -# Try to load antigen, if present -ANTIGEN_ZSH_PATH="$XDG_BIN_HOME/antigen.zsh" -# shellcheck source=../../.local/bin/antigen.zsh -[[ -f "$ANTIGEN_ZSH_PATH" ]] && source "$ANTIGEN_ZSH_PATH" + export ZSH_TMUX_AUTOSTART=true + export ZSH_TMUX_CONFIG="$DOTFILES/config/tmux/tmux.conf" + export ZSH_TMUX_UNICODE=true + export ZSH_TMUX_AUTOQUIT=false + export ZSH_TMUX_DEFAULT_SESSION_NAME=main -# antigen is present -antigen use oh-my-zsh + # z, the zsh version + export ZSHZ_DATA="$XDG_STATE_HOME/z" + antigen bundle z -export ZSH_TMUX_AUTOSTART=true -export ZSH_TMUX_CONFIG="$DOTFILES/config/tmux/tmux.conf" -export ZSH_TMUX_UNICODE=true -export ZSH_TMUX_AUTOQUIT=false -export ZSH_TMUX_DEFAULT_SESSION_NAME=main + # these should be always available + antigen bundle brew + antigen bundle tmux + antigen bundle colored-man-pages + antigen bundle ssh-agent + antigen bundle jreese/zsh-titles + antigen bundle zsh-users/zsh-completions -# z, the zsh version -export ZSHZ_DATA="$XDG_STATE_HOME/z" -antigen bundle z + x-have python && antigen bundle MichaelAquilina/zsh-autoswitch-virtualenv -# these should be always available -antigen bundle tmux -antigen bundle colored-man-pages -antigen bundle ssh-agent -antigen bundle jreese/zsh-titles -antigen bundle zsh-users/zsh-completions - -x-have python && antigen bundle MichaelAquilina/zsh-autoswitch-virtualenv - -# this needs to be the last item -antigen bundle zsh-users/zsh-syntax-highlighting -antigen apply - -# shellcheck source=../config/fzf/fzf.zsh -[ -f "${DOTFILES}/config/fzf/fzf.zsh" ] \ - && source "${DOTFILES}/config/fzf/fzf.zsh" - -x-have pyenv && { - [[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH" - eval "$(pyenv init -)" - eval "$(pyenv virtualenv-init -)" + # this needs to be the last item + antigen bundle zsh-users/zsh-syntax-highlighting + antigen apply + fi } -# Run only if tmux is active -[[ -n "$TMUX" ]] && { - # Autoupdate tmux window name - TMUX_WINDOW_NAME_PLUGIN="$DOTFILES/config/tmux/plugins/tmux-window-name/scripts/rename_session_windows.py" - [ -f "$TMUX_WINDOW_NAME_PLUGIN" ] && { - tmux_window_name() - { - ($TMUX_WINDOW_NAME_PLUGIN &) - } - add-zsh-hook chpwd tmux_window_name - tmux_window_name - } +# Function to source FZF configuration +source_fzf_config() +{ + local fzf_config="${DOTFILES}/config/fzf/fzf.zsh" + if [[ -f "$fzf_config" ]]; then + # shellcheck source=config/fzf/fzf.zsh + source "$fzf_config" + fi } -x-have antidot && { - eval "$(antidot init)" +# Function to initialize pyenv if available +initialize_pyenv() +{ + if x-have pyenv; then + [[ -d $PYENV_ROOT/bin ]] && x-path-append "$PYENV_ROOT/bin" + [[ -d $PYENV_ROOT/shims ]] && x-path-append "$PYENV_ROOT/shims" + eval "$(pyenv init -)" + eval "$(pyenv virtualenv-init -)" + fi } +# Function to set up tmux window name plugin if tmux is active +setup_tmux_window_name_plugin() +{ + if [[ -n "$TMUX" ]]; then + local tmux_window_name_plugin="$DOTFILES/config/tmux/plugins/tmux-window-name/scripts/rename_session_windows.py" + if [[ -f "$tmux_window_name_plugin" ]]; then + tmux_window_name() + { + ($tmux_window_name_plugin &) + } + add-zsh-hook chpwd tmux_window_name + tmux_window_name + fi + fi +} + +# Function to initialize antidot if available +initialize_antidot() +{ + if x-have antidot; then + eval "$(antidot init)" + fi +} + +main() +{ + load_antigen + source_fzf_config + initialize_pyenv + setup_tmux_window_name_plugin + initialize_antidot +} + +main "$@" + # Herd checks for a few environment variables to inject PHP binaries and configurations. # Herd injected PHP binary. # export PATH="/Users/ivuorinen/Library/Application\ Support/Herd/bin/":$PATH diff --git a/config/alias b/config/alias index c29ca7e..9c05e2e 100755 --- a/config/alias +++ b/config/alias @@ -1,6 +1,4 @@ #!/usr/bin/env bash -# shellcheck source="../scripts/shared.sh" -# shellcheck disable=1091,2139 # Color the grep output alias grep="grep --color" @@ -32,7 +30,6 @@ alias l="ls -a" # Prevent common typos alias cd..="cd .." alias sl="ls" -alias ls-="ls -$1" # List only directories alias lsd="ls -lF | grep '^d'" @@ -115,63 +112,3 @@ if [[ $(uname) == 'Darwin' ]]; then # Using herd for php now, so this is not needed anymore # x-set-php-aliases fi - -# Alacritty preexec hook to update dynamic title -preexec() -{ - print -Pn "\e]0;$1%~\a" -} - -# Update dotfiles -dfu() -{ - ( - cd "$DOTFILES" && git pull --ff-only && ./install -q - ) -} - -# Weather in Tampere, or other city -weather() -{ - # https://github.com/chubin/wttr.in#usage - local city="${1:-Tampere}" - curl "http://wttr.in/${city// /+}?2nFQM&lang=fi" -} - -# Docker -ssh_docker() -{ - docker exec -it "$@" bash -} - -# Rector project to php version 8.2 by default. -rector() -{ - local php="${1:-82}" - docker run -v "$(pwd)":/project rector/rector:latest process \ - "/project/$1" \ - --set "php${php}" \ - --autoload-file /project/vendor/autoload.php -} - -# Commit everything -commit() -{ - commitMessage="$*" - - if [ "$commitMessage" = "" ]; then - commitMessage="Automated commit" - fi - - git add . - eval "git commit -a -m '${commitMessage}'" -} - -scheduler() -{ - while :; do - php artisan schedule:run - echo "Sleeping 60 seconds..." - sleep 60 - done -} diff --git a/config/exports b/config/exports index 5fab715..d194d65 100755 --- a/config/exports +++ b/config/exports @@ -2,14 +2,35 @@ # shellcheck shell=bash # vim: filetype=zsh +# Set XDG directories if not already set +# https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html +[ -z "$XDG_CONFIG_HOME" ] && export $XDG_CONFIG_HOME="$HOME/.config" +[ -z "$XDG_DATA_HOME" ] && export $XDG_DATA_HOME="$HOME/.local/share" +[ -z "$XDG_CACHE_HOME" ] && export $XDG_CACHE_HOME="$HOME/.cache" +[ -z "$XDG_STATE_HOME" ] && export $XDG_STATE_HOME="$HOME/.local/state" +[ -z "$XDG_BIN_HOME" ] && export $XDG_BIN_HOME="$HOME/.local/bin" + +# if DOTFILES is not set, set it to the default location +[ -z "$DOTFILES" ] && export DOTFILES="$HOME/.dotfiles" + +if ! command -v msg &> /dev/null; then + # Function to print messages if VERBOSE is enabled + # $1 - message (string) + msg() + { + [[ "$VERBOSE" -eq 1 ]] && echo "-> $1" + return 0 + } +fi + # Cache commands using bkt if installed -if command -v bkt >&/dev/null; then +if command -v bkt &> /dev/null; then bkt() { command bkt --cache-dir="$XDG_CACHE_HOME/bkt" "$@" } else - # If bkt isn't installed skip its arguments and just execute directly. + # If bkt isn't installed, skip its arguments and just execute directly. # Optionally write a msg to stderr suggesting users install bkt. bkt() { @@ -18,48 +39,54 @@ else } fi -# shorthand for checking if the system has the bin in path, -# this version does not use caching -# usage: have_command php && php -v +# Shorthand for checking if the system has the bin in path, +# this version does not use caching. +# Usage: have_command php && php -v have_command() { - command -v "$1" >&/dev/null -} - -# shorthand for checking if the system has the bin in path, -# this version uses caching -# usage: have php && php -v -have() -{ - bkt -- which "$1" >&/dev/null -} - -# function to run dark-notify and change alacritty theme -# it uses flock to prevent running multiple instances -# install flock with `brew install flock` on macOS -function darknotify_alacritty -{ - have flock && [[ -f /tmp/dark-notify-alacritty.lock ]] && return - have dark-notify && { - # true is used to prevent the command show it was backgrounded - true \ - && flock /tmp/dark-notify-alacritty.lock dark-notify -c "$HOME/.dotfiles/local/bin/x-change-alacritty-theme" & + [ -z "$1" ] && { + echo "Usage: have_command " + return 1 } - return 0 + command -v "$1" &> /dev/null +} + +# Shorthand for checking if the system has the bin in path, +# this version uses caching. +# Usage: have php && php -v +have() +{ + bkt -- which "$1" &> /dev/null +} + +# Function to run dark-notify and change alacritty theme +# It uses flock to prevent running multiple instances. +# Install flock with `brew install flock` on macOS. +darknotify_alacritty() +{ + x-have flock && [[ -f /tmp/dark-notify-alacritty.lock ]] && return + x-have dark-notify && { + # subprocess is used to prevent the command from showing it was backgrounded + ( + flock /tmp/dark-notify-alacritty.lock dark-notify \ + -c "$HOME/.dotfiles/local/bin/x-change-alacritty-theme" & + ) &> /dev/null + } } darknotify_alacritty +# Function to list installed Homebrew packages using bkt caching brew_installed() { bkt -- brew list } -# shorthand for checking if brew package is installed -# usage: have_brew php && php -v +# Shorthand for checking if a Homebrew package is installed +# Usage: have_brew php && php -v have_brew() { - ! x-have brew && return 125 + ! have brew && return 125 if bkt -- brew list "$1" &> /dev/null; then return 0 @@ -68,9 +95,369 @@ have_brew() fi } -if [[ -f "$DOTFILES/config/exports-secret" ]]; then - source "$DOTFILES/config/exports-secret" -fi +# Alacritty preexec hook to update dynamic title +preexec() +{ + print -Pn "\e]0;$1%~\a" +} -source "$DOTFILES/config/exports-shell" -source "$DOTFILES/config/exports-apps" +# Update dotfiles +dfu() +{ + ( + cd "$DOTFILES" && git pull --ff-only && ./install -q + ) +} + +# Weather in Tampere, or other city +weather() +{ + # https://github.com/chubin/wttr.in#usage + local city="${1:-Tampere}" + curl "http://wttr.in/${city// /+}?2nFQM&lang=fi" +} + +# Docker +ssh_docker() +{ + docker exec -it "$@" bash +} + +# Rector project to php version 8.2 by default. +rector() +{ + local php="${1:-82}" + docker run -v "$(pwd)":/project rector/rector:latest process \ + "/project/$1" \ + --set "php${php}" \ + --autoload-file /project/vendor/autoload.php +} + +# Commit everything +commit() +{ + local commitMessage="$*" + + if [ -z "$commitMessage" ]; then + commitMessage="Automated commit" + fi + + git add . + git commit -a -m "$commitMessage" +} + +scheduler() +{ + while :; do + php artisan schedule:run + echo "Sleeping 60 seconds..." + sleep 60 + done +} + +# Run command silently +# Usage: silent uptime +silent() +{ + "$@" >&/dev/null +} + +# Check if a file contains non-ascii characters +nonascii() +{ + LC_ALL=C grep -n '[^[:print:][:space:]]' "${@}" +} + +# Remove non-ascii characters from string +# Usage: strip_nonascii "string" +strip_nonascii() +{ + echo "$1" | LC_ALL=C sed 's/[^[:print:][:space:]]//g' +} + +# Slugify a string +# Usage: slugify "string" +slugify() +{ + echo "$1" | iconv -t ascii//TRANSLIT | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g | tr A-Z a-z +} + +# https://stackoverflow.com/a/85932 +fn_exists() +{ + declare -f -F "$1" > /dev/null + return $? +} + +# Creates a random string +rnd() +{ + echo $RANDOM | md5sum | head -c 20 +} + +# return sha256sum for file +# $1 - filename (string) +get_sha256sum() +{ + sha256sum "$1" | head -c 64 +} + +# Replaceable file +# +# $1 - filename (string) +# $2 - filename (string) +# +# Returns 1 when replaceable, 0 when not replaceable. +replacable() +{ + FILE1="$1" + FILE2="$2" + + [[ ! -r "$FILE1" ]] && { + [[ $VERBOSE -eq 1 ]] && msg_err "File 1 ($FILE1) does not exist" + return 0 + } + [[ ! -r "$FILE2" ]] && { + [[ $VERBOSE -eq 1 ]] && msg_err "File 2 ($FILE2) does not exist, replaceable" + return 1 + } + + FILE1_HASH=$(get_sha256sum "$FILE1") + FILE2_HASH=$(get_sha256sum "$FILE2") + + [[ $FILE1_HASH = "" ]] && { + [[ $VERBOSE -eq 1 ]] && msg_err "Could not get hash for file 1 ($FILE1)" + return 0 + } + [[ $FILE2_HASH = "" ]] && { + [[ $VERBOSE -eq 1 ]] && msg_err "Could not get hash for file 2 ($FILE2), replaceable" + return 1 + } + + [[ "$FILE1_HASH" == "$FILE2_HASH" ]] && { + [[ $VERBOSE -eq 1 ]] && msg_ok "Files match, not replaceable: $FILE1" + return 0 + } + + [[ $VERBOSE -eq 1 ]] && msg_warn "Files do not match ($FILE1_HASH != $FILE2_HASH), replaceable" + + return 1 +} + +export COMPLETION_WAITING_DOTS=true + +# Bash completion file location +export BASH_COMPLETION_USER_FILE="${XDG_CONFIG_HOME}/bash-completion/bash_completion" + +# History env variables +export HIST_STAMPS="yyyy-mm-dd" +# Larger bash history (allow 32³ entries; default is 500) +export HISTSIZE=32768 +export HISTFILESIZE=$HISTSIZE +# don't put duplicate lines or lines starting with space in the history. +# See bash(1) for more options +export HISTCONTROL=ignoreboth +# Make some commands not show up in history +export HISTIGNORE="ls:cd:cd -:pwd:exit:date:* --help" +# And include the parameter for ZSH +export HISTORY_IGNORE="(ls|cd|cd -|pwd|exit|date|* --help)" + +# Less history location +export LESSHISTFILE="$XDG_STATE_HOME"/less/history + +# Highlight section titles in manual pages +# export LESS_TERMCAP_md="$ORANGE" + +# zsh autoloaded terminfo +export TERMINFO="${XDG_DATA_HOME}/terminfo" +export TERMINFO_DIRS="${XDG_DATA_HOME}/terminfo":/usr/share/terminfo + +# Don't clear the screen after quitting a manual page +export MANPAGER="less -X" + +# Always enable colored `grep` output +export GREP_OPTIONS="--color=auto" + +# check the window size after each command and, if necessary, +# update the values of LINES and COLUMNS. +hash shopt 2> /dev/null && shopt -s checkwinsize + +# Antigen configuration +# https://github.com/zsh-users/antigen/wiki/Configuration +msg "Setting up Antigen configuration" +export ADOTDIR="$XDG_DATA_HOME/antigen" +export ANTIGEN_CACHE="$XDG_CACHE_HOME/antigen" +export ANTIGEN_SYSTEM_RECEIPT_F=".local/share/antigen/antigen_system_lastupdate" +export ANTIGEN_PLUGIN_RECEIPT_F=".local/share/antigen/antigen_plugin_lastupdate" + +# Ansible configuration +# https://docs.ansible.com/ansible/latest/reference_appendices/config.html +msg "Setting up Ansible configuration" +export ANSIBLE_HOME="$XDG_CONFIG_HOME/ansible" +export ANSIBLE_CONFIG="$XDG_CONFIG_HOME/ansible.cfg" +export ANSIBLE_GALAXY_CACHE_DIR="$XDG_CACHE_HOME/ansible/galaxy_cache" +x-dc "$ANSIBLE_HOME" +x-dc "$ANSIBLE_GALAXY_CACHE_DIR" + +# asdf +# https://github.com/asdf-vm/asdf +msg "Setting up asdf configuration" +export ASDF_DIR="${XDG_BIN_HOME}/asdf" +export ASDF_CONFIG_FILE="${XDG_CONFIG_HOME}/asdf/asdfrc" +export ASDF_DATA_DIR="${ASDF_DIR}" +# This seems wrong, but `asdf info` and `versions.bash` differ on path resolution. +export ASDF_DEFAULT_TOOL_VERSIONS_FILENAME=".config/asdf/tool-versions" +export ASDF_PLUGIN_MANAGER_PLUGIN_VERSIONS_FILENAME="${XDG_CONFIG_HOME}/asdf/plugin-versions" +export ASDF_LOG_FILE="${XDG_CACHE_HOME}/asdf/asdf.log" +export ASDF_NODEJS_LEGACY_FILE_DYNAMIC_STRATEGY="latest_available" +export ASDF_NPM_DEFAULT_PACKAGES_FILE="${XDG_CONFIG_HOME}/asdf/npm-packages" +export ASDF_GOLANG_MOD_VERSION_ENABLED=true +export ASDF_GOLANG_DEFAULT_PACKAGES_FILE="${XDG_CONFIG_HOME}/asdf/golang-packages" +export ASDF_CRATE_DEFAULT_PACKAGES_FILE="${XDG_CONFIG_HOME}/asdf/cargo-packages" +export PATH="${ASDF_DIR}/bin:${PATH}" + +# bob manages nvim versions +msg "Setting up bob configuration" +x-path-prepend "$XDG_DATA_HOME/bob/nvim-bin" + +# bkt (shell command caching tool) configuration +msg "Setting up bkt configuration" +export BKT_TTL=1m + +# brew, https://docs.brew.sh/Manpage +msg "Setting up Homebrew configuration" +export HOMEBREW_NO_ANALYTICS=true +export HOMEBREW_NO_ENV_HINTS=true +export HOMEBREW_BUNDLE_MAS_SKIP=true +export HOMEBREW_BUNDLE_FILE="$XDG_CONFIG_HOME/homebrew/Brewfile" +x-have brew && { + eval "$(brew shellenv)" +} + +# composer, https://getcomposer.org/ +msg "Setting up Composer configuration" +export COMPOSER_HOME="$XDG_STATE_HOME/composer" +export COMPOSER_BIN="$COMPOSER_HOME/vendor/bin" +export PATH="$COMPOSER_BIN:$PATH" + +# docker, https://docs.docker.com/engine/reference/commandline/cli/ +msg "Setting up Docker configuration" +export DOCKER_CONFIG="$XDG_CONFIG_HOME/docker" +x-dc "$DOCKER_CONFIG" +# Docker: Disable snyk ad +export DOCKER_SCAN_SUGGEST=false + +# ffmpeg +# https://ffmpeg.org/ffmpeg.html +msg "Setting up FFmpeg configuration" +export FFMPEG_DATADIR="$XDG_CONFIG_HOME/ffmpeg" +x-have ffmpeg && x-dc "$FFMPEG_DATADIR" + +# GnuPG +# https://gnupg.org/documentation/manuals/gnupg/Invoking-GPG.html +msg "Setting up GnuPG configuration" +export GNUPGHOME="$XDG_DATA_HOME/gnupg" + +# Go +# https://golang.org/doc/code.html +msg "Setting up Go configuration" +export GOPATH="$XDG_DATA_HOME/go" +export GOBIN="$XDG_BIN_HOME" + +# Herd, herd.laravel.com +# Herd injected PHP binary. +msg "Setting up Herd configuration" +export PATH="$HOME/Library/Application\ Support/Herd/bin/":$PATH +x-have herd && { + # Herd injected PHP 8.3 configuration. + export HERD_PHP_83_INI_SCAN_DIR="$HOME/Library/Application\ Support/Herd/config/php/83/" + # Herd injected PHP 7.4 configuration. + export HERD_PHP_74_INI_SCAN_DIR="$HOME/Library/Application\ Support/Herd/config/php/74/" +} + +# nb, https://xwmx.github.io/nb/ +msg "Setting up nb configuration" +export NBRC_PATH="$XDG_CONFIG_HOME/nbrc" +export NB_DIR="$XDG_STATE_HOME/nb" + +# NPM: Add npm packages to path +msg "Setting up NPM configuration" +x-have node && { + NVM_NODE_BIN_DIR="$(dirname "$(which node)")" + export PATH="$NVM_NODE_BIN_DIR:$PATH" +} + +# oh-my-posh (omp) configuration +msg "Setting up oh-my-posh configuration" +export OHMYPOSH_CFG="$DOTFILES/config/omp/own.toml" + +# op (1Password cli) is present +msg "Setting up 1Password CLI configuration" +export OP_CACHE="$XDG_STATE_HOME/1password" + +# Python +# +# pyenv, python environments +msg "Setting up Python configuration" +export WORKON_HOME="$XDG_DATA_HOME/virtualenvs" +export PYENV_ROOT="$XDG_STATE_HOME/pyenv" +export PATH="$PYENV_ROOT/bin:$PYENV_ROOT/shims:$PATH" +x-have pyenv && { + eval "$(pyenv init -)" +} + +# Ruby +# +# including: bundler, rbenv +msg "Setting up Ruby configuration" +export GEM_HOME="${XDG_DATA_HOME}"/gem +export GEM_SPEC_CACHE="${XDG_CACHE_HOME}"/gem +export BUNDLE_USER_CONFIG="$XDG_CONFIG_HOME"/bundle +export BUNDLE_USER_CACHE="$XDG_CACHE_HOME"/bundle +export BUNDLE_USER_PLUGIN="$XDG_DATA_HOME"/bundle +export RBENV_ROOT="$XDG_STATE_HOME/rbenv" +x-dc "$RBENV_ROOT" +x-have gem && export PATH="${GEM_HOME}/bin:$PATH" + +# Rust / cargo +msg "Setting up Rust/Cargo configuration" +export RUSTUP_HOME="$XDG_DATA_HOME/rustup" +export CARGO_HOME="$XDG_DATA_HOME/cargo" +export PATH="$CARGO_HOME/bin:$PATH" + +# screen +# https://www.gnu.org/software/screen/manual/screen.html +msg "Setting up screen configuration" +export SCREENRC="$XDG_CONFIG_HOME/misc/screenrc" + +# sonarlint +# https://www.sonarlint.org/ +msg "Setting up Sonarlint configuration" +export SONARLINT_USER_HOME="$XDG_DATA_HOME/sonarlint" + +# terraform +# https://www.terraform.io/docs/cli/config/config-file.html +# https://www.terraform.io/docs/cli/config/environment-variables.html +msg "Setting up Terraform configuration" +export TF_DATA_DIR="$XDG_STATE_HOME/terraform" +export TF_CLI_CONFIG_FILE="$XDG_CONFIG_HOME/terraform/terraformrc" +export TF_PLUGIN_CACHE_DIR="$XDG_CACHE_HOME/terraform/plugin-cache" + +# tldr / tealdeer +msg "Setting up tldr configuration" +export TEALDEER_CONFIG_DIR="$XDG_CONFIG_HOME/tealdeer/" + +# tmux +# https://tmux.github.io/ +msg "Setting up tmux configuration" +export TMUX_CONF="$XDG_CONFIG_HOME/tmux/tmux.conf" + +# wakatime, https://github.com/wakatime/wakatime-cli +msg "Setting up Wakatime configuration" +export WAKATIME_HOME="$XDG_STATE_HOME/wakatime" +x-dc "$WAKATIME_HOME" + +# Misc +msg "Setting up miscellaneous configuration" +export CHEAT_USE_FZF=true +export SQLITE_HISTORY="${XDG_CACHE_HOME}/sqlite_history" diff --git a/config/exports-apps b/config/exports-apps deleted file mode 100755 index c8098a0..0000000 --- a/config/exports-apps +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env bash -# shellcheck shell=bash -# shellcheck enable=external-sources -# shellcheck disable=1091,2139 -# vim: filetype=bash - -# Antigen configuration -# https://github.com/zsh-users/antigen/wiki/Configuration -export ADOTDIR="$XDG_DATA_HOME/antigen" -export ANTIGEN_CACHE="$XDG_CACHE_HOME/antigen" -export ANTIGEN_SYSTEM_RECEIPT_F=".local/share/antigen/antigen_system_lastupdate" -export ANTIGEN_PLUGIN_RECEIPT_F=".local/share/antigen/antigen_plugin_lastupdate" - -# Ansible configuration -# https://docs.ansible.com/ansible/latest/reference_appendices/config.html -export ANSIBLE_HOME="$XDG_CONFIG_HOME/ansible" -export ANSIBLE_CONFIG="$XDG_CONFIG_HOME/ansible.cfg" -export ANSIBLE_GALAXY_CACHE_DIR="$XDG_CACHE_HOME/ansible/galaxy_cache" -x-dc "$ANSIBLE_HOME" -x-dc "$ANSIBLE_GALAXY_CACHE_DIR" - -export ANDROID_HOME="$XDG_DATA_HOME/android" - -# asdf -# https://github.com/asdf-vm/asdf -export ASDF_DIR="${XDG_BIN_HOME}/asdf" -export ASDF_CONFIG_FILE="${XDG_CONFIG_HOME}/asdf/asdfrc" -export ASDF_DATA_DIR="${ASDF_DIR}" -# This seems wrong, but `asdf info` and `versions.bash` differ on path resolution. -export ASDF_DEFAULT_TOOL_VERSIONS_FILENAME=".config/asdf/tool-versions" -export ASDF_PLUGIN_MANAGER_PLUGIN_VERSIONS_FILENAME="${XDG_CONFIG_HOME}/asdf/plugin-versions" -export ASDF_LOG_FILE="${XDG_CACHE_HOME}/asdf/asdf.log" -export ASDF_NODEJS_LEGACY_FILE_DYNAMIC_STRATEGY="latest_available" -export ASDF_NPM_DEFAULT_PACKAGES_FILE="${XDG_CONFIG_HOME}/asdf/npm-packages" -export ASDF_GOLANG_MOD_VERSION_ENABLED=true -export ASDF_GOLANG_DEFAULT_PACKAGES_FILE="${XDG_CONFIG_HOME}/asdf/golang-packages" -export ASDF_CRATE_DEFAULT_PACKAGES_FILE="${XDG_CONFIG_HOME}/asdf/cargo-packages" -export PATH="${ASDF_DIR}/bin:${PATH}" - -# bob manages nvim versions -export PATH="$XDG_DATA_HOME/bob/nvim-bin:$PATH" - -# bkt (shell command caching tool) configuration -export BKT_TTL=1m - -# brew, https://docs.brew.sh/Manpage -export HOMEBREW_NO_ENV_HINTS=true -export HOMEBREW_BUNDLE_MAS_SKIP=true -export HOMEBREW_BUNDLE_FILE="$XDG_CONFIG_HOME/homebrew/Brewfile" - -# composer, https://getcomposer.org/ -export COMPOSER_HOME="$XDG_STATE_HOME/composer" -export COMPOSER_BIN="$COMPOSER_HOME/vendor/bin" -export PATH="$COMPOSER_BIN:$PATH" - -# docker, https://docs.docker.com/engine/reference/commandline/cli/ -export DOCKER_CONFIG="$XDG_CONFIG_HOME/docker" -x-dc "$DOCKER_CONFIG" -# Docker: Disable snyk ad -export DOCKER_SCAN_SUGGEST=false - -# ffmpeg -export FFMPEG_DATADIR="$XDG_CONFIG_HOME/ffmpeg" -x-have ffmpeg && x-dc "$FFMPEG_DATADIR" - -# GnuPG -export GNUPGHOME="$XDG_DATA_HOME/gnupg" - -# Go -export GOPATH="$XDG_DATA_HOME/go" -export GOBIN="$XDG_BIN_HOME" - -# Herd, herd.laravel.com -# Herd injected PHP binary. -export PATH="$HOME/Library/Application\ Support/Herd/bin/":$PATH - -x-have herd && { - # Herd injected PHP 8.3 configuration. - export HERD_PHP_83_INI_SCAN_DIR="$HOME/Library/Application\ Support/Herd/config/php/83/" - # Herd injected PHP 7.4 configuration. - export HERD_PHP_74_INI_SCAN_DIR="$HOME/Library/Application\ Support/Herd/config/php/74/" -} - -# nb, https://xwmx.github.io/nb/ -export NBRC_PATH="$XDG_CONFIG_HOME/nbrc" -export NB_DIR="$XDG_STATE_HOME/nb" - -# NPM: Add npm packages to path -x-have node && { - NVM_NODE_BIN_DIR="$(dirname "$(which node)")" - export PATH="$NVM_NODE_BIN_DIR:$PATH" -} - -# op (1Password cli) is present -export OP_CACHE="$XDG_STATE_HOME/1password" - -# Python -# -# pyenv, python environments -export WORKON_HOME="$XDG_DATA_HOME/virtualenvs" -export PYENV_ROOT="$XDG_STATE_HOME/pyenv" -export PATH="$PYENV_ROOT/bin:$PYENV_ROOT/shims:$PATH" -x-have pyenv && { - eval "$(pyenv init -)" -} - -# Ruby -# -# including: bundler, rbenv -export GEM_HOME="${XDG_DATA_HOME}"/gem -export GEM_SPEC_CACHE="${XDG_CACHE_HOME}"/gem -export BUNDLE_USER_CONFIG="$XDG_CONFIG_HOME"/bundle -export BUNDLE_USER_CACHE="$XDG_CACHE_HOME"/bundle -export BUNDLE_USER_PLUGIN="$XDG_DATA_HOME"/bundle -export RBENV_ROOT="$XDG_STATE_HOME/rbenv" -x-dc "$RBENV_ROOT" -x-have gem && export PATH="${GEM_HOME}/bin:$PATH" - -# Rust / cargo -export RUSTUP_HOME="$XDG_DATA_HOME/rustup" -export CARGO_HOME="$XDG_DATA_HOME/cargo" -export PATH="$CARGO_HOME/bin:$PATH" - -# screen -export SCREENRC="$XDG_CONFIG_HOME/misc/screenrc" - -# sonarlint -export SONARLINT_USER_HOME="$XDG_DATA_HOME/sonarlint" - -# terraform -# https://www.terraform.io/docs/cli/config/config-file.html -# https://www.terraform.io/docs/cli/config/environment-variables.html -export TF_DATA_DIR="$XDG_STATE_HOME/terraform" -export TF_CLI_CONFIG_FILE="$XDG_CONFIG_HOME/terraform/terraformrc" -export TF_PLUGIN_CACHE_DIR="$XDG_CACHE_HOME/terraform/plugin-cache" - -# tldr / tealdeer -export TEALDEER_CONFIG_DIR="$XDG_CONFIG_HOME/tealdeer/" - -# tmux -export TMUX_CONF="$XDG_CONFIG_HOME/tmux/tmux.conf" - -# wakatime, https://github.com/wakatime/wakatime-cli -export WAKATIME_HOME="$XDG_STATE_HOME/wakatime" -x-dc "$WAKATIME_HOME" - -# Misc -export BAT_THEME="ansi" -export CHEAT_USE_FZF=true -export SQLITE_HISTORY="$XDG_CACHE_HOME"/sqlite_history diff --git a/config/exports-lakka b/config/exports-lakka index f4e473d..a9c6c46 100644 --- a/config/exports-lakka +++ b/config/exports-lakka @@ -1,19 +1,25 @@ # lakka exports ## LUA -x-have luarocks && $(luarocks path --bin) +if command -v luarocks &> /dev/null; then + eval "$(luarocks path --bin)" +fi export PATH="$HOME/.local/go/bin:$PATH" -alias logrotate='/usr/sbin/logrotate -s $HOME/logs/state' +alias logrotate='/usr/sbin/logrotate -s "$HOME/logs/state"' alias nano='nano -wS -$' alias gpg=gpg2 ACME_PATH="$HOME/.acme.sh" # shellcheck source=$HOME/.acme.sh/acme.sh.env -[[ -s "$ACME_PATH/acme.sh.env" ]] && . "$ACME_PATH/acme.sh.env" +if [[ -s "$ACME_PATH/acme.sh.env" ]]; then + source "$ACME_PATH/acme.sh.env" +fi export RVM_PATH="$HOME/.rvm" export PATH="$RVM_PATH/bin:$PATH" # shellcheck source=$HOME/.rvm/scripts/rvm -[[ -s "$RVM_PATH/scripts/rvm" ]] && source "$RVM_PATH/scripts/rvm" # Load RVM into a shell session *as a function* +if [[ -s "$RVM_PATH/scripts/rvm" ]]; then + source "$RVM_PATH/scripts/rvm" # Load RVM into a shell session *as a function* +fi diff --git a/config/exports-shell b/config/exports-shell deleted file mode 100755 index d32fb7f..0000000 --- a/config/exports-shell +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -# shellcheck shell=bash -# shellcheck disable=1091,2046 -# vim: filetype=bash - -# Bash completion file location -export BASH_COMPLETION_USER_FILE="${XDG_CONFIG_HOME}/bash-completion/bash_completion" - -# History env variables -export HIST_STAMPS="yyyy-mm-dd" -# Larger bash history (allow 32³ entries; default is 500) -export HISTSIZE=32768 -export HISTFILESIZE=$HISTSIZE -# don't put duplicate lines or lines starting with space in the history. -# See bash(1) for more options -export HISTCONTROL=ignoreboth -# Make some commands not show up in history -export HISTIGNORE="ls:cd:cd -:pwd:exit:date:* --help" -# And include the parameter for ZSH -export HISTORY_IGNORE="(ls|cd|cd -|pwd|exit|date|* --help)" - -# Less history location -export LESSHISTFILE="$XDG_STATE_HOME"/less/history - -# Highlight section titles in manual pages -# export LESS_TERMCAP_md="$ORANGE" - -# zsh autoloaded terminfo -export TERMINFO="${XDG_DATA_HOME}/terminfo" -export TERMINFO_DIRS="${XDG_DATA_HOME}/terminfo":/usr/share/terminfo - -# Don't clear the screen after quitting a manual page -export MANPAGER="less -X" - -# Always enable colored `grep` output -export GREP_OPTIONS="--color=auto" - -# check the window size after each command and, if necessary, -# update the values of LINES and COLUMNS. -hash shopt 2> /dev/null && shopt -s checkwinsize diff --git a/config/functions b/config/functions deleted file mode 100755 index a35326f..0000000 --- a/config/functions +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -# -# shell functions diff --git a/config/shared.sh b/config/shared.sh index 2faf6eb..fb055d9 100755 --- a/config/shared.sh +++ b/config/shared.sh @@ -1,23 +1,96 @@ +#!/usr/bin/env bash +# +# Shared configuration +# # shellcheck shell=bash # Defaults -export DOTFILES="$HOME/.dotfiles" +[ -z "$DOTFILES" ] && export DOTFILES="$HOME/.dotfiles" +export DOTFILES_CURRENT_SHELL=$(basename "$SHELL") -# Explicitly set XDG folders +# Enable verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" +# Enable debugging with DEBUG=1 +DEBUG="${DEBUG:-0}" + +# Enable debugging with DEBUG=1 +[ "${DEBUG:-0}" -eq 1 ] && set -x + +# Explicitly set XDG folders, if not already set # https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html -export XDG_CONFIG_HOME="$HOME/.config" -export XDG_DATA_HOME="$HOME/.local/share" -export XDG_STATE_HOME="$HOME/.local/state" - -# custom variables -export XDG_BIN_HOME="$HOME/.local/bin" -export XDG_CACHE_HOME="$HOME/.cache" -export XDG_RUNTIME_DIR="$HOME/.local/run" +[ -z "$XDG_CONFIG_HOME" ] && export XDG_CONFIG_HOME="$HOME/.config" +[ -z "$XDG_DATA_HOME" ] && export $XDG_DATA_HOME="$HOME/.local/share" +[ -z "$XDG_STATE_HOME" ] && export $XDG_STATE_HOME="$HOME/.local/state" +[ -z "$XDG_BIN_HOME" ] && export XDG_BIN_HOME="$HOME/.local/bin" +[ -z "$XDG_CACHE_HOME" ] && export XDG_CACHE_HOME="$HOME/.cache" # Paths -export PATH="$XDG_BIN_HOME:$DOTFILES/local/bin:$HOME/.local/go/bin:$XDG_DATA_HOME/bob/nvim-bin:$XDG_DATA_HOME/cargo/bin:/opt/homebrew/bin:/usr/local/bin:$PATH" +x-path-prepend "/usr/local/bin" +x-path-prepend "/opt/homebrew/bin" +x-path-prepend "$XDG_DATA_HOME/cargo/bin" +x-path-prepend "$XDG_DATA_HOME/bob/nvim-bin" +x-path-prepend "$DOTFILES/local/bin" +x-path-prepend "$XDG_BIN_HOME" + +# Custom completion paths +[ -z "$ZSH_CUSTOM_COMPLETION_PATH" ] && export ZSH_CUSTOM_COMPLETION_PATH="$XDG_CONFIG_HOME/zsh/completion" +x-dc "$ZSH_CUSTOM_COMPLETION_PATH" +export FPATH="$ZSH_CUSTOM_COMPLETION_PATH:$FPATH" + +if ! declare -f msg > /dev/null; then + # Function to print messages if VERBOSE is enabled + # $1 - message (string) + msg() + { + [ "$VERBOSE" -eq 1 ] && echo "$1" + return 0 + } + msg "msg was not defined, defined it now" +fi + +if ! declare -f msg_err > /dev/null; then + msg "msg_err was not defined, defined it now" + # Function to print error messages and exit + # $1 - error message (string) + msg_err() + { + echo "(!) ERROR: $1" >&2 + exit 1 + } +fi + +if ! declare -f msg_done > /dev/null; then + msg "msg_done was not defined, defined it now" + # Function to print done message + # $1 - message (string) + msg_done() + { + echo "✓ $1" + return 0 + } +fi + +if ! declare -f msg_run > /dev/null; then + msg "msg_run was not defined, defined it now" + # Function to print running message + # $1 - message (string) + msg_run() + { + echo "→ $1" + return 0 + } +fi + +if ! declare -f msg_ok > /dev/null; then + msg "msg_ok was not defined, defined it now" + # Function to print ok message + # $1 - message (string) + msg_ok() + { + echo "✓ $1" + return 0 + } +fi -# Split config files source "$DOTFILES/config/exports" -source "$DOTFILES/config/functions" source "$DOTFILES/config/alias" diff --git a/local/bin/dfm b/local/bin/dfm index 73c4e96..54e3001 100755 --- a/local/bin/dfm +++ b/local/bin/dfm @@ -14,19 +14,92 @@ SCRIPT=$(basename "$0") +if ! declare -f msg > /dev/null; then + # Function to print messages if VERBOSE is enabled + # $1 - message (string) + msg() + { + [ "$VERBOSE" -eq 1 ] && echo "$1" + return 0 + } +fi + +if ! declare -f msg_err > /dev/null; then + # Function to print error messages and exit + # $1 - error message (string) + msg_err() + { + echo "(!) ERROR: $1" >&2 + exit 1 + } +fi + +if ! declare -f msg_done > /dev/null; then + # Function to print done message + # $1 - message (string) + msg_done() + { + echo "✓ $1" + return 0 + } +fi + VERSION_NVM="v0.39.5" -export DOTFILES="$HOME/.dotfiles" -# shellcheck source=./../../scripts/shared.sh -source "$HOME/.dotfiles/scripts/shared.sh" -source "$DOTFILES/config/exports" -source "$DOTFILES/config/alias" -source "$DOTFILES/config/functions" - # Loads configs for better installation experience -x-load-configs +source "$DOTFILES/config/shared.sh" -function section_install +source "${DOTFILES}/local/bin/msgr" + +# -- Menu builder -- # +menu_section() +{ + LINE=$(printf '%-18s [ %-15s ]\n' "$1" "$2") + echo -e " $(__log_marker) $LINE" +} +menu_item() +{ + LINE=$(printf '%-15s %-30s\n' "$1" "$2") + echo -e "$(__log_indent)$(__log_marker) $LINE" +} + +# Takes a bash array ("cow:moo", "dinosaur:roar") and loops +# through the keys to build menu section listing. +menu_usage_header() +{ + MENU_CMD="$1" + shift + MENU_ARRAY=("$@") + + KEYS="" + for item in "${MENU_ARRAY[@]}"; do + CMD=$(echo "${item}" | awk -F ":" '{print $1}') + KEYS+="${CMD} | " + done + + # "???" removes 3 last characters, being " | " from the end + menu_section "$MENU_CMD" "${KEYS%???}" +} + +# Takes the usage command "$0 dotfiles" and a +# bash array ("cow:moo" "dinosaur:roar") and loops +# through in building a menu for dfm command usage listing. +menu_usage() +{ + MENU_CMD="$1" + shift + MENU_ARRAY=("$@") + + msg "$MENU_CMD" + + for item in "${MENU_ARRAY[@]}"; do + CMD=$(echo "${item}" | awk -F ":" '{print $1}') + DESC=$(echo "${item}" | awk -F ":" '{print $2}') + menu_item "$CMD" "$DESC" + done +} + +section_install() { USAGE_PREFIX="$SCRIPT install " @@ -56,7 +129,6 @@ function section_install case "$1" in all) msgr msg "Starting to install all and reloading configurations..." - x-load-configs $0 install macos $0 install fonts $0 install antigen @@ -79,7 +151,7 @@ function section_install $0 install ntfy $0 install z msgr msg "Reloading configurations again..." - x-load-configs + source "$DOTFILES/config/shared.sh" msgr yay "All done!" ;; antigen) @@ -210,7 +282,7 @@ function section_install esac } -function section_brew +section_brew() { USAGE_PREFIX="$SCRIPT brew " @@ -258,7 +330,7 @@ function section_brew ! x-have brew && menu_section "$USAGE_PREFIX" "brew not available on this system" } -function section_helpers +section_helpers() { USAGE_PREFIX="$SCRIPT helpers " MENU=( @@ -274,7 +346,7 @@ function section_helpers esac } -function section_docs +section_docs() { USAGE_PREFIX="$SCRIPT docs " @@ -288,7 +360,7 @@ function section_docs esac } -function section_dotfiles +section_dotfiles() { USAGE_PREFIX="$SCRIPT dotfiles " @@ -344,7 +416,7 @@ function section_dotfiles esac } -function section_check +section_check() { USAGE_PREFIX="$SCRIPT check " X_HOSTNAME=$(hostname) @@ -369,7 +441,7 @@ function section_check } # Secret menu for visual tests -function section_tests +section_tests() { USAGE_PREFIX="$SCRIPT tests " @@ -398,7 +470,7 @@ function section_tests esac } -function usage +usage() { echo "" msg_prompt "Usage: $SCRIPT
" diff --git a/local/bin/x-load-configs b/local/bin/x-load-configs index 9110820..8017818 100755 --- a/local/bin/x-load-configs +++ b/local/bin/x-load-configs @@ -2,76 +2,97 @@ # Load our configuration files # Copyright (c) 2023 Ismo Vuorinen. All Rights Reserved. +DOTFILES="${DOTFILES:-$HOME/.dotfiles}" + +source "$DOTFILES/config/shared.sh" + # Enable verbosity with VERBOSE=1 x-load-configs -VERBOSE="${VERBOSE:=0}" +VERBOSE="${VERBOSE:-0}" # Enable debugging with DEBUG=1 x-load-configs -DEBUG="${DEBUG:=0}" +DEBUG="${DEBUG:-0}" -[ "$DEBUG" = "1" ] && { - set -x +# Get the hostname +CONFIG_HOST="$(hostname -s)" + +# Enable debugging if requested +[ "$DEBUG" = "1" ] && set -x + +CONFIG_PATH="${DOTFILES}/config" + +[ -d "$DOTFILES" ] || { + msg_err "Error: DOTFILES is not set or $DOTFILES does not exist" } -CONFIG_PATH="$DOTFILES/config" +# Function to print messages if VERBOSE is enabled +# $1 - message type (string) +# $2 - message content (string) +config_msg() +{ + # if $1 is empty, return + [ -z "$1" ] && return + [ -z "$2" ] && $2="" -# Load the shell dotfiles, and then some: -HOST="$(hostname -s)" -[ "$VERBOSE" = "1" ] && { - echo "x-load-configs: VERBOSE=1" - echo "x-load-configs: HOST: $HOST" + local msg_type="$1" + local msg_content="$2" + [[ "$VERBOSE" -eq 1 ]] && printf 'x-load-configs: %s %s\n' "$msg_type" "$msg_content" + return 0 } -configFile() +# Function to get the full path of a config file +# $1 - filename (string) +config_file_path() { echo "$CONFIG_PATH/$1" } -configMsg() +# Function to source configuration files +source_config() { - printf 'x-load-configs: %s %s\n' "$1" "$2" + local config_file=$1 + if [ -f "$config_file" ]; then + eval "$config_file" + config_msg "Sourced" "$config_file" + else + msg "Config file $config_file not found" + fi + return 0 } -loadConfigFiles() +# Function to load a configuration file +# $1 - base config file name (string) +load_config_files() { - CONFIG_FILE=$1 - SECRET_FILE=$CONFIG_FILE-secret - HOST_FILE=$CONFIG_FILE-$HOST - SECRET_HOST=$HOST_FILE-secret + local config_file="$1" + local secret_file="${config_file}-secret" + local host_file="${config_file}-${CONFIG_HOST}" + local secret_host_file="${host_file}-secret" - [ "$VERBOSE" = "1" ] && configMsg "Looking for" "$CONFIG_FILE" - - # global (exports|alias|functions) FILENAME for all hosts - # shellcheck source=../config/exports - [ -r "$CONFIG_FILE" ] && { - source "$CONFIG_FILE" && [ "$VERBOSE" = "1" ] && configMsg "Found" "$CONFIG_FILE" + config_msg "Looking for" "$config_file" + [ -r "$config_file" ] && { + source_config "$config_file" } - # global secret FILENAME, git ignored - # shellcheck source=../config/exports-secret - [ "$VERBOSE" = "1" ] && configMsg "Looking for" "$SECRET_FILE" - [ -r "$SECRET_FILE" ] && { - source "$SECRET_FILE" && [ "$VERBOSE" = "1" ] && configMsg "Found" "$SECRET_FILE" + config_msg "Looking for" "$secret_file" + [ -r "$secret_file" ] && { + source_config "$secret_file" } - # host specific (exports|alias|functions) FILENAME - # shellcheck source=../config/exports - [ "$VERBOSE" = "1" ] && configMsg "Looking for" "$HOST_FILE" - [ -r "$HOST_FILE" ] && { - source "$HOST_FILE" && [ "$VERBOSE" = "1" ] && configMsg "Found" "$HOST_FILE" + + config_msg "Looking for" "$host_file" + [ -r "$host_file" ] && { + source_config "$host_file" } - # host specific (exports|alias|functions) FILENAME, git ignored - # shellcheck source=../config/exports - [ "$VERBOSE" = "1" ] && configMsg "Looking for" "$SECRET_HOST" - [ -r "$SECRET_HOST" ] && { - source "$SECRET_HOST" \ - && [ "$VERBOSE" = "1" ] && configMsg "Found" "$SECRET_HOST" + + config_msg "Looking for" "$secret_host_file" + [ -r "$secret_host_file" ] && { + source_config "$secret_host_file" } + return 0 } -FILE_EXPORTS=$(configFile "exports") -FILE_FUNCTIONS=$(configFile "functions") -FILE_ALIAS=$(configFile "alias") - -loadConfigFiles "$FILE_EXPORTS" -loadConfigFiles "$FILE_FUNCTIONS" -loadConfigFiles "$FILE_ALIAS" +config_msg "VERBOSE=1" "Verbose mode enabled" +config_msg "HOST" "$CONFIG_HOST" +load_config_files "$(config_file_path "exports")" +load_config_files "$(config_file_path "functions")" +load_config_files "$(config_file_path "alias")" exit 0 diff --git a/local/bin/x-path-append b/local/bin/x-path-append index 105a758..d8343f1 100755 --- a/local/bin/x-path-append +++ b/local/bin/x-path-append @@ -3,5 +3,65 @@ # Add a directory to the beginning of the PATH if it's not already there. # Usage: x-path-append -x-path-remove "$1" -export PATH="${PATH:+"$PATH:"}$1" +# Set verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" + +# Function to print usage information +usage() +{ + echo "Usage: $0 " + exit 1 +} + +# Function to print messages if VERBOSE is enabled +# $1 - message (string) +msg() +{ + [[ "$VERBOSE" -eq 1 ]] && echo "$1" +} + +# Function to remove a directory from PATH +# $1 - directory to remove (string) +remove_from_path() +{ + local dir=$1 + + if echo "$PATH" | grep -qE "(^|:)$dir($|:)"; then + export PATH=$(echo -n "$PATH" | awk -v RS=: -v ORS=: "\$0 != \"$dir\"" | sed 's/:$//') + msg "Directory $dir has been removed from PATH" + else + msg "Directory $dir is not in PATH" + fi +} + +# Function to append a directory to PATH +# $1 - directory to append (string) +append_to_path() +{ + local dir=$1 + + if [ ! -d "$dir" ]; then + msg "(?) Directory $dir does not exist" + exit 0 + fi + + if echo "$PATH" | grep -qE "(^|:)$dir($|:)"; then + msg "(!) Directory $dir is already in PATH" + else + export PATH="${PATH:+"$PATH:"}$dir" + msg "(!) Directory $dir has been added to the end of PATH" + fi +} + +# Main function +main() +{ + if [ "$#" -ne 1 ]; then + usage + fi + + remove_from_path "$1" + append_to_path "$1" +} + +main "$@" diff --git a/local/bin/x-path-prepend b/local/bin/x-path-prepend index 48204a4..883a98d 100755 --- a/local/bin/x-path-prepend +++ b/local/bin/x-path-prepend @@ -3,4 +3,50 @@ # Add a directory to the front of the PATH if it exists and is not already there # Usage: x-path-prepend -export PATH="$1${PATH:+":$PATH"}" +# Set verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" + +# Function to print usage information +usage() +{ + echo "Usage: $0 " + exit 1 +} + +# Function to print messages if VERBOSE is enabled +# $1 - message (string) +msg() +{ + [[ "$VERBOSE" -eq 1 ]] && echo "$1" +} + +# Function to add a directory to the front of PATH +# $1 - directory to add (string) +prepend_to_path() +{ + local dir=$1 + + if [ ! -d "$dir" ]; then + msg "(?) Directory $dir does not exist" + exit 0 + fi + + if echo "$PATH" | grep -qE "(^|:)$dir($|:)"; then + msg "(!) Directory $dir is already in PATH" + else + export PATH="$dir${PATH:+":$PATH"}" + msg "(!) Directory $dir has been added to the front of PATH" + fi +} + +# Main function +main() +{ + if [ "$#" -ne 1 ]; then + usage + fi + + prepend_to_path "$1" +} + +main "$@" diff --git a/local/bin/x-path-remove b/local/bin/x-path-remove index 8f43da3..23b4fe3 100755 --- a/local/bin/x-path-remove +++ b/local/bin/x-path-remove @@ -3,4 +3,46 @@ # Remove a directory from the PATH # Usage: x-path-remove -export PATH=$(echo -n "$PATH" | awk -v RS=: -v ORS=: "\$0 != \"$1\"" | sed 's/:$//') +# Set verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" + +# Function to print usage information +usage() +{ + echo "Usage: $0 " + exit 1 +} + +# Function to print messages if VERBOSE is enabled +# $1 - message (string) +msg() +{ + [[ "$VERBOSE" -eq 1 ]] && echo "$1" +} + +# Function to remove a directory from PATH +# $1 - directory to remove (string) +remove_from_path() +{ + local dir=$1 + + if ! echo "$PATH" | grep -qE "(^|:)$dir($|:)"; then + msg "(?) Directory $dir is not in PATH" + exit 0 + fi + + export PATH=$(echo -n "$PATH" | awk -v RS=: -v ORS=: "\$0 != \"$dir\"" | sed 's/:$//') + msg "(!) Directory $dir has been removed from PATH" +} + +# Main function +main() +{ + if [ "$#" -ne 1 ]; then + usage + fi + + remove_from_path "$1" +} + +main "$@" diff --git a/scripts/create-nvim-keymaps.sh b/scripts/create-nvim-keymaps.sh index f78bbef..994a7bf 100755 --- a/scripts/create-nvim-keymaps.sh +++ b/scripts/create-nvim-keymaps.sh @@ -1,20 +1,28 @@ #!/usr/bin/env bash # Create file containing key mappings for Neovim # Usage: ./create-nvim-keymaps.sh - -eval "$HOME/.dotfiles/scripts/shared.sh" - +# +# shellcheck source=shared.sh +source "${DOTFILES}/config/shared.sh" DEST="$HOME/.dotfiles/docs/nvim-keybindings.md" +main() { - printf "# nvim keybindings\n"; - printf "\n"; - printf "\`\`\`txt"; -} > "$DEST" + msg "Generating Neovim keybindings documentation" -NVIM_APPNAME="nvim-kickstart" nvim -c "redir! >> $DEST" -c 'silent verbose map' -c 'redir END' -c 'q' + { + printf "# nvim keybindings\n\n" + printf "\`\`\`txt\n" + } > "$DEST" -printf "\n\`\`\`\n\n- Generated on %s\n" "$(date)" >> "$DEST" + NVIM_APPNAME="nvim-kickstart" nvim -c "redir! >> $DEST" -c 'silent verbose map' -c 'redir END' -c 'q' -# Remove lines with "Last set from" from the file -sed -e '/^ Last set from/d' "$DEST" > "$DEST.tmp" && mv "$DEST.tmp" "$DEST" + printf "\n\`\`\`\n\n- Generated on %s\n" "$(date)" >> "$DEST" + + # Remove lines with "Last set from" from the file + sed -e '/^ Last set from/d' "$DEST" > "${DEST}.tmp" && mv "${DEST}.tmp" "$DEST" + + msg "Neovim keybindings documentation generated at $DEST" +} + +main "$@" diff --git a/scripts/create-omp-screenshot.sh b/scripts/create-omp-screenshot.sh index 125b410..732bc20 100755 --- a/scripts/create-omp-screenshot.sh +++ b/scripts/create-omp-screenshot.sh @@ -1,11 +1,18 @@ #!/usr/bin/env bash # +# Export oh-my-posh configuration as an image +# # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" -set -e +source "${DOTFILES}/config/shared.sh" -cd "$DOTFILES" || exit -oh-my-posh config export image \ - --config "$OHMYPOSH_CFG" \ - --output "$HOME/.dotfiles/.github/screenshots/oh-my-posh.png" \ - --author "Ismo Vuorinen" +main() +{ + cd "$DOTFILES" || msg_err "Failed to change directory to $DOTFILES" + + oh-my-posh config export image \ + --config "$OHMYPOSH_CFG" \ + --output "$HOME/.dotfiles/.github/screenshots/oh-my-posh.png" \ + --author "Ismo Vuorinen" +} + +main "$@" diff --git a/scripts/install-asdf.sh b/scripts/install-asdf.sh index 25c6962..19ba55e 100755 --- a/scripts/install-asdf.sh +++ b/scripts/install-asdf.sh @@ -1,9 +1,7 @@ #!/usr/bin/env bash # # Install asdf - -source "${XDG_CONFIG_HOME}/shared.sh" -source "${DOTFILES}/scripts/shared.sh" +source "${DOTFILES}/config/shared.sh" export ASDF_DIR="${XDG_BIN_HOME}/asdf" export PATH="${ASDF_DIR}/bin:$PATH" @@ -11,16 +9,19 @@ export PATH="${ASDF_DIR}/bin:$PATH" msg "Sourcing asdf in your shell" . "$ASDF_DIR/asdf.sh" -# Update asdf, and plugins -asdf update +# Function to update asdf and plugins +update_asdf() +{ + asdf update -asdf plugin add asdf-plugin-manager https://github.com/asdf-community/asdf-plugin-manager.git -asdf install asdf-plugin-manager latest -asdf global asdf-plugin-manager "$(asdf latest asdf-plugin-manager)" -asdf-plugin-manager version -asdf-plugin-manager add-all + asdf plugin add asdf-plugin-manager https://github.com/asdf-community/asdf-plugin-manager.git + asdf install asdf-plugin-manager latest + asdf global asdf-plugin-manager "$(asdf latest asdf-plugin-manager)" + asdf-plugin-manager version + asdf-plugin-manager add-all -asdf install + asdf install +} ASDF_INSTALLABLES=( "1password-cli:github.com/NeoHsu/asdf-1password-cli.git" @@ -51,14 +52,25 @@ ASDF_INSTALLABLES=( "yq:github.com/sudermanjr/asdf-yq.git" ) -msg "Installing asdf plugins, if not already installed" -for item in "${ASDF_INSTALLABLES[@]}"; do - CMD=$(echo "${item}" | awk -F ":" '{print $1}') - URL=$(echo "${item}" | awk -F ":" '{print $2}') - asdf plugin add "${CMD}" "https://${URL}" - asdf install "${CMD}" latest - asdf global "${CMD}" "$(asdf latest "${CMD}")" -done +# Function to install asdf plugins +install_asdf_plugins() +{ + msg "Installing asdf plugins, if not already installed" + for item in "${ASDF_INSTALLABLES[@]}"; do + CMD=$(echo "${item}" | awk -F ":" '{print $1}') + URL=$(echo "${item}" | awk -F ":" '{print $2}') + asdf plugin add "${CMD}" "https://${URL}" + asdf install "${CMD}" latest + asdf global "${CMD}" "$(asdf latest "${CMD}")" + done +} -msg "Reshim asdf" -asdf reshim +main() +{ + update_asdf + install_asdf_plugins + msg "Reshim asdf" + asdf reshim +} + +main "$@" diff --git a/scripts/install-cargo-packages.sh b/scripts/install-cargo-packages.sh index 047130c..99b0d43 100755 --- a/scripts/install-cargo-packages.sh +++ b/scripts/install-cargo-packages.sh @@ -2,18 +2,18 @@ # Install cargo/rust packages. # # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" +eval "$HOME/.dotfiles/config/shared.sh" msg "Starting to install rust/cargo packages" source "$CARGO_HOME/env" # If we have cargo install-update, use it first -x-have cargo-install-update && { +if command -v cargo-install-update &> /dev/null; then msg_run "Updating cargo packages with cargo install-update" cargo install-update -a msg_done "Done with cargo install-update" -} +fi packages=( # A cargo subcommand for checking and applying @@ -42,28 +42,41 @@ packages=( # Number of jobs to run in parallel, this helps to keep the system responsive BUILD_JOBS=$(nproc --ignore=2) -for pkg in "${packages[@]}"; do - # Trim spaces - pkg=${pkg// /} - # Skip comments - if [[ ${pkg:0:1} == "#" ]]; then continue; fi +# Function to install cargo packages +install_packages() +{ + for pkg in "${packages[@]}"; do + # Trim spaces + pkg=${pkg// /} + # Skip comments + if [[ ${pkg:0:1} == "#" ]]; then continue; fi - msg_run "Installing cargo package $pkg" - cargo install --jobs $BUILD_JOBS "$pkg" - - echo "" -done - -msg_done "Installed cargo packages!" - -msg_run "Now doing the next steps for cargo packages" - -# use bob to install latest stable nvim -x-have bob && { - bob use stable && x-path-append "$XDG_DATA_HOME/bob/nvim-bin" + msg_run "Installing cargo package $pkg" + cargo install --jobs $BUILD_JOBS "$pkg" + echo "" + done } -msg_run "Removing cargo cache" -cargo cache --autoclean -msg_done "Done removing cargo cache" +# Function to perform additional steps for installed cargo packages +post_install_steps() +{ + msg_run "Now doing the next steps for cargo packages" + # use bob to install latest stable nvim + if command -v bob &> /dev/null; then + bob use stable && x-path-append "$XDG_DATA_HOME/bob/nvim-bin" + fi + + msg_run "Removing cargo cache" + cargo cache --autoclean + msg_done "Done removing cargo cache" +} + +main() +{ + install_packages + msg_done "Installed cargo packages!" + post_install_steps +} + +main "$@" diff --git a/scripts/install-cheat-purebashbible.sh b/scripts/install-cheat-purebashbible.sh index a0d0af0..c54484f 100755 --- a/scripts/install-cheat-purebashbible.sh +++ b/scripts/install-cheat-purebashbible.sh @@ -1,58 +1,83 @@ #!/usr/bin/env bash # shellcheck disable=SC2231,SC2034,SC2181,SC2068 # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" +source "${DOTFILES}/config/shared.sh" PBB_REQUIRED_TOOLS=(git cheat) -for t in ${PBB_REQUIRED_TOOLS[@]}; do - ! x-have "$t" && echo "(!) $t is missing, can't continue..." && exit 1 -done - PBB_GIT="https://github.com/dylanaraps/pure-bash-bible.git" PBB_SOURCE="source: $PBB_GIT" PBB_SYNTAX="syntax: bash" PBB_TAGS="tags: [bash]" +PBB_TEMP_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/cheat/pbb" -PBB_TEMP_PREFIX=$(basename "$0") -PBB_TEMP_DIR="$XDG_CACHE_HOME/cheat/pbb" +check_required_tools() +{ + for t in "${PBB_REQUIRED_TOOLS[@]}"; do + if ! x-have "$t"; then + echo "(!) $t is missing, can't continue..." + exit 1 + fi + done +} -# If there's no .git, clone the folder -if [ ! -d "$PBB_TEMP_DIR/.git" ]; then - msg_run "Starting to clone $PBB_GIT" - git clone --depth 1 --single-branch -q "$PBB_GIT" "$PBB_TEMP_DIR" \ - && msg_yay "Cloned $PBB_GIT" -else - # Update the repo - msg_run "Starting to update $PBB_GIT" - git -C "$PBB_TEMP_DIR" reset --hard origin/master - git -C "$PBB_TEMP_DIR" pull -q \ - && msg_yay "Updated $PBB_GIT" -fi +clone_or_update_repo() +{ + if [ ! -d "$PBB_TEMP_DIR/.git" ]; then + msg_run "Starting to clone $PBB_GIT" + git clone --depth 1 --single-branch -q "$PBB_GIT" "$PBB_TEMP_DIR" \ + && msg_yay "Cloned $PBB_GIT" + else + msg_run "Starting to update $PBB_GIT" + git -C "$PBB_TEMP_DIR" reset --hard origin/master + git -C "$PBB_TEMP_DIR" pull -q \ + && msg_yay "Updated $PBB_GIT" + fi +} -PBB_CHAPTERS=$(ls -1v "$PBB_TEMP_DIR"/manuscript/chapter*) -CHEAT_DEST="$(cheat -d | grep pure-bash-bible | head -1 | awk '{print $2}')" +prepare_cheat_dest() +{ + local cheat_dest + cheat_dest="$(cheat -d | grep pure-bash-bible | head -1 | awk '{print $2}')" -if [ ! -d "$CHEAT_DEST" ]; then - mkdir -p "$CHEAT_DEST" -fi - -for f in ${PBB_CHAPTERS[@]}; do - # get all headers, take the first one, strip the # and return the first word in lowercase - HEADER=$(grep -e '^[#] ' "$f" | head -1 | awk '{print tolower($2)}') - CHEAT_FILE="$CHEAT_DEST/${HEADER}" - - replacable "$f" "$CHEAT_FILE" - override=$? - if [ "$override" -ne 1 ]; then - cp "$f" "$CHEAT_FILE" && msg_run "Updated: $CHEAT_FILE" + if [ ! -d "$cheat_dest" ]; then + mkdir -p "$cheat_dest" fi - LC_ALL=C perl -pi.bak -e 's/\<\!-- CHAPTER END --\>//' "$CHEAT_FILE" - rm "$CHEAT_FILE.bak" + echo "$cheat_dest" +} - # add tags if the file doesn't have them - if [ '---' != "$(head -1 < "$CHEAT_FILE")" ]; then - T="$PBB_SYNTAX\n$PBB_TAGS\n$PBB_SOURCE\n" - echo -e "---\n$T---\n$(cat "$CHEAT_FILE")" > "$CHEAT_FILE" - fi -done +process_chapters() +{ + local cheat_dest + cheat_dest=$(prepare_cheat_dest) + + mapfile -t PBB_CHAPTERS < <(ls -1v "$PBB_TEMP_DIR"/manuscript/chapter*) + + for f in "${PBB_CHAPTERS[@]}"; do + local header cheat_file + header=$(grep -e '^[#] ' "$f" | head -1 | awk '{print tolower($2)}') + cheat_file="$cheat_dest/$header" + + if ! replacable "$f" "$cheat_file"; then + cp "$f" "$cheat_file" && msg_run "Updated: $cheat_file" + fi + + LC_ALL=C perl -pi.bak -e 's/\<\!-- CHAPTER END --\>//' "$cheat_file" + rm "$cheat_file.bak" + + if [ '---' != "$(head -1 < "$cheat_file")" ]; then + local metadata + metadata="$PBB_SYNTAX\n$PBB_TAGS\n$PBB_SOURCE\n" + echo -e "---\n$metadata---\n$(cat "$cheat_file")" > "$cheat_file" + fi + done +} + +main() +{ + check_required_tools + clone_or_update_repo + process_chapters +} + +main "$@" diff --git a/scripts/install-composer.sh b/scripts/install-composer.sh index 1c130b6..51f2bd6 100755 --- a/scripts/install-composer.sh +++ b/scripts/install-composer.sh @@ -2,9 +2,12 @@ # Install PHP Package Manager Composer # # shellcheck source="shared.sh" -eval "$HOME/.dotfiles/scripts/shared.sh" +eval "$HOME/.dotfiles/config/shared.sh" -! x-have "php" && msg_err "PHP Not Available, cannot install composer" && exit 0 +if ! command -v php &> /dev/null; then + msg_err "PHP Not Available, cannot install composer" + exit 0 +fi EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')" php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" diff --git a/scripts/install-fonts.sh b/scripts/install-fonts.sh index e282ef3..4dfb0fa 100755 --- a/scripts/install-fonts.sh +++ b/scripts/install-fonts.sh @@ -2,7 +2,7 @@ # Install NerdFonts # # shellcheck source="shared.sh" -eval "$HOME/.dotfiles/scripts/shared.sh" +source "$DOTFILES/config/shared.sh" GIT_REPO="https://github.com/ryanoasis/nerd-fonts.git" TMP_PATH="$XDG_CACHE_HOME/nerd-fonts" @@ -17,28 +17,50 @@ fonts=( SpaceMono ) -if [ ! -d "$TMP_PATH" ]; then - git clone --filter=blob:none --sparse "$GIT_REPO" "$TMP_PATH" -fi +# Function to clone or update the NerdFonts repository +clone_or_update_repo() +{ + if [ ! -d "$TMP_PATH" ]; then + git clone --quiet --filter=blob:none --sparse "$GIT_REPO" "$TMP_PATH" + fi -cd "$TMP_PATH" || { - msg_err "No such folder $TMP_PATH" - exit 1 + cd "$TMP_PATH" || msg_err "No such folder $TMP_PATH" } -for ext in "${fonts[@]}"; do - # Trim spaces - ext=${ext// /} - # Skip comments - if [[ ${ext:0:1} == "#" ]]; then continue; fi +# Function to add fonts to sparse-checkout +add_fonts_to_sparse_checkout() +{ + for font in "${fonts[@]}"; do + # Trim spaces + font=${font// /} + # Skip comments + if [[ ${font:0:1} == "#" ]]; then continue; fi - msg_run "Adding $ext to sparse-checkout" - git sparse-checkout add "patched-fonts/$ext" - echo "" -done + msg_run "Adding $font to sparse-checkout" + git sparse-checkout add "patched-fonts/$font" + echo "" + done +} -msg "Starting to install NerdFonts..." +# Function to install NerdFonts +install_fonts() +{ + msg "Starting to install NerdFonts..." + ./install.sh -q -s ${fonts[*]} + msg_ok "Done" +} -./install.sh -s ${fonts[*]} +remove_tmp_path() +{ + rm -rf "$TMP_PATH" +} -msg_ok "Done" +main() +{ + clone_or_update_repo + add_fonts_to_sparse_checkout + install_fonts + remove_tmp_path +} + +main "$@" diff --git a/scripts/install-fzf.sh b/scripts/install-fzf.sh index 4eae119..6c03664 100755 --- a/scripts/install-fzf.sh +++ b/scripts/install-fzf.sh @@ -3,17 +3,23 @@ # Install fzf # # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" +eval "$DOTFILES/config/shared.sh" FZF_GIT="https://github.com/junegunn/fzf.git" FZF_PATH="${XDG_CONFIG_HOME}/fzf" FZF_BUILD="/tmp/fzf" -if [ ! -d "$FZF_BUILD" ]; then - git clone --depth 1 "$FZF_GIT" "$FZF_BUILD" - "$FZF_BUILD/install" \ - --xdg \ - --bin -else - msg_done "fzf ($FZF_PATH/) already installed" -fi +main() +{ + if [ ! -d "$FZF_BUILD" ]; then + git clone --depth 1 "$FZF_GIT" "$FZF_BUILD" + "$FZF_BUILD/install" \ + --xdg \ + --bin + msg_done "fzf installed" + else + msg_done "fzf ($FZF_PATH/) already installed" + fi +} + +main "$@" diff --git a/scripts/install-gh-extensions.sh b/scripts/install-gh-extensions.sh index 2c62df6..a61ff22 100755 --- a/scripts/install-gh-extensions.sh +++ b/scripts/install-gh-extensions.sh @@ -2,13 +2,17 @@ # Install GitHub CLI extensions # # shellcheck source="shared.sh" -eval "$HOME/.dotfiles/scripts/shared.sh" +source "${DOTFILES}/config/shared.sh" + +# Enable verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" msg_run "Installing gh (GitHub Client) extensions" -! x-have "gh" \ - && msg_err "gh (GitHub Client) could not be found, please install it first" \ - && exit 0 +if ! command -v gh &> /dev/null; then + msg_err "gh (GitHub Client) could not be found, please install it first" + exit 0 +fi extensions=( # GitHub CLI extension for generating a report on repository dependencies. @@ -30,15 +34,25 @@ extensions=( rsese/gh-actions-status ) -for ext in "${extensions[@]}"; do - # Trim spaces - ext=${ext// /} - # Skip comments - if [[ ${ext:0:1} == "#" ]]; then continue; fi +# Function to install GitHub CLI extensions +install_extensions() +{ + for ext in "${extensions[@]}"; do + # Trim spaces + ext=${ext// /} + # Skip comments + if [[ ${ext:0:1} == "#" ]]; then continue; fi - msg_nested "Installing $ext" - gh extensions install "$ext" - echo "" -done + msg_nested "Installing $ext" + gh extension install "$ext" + echo "" + done +} -msg_ok "Done" +main() +{ + install_extensions + msg_ok "Done" +} + +main "$@" diff --git a/scripts/install-git-crypt.sh b/scripts/install-git-crypt.sh index 9ba9dae..3fd4097 100755 --- a/scripts/install-git-crypt.sh +++ b/scripts/install-git-crypt.sh @@ -4,12 +4,14 @@ # NOTE: Experimental, wip # # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" +source "${DOTFILES}/config/shared.sh" + +# Enable verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" msg_run "Installing git-crypt" -x-have "git-crypt" || { - +if ! command -v git-crypt &> /dev/null; then REPO_URL="https://github.com/AGWA/git-crypt.git" CHECK_PATH="${XDG_BIN_HOME}/git-crypt" BUILD_PATH="/tmp/git-crypt" @@ -23,5 +25,6 @@ x-have "git-crypt" || { else msg_done "git-crypt ($CHECK_PATH) already installed" fi -} +fi + msg_done "Done installing git-crypt" diff --git a/scripts/install-go-packages.sh b/scripts/install-go-packages.sh index 477702e..356e5c1 100755 --- a/scripts/install-go-packages.sh +++ b/scripts/install-go-packages.sh @@ -2,7 +2,10 @@ # Install Go packages # # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" +eval "$DOTFILES/config/shared.sh" + +# Enable verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" msg_run "Installing go packages" @@ -33,32 +36,50 @@ packages=( github.com/doron-cohen/antidot@latest ) -for pkg in "${packages[@]}"; do - # Trim spaces - pkg=${pkg// /} - # Skip comments - if [[ ${pkg:0:1} == "#" ]]; then continue; fi +# Function to install go packages +install_packages() +{ + for pkg in "${packages[@]}"; do + # Trim spaces + pkg=${pkg// /} + # Skip comments + if [[ ${pkg:0:1} == "#" ]]; then continue; fi - msg_nested "Installing go package: $pkg" - go install "$pkg" - echo "" -done - -msg_run "Installing completions for selected packages" - -x-have git-profile && { - git-profile completion zsh > "$ZSH_CUSTOM_COMPLETION_PATH/_git-profile" \ - && msg_ok "Installed completions for git-profile" + msg_nested "Installing go package: $pkg" + go install "$pkg" + echo "" + done } -x-have antidot && { - antidot update \ - && msg_ok "Updated antidot database" +# Function to install completions and run actions for selected packages +post_install() +{ + msg_run "Installing completions for selected packages" + + if command -v git-profile &> /dev/null; then + git-profile completion zsh > "$ZSH_CUSTOM_COMPLETION_PATH/_git-profile" \ + && msg_ok "Installed completions for git-profile" + fi + + if command -v antidot &> /dev/null; then + antidot update \ + && msg_ok "Updated antidot database" + fi } -echo "" +# Function to clear go cache +clear_go_cache() +{ + msg_run "Clearing go cache" + go clean -cache -modcache +} -msg_run "Clearing go cache" -go clean -cache -modcache +main() +{ + install_packages + post_install + clear_go_cache + msg_ok "Done" +} -msg_ok "Done" +main "$@" diff --git a/scripts/install-neofetch.sh b/scripts/install-neofetch.sh index 0206536..5f691f9 100755 --- a/scripts/install-neofetch.sh +++ b/scripts/install-neofetch.sh @@ -3,23 +3,71 @@ # Install neofetch from source # # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" +source "$DOTFILES/config/shared.sh" -NEOFETCH_VERSION="7.1.0" +if ! declare -f msg > /dev/null; then + # Function to print messages if VERBOSE is enabled + # $1 - message (string) + msg() + { + [ "$VERBOSE" -eq 1 ] && echo "$1" + return 0 + } +fi + +if ! declare -f msg_err > /dev/null; then + # Function to print error messages and exit + # $1 - error message (string) + msg_err() + { + echo "(!) ERROR: $1" >&2 + exit 1 + } +fi + +if ! declare -f msg_done > /dev/null; then + # Function to print done message + # $1 - message (string) + msg_done() + { + echo "✓ $1" + return 0 + } +fi + +NEOFETCH_VERSION="$(x-gh-get-latest-version dylanaraps/neofetch)" NEOFETCH_REPO="https://github.com/dylanaraps/neofetch" NEOFETCH_URL="${NEOFETCH_REPO}/archive/refs/tags/${NEOFETCH_VERSION}.tar.gz" NEOFETCH_TEMP="/tmp/neofetch" NEOFETCH_INSTALL_PREFIX="$HOME/.local" -x-have "neofetch" || { +# Enable verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" + +# Function to install neofetch from source +install_neofetch() +{ LC_ALL=C mkdir -p "$NEOFETCH_TEMP" "$NEOFETCH_INSTALL_PREFIX" - curl -L "$NEOFETCH_URL" > "$NEOFETCH_TEMP.tar.gz" + curl -L "$NEOFETCH_URL" -o "$NEOFETCH_TEMP.tar.gz" tar zxvf "$NEOFETCH_TEMP.tar.gz" --directory="$NEOFETCH_TEMP" cd "$NEOFETCH_TEMP/neofetch-$NEOFETCH_VERSION" \ && make PREFIX="${NEOFETCH_INSTALL_PREFIX}" install \ && rm -rf "$NEOFETCH_TEMP*" \ && msg_yay "neofetch installed!" } + +main() +{ + if ! command -v neofetch &> /dev/null; then + install_neofetch + elif [ "$NEOFETCH_VERSION" != "$(neofetch --version | awk '{print $2}')" ]; then + install_neofetch + else + msg_done "neofetch v.${NEOFETCH_VERSION} already installed" + fi +} + +main "$@" diff --git a/scripts/install-npm-packages.sh b/scripts/install-npm-packages.sh index a6e96ad..afe4c16 100755 --- a/scripts/install-npm-packages.sh +++ b/scripts/install-npm-packages.sh @@ -2,11 +2,17 @@ # Install npm packages globally. # # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" +eval "$DOTFILES/config/shared.sh" + +# Enable verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" msg "Starting to install npm packages" -! x-have "npm" && msg_err "npm could not be found." && exit 0 +if ! command -v npm &> /dev/null; then + msg_err "npm could not be found." + exit 0 +fi packages=( # This is a tool to check if your files consider your .editorconfig rules. @@ -18,27 +24,48 @@ packages=( "corepack" ) -for pkg in "${packages[@]}"; do - # Trim spaces - pkg=${pkg// /} - # Skip comments - if [[ ${pkg:0:1} == "#" ]]; then continue; fi +# Function to install npm packages +install_packages() +{ + for pkg in "${packages[@]}"; do + # Trim spaces + pkg=${pkg// /} + # Skip comments + if [[ ${pkg:0:1} == "#" ]]; then continue; fi - if [[ $(npm ls -g -p "$pkg") != "" ]]; then - msg_run_done "$pkg" "already installed" - else - msg_run "Installing npm package:" "$pkg" - npm install -g --no-fund --no-progress --no-timing "$pkg" - fi + if npm ls -g -p "$pkg" &> /dev/null; then + msg_run_done "$pkg" "already installed" + else + msg_run "Installing npm package:" "$pkg" + npm install -g --no-fund --no-progress --no-timing "$pkg" + fi + echo "" + done +} - echo "" -done +# Function to upgrade all global npm packages +upgrade_global_packages() +{ + msg_run "Upgrading all global packages" + npm -g --no-progress --no-timing --no-fund outdated + npm -g --no-timing --no-fund upgrade +} -msg_run "Upgrading all global packages" -npm -g --no-progress --no-timing --no-fund outdated -npm -g --no-timing --no-fund upgrade +# Function to clean npm cache +clean_npm_cache() +{ + msg_run "Cleaning up npm cache" + npm cache verify + npm cache clean --force + npm cache verify +} -msg_run "Cleaning up npm cache" -npm cache verify -npm cache clean --force -npm cache verify +main() +{ + install_packages + upgrade_global_packages + clean_npm_cache + msg_yay "npm package installations complete" +} + +main "$@" diff --git a/scripts/install-ntfy.sh b/scripts/install-ntfy.sh index 6108196..07149ee 100755 --- a/scripts/install-ntfy.sh +++ b/scripts/install-ntfy.sh @@ -3,11 +3,18 @@ # Install ntfy # # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" -set -e +eval "$DOTFILES/config/shared.sh" -x-have "ntfy" && msg "ntfy already installed" && exit 0 +# Enable verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" +# Check if ntfy is already installed +if x-have "ntfy"; then + msg "ntfy already installed" + exit 0 +fi + +# Determine the architecture case $(dfm check arch) in Linux) NTFY_ARCH="linux_$(arch)" @@ -15,21 +22,36 @@ case $(dfm check arch) in Darwin) NTFY_ARCH="macOS_all" ;; + *) + msg_err "Unsupported OS" + ;; esac -NTFY_VERSION=2.2.0 +NTFY_VERSION="$(x-gh-get-latest-version binwiederhier/ntfy)" NTFY_URL="https://github.com/binwiederhier/ntfy" NTFY_DEST="/tmp/ntfy_${NTFY_VERSION}_${NTFY_ARCH}" -curl -L "$NTFY_URL/releases/download/v${NTFY_VERSION}/${NTFY_DEST}.tar.gz" \ - > "${NTFY_DEST}.tar.gz" -tar zxvf "${NTFY_DEST}.tar.gz" -cp -a "${NTFY_DEST}/ntfy" ~/.local/bin/ntfy -mkdir -p ~/.config/ntfy +# Download and extract ntfy +install_ntfy() +{ + curl -L "$NTFY_URL/releases/download/v${NTFY_VERSION}/${NTFY_DEST}.tar.gz" -o "${NTFY_DEST}.tar.gz" + tar zxvf "${NTFY_DEST}.tar.gz" + cp -a "${NTFY_DEST}/ntfy" ~/.local/bin/ntfy + mkdir -p ~/.config/ntfy -# copy config only if it does not exist -if [ ! -f "$HOME/.config/ntfy/client.yml" ]; then - cp "${NTFY_DEST}/client/client.yml" ~/.config/ntfy/client.yml -fi + # Copy config only if it does not exist + if [ ! -f "$HOME/.config/ntfy/client.yml" ]; then + cp "${NTFY_DEST}/client/client.yml" ~/.config/ntfy/client.yml + fi -rm -rf "${NTFY_DEST}" "${NTFY_DEST}.tar.gz" + # Clean up + rm -rf "${NTFY_DEST}" "${NTFY_DEST}.tar.gz" +} + +main() +{ + install_ntfy + msg "ntfy installation complete" +} + +main "$@" diff --git a/scripts/install-ohmybash.sh b/scripts/install-ohmybash.sh index cefad03..319f262 100755 --- a/scripts/install-ohmybash.sh +++ b/scripts/install-ohmybash.sh @@ -3,14 +3,31 @@ # Install oh-my-bash # # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" +source "${DOTFILES}/config/shared.sh" -export OSH="$HOME/.local/share/oh-my-bash" +set -euo pipefail -if [ ! -d "$OSH" ]; then - [ -f "$HOME/.bashrc" ] && mv "$HOME/.bashrc" "$HOME/.bashrc.temp" - bash -c "$(curl -fsSL https://raw.githubusercontent.com/ohmybash/oh-my-bash/master/tools/install.sh)" --unattended - [ -f "$HOME/.bashrc.temp" ] && mv "$HOME/.bashrc.temp" "$HOME/.bashrc" -else - msg_done "oh-my-bash ($OSH) already installed" -fi +# Enable verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" + +OSH="$HOME/.local/share/oh-my-bash" + +# Function to install oh-my-bash +install_oh_my_bash() +{ + if [ ! -d "$OSH" ]; then + [ -f "$HOME/.bashrc" ] && mv "$HOME/.bashrc" "$HOME/.bashrc.temp" + bash -c "$(curl -fsSL https://raw.githubusercontent.com/ohmybash/oh-my-bash/master/tools/install.sh)" --unattended + [ -f "$HOME/.bashrc.temp" ] && mv "$HOME/.bashrc.temp" "$HOME/.bashrc" + msg "oh-my-bash installed to $OSH" + else + msg_done "oh-my-bash ($OSH) already installed" + fi +} + +main() +{ + install_oh_my_bash +} + +main "$@" diff --git a/scripts/install-ohmyposh.sh b/scripts/install-ohmyposh.sh index 9e7c78e..7ff9a6f 100755 --- a/scripts/install-ohmyposh.sh +++ b/scripts/install-ohmyposh.sh @@ -3,9 +3,31 @@ # Install oh-my-posh # # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" +source "${DOTFILES}/config/shared.sh" -curl -s https://ohmyposh.dev/install.sh | bash -s -- -d ~/.local/bin +# Enable verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" -eval "$(oh-my-posh init zsh --config $OHMYPOSH_CFG)" +msg "Starting to install oh-my-posh" +# Install oh-my-posh +install_oh_my_posh() +{ + curl -s https://ohmyposh.dev/install.sh | bash -s -- -d ~/.local/bin + msg "oh-my-posh installed to ~/.local/bin" +} + +# Initialize oh-my-posh +init_oh_my_posh() +{ + eval "$(oh-my-posh init zsh --config $OHMYPOSH_CFG)" + msg "oh-my-posh initialized with config $OHMYPOSH_CFG" +} + +main() +{ + install_oh_my_posh + init_oh_my_posh +} + +main "$@" diff --git a/scripts/install-pip-packages.sh b/scripts/install-pip-packages.sh index 5ebd67a..e7166f7 100755 --- a/scripts/install-pip-packages.sh +++ b/scripts/install-pip-packages.sh @@ -2,13 +2,17 @@ # Install python/pip packages. # # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" +source "${DOTFILES}/config/shared.sh" + +# Enable verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" msg "Starting to install pip packages" -x-have "python3" || { - msg_err "Could not find python3, something really weird is going on." && exit 1 -} +if ! command -v python3 &> /dev/null; then + msg_err "Could not find python3, something really weird is going on." + exit 1 +fi msg_nested "Upgrading pip" python3 -m pip install --user --upgrade pip @@ -18,16 +22,20 @@ packages=( "libtmux" ) -for pkg in "${packages[@]}"; do - # Trim spaces - pkg=${pkg// /} - # Skip comments - if [[ ${pkg:0:1} == "#" ]]; then continue; fi +# Function to install pip packages +install_packages() +{ + for pkg in "${packages[@]}"; do + # Trim spaces + pkg=${pkg// /} + # Skip comments + if [[ ${pkg:0:1} == "#" ]]; then continue; fi - msg_nested "Installing pip package: $pkg" - python3 -m pip install --user --upgrade "$pkg" - - echo "" -done + msg_nested "Installing pip package: $pkg" + python3 -m pip install --user --upgrade "$pkg" + echo "" + done +} +install_packages msg_yay "Run pip package installations" diff --git a/scripts/install-xcode-cli-tools.sh b/scripts/install-xcode-cli-tools.sh index 5c1e8f2..959fefb 100755 --- a/scripts/install-xcode-cli-tools.sh +++ b/scripts/install-xcode-cli-tools.sh @@ -4,29 +4,40 @@ # Ismo Vuorinen 2018 # -[ "$(uname)" != "Darwin" ] && echo "Not a macOS system" && exit 0 +# Enable verbosity with VERBOSE=1 +VERBOSE="${VERBOSE:-0}" -! x-have xcode-select \ - && msg_err "xcode-select could not be found, skipping" \ - && exit 0 +# Check if the script is running on macOS +if [ "$(uname)" != "Darwin" ]; then + echo "Not a macOS system" + exit 0 +fi + +# Check if xcode-select is available +if ! command -v xcode-select &> /dev/null; then + msg_err "xcode-select could not be found, skipping" + exit 0 +fi # Ask for the administrator password upfront sudo -v -# Keep-alive: update existing `sudo` time stamp until `settler` has finished -while true; do - sudo -n true - sleep 60 - kill -0 "$$" || exit -done 2> /dev/null & +# Keep-alive: update existing `sudo` time stamp until the script has finished +keep_alive_sudo() +{ + while true; do + sudo -n true + sleep 60 + kill -0 "$$" || exit + done 2> /dev/null & +} XCODE_TOOLS_PATH=$(xcode-select -p) XCODE_SWIFT_PATH="$XCODE_TOOLS_PATH/usr/bin/swift" -# Modified from https://unix.stackexchange.com/a/408305 -if [ -a "$XCODE_SWIFT_PATH" ]; then - echo "You have swift from xcode-select. Continuing..." -else +# Function to prompt for XCode CLI Tools installation +prompt_xcode_install() +{ XCODE_MESSAGE="$( osascript -e \ 'tell app "System Events" to display dialog "Please click install when Command Line Developer Tools appears"' @@ -36,11 +47,25 @@ else xcode-select --install else echo "You have cancelled the installation, please rerun the installer." - exit + exit 1 fi -fi +} -until [ -f "$XCODE_SWIFT_PATH" ]; do - echo -n "." - sleep 1 -done +# Main function +main() +{ + keep_alive_sudo + + if [ -x "$XCODE_SWIFT_PATH" ]; then + echo "You have swift from xcode-select. Continuing..." + else + prompt_xcode_install + fi + + until [ -f "$XCODE_SWIFT_PATH" ]; do + echo -n "." + sleep 1 + done +} + +main "$@" diff --git a/scripts/install-z.sh b/scripts/install-z.sh index b1c5cb6..459aad9 100755 --- a/scripts/install-z.sh +++ b/scripts/install-z.sh @@ -3,13 +3,29 @@ # Install z # # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" +source "${DOTFILES}/config/shared.sh" Z_GIT_PATH="https://github.com/rupa/z.git" Z_BIN_PATH="$XDG_BIN_HOME/z" -if [ ! -d "$Z_BIN_PATH" ]; then - git clone "$Z_GIT_PATH" "$Z_BIN_PATH" -else - msg_done "z ($Z_BIN_PATH/) already installed" -fi +# Function to clone the z repository +clone_z_repo() +{ + local git_path=$1 + local bin_path=$2 + + if [ ! -d "$bin_path" ]; then + git clone "$git_path" "$bin_path" + msg "z installed at $bin_path" + else + msg "z ($bin_path/) already installed" + fi +} + +# Main function +main() +{ + clone_z_repo "$Z_GIT_PATH" "$Z_BIN_PATH" +} + +main "$@" diff --git a/scripts/set-macos-defaults.sh b/scripts/set-macos-defaults.sh index 8842165..9bd7497 100755 --- a/scripts/set-macos-defaults.sh +++ b/scripts/set-macos-defaults.sh @@ -9,7 +9,7 @@ [ "$(uname)" != "Darwin" ] && echo "Not a macOS system" && exit 0 # shellcheck source=shared.sh -eval "$HOME/.dotfiles/scripts/shared.sh" +eval "$HOME/.dotfiles/config/shared.sh" msg_run "Starting to set macOS defaults, these require sudo privileges:" @@ -63,7 +63,7 @@ defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool false # Automatically quit printer app once the print jobs complete defaults write com.apple.print.PrintingPrefs "Quit When Finished" -bool true -# Disable the “Are you sure you want to open this application?” dialog +# Disable the "Are you sure you want to open this application?" dialog defaults write com.apple.LaunchServices LSQuarantine -bool false # Disable Resume system-wide @@ -79,10 +79,10 @@ defaults write NSGlobalDomain NSDisableAutomaticTermination -bool true # in the login window sudo defaults write /Library/Preferences/com.apple.loginwindow AdminHostInfo HostName -# Disable smart quotes as they’re annoying when typing code +# Disable smart quotes as they're annoying when typing code defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool false -# Disable smart dashes as they’re annoying when typing code +# Disable smart dashes as they're annoying when typing code defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool false ############################################################################### @@ -94,7 +94,7 @@ msg_nested "Setting SSD-specific tweaks" # Disable hibernation (speeds up entering sleep mode) sudo pmset -a hibernatemode 0 -# Disable the sudden motion sensor as it’s not useful for SSDs +# Disable the sudden motion sensor as it's not useful for SSDs sudo pmset -a sms 0 ############################################################################### @@ -117,7 +117,7 @@ defaults write com.apple.BluetoothAudioAgent "Negotiated Bitpool Min" 80 defaults write NSGlobalDomain AppleKeyboardUIMode -int 3 # Set language and text formats -# Note: if you’re in the US, replace `EUR` with `USD`, `Centimeters` with +# Note: if you're in the US, replace `EUR` with `USD`, `Centimeters` with # `Inches`, `en_GB` with `en_US`, and `true` with `false`. defaults write NSGlobalDomain AppleLanguages -array "en" defaults write NSGlobalDomain AppleLocale -string "en_GB@currency=EUR" @@ -197,7 +197,7 @@ defaults write com.apple.finder WarnOnEmptyTrash -bool false # chflags nohidden /Users # Expand the following File Info panes: -# “General”, “Open with”, and “Sharing & Permissions” +# "General", "Open with", and "Sharing & Permissions" defaults write com.apple.finder FXInfoPanesExpanded -dict \ General -bool true \ OpenWith -bool true \ @@ -235,17 +235,17 @@ defaults write com.apple.dock tilesize -int 30 defaults write com.apple.dock show-process-indicators -bool true # Wipe all (default) app icons from the Dock -# This is only really useful when setting up a new Mac, or if you don’t use +# This is only really useful when setting up a new Mac, or if you don't use # the Dock to launch apps. # defaults write com.apple.dock persistent-apps -array "" # Disable Dashboard defaults write com.apple.dashboard mcx-disabled -bool true -# Don’t show Dashboard as a Space +# Don't show Dashboard as a Space defaults write com.apple.dock dashboard-in-overlay -bool true -# Don’t automatically rearrange Spaces based on most recent use +# Don't automatically rearrange Spaces based on most recent use defaults write com.apple.dock mru-spaces -bool false # Make Dock icons of hidden applications translucent @@ -257,7 +257,7 @@ defaults write com.apple.dock showhidden -bool true msg_nested "Settings for Safari & WebKit" -# Enable Safari’s debug menu +# Enable Safari's debug menu defaults write com.apple.Safari IncludeInternalDebugMenu -bool true # Enable the Develop menu and the Web Inspector in Safari @@ -268,7 +268,7 @@ defaults write com.apple.Safari \ com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled \ -bool true -# Don’t display the annoying prompt when quitting iTerm +# Don't display the annoying prompt when quitting iTerm defaults write com.googlecode.iterm2 PromptOnQuit -bool false # Use iTerm2 preferences from the .dotfiles folder. defaults write com.googlecode.iterm2 PrefsCustomFolder \ @@ -315,7 +315,7 @@ defaults write com.apple.TextEdit PlainTextEncodingForWrite -int 4 msg_nested "Settings for Messages" -# Disable smart quotes as it’s annoying for messages that contain code +# Disable smart quotes as it's annoying for messages that contain code defaults write com.apple.messageshelper.MessageController \ SOInputLineSettings \ -dict-add "automaticQuoteSubstitutionEnabled" \ @@ -335,7 +335,7 @@ msg_nested "Restarting applications to apply changes" for app in "Activity Monitor" "Address Book" "Calendar" "Contacts" "cfprefsd" \ "Dock" "Finder" "Mail" "Messages" "Safari" "SizeUp" "SystemUIServer" \ - "Terminal" "Transmission" "Twitter" "iCal"; do + "Terminal" "Transmission" "iCal"; do killall "${app}" > /dev/null 2>&1 done diff --git a/scripts/shared.sh b/scripts/shared.sh index 1b5cd51..a328f8d 100755 --- a/scripts/shared.sh +++ b/scripts/shared.sh @@ -6,164 +6,14 @@ # Helper env variables. Use like this: VERBOSE=1 ./script.sh : "${VERBOSE:=0}" -# Modified from https://stackoverflow.com/a/28776166 -( - [[ -n $ZSH_VERSION && $ZSH_EVAL_CONTEXT =~ :file$ ]] \ - || [[ -n $BASH_VERSION ]] && (return 0 2> /dev/null) -) && sourced=1 || sourced=0 +# Set variable that checks if the shared.sh script has been sourced only once +# If the script has been sourced more than once, the script not be sourced again +[ -z "$SHARED_SCRIPTS_SOURCED" ] && { -eval "$HOME/.dotfiles/config/shared.sh" + source "${DOTFILES}/config/shared.sh" + msgr done "(!) shared.sh not sourced" -DOTFILES_CURRENT_SHELL=$(ps -p $$ -oargs=) -export DOTFILES_CURRENT_SHELL - -# Other variables -export OHMYPOSH_CFG="$HOME/.dotfiles/config/omp/own.toml" - -# Remove directory from the PATH variable -# usage: path_remove ~/.local/bin -function path_remove -{ - x-path-remove "$1" -} - -# Append directory to the PATH -# usage: path_append ~/.local/bin -function path_append -{ - x-path-remove "$1" - x-path-prepend "$1" -} - -# Prepend directory to the PATH -# usage: path_prepend ~/.local/bin -function path_prepend -{ - x-path-remove "$1" - x-path-prepend "$1" -} - -# Run command silently -# Usage: silent uptime -silent() -{ - "$@" >&/dev/null -} - -# Check if a file contains non-ascii characters -nonascii() -{ - LC_ALL=C grep -n '[^[:print:][:space:]]' "${@}" -} - -source "$DOTFILES/local/bin/msgr" - -# -- Menu builder -- # -function menu_section() -{ - LINE=$(printf '%-18s [ %-15s ]\n' "$1" "$2") - echo -e " $(__log_marker) $LINE" -} -function menu_item() -{ - LINE=$(printf '%-15s %-30s\n' "$1" "$2") - echo -e "$(__log_indent)$(__log_marker) $LINE" -} - -# https://stackoverflow.com/a/85932 -function fn_exists() -{ - declare -f -F "$1" > /dev/null - return $? -} - -# Takes a bash array ("cow:moo", "dinosaur:roar") and loops -# through the keys to build menu section listing. -function menu_usage_header() -{ - MENU_CMD="$1" - shift - MENU_ARRAY=("$@") - - KEYS="" - for item in "${MENU_ARRAY[@]}"; do - CMD=$(echo "${item}" | awk -F ":" '{print $1}') - KEYS+="${CMD} | " - done - - # "???" removes 3 last characters, being " | " from the end - menu_section "$MENU_CMD" "${KEYS%???}" -} - -# Takes the usage command "$0 dotfiles" and a -# bash array ("cow:moo" "dinosaur:roar") and loops -# through in building a menu for dfm command usage listing. -function menu_usage() -{ - MENU_CMD="$1" - shift - MENU_ARRAY=("$@") - - msg "$MENU_CMD" - - for item in "${MENU_ARRAY[@]}"; do - CMD=$(echo "${item}" | awk -F ":" '{print $1}') - DESC=$(echo "${item}" | awk -F ":" '{print $2}') - menu_item "$CMD" "$DESC" - done -} - -# Creates a random string -rnd() -{ - echo $RANDOM | md5sum | head -c 20 -} - -# return sha256sum for file -# $1 - filename (string) -function get_sha256sum() -{ - sha256sum "$1" | head -c 64 -} - -# Replaceable file -# -# $1 - filename (string) -# $2 - filename (string) -# -# Returns 1 when replaceable, 0 when not replaceable. -function replacable() -{ - FILE1="$1" - FILE2="$2" - - [[ ! -r "$FILE1" ]] && { - [[ $VERBOSE -eq 1 ]] && msg_err "File 1 ($FILE1) does not exist" - return 0 - } - [[ ! -r "$FILE2" ]] && { - [[ $VERBOSE -eq 1 ]] && msg_err "File 2 ($FILE2) does not exist, replaceable" - return 1 - } - - FILE1_HASH=$(get_sha256sum "$FILE1") - FILE2_HASH=$(get_sha256sum "$FILE2") - - [[ $FILE1_HASH = "" ]] && { - [[ $VERBOSE -eq 1 ]] && msg_err "Could not get hash for file 1 ($FILE1)" - return 0 - } - [[ $FILE2_HASH = "" ]] && { - [[ $VERBOSE -eq 1 ]] && msg_err "Could not get hash for file 2 ($FILE2), replaceable" - return 1 - } - - [[ "$FILE1_HASH" == "$FILE2_HASH" ]] && { - [[ $VERBOSE -eq 1 ]] && msg_ok "Files match, not replaceable: $FILE1" - return 0 - } - - [[ $VERBOSE -eq 1 ]] && msg_warn "Files do not match ($FILE1_HASH != $FILE2_HASH), replaceable" - - return 1 + # Set variable that checks if the shared.sh script has been sourced only once + # shellcheck disable=SC2034 + export SHARED_SCRIPTS_SOURCED=1 }