Compare commits

..

1 Commits

Author SHA1 Message Date
renovate[bot]
f09bc32011 chore(deps): update image python to v3.14.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-05 17:57:53 +00:00
39 changed files with 534 additions and 311 deletions

12
.gitmodules vendored
View File

@@ -4,6 +4,11 @@
url = https://github.com/anishathalye/dotbot.git
ignore = dirty
[submodule "dotbot-brew"]
path = tools/dotbot-brew
url = https://github.com/wren/dotbot-brew.git
ignore = dirty
[submodule "dotbot-include"]
path = tools/dotbot-include
url = https://gitlab.com/gnfzdz/dotbot-include.git
@@ -24,6 +29,11 @@
url = https://github.com/tmux-plugins/tmux-sessionist.git
ignore = dirty
[submodule "dotbot-pip"]
path = tools/dotbot-pip
url = https://github.com/sobolevn/dotbot-pip.git
ignore = dirty
[submodule "tmux/tmux-suspend"]
path = config/tmux/plugins/tmux-suspend
url = https://github.com/MunifTanjim/tmux-suspend.git
@@ -53,8 +63,6 @@
[submodule "tmux/tmux-resurrect"]
path = config/tmux/plugins/tmux-resurrect
url = https://github.com/tmux-plugins/tmux-resurrect.git
ignore = dirty
[submodule "tmux/catppuccin"]
path = config/tmux/plugins/catppuccin
url = https://github.com/catppuccin/tmux.git
ignore = dirty

View File

@@ -6,5 +6,6 @@ config/tmux/plugins/**
config/vim/plugged/**
node_modules
tools/antidote/**
tools/dotbot-brew/**
tools/dotbot-include/**
tools/dotbot/**

View File

@@ -5,8 +5,12 @@ git submodule sync --recursive
# dotbot and plugins
git submodule add --name dotbot \
-f https://github.com/anishathalye/dotbot.git tools/dotbot
git submodule add --name dotbot-brew \
-f https://github.com/wren/dotbot-brew.git tools/dotbot-brew
git submodule add --name dotbot-include \
-f https://gitlab.com/gnfzdz/dotbot-include.git tools/dotbot-include
git submodule add --name dotbot-pip \
-f https://github.com/sobolevn/dotbot-pip.git tools/dotbot-pip
# other repos
git submodule add --name cheat-community \
@@ -42,64 +46,26 @@ done
# Mark certain repositories shallow
git config -f .gitmodules submodule.antidote.shallow true
_log() {
if command -v msgr > /dev/null 2>&1; then
msgr run_done "$1"
else
echo " [ok] $1"
fi
}
remove_old_submodule() {
local name="$1" path="$2"
# Remove working tree
if [ -d "$path" ]; then
rm -rf "$path"
_log "Removed $path"
fi
# Remove stale git index entry
git rm --cached "$path" 2> /dev/null || true
# Remove .git/config section keyed by path
git config --remove-section "submodule.$path" 2> /dev/null || true
# Skip name-based cleanup if no submodule name provided
[ -z "$name" ] && return 0
# Remove .git/config section keyed by name
git config --remove-section "submodule.$name" 2> /dev/null || true
# Remove .git/modules/<name>/ cached repository
if [ -d ".git/modules/$name" ]; then
rm -rf ".git/modules/$name"
_log "Removed .git/modules/$name"
fi
}
# remove old submodules (name:path pairs)
old_submodules=(
"tmux/tpm:config/tmux/plugins/tpm"
":config/tmux/plugins/tmux"
"tmux/tmux-menus:config/tmux/plugins/tmux-menus"
"dotbot-crontab:tools/dotbot-crontab"
"dotbot-snap:tools/dotbot-snap"
"tmux/tmux-window-name:config/tmux/plugins/tmux-window-name"
"tmux/tmux-sensible:config/tmux/plugins/tmux-sensible"
"tmux/tmux-mode-indicator:config/tmux/plugins/tmux-mode-indicator"
"tmux/tmux-yank:config/tmux/plugins/tmux-yank"
":config/tmux/plugins/tmux-fzf-url"
"nvim-kickstart:config/nvim-kickstart"
"asdf:local/bin/asdf"
"asdf:local/asdf"
"dotbot-asdf:tools/dotbot-asdf"
"dotbot-pip:tools/dotbot-pip"
"dotbot-brew:tools/dotbot-brew"
# remove old submodules
folders=(
"config/tmux/plugins/tpm"
"config/tmux/plugins/tmux"
"config/tmux/plugins/tmux-menus"
"tools/dotbot-crontab"
"tools/dotbot-snap"
"config/tmux/plugins/tmux-window-name"
"config/tmux/plugins/tmux-sensible"
"config/tmux/plugins/tmux-mode-indicator"
"config/tmux/plugins/tmux-yank"
"config/tmux/plugins/tmux-fzf-url"
"config/nvim-kickstart"
"local/bin/asdf"
"local/asdf"
"tools/dotbot-asdf"
)
for entry in "${old_submodules[@]}"; do
name="${entry%%:*}"
path="${entry#*:}"
remove_old_submodule "$name" "$path"
for folder in "${folders[@]}"; do
[ -d "$folder" ] \
&& rm -rf "$folder" \
&& msgr run_done "Removed old submodule $folder"
done

View File

@@ -2,14 +2,14 @@
-- These globals can be set and accessed:
--
globals = {
"rawrequire",
"rawrequire",
}
--
-- These globals can only be accessed:
--
read_globals = {
"hs",
"ls",
"spoon",
"hs",
"ls",
"spoon",
}

View File

@@ -370,7 +370,7 @@ def infer_type_from_param_name(param_name: str) -> str:
# Function indicators
if (param_name in ["fn", "func", "callback", "handler", "listener",
"predicate", "filter", "mapper", "reducer"]):
"predicate", "filter", "mapper", "reducer"]):
return "function"
# Number indicators

View File

@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
"$schema": "https://biomejs.dev/schemas/2.3.1/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",

View File

@@ -0,0 +1 @@
/Applications/OrbStack.app/Contents/MacOS/../Resources/completions/fish/kubectl.fish

View File

@@ -0,0 +1 @@
/Applications/OrbStack.app/Contents/MacOS/../Resources/completions/fish/orbctl.fish

View File

@@ -260,6 +260,8 @@ brew "php@8.2", link: true
brew "php@8.3"
# Pins GitHub Actions to full hashes and versions
brew "pinact"
# Execute binaries from Python packages in isolated environments
brew "pipx"
# Python version management
brew "pyenv"
# Migrate pip packages from one Python version to another

View File

@@ -40,8 +40,7 @@ return {
operators = {},
-- miscs = {}, -- Uncomment to turn off hard-coded styles
},
-- Style of specific lsp hl groups (`:h lsp-highlight`)
lsp_styles = {
lsp_styles = { -- Handles the style of specific lsp hl groups (see `:h lsp-highlight`).
virtual_text = {
errors = { 'italic' },
hints = { 'italic' },
@@ -73,8 +72,7 @@ return {
enabled = true,
indentscope_color = '',
},
-- More integrations:
-- github.com/catppuccin/nvim#integrations
-- For more plugins integrations please scroll down (https://github.com/catppuccin/nvim#integrations)
},
}
@@ -117,8 +115,7 @@ return {
{
'dmtrKovalenko/fff.nvim',
build = function()
-- Downloads prebuild binary or uses rustup
-- toolchain to build from source
-- this will download prebuild binary or try to use existing rustup toolchain to build from source
-- (if you are using lazy you can use gb for rebuilding a plugin if needed)
require('fff.download').download_or_build_binary()
end,
@@ -127,8 +124,7 @@ return {
opts = { -- (optional)
debug = {
enabled = true, -- we expect your collaboration at least during the beta
-- Share scores to help optimize scoring
show_scores = true,
show_scores = true, -- to help us optimize the scoring system, feel free to share your scores!
},
},
-- No need to lazy-load with lazy.nvim.

View File

@@ -15,7 +15,10 @@ git submodule update --init --recursive "${DOTBOT_DIR}"
"${DOTBOT_BIN_PATH}" \
-d "${BASEDIR}" \
--plugin-dir=tools/dotbot-asdf \
--plugin-dir=tools/dotbot-brew \
--plugin-dir=tools/dotbot-include \
--plugin-dir=tools/dotbot-pip \
-c "${CONFIG}" \
"${@}"
@@ -26,7 +29,10 @@ if [ "${DOTBOT_HOST}" != "" ]; then
echo "(!) Found $DOTBOT_HOST_CONFIG" &&
"$DOTBOT_BIN_PATH" \
-d "$BASEDIR" \
--plugin-dir=tools/dotbot-asdf \
--plugin-dir=tools/dotbot-brew \
--plugin-dir=tools/dotbot-include \
--plugin-dir=tools/dotbot-pip \
-c "$DOTBOT_HOST_CONFIG" \
"${@}"
fi

View File

@@ -78,3 +78,8 @@
- shell:
# Use my dotfiles manager to install everything
- bash local/bin/dfm install all
- pipx:
file: tools/requirements-pipx.txt
stdout: true
stderr: true

View File

@@ -15,37 +15,38 @@
SCRIPT=$(basename "$0")
# Require bash 4.0+ for associative arrays and mapfile
if ((BASH_VERSINFO[0] < 4)); then
echo "dfm requires bash 4.0+, found ${BASH_VERSION}"
if [[ "$(uname)" == "Darwin" ]]; then
if ! command -v brew &> /dev/null; then
echo "Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
echo "Installing modern bash via Homebrew..."
brew install bash
echo "Done. Restart your shell and run dfm again."
else
echo "Install bash 4.0+ and try again."
fi
exit 1
fi
# Detect the current shell
CURRENT_SHELL=$(ps -p $$ -ocomm= | awk -F/ '{print $NF}')
# shellcheck disable=SC1091
source "$DOTFILES/config/shared.sh"
# shellcheck disable=SC1090
source "${DOTFILES}/local/bin/msgr"
# Get description from a script file's @description tag
get_script_description()
# Function to source files based on the shell
source_file()
{
local file="$1"
local desc
desc=$(sed -n '/@description/s/.*@description *\(.*\)/\1/p' "$file" | head -1)
echo "${desc:-No description available}"
local file=$1
case "$CURRENT_SHELL" in
fish)
if [[ -f "$file.fish" ]]; then
# shellcheck disable=SC1090
source "$file.fish"
else
echo "Fish shell file not found: $file.fish"
exit 1
fi
;;
sh | bash | zsh)
# shellcheck disable=SC1090
source "$file"
;;
*)
echo "Unsupported shell: $CURRENT_SHELL"
exit 1
;;
esac
}
# Modify the source commands to use the new function
source_file "$DOTFILES/config/shared.sh"
source_file "${DOTFILES}/local/bin/msgr"
# Menu builder
menu_builder()
{
@@ -53,9 +54,9 @@ menu_builder()
local commands=("${@:2}")
local width=60
printf "\n%s\n" "$(printf '%.s─' $(seq 1 "$width"))"
printf "\n%s\n" "$(printf '%.s─' $(seq 1 $width))"
printf "%-${width}s\n" " $title"
printf "%s\n" "$(printf '%.s─' $(seq 1 "$width"))"
printf "%s\n" "$(printf '%.s─' $(seq 1 $width))"
for cmd in "${commands[@]}"; do
local name=${cmd%%:*}
@@ -79,6 +80,7 @@ section_install()
"imagick:Install ImageMagick CLI"
"macos:Setup nice macOS defaults"
"npm-packages:Install NPM Packages"
"ntfy:Install ntfy"
"nvm-latest:Install latest lts node using nvm"
"nvm:Install Node Version Manager (nvm)"
"z:Install z"
@@ -98,7 +100,6 @@ section_install()
$0 install npm-packages
$0 install z
msgr msg "Reloading configurations again..."
# shellcheck disable=SC1091
source "$DOTFILES/config/shared.sh"
msgr yay "All done!"
;;
@@ -207,88 +208,87 @@ section_brew()
"untracked:List untracked brew packages"
)
if ! x-have brew; then
msgr warn "brew not available, skipping"
return 0
fi
x-have brew && {
case "$1" in
install)
brew bundle install --file="$BREWFILE" --force --quiet && msgr yay "Done!"
;;
case "$1" in
install)
brew bundle install --file="$BREWFILE" --force --quiet && msgr yay "Done!"
;;
update)
brew update && brew outdated && brew upgrade && brew cleanup
msgr yay "Done!"
;;
update)
brew update && brew outdated && brew upgrade && brew cleanup
msgr yay "Done!"
;;
updatebundle)
# Updates .dotfiles/homebrew/Brewfile with descriptions
brew bundle dump \
--force \
--file="$BREWFILE" \
--cleanup \
--tap \
--formula \
--cask \
--describe && msgr yay "Done!"
;;
updatebundle)
# Updates .dotfiles/homebrew/Brewfile with descriptions
brew bundle dump \
--force \
--file="$BREWFILE" \
--cleanup \
--tap \
--formula \
--cask \
--describe && msgr yay "Done!"
;;
leaves)
brew leaves --installed-on-request
;;
leaves)
brew leaves --installed-on-request
;;
untracked)
declare -a BREW_LIST_ALL
while IFS= read -r line; do
BREW_LIST_ALL+=("$line")
done < <(brew list --formula --installed-on-request -1 --full-name)
while IFS= read -r c; do
BREW_LIST_ALL+=("$c")
done < <(brew list --cask -1 --full-name)
untracked)
declare -a BREW_LIST_ALL
while IFS= read -r line; do
BREW_LIST_ALL+=("$line")
done < <(brew list --formula --installed-on-request -1 --full-name)
while IFS= read -r c; do
BREW_LIST_ALL+=("$c")
done < <(brew list --cask -1 --full-name)
# Remove entries that are installed as dependencies
declare -a BREW_LIST_DEPENDENCIES
while IFS= read -r l; do
BREW_LIST_DEPENDENCIES+=("$l")
done < <(brew list -1 --installed-as-dependency)
# Remove entries that are installed as dependencies
declare -a BREW_LIST_DEPENDENCIES
while IFS= read -r l; do
BREW_LIST_DEPENDENCIES+=("$l")
done < <(brew list -1 --installed-as-dependency)
declare -a BREW_LIST_BUNDLED
while IFS= read -r b; do
BREW_LIST_BUNDLED+=("$b")
done < <(brew bundle list --all --file="$BREWFILE")
declare -a BREW_LIST_BUNDLED
while IFS= read -r b; do
BREW_LIST_BUNDLED+=("$b")
done < <(brew bundle list --all --file="$BREWFILE")
declare -a BREW_LIST_TRACKED_WITHOUT_DEPS
for f in "${BREW_LIST_ALL[@]}"; do
# shellcheck disable=SC2199
if [[ " ${BREW_LIST_DEPENDENCIES[@]} " != *" ${f} "* ]]; then
BREW_LIST_TRACKED_WITHOUT_DEPS+=("$f")
fi
done
declare -a BREW_LIST_TRACKED_WITHOUT_DEPS
for f in "${BREW_LIST_ALL[@]}"; do
# shellcheck disable=SC2199
if [[ " ${BREW_LIST_DEPENDENCIES[@]} " != *" ${f} "* ]]; then
BREW_LIST_TRACKED_WITHOUT_DEPS+=("$f")
array_diff BREW_LIST_UNTRACKED BREW_LIST_TRACKED_WITHOUT_DEPS BREW_LIST_BUNDLED
# If there are no untracked packages, exit
if [ ${#BREW_LIST_UNTRACKED[@]} -eq 0 ]; then
msgr yay "No untracked packages found!"
exit 0
fi
done
array_diff BREW_LIST_UNTRACKED BREW_LIST_TRACKED_WITHOUT_DEPS BREW_LIST_BUNDLED
echo "Untracked:"
for f in "${BREW_LIST_UNTRACKED[@]}"; do
echo " $f"
done
;;
# If there are no untracked packages, return
if [ ${#BREW_LIST_UNTRACKED[@]} -eq 0 ]; then
msgr yay "No untracked packages found!"
return 0
fi
autoupdate)
brew autoupdate delete
brew autoupdate start 43200 --upgrade --cleanup --immediate
;;
echo "Untracked:"
for f in "${BREW_LIST_UNTRACKED[@]}"; do
echo " $f"
done
;;
clean) brew bundle cleanup --file="$BREWFILE" && msgr yay "Done!" ;;
autoupdate)
brew autoupdate delete
brew autoupdate start 43200 --upgrade --cleanup --immediate
;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
clean) brew bundle cleanup --file="$BREWFILE" && msgr yay "Done!" ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
! x-have brew && menu_builder "$USAGE_PREFIX" "brew not available on this system"
}
section_helpers()
@@ -305,10 +305,10 @@ section_helpers()
"wezterm:Show wezterm keybindings"
)
CMD="${1:-}"
[[ $# -gt 0 ]] && shift
SECTION="${1:-}"
[[ $# -gt 0 ]] && shift
CMD="$1"
shift
SECTION="$1"
shift
case "$CMD" in
path)
@@ -379,60 +379,55 @@ section_apt()
"clean:Clean apt cache"
)
if ! x-have apt; then
msgr warn "apt not available, skipping"
return 0
fi
x-have apt && {
case "$1" in
upkeep)
sudo apt update \
&& sudo apt upgrade -y \
&& sudo apt autoremove -y \
&& sudo apt clean
;;
case "$1" in
upkeep)
sudo apt update \
&& sudo apt upgrade -y \
&& sudo apt autoremove -y \
&& sudo apt clean
;;
install)
# if apt.txt is not found, exit
[ ! -f "$DOTFILES/tools/apt.txt" ] && msgr err "apt.txt not found" && exit 0
install)
# if apt.txt is not found, return with error
if [ ! -f "$DOTFILES/tools/apt.txt" ]; then
msgr err "apt.txt not found"
return 1
fi
# Load apt.txt, remove comments (even if trailing comment) and empty lines.
#
# Ignoring "Quote this to prevent word splitting."
# shellcheck disable=SC2046
sudo apt install \
-y $(
grep -vE '^\s*#' "$DOTFILES/tools/apt.txt" \
| sed -e 's/#.*//' \
| tr '\n' ' '
)
# If there's a apt.txt file under hosts/$hostname/apt.txt,
# run install on those lines too.
HOSTNAME=$(hostname -s)
HOST_APT="$DOTFILES/hosts/$HOSTNAME/apt.txt"
[[ -f $HOST_APT ]] && {
# Load apt.txt, remove comments (even if trailing comment) and empty lines.
#
# Ignoring "Quote this to prevent word splitting."
# shellcheck disable=SC2046
sudo apt install -y $(
grep -vE '^\s*#' "$HOST_APT" \
| sed -e 's/#.*//' \
| tr '\n' ' '
)
}
sudo apt install \
-y $(
grep -vE '^\s*#' "$DOTFILES/tools/apt.txt" \
| sed -e 's/#.*//' \
| tr '\n' ' '
)
# Try this for an alternative way to install packages
# xargs -a <(awk '! /^ *(#|$)/' "$packagelist") -r -- sudo apt-get install -y
;;
# If there's a apt.txt file under hosts/$hostname/apt.txt,
# run install on those lines too.
HOSTNAME=$(hostname -s)
HOST_APT="$DOTFILES/hosts/$HOSTNAME/apt.txt"
[[ -f $HOST_APT ]] && {
# shellcheck disable=SC2046
sudo apt install -y $(
grep -vE '^\s*#' "$HOST_APT" \
| sed -e 's/#.*//' \
| tr '\n' ' '
)
}
update) sudo apt update ;;
upgrade) sudo apt upgrade -y ;;
autoremove) sudo apt autoremove -y ;;
clean) sudo apt clean ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
# Try this for an alternative way to install packages
# xargs -a <(awk '! /^ *(#|$)/' "$packagelist") -r -- sudo apt-get install -y
;;
update) sudo apt update ;;
upgrade) sudo apt upgrade -y ;;
autoremove) sudo apt autoremove -y ;;
clean) sudo apt clean ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
! x-have apt && menu_builder "$USAGE_PREFIX" "apt not available on this system"
}
section_docs()
@@ -539,13 +534,13 @@ section_check()
case "$1" in
a | arch)
[[ $2 == "" ]] && echo "$X_ARCH" && return 0
[[ $X_ARCH == "$2" ]] && return 0 || return 1
[[ $2 == "" ]] && echo "$X_ARCH" && exit 0
[[ $X_ARCH == "$2" ]] && exit 0 || exit 1
;;
h | host | hostname)
[[ $2 == "" ]] && echo "$X_HOSTNAME" && return 0
[[ $X_HOSTNAME == "$2" ]] && return 0 || return 1
[[ $2 == "" ]] && echo "$X_HOSTNAME" && exit 0
[[ $X_HOSTNAME == "$2" ]] && exit 0 || exit 1
;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
@@ -556,18 +551,33 @@ section_scripts()
{
USAGE_PREFIX="$SCRIPT scripts <command>"
# Get description from a file
get_script_description()
{
local file
local desc
file="$1"
desc=$(sed -n '/@description/s/.*@description *\(.*\)/\1/p' "$file" | head -1)
echo "${desc:-No description available}"
}
# Collect scripts and their descriptions
local menu_items=()
declare -A SCRIPT_MENU
for script in "$DOTFILES/scripts/install-"*.sh; do
if [ -f "$script" ]; then
name=$(basename "$script" .sh | sed 's/install-//')
desc=$(get_script_description "$script")
menu_items+=("$name:$desc")
SCRIPT_MENU[$name]="$desc"
fi
done
case "$1" in
"")
# Show the menu
local menu_items=()
for name in "${!SCRIPT_MENU[@]}"; do
menu_items+=("$name:${SCRIPT_MENU[$name]}")
done
menu_builder "$USAGE_PREFIX" "${menu_items[@]}"
;;
*)
@@ -599,7 +609,7 @@ section_tests()
echo " $i"
done
;;
msgr)
msg)
# shellcheck disable=SC1010
msgr done "msgr done"
msgr done_suffix "msgr done_suffix"
@@ -623,7 +633,7 @@ usage()
{
echo ""
msgr prompt "Usage: $SCRIPT <section> <command>"
echo " Empty <command> prints <section> help."
echo $" Empty <command> prints <section> help."
echo ""
section_install
echo ""
@@ -644,8 +654,8 @@ usage()
main()
{
SECTION="${1:-}"
[[ $# -gt 0 ]] && shift
SECTION="$1"
shift
# The main loop. The first keyword after $0 triggers section, or help.
case "$SECTION" in
install) section_install "$@" ;;
@@ -657,7 +667,7 @@ main()
docs) section_docs "$@" ;;
scripts) section_scripts "$@" ;;
tests) section_tests "$@" ;;
*) usage && return 0 ;;
*) usage && exit 0 ;;
esac
}

View File

@@ -8,7 +8,7 @@ set -euo pipefail
# Enable verbosity with VERBOSE=1
VERBOSE="${VERBOSE:-0}"
A_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/alacritty"
A_DIR="$HOME/.config/alacritty"
# Function to print usage information
usage()

View File

@@ -7,15 +7,13 @@
# Author: Ismo Vuorinen 2025
# License: MIT
set -euo pipefail
# Check if the user has provided a directory as an argument
if [ "${1:-}" ]; then
if [ "$1" ]; then
# Check if the directory exists
if [ -d "$1" ]; then
CLEANDIR="$1"
else
echo "Error: Directory $1 does not exist." >&2
msgr err "Directory $1 does not exist."
exit 1
fi
else
@@ -29,7 +27,7 @@ remove_node_modules_vendor()
# If the directory is a symlink, skip it
if [ -L "$dir" ]; then
echo "Skipping symlink $dir"
msgr msg "Skipping symlink $dir"
return
fi
@@ -37,18 +35,18 @@ remove_node_modules_vendor()
if [ -d "$dir" ]; then
# If node_modules or vendor folder exists, remove it and all its contents
if [ -d "$dir/node_modules" ]; then
echo "Removing $dir/node_modules"
msgr run "Removing $dir/node_modules"
rm -rf "$dir/node_modules"
fi
if [ -d "$dir/vendor" ]; then
echo "Removing $dir/vendor"
msgr run "Removing $dir/vendor"
rm -rf "$dir/vendor"
fi
# Recursively check subdirectories
for item in "$dir"/*; do
[ -d "$item" ] && remove_node_modules_vendor "$item"
remove_node_modules_vendor "$item"
done
fi
}

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
#
# List environment variables grouped by the first part before underscore
# protecting environment variables that possibly contain sensitive information.

View File

@@ -1,26 +1,18 @@
#!/usr/bin/env bash
#
# Run a command in each directory matching a pattern.
#
# Usage: x-foreach <listing-command> <command> [args...]
# x-foreach "ls -d */" "git status"
# foreach <folder> <commands that should be run to each file>
# foreach "ls -d */" "git status" # run git status in each folder
#
# Source: https://github.com/mvdan/dotfiles/blob/master/.bin/foreach
set -euo pipefail
if [ $# -lt 2 ]; then
echo "Usage: $0 <listing-command> <command> [args...]"
exit 1
fi
listing=$1
cmd=$1
shift
for dir in $(eval "$listing"); do
for dir in $($cmd); do
(
echo "$dir"
cd "$dir" || exit 1
"$@"
# shellcheck disable=SC2294,SC2034
eval "$@" # allow multiple commands like "foo && bar"
)
done

View File

@@ -1,14 +1,4 @@
#!/usr/bin/env bash
#
# Display external IP address.
#
# Source: https://github.com/thirtythreeforty/dotfiles/blob/master/bin/extip
set -euo pipefail
if ! command -v curl &> /dev/null; then
echo "Error: curl is required" >&2
exit 1
fi
curl -sf icanhazip.com
curl icanhazip.com "${@}"

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
#
# x-localip: script to display the local IP addresses of the system
#

50
local/bin/x-mkd Executable file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env bash
#
# Create a directory and cd into it
# Usage: x-mkd <dir>
set -euo pipefail
# Set verbosity with VERBOSE=1
VERBOSE="${VERBOSE:-0}"
# Function to print usage information
usage()
{
echo "Usage: $0 <dir>"
exit 1
}
# Function to print messages if VERBOSE is enabled
# $1 - message (string)
msg()
{
[[ "$VERBOSE" -eq 1 ]] && echo "$1"
}
# Function to create a directory and cd into it
# $1 - directory to create and cd into (string)
mkcd()
{
local dir=$1
mkdir -p "$dir" && msg "Directory $dir created"
cd "$dir" || {
msg "Failed to cd into $dir"
exit 1
}
msg "Changed directory to $dir"
}
# Main function
main()
{
if [ "$#" -ne 1 ]; then
usage
fi
mkcd "$1"
}
main "$@"

19
local/bin/x-mkd.md Normal file
View File

@@ -0,0 +1,19 @@
# x-mkd
Create a directory and immediately `cd` into it.
## Usage
```bash
x-mkd <dir>
```
Set `VERBOSE=1` for status messages.
## Example
```bash
x-mkd project && git init
```
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->

View File

@@ -39,6 +39,7 @@
# Defaults
LOOP=0
SLEEP=1
VERBOSE=0
TIMEOUT=5
usage()
@@ -59,6 +60,8 @@ while [[ $# -gt 0 ]]; do
exit 0
;;
--verbose)
# shellcheck disable=SC2034
VERBOSE=1
shift
;;
--loop | --forever)

View File

@@ -227,9 +227,6 @@ do_check()
fi
}
# If sourced, provide functions without executing main logic
(return 0 2> /dev/null) && return
#######################################
# Main routine: Parse subcommand and arguments, normalize PATH,
# and dispatch to the appropriate functionality.

View File

@@ -1,17 +1,44 @@
#!/usr/bin/env bash
#
# Thin wrapper — delegates to x-path append.
# Can be sourced (PATH changes propagate) or executed.
# Optimized script to append directories to PATH.
# For each given directory, it removes all duplicate occurrences from PATH
# and then appends it if the directory exists.
#
# Usage: x-path-append <directory1> [<directory2> ...]
#
# Enable verbose output by setting the environment variable VERBOSE=1.
#
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2024
# License: MIT
VERBOSE="${VERBOSE:-0}"
# shellcheck source=./x-path
. "$(dirname "${BASH_SOURCE[0]:-$0}")/x-path"
# Ensure that at least one directory is provided.
[ "$#" -lt 1 ] && {
echo "Usage: $0 <directory> [<directory> ...]"
exit 1
}
normalize_path_var
do_append "$@"
for dir in "$@"; do
# Check if the specified directory exists.
if [ ! -d "$dir" ]; then
[ "$VERBOSE" -eq 1 ] && echo "(?) Directory '$dir' does not exist. Skipping."
continue
fi
# Remove all duplicate occurrences of the directory from PATH.
case ":$PATH:" in
*":$dir:"*)
PATH=":${PATH}:"
PATH="${PATH//:$dir:/:}"
PATH="${PATH#:}"
PATH="${PATH%:}"
[ "$VERBOSE" -eq 1 ] && echo "Removed previous occurrences of '$dir' from PATH."
;;
*) ;;
esac
# Append the directory to PATH.
export PATH="${PATH:+$PATH:}$dir"
[ "$VERBOSE" -eq 1 ] && echo "Appended '$dir' to PATH."
done

View File

@@ -1,17 +1,50 @@
#!/usr/bin/env bash
#
# Thin wrapper — delegates to x-path prepend.
# Can be sourced (PATH changes propagate) or executed.
# Optimized script to batch prepend directories to PATH.
# For each given directory, it removes all duplicate occurrences from PATH
# and then prepends it. Directories that do not exist are skipped.
#
# Usage: x-path-prepend <directory1> [<directory2> ...]
#
# Enable verbose output by setting the environment variable VERBOSE=1.
#
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2024
# License: MIT
VERBOSE="${VERBOSE:-0}"
# shellcheck source=./x-path
. "$(dirname "${BASH_SOURCE[0]:-$0}")/x-path"
# Ensure that at least one argument is provided.
[ "$#" -lt 1 ] && {
echo "Usage: $0 <directory> [<directory> ...]"
exit 1
}
normalize_path_var
do_prepend "$@"
# Save the arguments in an array.
dirs=("$@")
# Process the directories in reverse order so that the first argument ends up leftmost in PATH.
for ((idx = ${#dirs[@]} - 1; idx >= 0; idx--)); do
dir="${dirs[idx]}"
# Check if the specified directory exists.
if [ ! -d "$dir" ]; then
[ "$VERBOSE" -eq 1 ] && echo "(?) Directory '$dir' does not exist. Skipping."
continue
fi
# Remove all duplicate occurrences of the directory from PATH using built-in string operations.
case ":$PATH:" in
*":$dir:"*)
PATH=":${PATH}:"
PATH="${PATH//:$dir:/:}"
PATH="${PATH#:}"
PATH="${PATH%:}"
[ "$VERBOSE" -eq 1 ] && echo "Removed duplicate occurrences of '$dir' from PATH."
;;
*) ;;
esac
# Prepend the directory to PATH.
export PATH="$dir${PATH:+":$PATH"}"
[ "$VERBOSE" -eq 1 ] && echo "Prepended '$dir' to PATH."
done

View File

@@ -1,17 +1,41 @@
#!/usr/bin/env bash
#
# Thin wrapper — delegates to x-path remove.
# Can be sourced (PATH changes propagate) or executed.
# Optimized script to remove directories from PATH.
# For each specified directory, all occurrences are removed from PATH.
#
# Usage: x-path-remove <directory1> [<directory2> ...]
#
# Enable verbose output by setting the environment variable VERBOSE=1.
#
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2024
# License: MIT
VERBOSE="${VERBOSE:-0}"
# shellcheck source=./x-path
. "$(dirname "${BASH_SOURCE[0]:-$0}")/x-path"
# Ensure that at least one directory is provided.
[ "$#" -lt 1 ] && {
echo "Usage: $0 <directory> [<directory> ...]"
exit 1
}
normalize_path_var
do_remove "$@"
for dir in "$@"; do
# Remove trailing slash if present, unless the directory is "/"
[ "$dir" != "/" ] && dir="${dir%/}"
# Check if the directory is present in PATH.
case ":$PATH:" in
*":$dir:"*)
# Remove all occurrences of the directory from PATH using parameter expansion.
PATH=":${PATH}:"
PATH="${PATH//:$dir:/:}"
PATH="${PATH#:}"
PATH="${PATH%:}"
[ "$VERBOSE" -eq 1 ] && echo "Removed '$dir' from PATH."
;;
*)
[ "$VERBOSE" -eq 1 ] && echo "(?) '$dir' is not in PATH."
;;
esac
done
export PATH

View File

@@ -35,7 +35,7 @@ msg()
# Notify function
notify()
{
notify-send.sh --replace-file "$replace_id" "$@"
notify-call --replace-file "$replace_id" "$@"
}
# Stop recording function

View File

@@ -37,7 +37,7 @@ The script automatically tries authentication methods in this order:
1. **Specific key** (if provided in host file)
2. **Auto-detected default keys** (`~/.ssh/id_ed25519`, `id_rsa`, `id_ecdsa`,
`id_dsa`)
`id_dsa`)
3. **SSH agent or system default authentication**
This means you can mix hosts with and without specific keys, and the script will
@@ -178,7 +178,7 @@ SSH_RETRIES=3
3. **Staged Rollout**: Test on non-critical hosts first
4. **Review Logs**: Check log files for detailed information
5. **Preserve Access**: Script ensures key-based auth works before disabling
passwords
passwords
## Version

View File

@@ -1,13 +1,11 @@
#!/usr/bin/env bash
#
# Display 24-bit terminal color test.
#
# Usage: x-term-colors
#
# The foreground escape sequence is ^[38;2;<r>;<g>;<b>m
# The background escape sequence is ^[48;2;<r>;<g>;<b>m
# <r> <g> <b> range from 0 to 255 inclusive.
# The escape sequence ^[0m returns output to default
# This file echoes a bunch of 24-bit color codes
# to the terminal to demonstrate its functionality.
# The foreground escape sequence is ^[38;2;<r>;<g>;<b>m
# The background escape sequence is ^[48;2;<r>;<g>;<b>m
# <r> <g> <b> range from 0 to 255 inclusive.
# The escape sequence ^[0m returns output to default
setBackgroundColor()
{

View File

@@ -0,0 +1,68 @@
#!/usr/bin/env bash
#
# This script contains a helper for sha256 validating your downloads
#
# Source: https://gist.github.com/onnimonni/b49779ebc96216771a6be3de46449fa1
# Author: Onni Hakala
# License: MIT
#
# Updated by Ismo Vuorinen <https://github.com/ivuorinen> 2022
##
set -euo pipefail
# Stop program and give error message
# $1 - error message (string)
error()
{
echo "(!) ERROR: $1" >&2
exit 1
}
# Check for sha256sum command
if ! command -v sha256sum &> /dev/null; then
error "sha256sum could not be found, please install it first"
fi
# Return sha256sum for file
# $1 - filename (string)
get_sha256sum()
{
sha256sum "$1" | head -c 64
}
# Validate input arguments
validate_inputs()
{
if [ -z "${filename:-}" ]; then
error "You need to provide filename as the first parameter"
fi
if [ -z "${file_hash:-}" ]; then
error "You need to provide sha256sum as the second parameter"
fi
}
# Main validation logic
validate_file()
{
if [ ! -f "$filename" ]; then
error "File $filename doesn't exist"
elif [ "$(get_sha256sum "$filename")" = "$file_hash" ]; then
echo "(*) Success: $filename matches provided sha256sum"
else
error "$filename doesn't match provided sha256sum"
fi
}
# Main function
main()
{
filename=$1
file_hash=$2
validate_inputs
validate_file
}
main "$@"

View File

@@ -0,0 +1,14 @@
# x-validate-sha256sum.sh
This script contains a helper for sha256 validating your downloads
## Usage
```bash
x-validate-sha256sum.sh file sha256sum
```
The script computes the SHA256 hash of `file` and compares it to the
expected value. It exits non-zero if the sums differ.
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env bash
set -euo pipefail
#
# Wait until a given host is down (determined by ping) then execute the
# given command

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env bash
set -euo pipefail
#
# Wait until a given host is online (determined by ping) then execute the
# given command

View File

@@ -11,10 +11,10 @@ scripts/install-cargo-packages.sh
## What it does
1. If `cargo-install-update` is available, updates all existing packages first
and tracks which packages are already installed.
and tracks which packages are already installed.
2. Installs each package from the inline list using `cargo install`,
skipping any already handled by the update step.
Builds run in parallel using available CPU cores (minus two).
skipping any already handled by the update step.
Builds run in parallel using available CPU cores (minus two).
3. Runs package-specific post-install steps.
4. Cleans the cargo cache with `cargo cache --autoclean`.

View File

@@ -18,8 +18,7 @@ fi
# CLI tools — installed isolated with `uv tool install`
tools=(
ansible # IT automation and configuration management
openapi-python-client # Generate Python API clients from OpenAPI specs
ansible # IT automation and configuration management
)
# Library packages — installed into system Python with `uv pip install --system`

14
tests/x-mkd.bats Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bats
@test "x-mkd creates directory" {
dir="$BATS_TMPDIR/mkd-test"
run env VERBOSE=1 bash local/bin/x-mkd "$dir"
[ "$status" -eq 0 ]
[ -d "$dir" ]
}
@test "x-mkd with no args shows usage" {
run bash local/bin/x-mkd
[ "$status" -eq 1 ]
[[ "$output" == "Usage:"* ]]
}

1
tools/dotbot-brew Submodule

Submodule tools/dotbot-brew added at 98e346360b

1
tools/dotbot-pip Submodule

Submodule tools/dotbot-pip added at 4d0cc116e8

View File

@@ -0,0 +1 @@
openapi-python-client