Compare commits

..

46 Commits

Author SHA1 Message Date
b327a99991 feat(python): add ruff linter and formatter configuration 2026-02-07 15:08:40 +02:00
c0665a3161 fix(shell): fix heredoc indentation in x-sonarcloud 2026-02-07 15:07:44 +02:00
3ff83754b1 docs(shell): add function docstring comments 2026-02-07 15:07:22 +02:00
4266567327 fix(shell): fix husky shebang and tolerate npm outdated exit code 2026-02-07 14:13:48 +02:00
0104aff8d4 fix(python): replace dict() constructor with literal
Use {} instead of dict() for empty dictionary initialization
(SonarCloud rule python:S7498).
2026-02-07 14:03:16 +02:00
1ee6545597 fix(shell): assign positional parameters to local variables
Replace direct $1/$2/$3 usage with named local variables in _log(),
msg(), msg_err(), msg_done(), msg_run(), msg_ok(), and array_diff()
(SonarCloud rule shelldre:S7679).
2026-02-07 14:02:58 +02:00
473fc820b9 fix(shell): add explicit return statements to functions
Add return 0 as the last statement in ~46 shell functions across
17 files that previously relied on implicit return codes
(SonarCloud rule shelldre:S7682).
2026-02-07 14:00:58 +02:00
63a21d08b4 fix(shell): use [[ instead of [ for conditional tests
Replace single brackets with double brackets in bash conditional
expressions across 14 files (28 changes). All scripts use bash
shebangs so [[ is safe everywhere (SonarCloud rule shelldre:S7688).
2026-02-07 13:59:08 +02:00
89aeb29c04 fix(ci): replace broad permissions with specific scopes in workflows
Replace read-all/write-all with minimum required permission scopes
across all GitHub Actions workflows to follow the principle of least
privilege (SonarCloud rule githubactions:S8234).
2026-02-07 13:46:03 +02:00
cff3d1dd8a feat(scripts): add x-sonarcloud script for LLM-driven issue analysis
Bridges LLM agents with SonarCloud's REST API to fetch and format
code quality issues as structured markdown with processing instructions.
2026-02-07 13:24:29 +02:00
a47ce85991 chore: remove hammerspoon type generator and types 2026-02-06 09:12:06 +02:00
13dd701eb7 feat(a): improve encryption script with better error handling
- Add dependency check for age and curl with install instructions
- Add --delete flag to remove originals after encryption
- Add -f/--force flag to control overwrite behavior
- Skip already-encrypted .age files during encryption
- Include hidden files (dotglob) when encrypting directories
- Handle empty directories gracefully with nullglob
- Allow flags in any position (proper option parsing)
- Add set -euo pipefail for better error handling
- Update documentation with all features and examples
- Bump version to 1.1.0
2026-02-06 01:51:01 +02:00
cfde007494 fix(shell): clean up rcfiles and remove redundancies
- Remove deprecated GREP_OPTIONS (handled via alias)
- Quote $ZSH_COMPDUMP to prevent word splitting
- Remove duplicate vim alias (nvim alias takes precedence)
- Consolidate completion path to ZSH_CUSTOM_COMPLETION_PATH
- Simplify PATH setup in rcfiles, centralize in exports
- Move LM Studio PATH from rcfiles to exports
- Add clarifying comments for macOS-specific ssh-add
2026-02-06 00:09:03 +02:00
ed4aa2ffe1 feat(scripts): add install-dnf-packages.sh for Fedora/RHEL 2026-02-05 23:46:10 +02:00
bcf11406b6 feat(scripts): add install-apt-packages.sh for Debian/Ubuntu
Install essential developer packages via apt:
- Build tools: build-essential, cmake, pkg-config, autoconf, automake, libtool
- Dev libraries: libssl-dev, libffi-dev, zlib1g-dev, libreadline-dev, etc.
- CLI utilities: jq, tmux, tree, unzip, shellcheck, socat, gnupg

Curated to avoid duplicates with cargo/go installs (ripgrep, fd, fzf, etc.).
Uses batched apt install for efficiency, exits gracefully on non-Debian systems.
2026-02-05 23:42:16 +02:00
443361cddb chore(scripts): remove unused VERBOSE declarations
Remove VERBOSE="${VERBOSE:-0}" from scripts that never reference
$VERBOSE after setting it. The variable is already set in
scripts/shared.sh line 5.
2026-02-05 22:57:20 +02:00
083d30a0c3 fix(scripts): fix shared.sh guard logic and echo -e portability
- shared.sh: simplify guard logic, remove misleading warning message,
  use ${VAR:-} pattern to avoid unbound variable error
- install-cheat-purebashbible.sh: replace echo -e with printf for
  POSIX portability
2026-02-05 22:55:27 +02:00
81190c051a fix(scripts): standardize source paths and quoting
- install-composer.sh: use $DOTFILES instead of $HOME/.dotfiles
- install-macos-defaults.sh: use $DOTFILES, replace which with command -v
- install-xcode-cli-tools.sh: quote command substitution
- create-nvim-keymaps.sh: quote $DEST in nvim redir command
2026-02-05 22:53:04 +02:00
de773ad68f refactor(scripts): add set -euo pipefail to all installer scripts
Add strict error handling to all scripts:
- 13 scripts get `set -euo pipefail`
- install-macos-defaults.sh gets `set -uo pipefail` (without -e) because
  defaults write commands may fail on newer macOS versions
- install-cargo-packages.sh: also add missing source of shared.sh
2026-02-05 22:51:40 +02:00
e8725c4b47 fix(scripts): use safe temp directories and fix composer exit code
- install-ntfy.sh: use mktemp -d with cleanup trap instead of /tmp/ntfy_*
- install-git-crypt.sh: use mktemp -d with cleanup trap instead of /tmp/git-crypt
- install-composer.sh: only move composer.phar if installation succeeded
2026-02-05 22:49:36 +02:00
b8070e2815 fix(scripts): add missing exit after error handlers
Critical bugs where error paths print a message but don't stop execution:
- install-fonts.sh: cd failure now exits properly
- install-ntfy.sh: unsupported OS case now exits with error
- install-git-crypt.sh: git clone and cd failures now exit properly
2026-02-05 22:44:44 +02:00
9de394d8e9 chore(python): add openapi-python-client to uv tools 2026-02-05 22:07:03 +02:00
08de5ea4a6 refactor(submodules): improve old submodule cleanup in add-submodules.sh 2026-02-05 22:07:03 +02:00
0e69b7cb16 refactor: remove dotbot-brew, dotbot-pip submodules and pipx 2026-02-05 22:07:03 +02:00
7c9096d666 fix: standardize shebangs, error handling, and minor issues in x-* scripts
Normalize shebangs to #!/usr/bin/env bash (x-env-list, x-localip).
Use XDG_CONFIG_HOME in x-change-alacritty-theme. Remove unused
VERBOSE variable in x-multi-ping. Add set -euo pipefail to x-when-down
and x-when-up. Add usage header to x-term-colors. Fix notify-call
to notify-send.sh in x-record.
2026-02-05 22:07:03 +02:00
efd9eebc85 fix: resolve critical issues in x-clean-vendordirs, x-foreach, x-ip
x-clean-vendordirs: remove broken msgr dependency (not sourced),
add set -euo pipefail. x-foreach: replace eval on command args with
direct "$@" execution, add usage guard. x-ip: add set -euo pipefail,
curl dependency check, and silent-fail flag.
2026-02-05 22:07:03 +02:00
fc8db1f5b5 refactor(path): consolidate x-path-{append,prepend,remove} as thin wrappers
Add source guard to x-path so its functions can be loaded without
executing the main logic. Rewrite standalone path scripts to source
x-path and call the appropriate function directly, eliminating code
duplication while preserving source-ability for shell integration.
2026-02-05 22:07:03 +02:00
4414e0c3b6 chore: remove unused x-mkd and x-validate-sha256sum.sh scripts
x-mkd's cd-in-subshell cannot work when executed (only sourced) and
is unused in the repo. x-validate-sha256sum.sh duplicates the
functionality of x-sha256sum-matcher.
2026-02-05 22:07:03 +02:00
abb6c9f615 refactor(dfm): clean up portability, dead code, and error handling
Add bash 4.0+ version check with macOS Homebrew bootstrap. Remove
unreachable fish shell detection and source_file function. Fix bugs:
remove dead ntfy menu entry, fix msg/msgr case mismatch in tests,
guard shift calls against empty args, quote $width, fix $"..." locale
string, fix exit 0 on apt error. Replace declare -A with indexed
array in section_scripts. Use early-return guards with msgr warn for
unavailable brew/apt. Replace exit with return in section functions.
2026-02-05 22:07:03 +02:00
57b566704e fix(lint): resolve all lint errors and remove dangling symlinks
Fix 14 editorconfig/biome errors across 6 files: update biome schema
version, replace tabs with spaces, fix continuation indents, and wrap
long lines. Remove dangling OrbStack fish completion symlinks.
2026-02-05 22:07:03 +02:00
renovate[bot]
4510e62070 chore(deps): update ivuorinen/actions action (v2026.01.21 → v2026.02.03) (#278)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-05 17:56:56 +00:00
959e7c418e chore: remove 15 unused config directories and stale references
Drop config folders (aerospace, aqua, asdf, direnv, flipperdevices,
ghostty, htop, misc, nano, task, tealdeer, tms, wtf, yamlfmt,
yamllint) along with starship.toml, nbrc, and aerospace scripts/docs.

Clean up references in dfm, _dfm completions, bashrc, exports, and
exports-lakka to match.
2026-02-04 08:05:37 +02:00
3fb9d2a32e refactor(python): migrate pip to uv and inline packages
Replace pip install --user with uv tool install for CLI tools
(ansible) and uv pip install --system for libraries (libtmux, pynvim).
Drop pipx and pipenv (uv replaces both), delete the external
config/asdf/python-packages file, and rename the script to
install-python-packages to reflect the broader scope.
2026-02-04 03:22:17 +02:00
e1050fc7e1 refactor(npm): inline packages and drop unused dependencies 2026-02-04 03:22:17 +02:00
9d7a1acd30 refactor(go): inline packages and drop unused dependencies
Replace external golang-packages config file with an inline array,
remove 6 unused packages (actionlint, antidot, gopls, templ, html2md,
pup), and update documentation to match cargo script style.
2026-02-04 03:22:17 +02:00
9b7942a9fb refactor(tmux): combine sesh scripts into single bash script
Replace sesh-gum.sh and sesh-tmux.fish with a unified sesh.sh that
cascades through available tools: gum, fzf-tmux, fzf, bash select.
Falls back to native tmux choose-tree if sesh is not installed.
2026-02-04 03:22:17 +02:00
3e6b80b598 chore(tmux): remove unused plugins
Remove tmux-sensible, tmux-mode-indicator, tmux-yank, and
tmux-fzf-url submodules, configurations, and run-shell lines.
2026-02-04 03:22:17 +02:00
f6fb14d651 feat(tmux): configure tmux-suspend with F8 key and visual indicator
Enable suspend key (F8) and add @suspend_suspended_options to show
a ⏸ indicator in the status bar when session is suspended.
2026-02-04 03:22:17 +02:00
bafb8fc2f6 refactor(tmux): update keybindings for pane nav and copy mode
Switch pane navigation from Alt-arrow to Ctrl-arrow (Alt doesn't
work reliably on Linux). Add copy-mode-vi clipboard bindings and
C-p/C-n for window switching.
2026-02-04 03:22:17 +02:00
6b11727540 refactor(tmux): consolidate terminal capabilities into terminal-features
Replace terminal-overrides + terminal-features with a single
terminal-features line declaring RGB, clipboard, usstyle,
strikethrough and overline for xterm-256color (WezTerm).
2026-02-04 03:22:17 +02:00
5f4268d2e0 fix(tmux): correct catppuccin config and remove no-op options
Fix @catppuccin_flavor → @catppuccin_flavour spelling so theme
switching via tmux-dark-notify actually applies mocha/latte.
Remove non-existent variables (@catppuccin_status_background,
@catppuccin_window_flags, @catppuccin_window_text,
@catppuccin_window_current_text) and conflicting status overrides
that catppuccin manages. Add rounded window separators.
2026-02-04 03:22:17 +02:00
ed3f881b93 chore(tmux): remove tmux-window-name submodule
Remove the git submodule, its config in tmux.conf, the zsh hook
in zshrc, and add cleanup entry in add-submodules.sh.
2026-02-04 03:22:17 +02:00
939ee65e7a chore(tmux): remove tmux-window-name plugin 2026-02-04 03:22:17 +02:00
14f0cd00e2 chore(deps): update ivuorinen/phpenv.fish plugin 2026-02-04 03:22:17 +02:00
ddbfed1dd9 chore(fish): update fisher, plugins, and Catppuccin themes
Update fisher to v4.4.8 with uninstall alias and rate limit
handling. Add catppuccin/fish plugin, consolidate Latte theme
into Mocha as light/dark variants, and add Frappe and Macchiato
themes. Set Catppuccin Mocha as the default theme in config.
2026-02-04 03:22:17 +02:00
e19120c45a refactor(scripts): inline cargo packages into install script
Move package list from config/asdf/cargo-packages into
install-cargo-packages.sh as a bash array and remove the
external file. Update documentation accordingly.
2026-02-04 03:22:17 +02:00
150 changed files with 3244 additions and 21490 deletions

View File

@@ -8,6 +8,10 @@ indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.py]
indent_size = 4
max_line_length = 120
[*.fish]
max_line_length = 120

View File

@@ -9,13 +9,15 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: read-all
permissions:
contents: read
jobs:
debug-changelog:
runs-on: ubuntu-latest
permissions: write-all
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

View File

@@ -11,7 +11,8 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: read-all
permissions:
contents: read
jobs:
Linter:
@@ -35,4 +36,4 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Run PR Lint
uses: ivuorinen/actions/pr-lint@f98ae7cd7d0feb1f9d6b01de0addbb11414cfc73 # v2026.01.21
uses: ivuorinen/actions/pr-lint@f371da218e9152e7d29ee39358454e41010c36dc # v2026.02.03

View File

@@ -11,13 +11,15 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: read-all
permissions:
contents: read
jobs:
new-daily-release:
runs-on: ubuntu-latest
permissions: write-all
permissions:
contents: write
outputs:
created: ${{ steps.daily-version.outputs.created }}

View File

@@ -12,7 +12,8 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: read-all
permissions:
contents: read
jobs:
auto-update:

View File

@@ -14,7 +14,8 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: read-all
permissions:
pull-requests: read
jobs:
semantic-pr:

View File

@@ -19,7 +19,8 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: read-all
permissions:
contents: read
jobs:
SyncLabels:
@@ -29,4 +30,4 @@ jobs:
issues: write
steps:
- uses: ivuorinen/actions/sync-labels@f98ae7cd7d0feb1f9d6b01de0addbb11414cfc73 # v2026.01.21
- uses: ivuorinen/actions/sync-labels@f371da218e9152e7d29ee39358454e41010c36dc # v2026.02.03

View File

@@ -12,13 +12,15 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: read-all
permissions:
contents: read
jobs:
update-submodules:
runs-on: ubuntu-latest
permissions: write-all
permissions:
contents: write
steps:
- name: Checkout repository

32
.gitmodules vendored
View File

@@ -4,11 +4,6 @@
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,41 +19,16 @@
url = https://github.com/tmux-plugins/tmux-continuum
ignore = dirty
[submodule "tmux/tmux-sensible"]
path = config/tmux/plugins/tmux-sensible
url = https://github.com/tmux-plugins/tmux-sensible.git
ignore = dirty
[submodule "tmux/tmux-sessionist"]
path = config/tmux/plugins/tmux-sessionist
url = https://github.com/tmux-plugins/tmux-sessionist.git
ignore = dirty
[submodule "tmux/tmux-yank"]
path = config/tmux/plugins/tmux-yank
url = https://github.com/tmux-plugins/tmux-yank.git
ignore = dirty
[submodule "tmux/tmux-window-name"]
path = config/tmux/plugins/tmux-window-name
url = https://github.com/ivuorinen/tmux-window-name.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
ignore = dirty
[submodule "tmux/tmux-mode-indicator"]
path = config/tmux/plugins/tmux-mode-indicator
url = https://github.com/MunifTanjim/tmux-mode-indicator.git
ignore = dirty
[submodule "tmux/tmux-current-pane-hostname"]
path = config/tmux/plugins/tmux-current-pane-hostname
url = https://github.com/soyuka/tmux-current-pane-hostname.git
@@ -83,6 +53,8 @@
[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,6 +6,5 @@ config/tmux/plugins/**
config/vim/plugged/**
node_modules
tools/antidote/**
tools/dotbot-brew/**
tools/dotbot-include/**
tools/dotbot/**

View File

@@ -60,3 +60,10 @@ repos:
hooks:
- id: fish_syntax
- id: fish_indent
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.6
hooks:
- id: ruff
args: [--fix]
- id: ruff-format

View File

@@ -5,12 +5,8 @@ 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 \
@@ -24,20 +20,12 @@ git submodule add --name antidote \
# tmux plugin manager and plugins
git submodule add --name tmux/tmux-continuum \
-f https://github.com/tmux-plugins/tmux-continuum config/tmux/plugins/tmux-continuum
git submodule add --name tmux/tmux-mode-indicator \
-f https://github.com/MunifTanjim/tmux-mode-indicator.git config/tmux/plugins/tmux-mode-indicator
git submodule add --name tmux/tmux-resurrect \
-f https://github.com/tmux-plugins/tmux-resurrect.git config/tmux/plugins/tmux-resurrect
git submodule add --name tmux/tmux-sensible \
-f https://github.com/tmux-plugins/tmux-sensible.git config/tmux/plugins/tmux-sensible
git submodule add --name tmux/tmux-sessionist \
-f https://github.com/tmux-plugins/tmux-sessionist.git config/tmux/plugins/tmux-sessionist
git submodule add --name tmux/tmux-suspend \
-f https://github.com/MunifTanjim/tmux-suspend.git config/tmux/plugins/tmux-suspend
git submodule add --name tmux/tmux-window-name \
-f https://github.com/ivuorinen/tmux-window-name.git config/tmux/plugins/tmux-window-name
git submodule add --name tmux/tmux-yank \
-f https://github.com/tmux-plugins/tmux-yank.git config/tmux/plugins/tmux-yank
git submodule add --name tmux/tmux-current-pane-hostname \
-f https://github.com/soyuka/tmux-current-pane-hostname.git config/tmux/plugins/tmux-current-pane-hostname
git submodule add --name tmux/tmux-dark-notify \
@@ -54,21 +42,68 @@ done
# Mark certain repositories shallow
git config -f .gitmodules submodule.antidote.shallow true
# remove old submodules
folders=(
"config/tmux/plugins/tpm"
"config/tmux/plugins/tmux"
"config/tmux/plugins/tmux-menus"
"tools/dotbot-crontab"
"tools/dotbot-snap"
"config/nvim-kickstart"
"local/bin/asdf"
"local/asdf"
"tools/dotbot-asdf"
# Log a message using msgr if available, else echo
_log() {
local msg="$1"
if command -v msgr > /dev/null 2>&1; then
msgr run_done "$msg"
else
echo " [ok] $msg"
fi
return 0
}
# Remove a stale git submodule and clean up references
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"
)
for folder in "${folders[@]}"; do
[ -d "$folder" ] \
&& rm -rf "$folder" \
&& msgr run_done "Removed old submodule $folder"
for entry in "${old_submodules[@]}"; do
name="${entry%%:*}"
path="${entry#*:}"
remove_old_submodule "$name" "$path"
done

View File

@@ -2,20 +2,17 @@
# shellcheck shell=bash
export DOTFILES="$HOME/.dotfiles"
# Minimal PATH for x-have and utilities; full PATH set in shared.sh/exports
export PATH="$HOME/.local/bin:$DOTFILES/local/bin:$PATH"
export SHARED_SCRIPTS_SOURCED=0
source "$DOTFILES/config/shared.sh"
if [ -n "${GHOSTTY_RESOURCES_DIR}" ]; then
builtin source "${GHOSTTY_RESOURCES_DIR}/shell-integration/bash/ghostty.bash"
fi
# shellcheck source=../config/fzf/fzf.bash
[ -f "${DOTFILES}/config/fzf/fzf.bash" ] &&
source "${DOTFILES}/config/fzf/fzf.bash"
# Import ssh keys in keychain
# Import ssh keys in keychain (macOS-specific -A flag, silently fails on Linux)
ssh-add -A 2>/dev/null
x-have antidot && {
@@ -26,5 +23,3 @@ PROMPT_DIRTRIM=3
PROMPT_COMMAND='PS1_CMD1=$(git branch --show-current 2>/dev/null)'
PS1='\[\e[95m\]\u\[\e[0m\]@\[\e[38;5;22;2m\]\h\[\e[0m\] \[\e[38;5;33m\]\w\[\e[0m\] \[\e[92;2m\]${PS1_CMD1}\n\[\e[39m\]➜\[\e[0m\] '
# Added by LM Studio CLI (lms)
export PATH="$PATH:$HOME/.lmstudio/bin"

View File

@@ -1 +0,0 @@
use node

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",
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -7,18 +7,13 @@
autoload -U promptinit; promptinit
export DOTFILES="$HOME/.dotfiles"
LOCAL_SHARE="$HOME/.local/share"
export PATH="$HOME/.local/bin:$DOTFILES/local/bin:$LOCAL_SHARE/nvim/mason/bin:$LOCAL_SHARE/bob/nvim-bin:$LOCAL_SHARE/cargo/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"
# Minimal PATH for x-have and utilities; full PATH set in shared.sh/exports
export PATH="$HOME/.local/bin:$DOTFILES/local/bin:$PATH"
export SHARED_SCRIPTS_SOURCED=0
source "$DOTFILES/config/shared.sh"
# zsh completions directory
[ -z "$ZSH_COMPLETIONS" ] && export ZSH_COMPLETIONS="$XDG_CONFIG_HOME/zsh/completion"
# Add zsh completions to FPATH, compinit will be called later
FPATH="$ZSH_COMPLETIONS:$FPATH"
# zsh completions directory (ZSH_CUSTOM_COMPLETION_PATH set in shared.sh)
ZSH_COMPDUMP="$XDG_CACHE_HOME/zsh/zcompdump-${SHORT_HOST}-${ZSH_VERSION}"
source "$DOTFILES/config/zsh/antidote.zsh"
@@ -33,33 +28,14 @@ source_fzf_config()
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="$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
}
source_fzf_config
setup_tmux_window_name_plugin
x-have antidot && eval "$(antidot init)"
autoload -Uz compinit bashcompinit
compinit -d $ZSH_COMPDUMP
compinit -d "$ZSH_COMPDUMP"
bashcompinit
# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
export P10K_CONFIG="$DOTFILES/config/zsh/p10k.zsh"
[[ ! -f "$P10K_CONFIG" ]] || source "$P10K_CONFIG"
# Added by LM Studio CLI (lms)
export PATH="$PATH:$HOME/.lmstudio/bin"

View File

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

View File

@@ -1,251 +0,0 @@
# Start AeroSpace at login
start-at-login = false
# Normalizations. See: https://nikitabobko.github.io/AeroSpace/guide#normalization
enable-normalization-flatten-containers = true
enable-normalization-opposite-orientation-for-nested-containers = true
# See: https://nikitabobko.github.io/AeroSpace/guide#layouts
# The 'accordion-padding' specifies the size of accordion padding
# You can set 0 to disable the padding feature
accordion-padding = 10
# Possible values: tiles|accordion
default-root-container-layout = 'tiles'
# Possible values: horizontal|vertical|auto
# 'auto' means: wide monitor (anything wider than high) gets horizontal orientation,
# tall monitor (anything higher than wide) gets vertical orientation
default-root-container-orientation = 'auto'
# Mouse follows focus when focused monitor changes
# Drop it from your config, if you don't like this behavior
# See https://nikitabobko.github.io/AeroSpace/guide#on-focus-changed-callbacks
# See https://nikitabobko.github.io/AeroSpace/commands#move-mouse
# Fallback value (if you omit the key): on-focused-monitor-changed = []
on-focused-monitor-changed = ['move-mouse monitor-lazy-center']
# You can effectively turn off macOS "Hide application" (cmd-h) feature by toggling this flag
# Useful if you don't use this macOS feature, but accidentally hit cmd-h or cmd-alt-h key
# Also see: https://nikitabobko.github.io/AeroSpace/goodness#disable-hide-app
automatically-unhide-macos-hidden-apps = true
# [[on-window-detected]]
# if.app-id = 'com.apple.systempreferences'
# if.app-name-regex-substring = 'settings'
# if.window-title-regex-substring = 'substring'
# if.workspace = 'workspace-name'
# if.during-aerospace-startup = true
# check-further-callbacks = true
# run = ['layout floating', 'move-node-to-workspace S'] # The callback itself
[[on-window-detected]]
if.app-name-regex-substring = 'settings' # All settings
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.systempreferences' # macOS System Preferences
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.1password.1password' # 1Password
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'org.ferdium.ferdium-app' # Ferdium, has WhatsApp etc.
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.jetbrains.PhpStorm' # PhpStorm
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.finder' # Finder
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.Preview' # Preview
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.mail' # Mail
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.DanPristupov.Fork' # Fork
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.flexibits.fantastical2.mac' # Fantastical
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'org.whispersystems.signal-desktop' # Signal
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.tidal.desktop' # TIDAL
run = ['layout floating', 'move-node-to-workspace 2'] # Float and move to workspace 2
[[on-window-detected]]
if.app-id = 'com.apple.TV' # Apple TV app
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.setapp.DesktopClient' # Setapp
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.electron.dockerdesktop' # Docker Desktop
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.tinyspeck.slackmacgap' # Slack
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'md.obsidia' # Obsidian
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.todoist.mac.Todoist' # Todoist
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.backup.launcher' # TimeMachine
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.philipyoungg.session-setapp' # Session app (Setapp)
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.microsoft.rdc.macos' # Remote Desktop
run = ['layout floating']
# Possible values: (qwerty|dvorak)
# See https://nikitabobko.github.io/AeroSpace/guide#key-mapping
[key-mapping]
preset = 'qwerty'
# Gaps between windows (inner-*) and between monitor edges (outer-*).
# Possible values:
# - Constant: gaps.outer.top = 8
# - Per monitor: gaps.outer.top = [{ monitor.main = 16 }, { monitor."some-pattern" = 32 }, 24]
# In this example, 24 is a default value when there is no match.
# Monitor pattern is the same as for 'workspace-to-monitor-force-assignment'.
# See: https://nikitabobko.github.io/AeroSpace/guide#assign-workspaces-to-monitors
[gaps]
inner.horizontal = 5
inner.vertical = 5
outer.top = [{ monitor.'^built-in retina display$' = 0 }, 0]
outer.right = 0
outer.bottom = 0
outer.left = 0
# 'main' binding mode declaration
# See: https://nikitabobko.github.io/AeroSpace/guide#binding-modes
# 'main' binding mode must be always presented
# Fallback value (if you omit the key): mode.main.binding = {}
[mode.main.binding]
cmd-h = [] # Disable "hide application"
cmd-alt-h = [] # Disable "hide others"
# All possible keys:
# - Letters. a, b, c, ..., z
# - Numbers. 0, 1, 2, ..., 9
# - Keypad numbers. keypad0, keypad1, keypad2, ..., keypad9
# - F-keys. f1, f2, ..., f20
# - Special keys. minus, equal, period, comma, slash, backslash, quote, semicolon, backtick,
# leftSquareBracket, rightSquareBracket, space, enter, esc, backspace, tab
# - Keypad special. keypadClear, keypadDecimalMark, keypadDivide, keypadEnter, keypadEqual,
# keypadMinus, keypadMultiply, keypadPlus
# - Arrows. left, down, up, right
# All possible modifiers: cmd, alt, ctrl, shift
# All possible commands: https://nikitabobko.github.io/AeroSpace/commands
# See: https://nikitabobko.github.io/AeroSpace/commands#exec-and-forget
# You can uncomment the following lines to open up terminal with alt + enter shortcut (like in i3)
# alt-enter = '''exec-and-forget osascript -e '
# tell application "Terminal"
# do script
# activate
# end tell'
# '''
# alt-cmd-shift-f = 'fullscreen'
# alt-shift-f = 'layout floating'
# alt-shift-tab = 'move-workspace-to-monitor --wrap-around next'
# See: https://nikitabobko.github.io/AeroSpace/commands#focus
alt-h = 'focus left'
alt-j = 'focus down'
alt-k = 'focus up'
alt-l = 'focus right'
# See: https://nikitabobko.github.io/AeroSpace/commands#workspace
alt-shift-1 = 'workspace 1' # Main
alt-shift-2 = 'workspace 2' # Media
ctrl-shift-1 = 'move-node-to-workspace 1' # Move node to Main
ctrl-shift-2 = 'move-node-to-workspace 2' # Move node to Media
alt-shift-tab = 'workspace-back-and-forth' # Switch between workspaces
ctrl-shift-tab = 'move-workspace-to-monitor --wrap-around prev'
# See: https://nikitabobko.github.io/AeroSpace/commands#mode
# See: https://nikitabobko.github.io/AeroSpace/guide#binding-modes
alt-a = 'mode apps'
alt-s = 'mode service'
alt-m = 'mode move'
# ╭──────────────────────────────────────────────────────────╮
# │ alt-m │
# ╰──────────────────────────────────────────────────────────╯
[mode.move.binding]
esc = ['reload-config', 'mode main']
# See: https://nikitabobko.github.io/AeroSpace/commands#move-node-to-workspace
1 = ['move-node-to-workspace 1 --focus-follows-window']
2 = ['move-node-to-workspace 2 --focus-follows-window']
# See: https://nikitabobko.github.io/AeroSpace/commands#move
h = 'move left'
j = 'move down'
k = 'move up'
l = 'move right'
# See: https://nikitabobko.github.io/AeroSpace/commands#join-with
shift-h = 'join-with left'
shift-j = 'join-with down'
shift-k = 'join-with up'
shift-l = 'join-with right'
# https://nikitabobko.github.io/AeroSpace/commands#resize
ctrl-h = 'resize smart -70'
ctrl-l = 'resize smart +70'
shift-left = 'resize smart +70'
shift-right = 'resize smart -70'
# https://nikitabobko.github.io/AeroSpace/commands#flatten-workspace-tree
r = ['flatten-workspace-tree', 'mode main'] # reset layout
# ╭──────────────────────────────────────────────────────────╮
# │ alt-a │
# ╰──────────────────────────────────────────────────────────╯
[mode.apps.binding]
esc = ['reload-config', 'mode main']
b = ['exec-and-forget open -a /Applications/Brave Browser.app', 'mode main'] # Browser
c = ['exec-and-forget open -a /Applications/Ferdium.app', 'mode main'] # Chat
g = ['exec-and-forget open -a /Applications/Ghostty.app', 'mode main'] # Ghostty
o = ['exec-and-forget open -a /Applications/Obsidian.app', 'mode main'] # Obsidian
s = ['exec-and-forget open -a /Applications/Slack.app', 'mode main'] # Slack
t = ['exec-and-forget open -a /Applications/TIDAL.app', 'mode main'] # Tidal
w = ['exec-and-forget open -a /Applications/WezTerm.app', 'mode main'] # WezTerm
# ╭──────────────────────────────────────────────────────────╮
# │ alt-s │
# ╰──────────────────────────────────────────────────────────╯
[mode.service.binding]
esc = ['reload-config', 'mode main'] # reload config
r = ['flatten-workspace-tree', 'mode main'] # reset layout
# See: https://nikitabobko.github.io/AeroSpace/commands#layout
f = ['layout floating tiling', 'mode main'] # Toggle between floating and tiling layout
backspace = ['close-all-windows-but-current', 'mode main']

View File

@@ -7,8 +7,6 @@ x-have eza && {
alias ls="eza -h -s=type --git --icons --group-directories-first"
}
alias vim='vim -u "$XDG_CONFIG_HOME/vim/vimrc"'
# Easier navigation: .., ..., ....
alias ..="cd .."
alias ...="cd ../.."

View File

@@ -1,15 +0,0 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/aquaproj/aqua/main/json-schema/aqua-yaml.json
# aqua - Declarative CLI Version Manager
# https://aquaproj.github.io/
# checksum:
# enabled: true
# require_checksum: true
# supported_envs:
# - all
registries:
- type: standard
ref: v4.346.0 # renovate: depName=aquaproj/aqua-registry
packages:
- name: cli/cli
version: 'v2.69.0'

View File

@@ -1,5 +0,0 @@
# See the docs for explanations: https://asdf-vm.com/manage/configuration.html
legacy_version_file=yes
use_release_candidates=no
concurrency=auto

View File

@@ -1,27 +0,0 @@
// A cargo subcommand for checking and applying
// updates to installed executables
cargo-update
// Cargo cache management utility
cargo-cache
// An incremental parsing system for programming tools
tree-sitter-cli
// a subprocess caching utility
bkt
// a structural diff that understands syntax
difftastic
// A simple, fast and user-friendly alternative to 'find'
fd-find
// recursively searches directories for a
// regex pattern while respecting your gitignore
ripgrep
// A version manager for neovim
bob-nvim
// bottom, btm - A cross-platform graphical process/system monitor with
// a customizable interface and a multitude of features.
bottom
// A modern alternative to ls
eza
// Tmux Sessionizer: A tool for opening git repositories as tmux sessions
tmux-sessionizer
// zoxide, a smarter cd command
zoxide

View File

@@ -1 +0,0 @@
bundler

View File

@@ -1,29 +0,0 @@
// These are golang packages I use,
// so they should be available with all versions
// Git Profile allows you to switch between user profiles in git repos
github.com/dotzero/git-profile@latest
// An extensible command line tool or library to format yaml files.
github.com/google/yamlfmt/cmd/yamlfmt@latest
// Parsing HTML at the command line
github.com/ericchiang/pup@latest
// HTML to Markdown converter
github.com/suntong/html2md@latest
// cheat allows you to create and view interactive cheatsheets on the cli.
github.com/cheat/cheat/cmd/cheat@latest
// Render markdown on the CLI, with pizzazz! 💅
github.com/charmbracelet/glow@latest
// Static checker for GitHub Actions workflow files
github.com/rhysd/actionlint/cmd/actionlint@latest
// Cleans up your $HOME from those pesky dotfiles
github.com/doron-cohen/antidot@latest
// FZF is a general-purpose command-line fuzzy finder.
github.com/junegunn/fzf@latest
// gopls, the Go language server
golang.org/x/tools/gopls@latest
// A language for writing HTML user interfaces in Go.
github.com/a-h/templ/cmd/templ@latest
// A tool for glamorous shell scripts 🎀
github.com/charmbracelet/gum@latest
// A terminal session manager
github.com/joshmedeski/sesh/v2@latest

View File

@@ -1,7 +0,0 @@
blade-formatter
corepack
editorconfig-checker
github-release-notes
neovim
npm
stylelint-lsp

View File

@@ -1,20 +0,0 @@
1password-cli https://github.com/NeoHsu/asdf-1password-cli.git f5d5aab
age https://github.com/threkk/asdf-age.git 396bdf6
asdf-plugin-manager https://github.com/asdf-community/asdf-plugin-manager.git b5862c1
direnv https://github.com/asdf-community/asdf-direnv.git 6ff3dbe
dotenv-linter https://github.com/wesleimp/asdf-dotenv-linter.git 1369f53
editorconfig-checker https://github.com/gabitchov/asdf-editorconfig-checker.git 585c1d5
fd https://gitlab.com/wt0f/asdf-fd.git 17d56e0
github-cli https://github.com/bartlomiejdanek/asdf-github-cli.git e0605b7
golang https://github.com/asdf-community/asdf-golang.git e2527a3
hadolint https://github.com/devlincashman/asdf-hadolint.git c8eb88b
kubectl https://github.com/asdf-community/asdf-kubectl.git 2fb3b57
pre-commit https://github.com/jonathanmorley/asdf-pre-commit.git 26bfc42
ripgrep https://gitlab.com/wt0f/asdf-ripgrep.git e836665
rust https://github.com/code-lever/asdf-rust.git 95acf4f
shellcheck https://github.com/luizm/asdf-shellcheck.git 66200ff
shfmt https://github.com/luizm/asdf-shfmt.git a42c5ff
terragrunt https://github.com/ohmer/asdf-terragrunt.git 29f2935
tf-summarize https://github.com/adamcrews/asdf-tf-summarize.git 880ad26
yamllint https://github.com/ericcornelissen/asdf-yamllint.git e4cfb17
yq https://github.com/sudermanjr/asdf-yq.git 772992f

View File

@@ -1,4 +0,0 @@
ansible
pipenv
neovim
libtmux

View File

@@ -1,12 +0,0 @@
[global]
disable_stdin = false
load_dotenv = true
hide_env_diff = false
[whitelist]
prefix = [
"~/Code/"
]
exact = [
"~/.dotfiles/.envrc"
]

View File

@@ -1,6 +0,0 @@
### Do not edit. This was autogenerated by 'asdf direnv setup' ###
# shellcheck shell=bash
use_asdf()
{
source_env "$(asdf direnv envrc "$@")"
}

View File

@@ -150,6 +150,7 @@ commit()
git commit -a -m "$commitMessage"
}
# Run Laravel scheduler in a loop
scheduler()
{
while :; do
@@ -282,7 +283,8 @@ export LESSHISTFILE="$XDG_STATE_HOME"/less/history
export MANPAGER="less -X"
# Always enable colored `grep` output
export GREP_OPTIONS="--color=auto"
# Note: GREP_OPTIONS is deprecated since GNU grep 2.21
# Color is handled via alias in config/alias
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
@@ -348,12 +350,6 @@ export COMPOSER_HOME="$XDG_STATE_HOME/composer"
export COMPOSER_BIN="$COMPOSER_HOME/vendor/bin"
export PATH="$COMPOSER_BIN:$PATH"
# direnv, https://direnv.net/
# https://direnv.net/docs/hook.html
# Set the hook to show the direnv message in a different color
# export DIRENV_LOG_FORMAT=$'\033[2mdirenv: %s\033[0m'
export DIRENV_LOG_FORMAT=
# docker, https://docs.docker.com/engine/reference/commandline/cli/
msg "Setting up Docker configuration"
export DOCKER_CONFIG="${XDG_CONFIG_HOME}/docker"
@@ -410,11 +406,6 @@ x-have pyenv && eval "$(pyenv init -)"
msg "Setting up Rust/Cargo configuration"
export RUST_WITHOUT=rust-docs
# 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"
@@ -442,14 +433,15 @@ export ZSH_TMUX_UNICODE=true
export ZSH_TMUX_AUTOQUIT=false
export ZSH_TMUX_DEFAULT_SESSION_NAME=main
# tms, https://github.com/jrmoulton/tmux-sessionizer
export TMS_CONFIG_FILE="${XDG_CONFIG_HOME}/tms/config.toml"
# wakatime, https://github.com/wakatime/wakatime-cli
msg "Setting up Wakatime configuration"
export WAKATIME_HOME="$XDG_STATE_HOME/wakatime"
x-dc "$WAKATIME_HOME"
# LM Studio CLI
msg "Setting up LM Studio configuration"
export PATH="$PATH:$HOME/.lmstudio/bin"
# Misc
msg "Setting up miscellaneous configuration"
export ZSHZ_DATA="$XDG_STATE_HOME/z"

View File

@@ -8,7 +8,6 @@ fi
export PATH="$HOME/.local/go/bin:$PATH"
alias logrotate='/usr/sbin/logrotate -s "$HOME/logs/state"'
alias nano='nano -wS -$'
alias gpg=gpg2
ACME_PATH="$HOME/.acme.sh"

View File

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

View File

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

View File

@@ -3,6 +3,13 @@
# Set default configuration using session variables for most settings
# Only PHPENV_GLOBAL_VERSION needs to persist across shells
# Provider override (empty = auto-detect)
# Valid values: homebrew, apt
if not set -q PHPENV_PROVIDER
set -g PHPENV_PROVIDER ""
end
if not set -q PHPENV_AUTO_INSTALL
set -g PHPENV_AUTO_INSTALL false
end

View File

@@ -2,6 +2,8 @@
# │ fish/config.fish
# ╰──────────────────────────────────────────────────────────╯
fish_config theme choose "Catppuccin Mocha"
test -e "$HOME/.config/fish/alias.fish" &&
source "$HOME/.config/fish/alias.fish"

View File

@@ -1,4 +1,5 @@
jorgebucaran/fisher
ilancosman/tide@v6
jethrokuan/z
ivuorinen/phpenv.fish
ilancosman/tide@v6
catppuccin/fish

View File

@@ -7,65 +7,67 @@ To be used with a companion fish function like this:
"""
from __future__ import print_function
import json
import os
import signal
import subprocess
import sys
import traceback
BASH = 'bash'
BASH = "bash"
FISH_READONLY = [
'PWD', 'SHLVL', 'history', 'pipestatus', 'status', 'version',
'FISH_VERSION', 'fish_pid', 'hostname', '_', 'fish_private_mode'
"PWD",
"SHLVL",
"history",
"pipestatus",
"status",
"version",
"FISH_VERSION",
"fish_pid",
"hostname",
"_",
"fish_private_mode",
]
IGNORED = [
'PS1', 'XPC_SERVICE_NAME'
]
IGNORED = ["PS1", "XPC_SERVICE_NAME"]
def ignored(name):
if name == 'PWD': # this is read only, but has special handling
if name == "PWD": # this is read only, but has special handling
return False
# ignore other read only variables
if name in FISH_READONLY:
return True
if name in IGNORED or name.startswith("BASH_FUNC"):
return True
if name.startswith('%'):
return True
return False
return name.startswith("%")
def escape(string):
# use json.dumps to reliably escape quotes and backslashes
return json.dumps(string).replace(r'$', r'\$')
return json.dumps(string).replace(r"$", r"\$")
def escape_identifier(word):
return escape(word.replace('?', '\\?'))
return escape(word.replace("?", "\\?"))
def comment(string):
return '\n'.join(['# ' + line for line in string.split('\n')])
return "\n".join(["# " + line for line in string.split("\n")])
def gen_script():
# Use the following instead of /usr/bin/env to read environment so we can
# deal with multi-line environment variables (and other odd cases).
env_reader = "%s -c 'import os,json; print(json.dumps({k:v for k,v in os.environ.items()}))'" % (sys.executable)
args = [BASH, '-c', env_reader]
env_reader = f"{sys.executable} -c 'import os,json; print(json.dumps({{k:v for k,v in os.environ.items()}}))'"
args = [BASH, "-c", env_reader]
output = subprocess.check_output(args, universal_newlines=True)
old_env = output.strip()
pipe_r, pipe_w = os.pipe()
if sys.version_info >= (3, 4):
os.set_inheritable(pipe_w, True)
command = 'eval $1 && ({}; alias) >&{}'.format(
env_reader,
pipe_w
)
args = [BASH, '-c', command, 'bass', ' '.join(sys.argv[1:])]
os.set_inheritable(pipe_w, True)
command = f"eval $1 && ({env_reader}; alias) >&{pipe_w}"
args = [BASH, "-c", command, "bass", " ".join(sys.argv[1:])]
p = subprocess.Popen(args, universal_newlines=True, close_fds=False)
os.close(pipe_w)
with os.fdopen(pipe_r) as f:
@@ -73,9 +75,7 @@ def gen_script():
alias_str = f.read()
if p.wait() != 0:
raise subprocess.CalledProcessError(
returncode=p.returncode,
cmd=' '.join(sys.argv[1:]),
output=new_env + alias_str
returncode=p.returncode, cmd=" ".join(sys.argv[1:]), output=new_env + alias_str
)
new_env = new_env.strip()
@@ -89,41 +89,41 @@ def gen_script():
continue
v1 = old_env.get(k)
if not v1:
script_lines.append(comment('adding %s=%s' % (k, v)))
script_lines.append(comment(f"adding {k}={v}"))
elif v1 != v:
script_lines.append(comment('updating %s=%s -> %s' % (k, v1, v)))
script_lines.append(comment(f"updating {k}={v1} -> {v}"))
# process special variables
if k == 'PWD':
script_lines.append('cd %s' % escape(v))
if k == "PWD":
script_lines.append(f"cd {escape(v)}")
continue
else:
continue
if k == 'PATH':
value = ' '.join([escape(directory)
for directory in v.split(':')])
if k == "PATH": # noqa: SIM108
value = " ".join([escape(directory) for directory in v.split(":")])
else:
value = escape(v)
script_lines.append('set -g -x %s %s' % (k, value))
script_lines.append(f"set -g -x {k} {value}")
for var in set(old_env.keys()) - set(new_env.keys()):
script_lines.append(comment('removing %s' % var))
script_lines.append('set -e %s' % var)
script_lines.append(comment(f"removing {var}"))
script_lines.append(f"set -e {var}")
script = '\n'.join(script_lines)
script = "\n".join(script_lines)
alias_lines = []
for line in alias_str.splitlines():
_, rest = line.split(None, 1)
k, v = rest.split("=", 1)
alias_lines.append("alias " + escape_identifier(k) + "=" + v)
alias = '\n'.join(alias_lines)
alias = "\n".join(alias_lines)
return script + '\n' + alias
return script + "\n" + alias
script_file = os.fdopen(3, 'w')
script_file = os.fdopen(3, "w")
if not sys.argv[1:]:
print('__bass_usage', file=script_file, end='')
print("__bass_usage", file=script_file, end="")
sys.exit(0)
try:
@@ -131,8 +131,8 @@ try:
except subprocess.CalledProcessError as e:
sys.exit(e.returncode)
except Exception:
print('Bass internal error!', file=sys.stderr)
raise # traceback will output to stderr
print("Bass internal error!", file=sys.stderr)
raise # traceback will output to stderr
except KeyboardInterrupt:
signal.signal(signal.SIGINT, signal.SIG_DFL)
os.kill(os.getpid(), signal.SIGINT)

View File

@@ -1,17 +1,18 @@
function fisher --argument-names cmd --description "A plugin manager for Fish"
set --query fisher_path || set --local fisher_path $__fish_config_dir
set --local fisher_version 4.4.5
set --local fisher_version 4.4.8
set --local fish_plugins $__fish_config_dir/fish_plugins
switch "$cmd"
case -v --version
echo "fisher, version $fisher_version"
case "" -h --help
echo "Usage: fisher install <plugins...> Install plugins"
echo " fisher remove <plugins...> Remove installed plugins"
echo " fisher update <plugins...> Update installed plugins"
echo " fisher update Update all installed plugins"
echo " fisher list [<regex>] List installed plugins matching regex"
echo "Usage: fisher install <plugins...> Install plugins"
echo " fisher remove <plugins...> Remove installed plugins"
echo " fisher uninstall <plugins...> Remove installed plugins (alias)"
echo " fisher update <plugins...> Update installed plugins"
echo " fisher update Update all installed plugins"
echo " fisher list [<regex>] List installed plugins matching regex"
echo "Options:"
echo " -v, --version Print version"
echo " -h, --help Print this help message"
@@ -19,9 +20,11 @@ function fisher --argument-names cmd --description "A plugin manager for Fish"
echo " \$fisher_path Plugin installation path. Default: $__fish_config_dir" | string replace --regex -- $HOME \~
case ls list
string match --entire --regex -- "$argv[2]" $_fisher_plugins
case install update remove
case install update remove uninstall
isatty || read --local --null --array stdin && set --append argv $stdin
test "$cmd" = uninstall && set cmd remove
set --local install_plugins
set --local update_plugins
set --local remove_plugins
@@ -38,6 +41,8 @@ function fisher --argument-names cmd --description "A plugin manager for Fish"
echo "fisher: \"$fish_plugins\" file not found: \"$cmd\"" >&2 && return 1
end
set arg_plugins $file_plugins
else if test "$cmd" = install && ! set --query old_plugins[1]
set --append arg_plugins $file_plugins
end
for plugin in $arg_plugins
@@ -86,6 +91,7 @@ function fisher --argument-names cmd --description "A plugin manager for Fish"
if test -e $plugin
command cp -Rf $plugin/* $source
else
set resp (command mktemp)
set temp (command mktemp -d)
set repo (string split -- \@ $plugin) || set repo[2] HEAD
@@ -98,8 +104,13 @@ function fisher --argument-names cmd --description "A plugin manager for Fish"
echo Fetching (set_color --underline)\$url(set_color normal)
if command curl -q --silent -L \$url | command tar -xzC \$temp -f - 2>/dev/null
set http (command curl -q --silent -L -o \$resp -w %{http_code} \$url)
if test \"\$http\" = 200 && command tar -xzC \$temp -f \$resp 2>/dev/null
command cp -Rf \$temp/*/* $source
else if test \"\$http\" = 403
echo fisher: GitHub API rate limit exceeded \(HTTP 403\) >&2
command rm -rf $source
else
echo fisher: Invalid plugin name or host unavailable: \\\"$plugin\\\" >&2
command rm -rf $source

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,61 @@
# name: 'Catppuccin Frappé'
# url: 'https://github.com/catppuccin/fish'
[light]
# preferred_background: eff1f5
fish_color_normal 4c4f69
fish_color_command 1e66f5
fish_color_param dd7878
fish_color_keyword 8839ef
fish_color_quote 40a02b
fish_color_redirection ea76cb
fish_color_end fe640b
fish_color_comment 8c8fa1
fish_color_error d20f39
fish_color_gray 9ca0b0
fish_color_selection --background=ccd0da
fish_color_search_match --background=ccd0da
fish_color_option 40a02b
fish_color_operator ea76cb
fish_color_escape e64553
fish_color_autosuggestion 9ca0b0
fish_color_cancel d20f39
fish_color_cwd df8e1d
fish_color_user 179299
fish_color_host 1e66f5
fish_color_host_remote 40a02b
fish_color_status d20f39
fish_pager_color_progress 9ca0b0
fish_pager_color_prefix ea76cb
fish_pager_color_completion 4c4f69
fish_pager_color_description 9ca0b0
[dark]
# preferred_background: 303446
fish_color_normal c6d0f5
fish_color_command 8caaee
fish_color_param eebebe
fish_color_keyword ca9ee6
fish_color_quote a6d189
fish_color_redirection f4b8e4
fish_color_end ef9f76
fish_color_comment 838ba7
fish_color_error e78284
fish_color_gray 737994
fish_color_selection --background=414559
fish_color_search_match --background=414559
fish_color_option a6d189
fish_color_operator f4b8e4
fish_color_escape ea999c
fish_color_autosuggestion 737994
fish_color_cancel e78284
fish_color_cwd e5c890
fish_color_user 81c8be
fish_color_host 8caaee
fish_color_host_remote a6d189
fish_color_status e78284
fish_pager_color_progress 737994
fish_pager_color_prefix f4b8e4
fish_pager_color_completion c6d0f5
fish_pager_color_description 737994

View File

@@ -1,30 +0,0 @@
# name: 'Catppuccin Latte'
# url: 'https://github.com/catppuccin/fish'
# preferred_background: eff1f5
fish_color_normal 4c4f69
fish_color_command 1e66f5
fish_color_param dd7878
fish_color_keyword d20f39
fish_color_quote 40a02b
fish_color_redirection ea76cb
fish_color_end fe640b
fish_color_comment 8c8fa1
fish_color_error d20f39
fish_color_gray 9ca0b0
fish_color_selection --background=ccd0da
fish_color_search_match --background=ccd0da
fish_color_option 40a02b
fish_color_operator ea76cb
fish_color_escape e64553
fish_color_autosuggestion 9ca0b0
fish_color_cancel d20f39
fish_color_cwd df8e1d
fish_color_user 179299
fish_color_host 1e66f5
fish_color_host_remote 40a02b
fish_color_status d20f39
fish_pager_color_progress 9ca0b0
fish_pager_color_prefix ea76cb
fish_pager_color_completion 4c4f69
fish_pager_color_description 9ca0b0

View File

@@ -0,0 +1,61 @@
# name: 'Catppuccin Macchiato'
# url: 'https://github.com/catppuccin/fish'
[light]
# preferred_background: eff1f5
fish_color_normal 4c4f69
fish_color_command 1e66f5
fish_color_param dd7878
fish_color_keyword 8839ef
fish_color_quote 40a02b
fish_color_redirection ea76cb
fish_color_end fe640b
fish_color_comment 8c8fa1
fish_color_error d20f39
fish_color_gray 9ca0b0
fish_color_selection --background=ccd0da
fish_color_search_match --background=ccd0da
fish_color_option 40a02b
fish_color_operator ea76cb
fish_color_escape e64553
fish_color_autosuggestion 9ca0b0
fish_color_cancel d20f39
fish_color_cwd df8e1d
fish_color_user 179299
fish_color_host 1e66f5
fish_color_host_remote 40a02b
fish_color_status d20f39
fish_pager_color_progress 9ca0b0
fish_pager_color_prefix ea76cb
fish_pager_color_completion 4c4f69
fish_pager_color_description 9ca0b0
[dark]
# preferred_background: 24273a
fish_color_normal cad3f5
fish_color_command 8aadf4
fish_color_param f0c6c6
fish_color_keyword c6a0f6
fish_color_quote a6da95
fish_color_redirection f5bde6
fish_color_end f5a97f
fish_color_comment 8087a2
fish_color_error ed8796
fish_color_gray 6e738d
fish_color_selection --background=363a4f
fish_color_search_match --background=363a4f
fish_color_option a6da95
fish_color_operator f5bde6
fish_color_escape ee99a0
fish_color_autosuggestion 6e738d
fish_color_cancel ed8796
fish_color_cwd eed49f
fish_color_user 8bd5ca
fish_color_host 8aadf4
fish_color_host_remote a6da95
fish_color_status ed8796
fish_pager_color_progress 6e738d
fish_pager_color_prefix f5bde6
fish_pager_color_completion cad3f5
fish_pager_color_description 6e738d

View File

@@ -1,11 +1,41 @@
# name: 'Catppuccin Mocha'
# url: 'https://github.com/catppuccin/fish'
# preferred_background: 1e1e2e
[light]
# preferred_background: eff1f5
fish_color_normal 4c4f69
fish_color_command 1e66f5
fish_color_param dd7878
fish_color_keyword 8839ef
fish_color_quote 40a02b
fish_color_redirection ea76cb
fish_color_end fe640b
fish_color_comment 8c8fa1
fish_color_error d20f39
fish_color_gray 9ca0b0
fish_color_selection --background=ccd0da
fish_color_search_match --background=ccd0da
fish_color_option 40a02b
fish_color_operator ea76cb
fish_color_escape e64553
fish_color_autosuggestion 9ca0b0
fish_color_cancel d20f39
fish_color_cwd df8e1d
fish_color_user 179299
fish_color_host 1e66f5
fish_color_host_remote 40a02b
fish_color_status d20f39
fish_pager_color_progress 9ca0b0
fish_pager_color_prefix ea76cb
fish_pager_color_completion 4c4f69
fish_pager_color_description 9ca0b0
[dark]
# preferred_background: 1e1e2e
fish_color_normal cdd6f4
fish_color_command 89b4fa
fish_color_param f2cdcd
fish_color_keyword f38ba8
fish_color_keyword cba6f7
fish_color_quote a6e3a1
fish_color_redirection f5c2e7
fish_color_end fab387
@@ -28,3 +58,4 @@ fish_pager_color_progress 6c7086
fish_pager_color_prefix f5c2e7
fish_pager_color_completion cdd6f4
fish_pager_color_description 6c7086

View File

@@ -1,6 +0,0 @@
[General]
ApplicationUpdateChannel=release
CheckApplicatonUpdates=true
FirmwareUpdateChannel=release
LastFolderUrl=/Users/ivuorinen
ShowHiddenFiles=false

View File

@@ -1,15 +0,0 @@
# vim: ft=ghostty
theme = "light:tokyonight-day,dark:tokyonight-storm"
font-family = "JetBrainsMono Nerd Font Mono"
background-blur-radius = 15
background-opacity = 0.95
clipboard-read = allow
clipboard-write = allow
cursor-style = bar
custom-shader-animation = true
gtk-single-instance = true
mouse-hide-while-typing = true
shell-integration-features = true
window-theme = system

View File

@@ -260,8 +260,6 @@ 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

@@ -1,54 +0,0 @@
# Beware! This file is rewritten by htop when settings are changed in the interface.
# The parser is also very primitive, and not human-friendly.
htop_version=3.4.1
config_reader_min_version=3
fields=0 48 17 18 38 39 2 46 47 49 1
hide_kernel_threads=1
hide_userland_threads=0
hide_running_in_container=0
shadow_other_users=0
show_thread_names=0
show_program_path=1
highlight_base_name=0
highlight_deleted_exe=1
shadow_distribution_path_prefix=0
highlight_megabytes=1
highlight_threads=1
highlight_changes=0
highlight_changes_delay_secs=5
find_comm_in_cmdline=1
strip_exe_from_cmdline=1
show_merged_command=0
header_margin=1
screen_tabs=1
detailed_cpu_time=0
cpu_count_from_one=0
show_cpu_usage=1
show_cpu_frequency=0
show_cached_memory=1
update_process_names=0
account_guest_in_cpu_meter=0
color_scheme=0
enable_mouse=1
delay=15
hide_function_bar=0
header_layout=two_50_50
column_meters_0=LeftCPUs2 Memory Swap
column_meter_modes_0=1 1 1
column_meters_1=RightCPUs2 Tasks LoadAverage Uptime
column_meter_modes_1=1 2 2 2
tree_view=0
sort_key=46
tree_sort_key=0
sort_direction=-1
tree_sort_direction=1
tree_view_always_by_pid=0
all_branches_collapsed=0
screen:Main=PID USER PRIORITY NICE M_VIRT M_RESIDENT STATE PERCENT_CPU PERCENT_MEM TIME Command
.sort_key=PERCENT_CPU
.tree_sort_key=PID
.tree_view_always_by_pid=0
.tree_view=0
.sort_direction=-1
.tree_sort_direction=1
.all_branches_collapsed=0

View File

@@ -1,4 +1,4 @@
#!/bin/env bash
#!/usr/bin/env bash
[ -z "$NVM_DIR" ] && export NVM_DIR="$HOME/.config/nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[[ -z "$NVM_DIR" ]] && export NVM_DIR="$HOME/.config/nvm"
[[ -s "$NVM_DIR/nvm.sh" ]] && \. "$NVM_DIR/nvm.sh" # This loads nvm

View File

@@ -1,15 +0,0 @@
# Disable the startup message
startup_message off
# Set a large scrollback buffer
defscrollback 32000
# Always start `screen` with UTF-8 enabled (`screen -U`)
defutf8 on
# Scroll with mouse wheel (http://stackoverflow.com/a/1125947)
termcapinfo xterm* ti@:te@
# Some settings for screen + vim
term xterm-256color
maptimeout 10

View File

@@ -1 +0,0 @@
set tabsize 2

View File

@@ -1,18 +0,0 @@
#!/usr/bin/env bash
###############################################################################
# .nbrc
#
# Configuration file for `nb`, a command line note-taking, bookmarking,
# and knowledge base application with encryption, search, Git-backed syncing,
# and more in a single portable script.
#
# Edit this file manually or manage settings using the `nb settings`
# subcommand. Configuration options are set as environment variables, eg:
# export NB_ENCRYPTION_TOOL=gpg
#
# https://github.com/xwmx/nb
###############################################################################
export NB_DIR="${NB_DIR:-$HOME/.local/state/nb}" # Set by `nb` • Mon May 8 15:25:12 EEST 2023
export NB_COLOR_THEME="${NB_COLOR_THEME:-unicorn}" # Set by `nb` • Mon May 8 15:41:22 EEST 2023

View File

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

View File

@@ -5,7 +5,7 @@
# shellcheck shell=bash
# Defaults
[ -z "$DOTFILES" ] && export DOTFILES="$HOME/.dotfiles"
[[ -z "$DOTFILES" ]] && export DOTFILES="$HOME/.dotfiles"
DOTFILES_CURRENT_SHELL=$(basename "$SHELL")
export DOTFILES_CURRENT_SHELL
@@ -15,7 +15,7 @@ VERBOSE="${VERBOSE:-0}"
DEBUG="${DEBUG:-0}"
# Enable debugging with DEBUG=1
[ "${DEBUG:-0}" -eq 1 ] && set -x
[[ "${DEBUG:-0}" -eq 1 ]] && set -x
# Detect the current shell
CURRENT_SHELL=$(ps -p $$ -ocomm= | awk -F/ '{print $NF}')
@@ -36,6 +36,7 @@ x-path-prepend()
exit 1
;;
esac
return 0
}
# Function to set environment variables based on the shell
@@ -55,6 +56,7 @@ x-set-env()
exit 1
;;
esac
return 0
}
# Explicitly set XDG folders, if not already set
@@ -74,7 +76,7 @@ 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"
[[ -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"
@@ -83,7 +85,8 @@ if ! declare -f msg > /dev/null; then
# $1 - message (string)
msg()
{
[ "$VERBOSE" -eq 1 ] && msgr msg "$1"
local message="$1"
[[ "$VERBOSE" -eq 1 ]] && msgr msg "$message"
return 0
}
msg "msg was not defined, defined it now"
@@ -95,7 +98,8 @@ if ! declare -f msg_err > /dev/null; then
# $1 - error message (string)
msg_err()
{
msgr err "$1" >&2
local message="$1"
msgr err "$message" >&2
exit 1
}
fi
@@ -106,7 +110,8 @@ if ! declare -f msg_done > /dev/null; then
# $1 - message (string)
msg_done()
{
msgr "done" "$1"
local message="$1"
msgr "done" "$message"
return 0
}
fi
@@ -117,7 +122,8 @@ if ! declare -f msg_run > /dev/null; then
# $1 - message (string)
msg_run()
{
msgr run "$1"
local message="$1"
msgr run "$message"
return 0
}
fi
@@ -128,7 +134,8 @@ if ! declare -f msg_ok > /dev/null; then
# $1 - message (string)
msg_ok()
{
msgr ok "$1"
local message="$1"
msgr ok "$message"
return 0
}
fi
@@ -143,12 +150,16 @@ if ! declare -f array_diff > /dev/null; then
# Source: https://stackoverflow.com/a/42399479/594940
array_diff()
{
local result_var="$1"
local arr1_name="$2"
local arr2_name="$3"
# shellcheck disable=SC1083,SC2086
eval local ARR1=\(\"\${$2[@]}\"\)
eval local ARR1=\(\"\${${arr1_name}[@]}\"\)
# shellcheck disable=SC1083,SC2086
eval local ARR2=\(\"\${$3[@]}\"\)
eval local ARR2=\(\"\${${arr2_name}[@]}\"\)
local IFS=$'\n'
mapfile -t "$1" < <(comm -23 <(echo "${ARR1[*]}" | sort) <(echo "${ARR2[*]}" | sort))
mapfile -t "$result_var" < <(comm -23 <(echo "${ARR1[*]}" | sort) <(echo "${ARR2[*]}" | sort))
return 0
}
fi

View File

@@ -1,154 +0,0 @@
# Get editor completions based on the config schema
"$schema" = 'https://starship.rs/config-schema.json'
format = """
$os\
$directory\
$git_branch\
$git_state\
$git_status\
$fill \
$battery\
$username\
$hostname\
$aws\
$gcloud\
$conda\
$golang\
$nodejs\
$php\
$python\
$package\
$line_break\
$character"""
# Timeout for commands executed by starship (in milliseconds).
command_timeout = 1500
[character]
success_symbol = "[→](bold green)"
error_symbol = "[→](red)"
vimcmd_symbol = "[←](green)"
[aws]
symbol = " "
format = '[$symbol($profile )(\($region\) )(\[$duration\] )]($style)'
[cmd_duration]
disabled = true
[directory]
read_only = " 󰌾"
style = "blue"
before_repo_root_style = "white"
truncation_symbol = "…/"
[docker_context]
symbol = " "
format = '[$symbol$context]($style) '
[fill]
symbol = '·'
style = 'bold black'
[gcloud]
format = '[($symbol)$account(@$domain)(\($region\))]($style) '
[git_branch]
symbol = " "
format = '[$symbol$branch(:$remote_branch)]($style) '
truncation_length = 20
truncation_symbol = '…'
ignore_branches = ['master', 'main']
[git_status]
up_to_date = '✓'
staged = '[++\($count\)](green)'
[git_state]
format = '\([$state( $progress_current/$progress_total)]($style)\) '
style = "bright-black"
[git_metrics]
added_style = 'bold blue'
format = '[+$added]($added_style)/[-$deleted]($deleted_style) '
disabled = false
[golang]
symbol = " "
format = '[$symbol($version )]($style) '
[hostname]
ssh_symbol = " "
ssh_only = false
format = '[$ssh_symbol](bold blue)[$hostname](bold red) '
[lua]
format = '[$symbol($version )]($style)'
[nodejs]
symbol = " "
format = '[$symbol($version )]($style)'
version_format = '${major}.${minor}'
[os]
format = "[$symbol]($style) "
style = "bold blue"
disabled = false
[os.symbols]
Alpaquita = " "
Alpine = " "
Amazon = " "
Android = " "
Arch = " "
Artix = " "
CentOS = " "
Debian = " "
DragonFly = " "
Emscripten = " "
EndeavourOS = " "
Fedora = " "
FreeBSD = " "
Garuda = "󰛓 "
Gentoo = " "
HardenedBSD = "󰞌 "
Illumos = "󰈸 "
Linux = " "
Mabox = " "
Macos = " "
Manjaro = " "
Mariner = " "
MidnightBSD = " "
Mint = " "
NetBSD = " "
NixOS = " "
OpenBSD = "󰈺 "
openSUSE = " "
OracleLinux = "󰌷 "
Pop = " "
Raspbian = " "
Redhat = " "
RedHatEnterprise = " "
Redox = "󰀘 "
Solus = "󰠳 "
SUSE = " "
Ubuntu = " "
Unknown = " "
Windows = "󰍲 "
[package]
symbol = "󰏗 "
format = '[$symbol($version )]($style)'
version_format = '${major}.${minor}'
[php]
format = '[$symbol($version )]($style)'
version_format = '${major}.${minor}'
[python]
symbol = " "
format = "[$virtualenv]($style) "
[username]
format = "[$user]($style) "

View File

@@ -1,81 +0,0 @@
# [Created by task 2.6.2 5/11/2023 09:33:14]
# Taskwarrior program configuration file.
# For more documentation, see https://taskwarrior.org or try 'man task', 'man task-color',
# 'man task-sync' or 'man taskrc'
# Here is an example of entries that use the default, override and blank values
# variable=foo -- By specifying a value, this overrides the default
# variable= -- By specifying no value, this means no default
# #variable=foo -- By commenting out the line, or deleting it, this uses the default
# You can also refence environment variables:
# variable=$HOME/task
# variable=$VALUE
# Use the command 'task show' to see all defaults and overrides
# Files
data.location=$XDG_DATA_HOME/task/
# To use the default location of the XDG directories,
# move this configuration file from ~/.taskrc to ~/.config/task/taskrc and uncomment below
#data.location=$XDG_DATA_HOME/task
#hooks.location=~/.config/task/hooks
# Color theme (uncomment one to use)
#include light-16.theme
#include light-256.theme
#include dark-16.theme
#include dark-256.theme
#include dark-red-256.theme
#include dark-green-256.theme
#include dark-blue-256.theme
#include dark-violets-256.theme
#include dark-yellow-green.theme
#include dark-gray-256.theme
#include dark-gray-blue-256.theme
#include solarized-dark-256.theme
#include solarized-light-256.theme
#include no-color.theme
weekstart=monday
news.version=2.6.0
default.project=Inbox
calendar.details=full
calendar.holidays=sparse
recurrence=on
uda.taskwarrior-tui.keyconfig.quit=q
uda.taskwarrior-tui.keyconfig.refresh=r
uda.taskwarrior-tui.keyconfig.go-to-bottom=G
uda.taskwarrior-tui.keyconfig.go-to-top=g
uda.taskwarrior-tui.keyconfig.down=j
uda.taskwarrior-tui.keyconfig.up=k
uda.taskwarrior-tui.keyconfig.page-down=J
uda.taskwarrior-tui.keyconfig.page-up=K
uda.taskwarrior-tui.keyconfig.delete=x
uda.taskwarrior-tui.keyconfig.done=d
uda.taskwarrior-tui.keyconfig.start-stop=s
uda.taskwarrior-tui.keyconfig.quick-tag=t
uda.taskwarrior-tui.keyconfig.undo=u
uda.taskwarrior-tui.keyconfig.edit=e
uda.taskwarrior-tui.keyconfig.modify=m
uda.taskwarrior-tui.keyconfig.shell=!
uda.taskwarrior-tui.keyconfig.log=l
uda.taskwarrior-tui.keyconfig.add=a
uda.taskwarrior-tui.keyconfig.annotate=A
uda.taskwarrior-tui.keyconfig.filter=/
uda.taskwarrior-tui.keyconfig.zoom=z
uda.taskwarrior-tui.keyconfig.context-menu=c
uda.taskwarrior-tui.keyconfig.next-tab=.
uda.taskwarrior-tui.keyconfig.previous-tab=,
taskd.certificate=$XDG_DATA_HOME/task/private.certificate.pem
taskd.key=$XDG_DATA_HOME/task/private.key.pem
taskd.ca=$XDG_DATA_HOME/task/ca.cert.pem
taskd.server=inthe.am:53589
taskd.credentials=inthe_am/ivuorinen/b99a4970-94fb-4fb8-b9fe-e1a8140dd44d
taskd.trust=strict

View File

@@ -1,38 +0,0 @@
[style.description]
underline = false
bold = false
italic = false
[style.command_name]
foreground = "cyan"
underline = false
bold = false
italic = false
[style.example_text]
foreground = "green"
underline = false
bold = false
italic = false
[style.example_code]
foreground = "cyan"
underline = false
bold = false
italic = false
[style.example_variable]
foreground = "cyan"
underline = true
bold = false
italic = false
[display]
compact = false
use_pager = false
[updates]
auto_update = false
auto_update_interval_hours = 720
[directories]

View File

@@ -1,11 +0,0 @@
default_session = "main"
display_full_path = true
[[search_dirs]]
path = "~/Code"
depth = 3
[picker_colors]
highlight_color = "#31748f"
highlight_text_color = "#e0def4"
border_color = "#524F67"

View File

@@ -1 +0,0 @@
https://wfxr.mit-license.org/2018

View File

@@ -1,64 +0,0 @@
#!/usr/bin/env bash
#===============================================================================
# Author: Wenxuan
# Email: wenxuangm@gmail.com
# Created: 2018-04-06 12:12
#===============================================================================
get_fzf_options()
{
local fzf_options
local fzf_default_options='-w 100% -h 50% --multi -0 --no-preview'
fzf_options="$(tmux show -gqv '@fzf-url-fzf-options')"
[ -n "$fzf_options" ] && echo "$fzf_options" || echo "$fzf_default_options"
}
fzf_filter()
{
eval "fzf-tmux $(get_fzf_options)"
}
custom_open=$3
open_url()
{
if [[ -n $custom_open ]]; then
$custom_open "$@"
elif hash xdg-open &> /dev/null; then
nohup xdg-open "$@"
elif hash open &> /dev/null; then
nohup open "$@"
elif [[ -n $BROWSER ]]; then
nohup "$BROWSER" "$@"
fi
}
limit='screen'
[[ $# -ge 2 ]] && limit=$2
if [[ $limit == 'screen' ]]; then
content="$(tmux capture-pane -J -p -e | sed -r 's/\x1B\[[0-9;]*[mK]//g'))"
else
content="$(tmux capture-pane -J -p -e -S -"$limit" | sed -r 's/\x1B\[[0-9;]*[mK]//g'))"
fi
urls=$(echo "$content" | grep -oE '(https?|ftp|file):/?//[-A-Za-z0-9+&@#/%?=~_|!:,.;]*[-A-Za-z0-9+&@#/%=~_|]')
wwws=$(echo "$content" | grep -oE '(http?s://)?www\.[a-zA-Z](-?[a-zA-Z0-9])+\.[a-zA-Z]{2,}(/\S+)*' | grep -vE '^https?://' | sed 's/^\(.*\)$/http:\/\/\1/')
ips=$(echo "$content" | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(:[0-9]{1,5})?(/\S+)*' | sed 's/^\(.*\)$/http:\/\/\1/')
gits=$(echo "$content" | grep -oE '(ssh://)?git@\S*' | sed 's/:/\//g' | sed 's/^\(ssh\/\/\/\)\{0,1\}git@\(.*\)$/https:\/\/\2/')
gh=$(echo "$content" | grep -oE "['\"]([_A-Za-z0-9-]*/[_.A-Za-z0-9-]*)['\"]" | sed "s/['\"]//g" | sed 's#.#https://github.com/&#')
if [[ $# -ge 1 && $1 != '' ]]; then
extras=$(echo "$content" | eval "$1")
fi
items=$(
printf '%s\n' "${urls[@]}" "${wwws[@]}" "${gh[@]}" "${ips[@]}" "${gits[@]}" "${extras[@]}" \
| grep -v '^$' \
| sort -u \
| nl -w3 -s ' '
)
[ -z "$items" ] && tmux display 'tmux-fzf-url: no URLs found' && exit
fzf_filter <<< "$items" | awk '{print $2}' \
| while read -r chosen; do
open_url "$chosen" &> "/tmp/tmux-$(id -u)-fzf-url.log"
done

View File

@@ -1,23 +0,0 @@
#!/usr/bin/env bash
#===============================================================================
# Author: Wenxuan
# Email: wenxuangm@gmail.com
# Created: 2018-04-06 09:30
#===============================================================================
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# $1: option
# $2: default value
tmux_get() {
local value
value="$(tmux show -gqv "$1")"
[ -n "$value" ] && echo "$value" || echo "$2"
}
key="$(tmux_get '@fzf-url-bind' 'u')"
history_limit="$(tmux_get '@fzf-url-history-limit' 'screen')"
extra_filter="$(tmux_get '@fzf-url-extra-filter' '')"
custom_open="$(tmux_get '@fzf-url-open' '')"
echo "$extra_filter" >/tmp/filter
tmux bind-key "$key" run -b "$SCRIPT_DIR/fzf-url.sh '$extra_filter' $history_limit '$custom_open'"

View File

@@ -7,13 +7,13 @@ DEFAULT_NAME="main"
CURRENT_SESSION=$(tmux display-message -p "#{session_name}")
# Check that the session has a name
if [ "$CURRENT_SESSION" = "#{session_name}" ] || [ "$CURRENT_SESSION" = "0" ]; then
if [[ "$CURRENT_SESSION" = "#{session_name}" ]] || [[ "$CURRENT_SESSION" = "0" ]]; then
# Check if the default name is already in use
if tmux has-session -t "$DEFAULT_NAME" 2> /dev/null; then
# Query the user for a new name
echo "Session name '$DEFAULT_NAME' is already in use. Enter a new name:"
read -r NEW_NAME
while tmux has-session -t "$NEW_NAME" 2> /dev/null || [ -z "$NEW_NAME" ]; do
while tmux has-session -t "$NEW_NAME" 2> /dev/null || [[ -z "$NEW_NAME" ]]; do
echo "Name '$NEW_NAME' is invalid or already in use. Enter a new name:"
read -r NEW_NAME
done

View File

@@ -1,18 +0,0 @@
#!/usr/bin/env bash
# Get session list and pipe it to gum for selection
SESH_LIST=$(
sesh list -i \
| gum filter \
--limit 1 \
--no-sort \
--fuzzy \
--placeholder 'Pick a sesh' \
--height 50 \
--prompt='⚡'
)
# If a session was selected, connect to it
if [ "$SESH_LIST" != "" ]; then
sesh connect "$SESH_LIST"
fi

View File

@@ -1,18 +0,0 @@
#!/usr/bin/env fish
set selection (sesh list --icons | fzf-tmux -p 80%,70% \
--no-sort --ansi --border-label ' sesh ' --prompt '⚡ ' \
--header ' ^a all ^t tmux ^g configs ^x zoxide ^d tmux kill ^f find' \
--bind 'tab:down,btab:up' \
--bind 'ctrl-a:change-prompt(⚡ )+reload(sesh list --icons)' \
--bind 'ctrl-t:change-prompt(🪟 )+reload(sesh list -t --icons)' \
--bind 'ctrl-g:change-prompt(⚙️ )+reload(sesh list -c --icons)' \
--bind 'ctrl-x:change-prompt(📁 )+reload(sesh list -z --icons)' \
--bind 'ctrl-f:change-prompt(🔎 )+reload(fd -H -d 2 -t d -E .Trash . ~)' \
--bind 'ctrl-d:execute(tmux kill-session -t {2..})+change-prompt(⚡ )+reload(sesh list --icons)' \
--preview-window 'right:55%' \
--preview 'sesh preview {}')
if test -n "$selection"
sesh connect "$selection"
end

86
config/tmux/sesh.sh Executable file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/env bash
# Unified sesh session picker with cascading tool detection:
# 1. gum — simple fuzzy filter
# 2. fzf-tmux — rich UI with keybinds, preview, session kill
# 3. fzf — same as fzf-tmux but inline
# 4. select — bare minimum numbered menu
set -euo pipefail
# Fall back to native tmux session picker if sesh is not installed
if ! command -v sesh &>/dev/null; then
tmux choose-tree -Zs
exit 0
fi
# Pick a sesh session using gum filter
pick_with_gum() {
sesh list -i \
| gum filter \
--limit 1 \
--no-sort \
--fuzzy \
--placeholder 'Pick a sesh' \
--height 50 \
--prompt='⚡'
return 0
}
FZF_COMMON_OPTS=(
--no-sort --ansi
--border-label ' sesh '
--prompt '⚡ '
--header ' ^a all ^t tmux ^g configs ^x zoxide ^d tmux kill ^f find'
--bind 'tab:down,btab:up'
--bind 'ctrl-a:change-prompt(⚡ )+reload(sesh list --icons)'
--bind 'ctrl-t:change-prompt(🪟 )+reload(sesh list -t --icons)'
--bind 'ctrl-g:change-prompt(⚙️ )+reload(sesh list -c --icons)'
--bind 'ctrl-x:change-prompt(📁 )+reload(sesh list -z --icons)'
--bind 'ctrl-f:change-prompt(🔎 )+reload(fd -H -d 2 -t d -E .Trash . ~)'
--bind 'ctrl-d:execute(tmux kill-session -t {2..})+change-prompt(⚡ )+reload(sesh list --icons)'
--preview-window 'right:55%'
--preview 'sesh preview {}'
)
# Pick a sesh session using fzf-tmux popup
pick_with_fzf_tmux() {
sesh list --icons | fzf-tmux -p 80%,70% "${FZF_COMMON_OPTS[@]}"
return 0
}
# Pick a sesh session using fzf inline
pick_with_fzf() {
sesh list --icons | fzf "${FZF_COMMON_OPTS[@]}"
return 0
}
# Pick a sesh session using bash select menu
pick_with_select() {
local sessions
mapfile -t sessions < <(sesh list)
if [[ ${#sessions[@]} -eq 0 ]]; then
return
fi
PS3="Select session: "
select choice in "${sessions[@]}"; do
if [[ -n "${choice-}" ]]; then
printf '%s' "$choice"
break
fi
done
}
# Cascading tool detection
if command -v gum &>/dev/null; then
selection=$(pick_with_gum)
elif command -v fzf-tmux &>/dev/null; then
selection=$(pick_with_fzf_tmux)
elif command -v fzf &>/dev/null; then
selection=$(pick_with_fzf)
else
selection=$(pick_with_select)
fi
if [[ -n "${selection-}" ]]; then
sesh connect "$selection"
fi

View File

@@ -1 +1 @@
set -g @catppuccin_flavor "mocha"
set -g @catppuccin_flavour "mocha"

View File

@@ -1 +1 @@
set -g @catppuccin_flavor "latte"
set -g @catppuccin_flavour "latte"

View File

@@ -15,19 +15,21 @@
# -o : Set the option only if it is not already set.
# -u : Unset the specified option.
set -ag terminal-overrides ",xterm-256color:RGB"
# Enable proper color support
set -as terminal-features ",*:RGB"
set -as terminal-features ",xterm-256color:RGB:clipboard:usstyle:strikethrough:overline"
set -s escape-time 0 # Address vim mode switching delay
set -s set-clipboard on # System clipboard via OSC 52
set -g default-terminal "tmux-256color" # Set default terminal to 256 colors
set -g detach-on-destroy off # don't detach tmux when killing a session
set -g display-time 0 # Hide clock
set -g focus-events on # Focus events enabled for terminals that support them
set -g history-limit 50000 # Increase scrollback buffer size
set -g mouse on # Mouse support
set -g set-titles on # Allow tmux to set the terminal title
set -g status on # Setting status on
set -g status-interval 5 # Refresh status more often
set -g status-keys vi # vi keys to move between panes
set -wg aggressive-resize on # Better for grouped sessions and multi-monitor
# Keep Tmux alive when the initial command is finished
set -g remain-on-exit off
@@ -41,19 +43,10 @@ set -g renumber-windows on
# │ Theme │
# ╰──────────────────────────────────────────────────────────╯
set -g status-bg default
set -g status-justify left
set -g status-left ''
set -g status-left-length "0"
set -g status-position "bottom"
#set -g status-right "#S@#h #{tmux_mode_indicator}"
set -g status-right-length "50"
#set -g window-status-current-format ' #I:#W#{?window_zoomed_flag, ◈ ,} '
#set -g window-status-format ' #I:#W '
set -g @catppuccin_status_background 'none'
set -g @catppuccin_window_flags 'icon'
set -g @catppuccin_window_text "#T"
set -g @catppuccin_window_current_text "#T"
set -g @catppuccin_window_left_separator "█"
set -g @catppuccin_window_right_separator ""
set -g @catppuccin_window_middle_separator " "
# ╭──────────────────────────────────────────────────────────╮
# │ Bindings │
@@ -69,11 +62,11 @@ set -g @catppuccin_window_current_text "#T"
set -g prefix C-Space
bind C-Space send-prefix
# Use Alt-arrow keys without prefix key to switch panes
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D
# Use Ctrl-arrow keys without prefix key to switch panes
bind -n C-Left select-pane -L
bind -n C-Right select-pane -R
bind -n C-Up select-pane -U
bind -n C-Down select-pane -D
# Reload tmux config with <prefix> + r
unbind r
@@ -87,8 +80,16 @@ bind Escape copy-mode
unbind p
bind p paste-buffer
# copy-mode-vi: y copies to system clipboard, Y copies and pastes
bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel
bind -T copy-mode-vi Y send-keys -X copy-pipe-and-cancel "tmux paste-buffer"
# easier switching between next/prev window
bind C-p previous-window
bind C-n next-window
# global sessions
bind -N "sesh selection" t display-popup -E "$HOME/.dotfiles/config/tmux/sesh-gum.sh"
bind -N "sesh selection" t display-popup -E "$HOME/.dotfiles/config/tmux/sesh.sh"
bind -N "last-session (via sesh) " L run-shell "sesh last"
bind -N "sesh ui" N display-popup -E "sesh ui"
@@ -101,33 +102,16 @@ bind -N "sesh ui" N display-popup -E "sesh ui"
# Plugin that lets you suspend local tmux session,
# so that you can work with nested remote tmux session painlessly.
# https://github.com/MunifTanjim/tmux-suspend
# set -g @suspend_key 'F8' # Default is F12
## A plugin to name your tmux windows smartly.
## https://github.com/ofirgall/tmux-window-name
### Maximum name length of a window
set -g @tmux_window_name_max_name_len "25"
### Replace $HOME with ~ in window names
set -g @tmux_window_dir_programs "['nvim', 'vim', 'vi', 'git']"
set -g @tmux_window_name_ignored_programs "['sqlite3', 'antidote', 'direnv', 'md5']" # Default is []
set -g @tmux_window_name_shells "['bash', 'fish', 'sh', 'zsh']"
set -g @tmux_window_name_substitute_sets "[('.+ipython2', 'ipython2'), ('.+ipython3', 'ipython3'), ('.+\.local', '.local'), ('.+asdf', 'asdf')]"
set -g @tmux_window_name_use_tilde "True"
set -g @suspend_key 'F8' # Default is F12
set -g @suspend_suspended_options " \
status-left-style::bg=brightblack\\,fg=black, \
status-left:: ⏸ , \
"
# https://github.com/erikw/tmux-dark-notify
set -g @dark-notify-theme-path-light "$HOME/.dotfiles/config/tmux/theme-light.conf"
set -g @dark-notify-theme-path-dark "$HOME/.dotfiles/config/tmux/theme-dark.conf"
## https://github.com/MunifTanjim/tmux-mode-indicator
set -g @mode_indicator_copy_mode_style 'bg=default,fg=yellow'
set -g @mode_indicator_empty_mode_style 'bg=default,fg=#7aa2f7'
set -g @mode_indicator_prefix_mode_style 'bg=default,fg=#7aa2f7'
set -g @mode_indicator_sync_mode_style 'bg=default,fg=red'
# https://github.com/wfxr/tmux-fzf-url
set -g @fzf-url-bind 'u'
set -g @fzf-url-history-limit '2000'
# https://github.com/tmux-plugins/tmux-continuum
set -g @continuum-restore 'on'
@@ -143,14 +127,9 @@ run-shell "$HOME/.dotfiles/config/tmux/theme-activate.sh"
# ── Sourcing the plugins ──────────────────────────────────────────────
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-sensible/sensible.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-window-name/tmux_window_name.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-mode-indicator/mode_indicator.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-suspend/suspend.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-sessionist/sessionist.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-yank/yank.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-current-pane-hostname/current_pane_hostname.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-fzf-url/fzf-url.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-resurrect/resurrect.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-continuum/continuum.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/catppuccin/catppuccin.tmux"

View File

@@ -1,181 +0,0 @@
---
wtf:
colors:
background: black
border:
focusable: darkslateblue
focused: orange
normal: gray
checked: yellow
highlight:
fore: black
back: gray
rows:
even: yellow
odd: white
grid:
# How _wide_ the columns are, in terminal characters. In this case we have
# four columns, each of which are 35 characters wide.
columns: [35, 35, 30, 20]
# How _high_ the rows are, in terminal lines. In this case we have four rows
# that support ten line of text and one of four.
rows: [10, 10, 10, 20, 10, 4]
refreshInterval: 1
openFileUtil: 'open'
mods:
# You can have multiple widgets of the same type.
# The "key" is the name of the widget and the type is the actual
# widget you want to implement.
europe_time:
title: 'Europe'
type: clocks
colors:
rows:
even: 'lightblue'
odd: 'white'
enabled: true
locations:
GMT: 'Etc/GMT'
Amsterdam: 'Europe/Amsterdam'
Berlin: 'Europe/Berlin'
Barcelona: 'Europe/Madrid'
Copenhagen: 'Europe/Copenhagen'
London: 'Europe/London'
Rome: 'Europe/Rome'
Stockholm: 'Europe/Stockholm'
position:
top: 0
left: 0
height: 1
width: 1
refreshInterval: 15
sort: 'alphabetical'
americas_time:
title: 'Americas'
type: clocks
colors:
rows:
even: 'lightblue'
odd: 'white'
enabled: true
locations:
UTC: 'Etc/UTC'
Vancouver: 'America/Vancouver'
New_York: 'America/New_York'
Sao_Paulo: 'America/Sao_Paulo'
Denver: 'America/Denver'
Iqaluit: 'America/Iqaluit'
Bahamas: 'America/Nassau'
Chicago: 'America/Chicago'
position:
top: 0
left: 1
height: 1
width: 1
refreshInterval: 15
sort: 'alphabetical'
battery:
type: power
title: '⚡️'
enabled: true
position:
top: 1
left: 2
height: 1
width: 2
refreshInterval: 15
todolist:
type: todo
checkedIcon: 'X'
colors:
checked: gray
highlight:
fore: 'black'
back: 'orange'
enabled: true
filename: 'todo.yml'
position:
top: 1
left: 0
height: 2
width: 1
refreshInterval: 3600
ip:
type: ipinfo
title: 'My IP'
colors:
name: 'lightblue'
value: 'white'
enabled: true
position:
top: 0
left: 2
height: 1
width: 2
refreshInterval: 150
security_info:
type: security
title: 'Staying safe'
enabled: true
position:
top: 1
left: 1
height: 1
width: 1
refreshInterval: 3600
readme:
type: textfile
enabled: true
filePaths:
- '~/.config/wtf/config.yml'
format: true
formatStyle: 'monokai'
position:
top: 3
left: 0
height: 1
width: 1
refreshInterval: 15
news:
type: hackernews
title: 'HackerNews'
enabled: true
numberOfStories: 10
position:
top: 3
left: 1
height: 1
width: 3
storyType: top
refreshInterval: 900
resources:
type: resourceusage
enabled: true
position:
top: 4
left: 0
height: 2
width: 1
refreshInterval: 1
uptime:
type: cmdrunner
args: []
cmd: 'uptime'
enabled: true
position:
top: 5
left: 1
height: 1
width: 3
refreshInterval: 30
disks:
type: cmdrunner
cmd: 'df'
args: ['-h']
enabled: true
position:
top: 4
left: 1
height: 1
width: 3
refreshInterval: 3600

View File

@@ -20,7 +20,6 @@ yabai -m config \
window_shadow float
# apps to not manage (ignore)
# TODO: add apps from aerospace config to here
# list active apps:
# > yabai -m query --windows | jq .[].app | sort | uniq
yabai -m rule --add app="1Password" manage=off

View File

@@ -1,8 +0,0 @@
formatter:
type: basic
indent: 2
retain_line_breaks: false
disallow_anchors: false
max_line_length: 0
scan_folded_as_literal: false
indentless_arrays: false

View File

@@ -1,31 +0,0 @@
---
extends: default
ignore-from-file: [.gitignore, .yamlignore]
rules:
braces:
level: warning
max-spaces-inside: 1
brackets:
level: warning
max-spaces-inside: 1
colons:
level: warning
commas:
level: warning
comments: disable
comments-indentation: disable
document-start: disable
empty-lines:
level: warning
hyphens:
level: warning
indentation:
level: warning
indent-sequences: consistent
line-length:
level: warning
allow-non-breakable-inline-mappings: true
max: 120
truthy: disable

View File

@@ -37,7 +37,6 @@ zdharma-continuum/fast-syntax-highlighting
# Add some plugins that are not in OMZ
jreese/zsh-titles
yuki-ycino/tms
# This needs to be last bundle
# zsh-users/zsh-syntax-highlighting

View File

@@ -28,7 +28,6 @@ _dfm()
sections=(
'install:Installation commands'
'asdf:ASDF version manager commands'
'brew:Homebrew package manager commands'
'check:System check commands'
'dotfiles:Dotfiles management commands'
@@ -69,24 +68,6 @@ _dfm()
_describe 'install commands' install_cmds
;;
asdf)
local -a asdf_cmds
asdf_cmds=(
'current:Show current versions'
'global:Show global versions'
'installed:Show installed versions'
'plugins-update:Update all plugins'
'plugins-install:Install plugins from configuration'
'plugins-remove:Remove installed plugins'
'reset:Reset plugins'
'fix-tool-versions:Remove uninstalled plugins from .tool-versions'
'versions:Show versions'
'where:Show where'
'which:Show which'
)
_describe 'asdf commands' asdf_cmds
;;
brew)
local -a brew_cmds
brew_cmds=(

View File

@@ -1,66 +0,0 @@
# aerospace keybindings
## main
| Key | Command(s) and actions |
| -------------- | -------------------------------------------- |
| alt-a | mode apps |
| alt-h | focus left |
| alt-j | focus down |
| alt-k | focus up |
| alt-l | focus right |
| alt-m | mode move |
| alt-s | mode service |
| alt-shift-1 | workspace 1 |
| alt-shift-2 | workspace 2 |
| alt-shift-tab | workspace-back-and-forth |
| ctrl-shift-1 | move-node-to-workspace 1 |
| ctrl-shift-2 | move-node-to-workspace 2 |
| ctrl-shift-tab | move-workspace-to-monitor --wrap-around prev |
## apps
| Key | Command(s) and actions |
| --- | ------------------------------------------------------------------ |
| b | exec-and-forget open -a /Applications/Brave Browser.app; mode main |
| c | exec-and-forget open -a /Applications/Ferdium.app; mode main |
| esc | reload-config; mode main |
| g | exec-and-forget open -a /Applications/Ghostty.app; mode main |
| o | exec-and-forget open -a /Applications/Obsidian.app; mode main |
| s | exec-and-forget open -a /Applications/Slack.app; mode main |
| t | exec-and-forget open -a /Applications/TIDAL.app; mode main |
| w | exec-and-forget open -a /Applications/WezTerm.app; mode main |
## move
| Key | Command(s) and actions |
| ----------- | ----------------------------------------------- |
| 1 | move-node-to-workspace 1 --focus-follows-window |
| 2 | move-node-to-workspace 2 --focus-follows-window |
| ctrl-h | resize smart -70 |
| ctrl-l | resize smart +70 |
| esc | reload-config; mode main |
| h | move left |
| j | move down |
| k | move up |
| l | move right |
| r | flatten-workspace-tree; mode main |
| shift-h | join-with left |
| shift-j | join-with down |
| shift-k | join-with up |
| shift-l | join-with right |
| shift-left | resize smart +70 |
| shift-right | resize smart -70 |
## service
| Key | Command(s) and actions |
| --------- | ---------------------------------------- |
| backspace | close-all-windows-but-current; mode main |
| esc | reload-config; mode main |
| f | layout floating tiling; mode main |
| r | flatten-workspace-tree; mode main |
File generated: 2025-01-15 13:32:41
Config file: [config/aerospace/aerospace.toml](./../config/aerospace/aerospace.toml)

View File

@@ -15,10 +15,7 @@ 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}" \
"${@}"
@@ -29,10 +26,7 @@ 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,8 +78,3 @@
- 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

@@ -1,7 +1,9 @@
#!/usr/bin/env bash
# A script for encrypting and decrypting files or directories with age and SSH keys
VERSION="1.0.0"
set -euo pipefail
VERSION="1.1.0"
# Default ENV values
KEYS_FILE="${AGE_KEYSFILE:-$HOME/.ssh/keys.txt}"
@@ -9,14 +11,49 @@ KEYS_SOURCE="${AGE_KEYSSOURCE:-https://github.com/ivuorinen.keys}"
LOG_FILE="${AGE_LOGFILE:-$HOME/.cache/a.log}"
VERBOSE=false
DELETE_ORIGINAL=false
FORCE=false
# Parse flags for verbosity
for arg in "$@"; do
if [[ "$arg" == "-v" || "$arg" == "--verbose" ]]; then
VERBOSE=true
break
# Check for required dependencies
check_dependencies()
{
if ! command -v age &> /dev/null; then
echo "Error: 'age' is not installed. Please install it first." >&2
echo " brew install age # macOS" >&2
echo " apt install age # Debian/Ubuntu" >&2
echo " dnf install age # Fedora" >&2
exit 1
fi
done
if ! command -v curl &> /dev/null; then
echo "Error: 'curl' is not installed." >&2
exit 1
fi
}
# Parse flags
parse_flags()
{
local args=()
for arg in "$@"; do
case "$arg" in
-v | --verbose)
VERBOSE=true
;;
--delete)
DELETE_ORIGINAL=true
;;
-f | --force)
FORCE=true
;;
*)
args+=("$arg")
;;
esac
done
# Return remaining arguments
printf '%s\n' "${args[@]}"
}
# Ensure log directory and file exist with correct permissions
prepare_log_file()
@@ -38,8 +75,6 @@ prepare_log_file()
chmod 0600 "$LOG_FILE"
}
prepare_log_file
# Logging function
log_message()
{
@@ -56,7 +91,7 @@ log_message()
print_help()
{
cat << EOF
Usage: a [command] [file_or_directory] [options]
Usage: a [options] [command] [file_or_directory]
Commands:
e, enc, encrypt Encrypt the specified file or directory
@@ -65,12 +100,14 @@ Commands:
version, --version Show version information
Options:
-v, --verbose Print log messages to console in addition to writing to log file
-v, --verbose Print log messages to console
--delete Delete original files after successful encryption
-f, --force Overwrite existing output files without prompting
Environment Variables:
AGE_KEYSFILE Path to the SSH keys file (default: $HOME/.ssh/keys.txt)
AGE_KEYSFILE Path to the SSH keys file (default: \$HOME/.ssh/keys.txt)
AGE_KEYSSOURCE URL to fetch SSH keys if keys file does not exist
AGE_LOGFILE Path to the log file (default: $HOME/.cache/a.log)
AGE_LOGFILE Path to the log file (default: \$HOME/.cache/a.log)
Examples:
Encrypt a file:
@@ -79,14 +116,21 @@ Examples:
Encrypt a directory:
a e /path/to/directory
Encrypt and delete originals:
a --delete e file.txt
Decrypt a file:
a d file.txt.age
Force overwrite existing files:
a -f e file.txt
Specify a custom keys file:
AGE_KEYSFILE=/path/to/keys.txt a e file.txt
Specify a custom keys source and log file:
AGE_KEYSSOURCE=https://example.com/keys.txt AGE_LOGFILE=/tmp/a.log a d file.txt.age
Requirements:
- age (encryption tool): https://github.com/FiloSottile/age
- curl (for fetching keys)
EOF
}
@@ -115,26 +159,104 @@ fetch_keys_if_missing()
fi
}
# Function to encrypt a single file
encrypt_single_file()
{
local file="$1"
# Skip already encrypted files
if [[ "$file" == *.age ]]; then
log_message "Skipping already encrypted file: $file"
return 0
fi
local output_file="${file}.age"
# Check if output file exists
if [[ -f "$output_file" && "$FORCE" != true ]]; then
log_message "Error: Output file '$output_file' already exists. Use --force to overwrite."
return 1
fi
fetch_keys_if_missing
local temp_file
temp_file="$(mktemp -p "$(dirname "$file")")"
if age -R "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
log_message "File encrypted successfully: $output_file"
if [[ "$DELETE_ORIGINAL" == true ]]; then
rm -f "$file"
log_message "Original file deleted: $file"
fi
else
rm -f "$temp_file"
log_message "Error: Failed to encrypt file '$file'."
return 1
fi
}
# Function to encrypt files or directories
encrypt_file_or_directory()
{
local file="$1"
if [[ -d "$file" ]]; then
for f in "$file"/*; do
# Enable dotglob to include hidden files
shopt -s dotglob nullglob
local files=("$file"/*)
shopt -u dotglob nullglob
if [[ ${#files[@]} -eq 0 ]]; then
log_message "Warning: Directory '$file' is empty."
return 0
fi
for f in "${files[@]}"; do
encrypt_file_or_directory "$f"
done
elif [[ -f "$file" ]]; then
fetch_keys_if_missing
local output_file="${file}.age"
local temp_file
temp_file="$(mktemp -p "$(dirname "$file")")"
if age -R "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
log_message "File encrypted successfully: $output_file"
else
rm -f "$temp_file"
log_message "Error: Failed to encrypt file '$file'."
exit 1
encrypt_single_file "$file"
else
log_message "Warning: '$file' is not a file or directory, skipping."
fi
}
# Function to decrypt a single file
decrypt_single_file()
{
local file="$1"
if [[ ! "$file" == *.age ]]; then
log_message "Skipping non-.age file: $file"
return 0
fi
local output_file="${file%.age}"
# Check if output file exists
if [[ -f "$output_file" && "$FORCE" != true ]]; then
log_message "Error: Output file '$output_file' already exists. Use --force to overwrite."
return 1
fi
fetch_keys_if_missing
local temp_file
temp_file="$(mktemp -p "$(dirname "$file")")"
if age -d -i "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
log_message "File decrypted successfully: $output_file"
if [[ "$DELETE_ORIGINAL" == true ]]; then
rm -f "$file"
log_message "Encrypted file deleted: $file"
fi
else
rm -f "$temp_file"
log_message "Error: Failed to decrypt file '$file'."
return 1
fi
}
@@ -142,54 +264,76 @@ encrypt_file_or_directory()
decrypt_file_or_directory()
{
local file="$1"
if [[ -d "$file" ]]; then
for f in "$file"/*.age; do
decrypt_file_or_directory "$f"
# Enable nullglob to handle no matches gracefully
shopt -s nullglob
local files=("$file"/*.age)
shopt -u nullglob
if [[ ${#files[@]} -eq 0 ]]; then
log_message "Warning: No .age files found in directory '$file'."
return 0
fi
for f in "${files[@]}"; do
decrypt_single_file "$f"
done
elif [[ -f "$file" ]]; then
fetch_keys_if_missing
local output_file="${file%.age}"
local temp_file
temp_file="$(mktemp -p "$(dirname "$file")")"
if age -d -i "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
log_message "File decrypted successfully: $output_file"
else
rm -f "$temp_file"
log_message "Error: Failed to decrypt file '$file'."
exit 1
fi
decrypt_single_file "$file"
else
log_message "Warning: '$file' is not a file or directory, skipping."
fi
}
# Main logic
case "$1" in
e | enc | encrypt)
if [[ $# -lt 2 ]]; then
log_message "Error: No file or directory specified for encryption."
# Main entry point
main()
{
check_dependencies
# Parse flags and get remaining arguments
mapfile -t ARGS < <(parse_flags "$@")
prepare_log_file
local command="${ARGS[0]:-}"
local target="${ARGS[1]:-}"
case "$command" in
e | enc | encrypt)
if [[ -z "$target" ]]; then
log_message "Error: No file or directory specified for encryption."
print_help
exit 1
fi
encrypt_file_or_directory "$target"
;;
d | dec | decrypt)
if [[ -z "$target" ]]; then
log_message "Error: No file or directory specified for decryption."
print_help
exit 1
fi
decrypt_file_or_directory "$target"
;;
help | --help | -h)
print_help
;;
version | --version)
print_version
;;
"")
print_help
exit 1
fi
encrypt_file_or_directory "$2"
;;
d | dec | decrypt)
if [[ $# -lt 2 ]]; then
log_message "Error: No file or directory specified for decryption."
;;
*)
log_message "Error: Unknown command '$command'"
print_help
exit 1
fi
decrypt_file_or_directory "$2"
;;
help | --help)
print_help
;;
version | --version)
print_version
;;
*)
log_message "Error: Unknown command '$1'"
print_help
exit 1
;;
esac
;;
esac
}
main "$@"
# vim: ft=bash:syn=sh:ts=2:sw=2:et:ai:nowrap

View File

@@ -2,28 +2,76 @@
Encrypt or decrypt files and directories using `age` and your GitHub SSH keys.
## Requirements
- [age](https://github.com/FiloSottile/age) - encryption tool
- curl - for fetching SSH keys
Install age:
```bash
brew install age # macOS
apt install age # Debian/Ubuntu
dnf install age # Fedora
```
## Usage
```bash
a encrypt <file|dir>
a decrypt <file.age|dir>
a [options] <command> <file|directory>
```
Commands:
- `e`, `enc`, `encrypt` - encrypt files
- `d`, `dec`, `decrypt` - decrypt files
- `help`, `--help`, `-h` - show help
- `version`, `--version` - show version
Options:
- `-v`, `--verbose` show log output
- `-v`, `--verbose` - show log output
- `--delete` - delete original files after successful operation
- `-f`, `--force` - overwrite existing output files
Environment variables:
- `AGE_KEYSFILE` location of the keys file
- `AGE_KEYSSOURCE` URL to fetch keys if missing
- `AGE_LOGFILE` log file path
- `AGE_KEYSFILE` - location of the keys file (default: `~/.ssh/keys.txt`)
- `AGE_KEYSSOURCE` - URL to fetch keys if missing (default: GitHub keys)
- `AGE_LOGFILE` - log file path (default: `~/.cache/a.log`)
## Example
## Examples
```bash
# Encrypt a file
a encrypt secret.txt
# Encrypt with short command
a e secret.txt
# Decrypt a file
a decrypt secret.txt.age
a d secret.txt.age
# Encrypt a directory (includes hidden files)
a e /path/to/secrets/
# Encrypt and delete originals
a --delete e secret.txt
# Force overwrite existing .age file
a -f e secret.txt
# Verbose output
a -v e secret.txt
```
## Behavior
- Encrypting a directory processes all files recursively, including hidden files
- Already encrypted files (`.age`) are skipped during encryption
- Only `.age` files are processed during directory decryption
- Original files are preserved by default (use `--delete` to remove them)
- Output files are not overwritten by default (use `--force` to overwrite)
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->

View File

@@ -15,38 +15,37 @@
SCRIPT=$(basename "$0")
# Detect the current shell
CURRENT_SHELL=$(ps -p $$ -ocomm= | awk -F/ '{print $NF}')
# 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
# Function to source files based on the shell
source_file()
# 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()
{
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
local file="$1"
local desc
desc=$(sed -n '/@description/s/.*@description *\(.*\)/\1/p' "$file" | head -1)
echo "${desc:-No description available}"
}
# 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()
{
@@ -54,9 +53,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%%:*}
@@ -65,6 +64,7 @@ menu_builder()
done
}
# Handle install section commands
section_install()
{
USAGE_PREFIX="$SCRIPT install <command>"
@@ -80,7 +80,6 @@ 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"
@@ -100,6 +99,7 @@ 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!"
;;
@@ -194,6 +194,7 @@ section_install()
esac
}
# Handle Homebrew section commands
section_brew()
{
USAGE_PREFIX="$SCRIPT brew <command>"
@@ -208,89 +209,91 @@ section_brew()
"untracked:List untracked brew packages"
)
x-have brew && {
case "$1" in
install)
brew bundle install --file="$BREWFILE" --force --quiet && msgr yay "Done!"
;;
if ! x-have brew; then
msgr warn "brew not available, skipping"
return 0
fi
update)
brew update && brew outdated && brew upgrade && brew cleanup
msgr yay "Done!"
;;
case "$1" in
install)
brew bundle install --file="$BREWFILE" --force --quiet && msgr yay "Done!"
;;
updatebundle)
# Updates .dotfiles/homebrew/Brewfile with descriptions
brew bundle dump \
--force \
--file="$BREWFILE" \
--cleanup \
--tap \
--formula \
--cask \
--describe && msgr yay "Done!"
;;
update)
brew update && brew outdated && brew upgrade && brew cleanup
msgr yay "Done!"
;;
leaves)
brew leaves --installed-on-request
;;
updatebundle)
# Updates .dotfiles/homebrew/Brewfile with descriptions
brew bundle dump \
--force \
--file="$BREWFILE" \
--cleanup \
--tap \
--formula \
--cask \
--describe && msgr yay "Done!"
;;
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)
leaves)
brew leaves --installed-on-request
;;
# 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)
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)
declare -a BREW_LIST_BUNDLED
while IFS= read -r b; do
BREW_LIST_BUNDLED+=("$b")
done < <(brew bundle list --all --file="$BREWFILE")
# 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_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_BUNDLED
while IFS= read -r b; do
BREW_LIST_BUNDLED+=("$b")
done < <(brew bundle list --all --file="$BREWFILE")
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
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
echo "Untracked:"
for f in "${BREW_LIST_UNTRACKED[@]}"; do
echo " $f"
done
;;
array_diff BREW_LIST_UNTRACKED BREW_LIST_TRACKED_WITHOUT_DEPS BREW_LIST_BUNDLED
autoupdate)
brew autoupdate delete
brew autoupdate start 43200 --upgrade --cleanup --immediate
;;
# If there are no untracked packages, return
if [ ${#BREW_LIST_UNTRACKED[@]} -eq 0 ]; then
msgr yay "No untracked packages found!"
return 0
fi
clean) brew bundle cleanup --file="$BREWFILE" && msgr yay "Done!" ;;
echo "Untracked:"
for f in "${BREW_LIST_UNTRACKED[@]}"; do
echo " $f"
done
;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
autoupdate)
brew autoupdate delete
brew autoupdate start 43200 --upgrade --cleanup --immediate
;;
! x-have brew && menu_builder "$USAGE_PREFIX" "brew not available on this system"
clean) brew bundle cleanup --file="$BREWFILE" && msgr yay "Done!" ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
# Handle helper utility commands
section_helpers()
{
USAGE_PREFIX="$SCRIPT helpers <command>"
@@ -299,17 +302,16 @@ section_helpers()
"colors:Show colors"
"env:Show environment variables"
"functions:Show functions"
"aerospace:Show aerospace keybindings"
"nvim:Show nvim keybindings"
'path:Show $PATH dir by dir'
"tmux:Show tmux keybindings"
"wezterm:Show wezterm keybindings"
)
CMD="$1"
shift
SECTION="$1"
shift
CMD="${1:-}"
[[ $# -gt 0 ]] && shift
SECTION="${1:-}"
[[ $# -gt 0 ]] && shift
case "$CMD" in
path)
@@ -361,7 +363,6 @@ section_helpers()
"env") env | sort ;;
"functions") declare -F ;;
"aerospace") cat "$DOTFILES/docs/aerospace-keybindings.md" ;;
"nvim") cat "$DOTFILES/docs/nvim-keybindings.md" ;;
"tmux") cat "$DOTFILES/docs/tmux-keybindings.md" ;;
"wezterm") cat "$DOTFILES/docs/wezterm-keybindings.md" ;;
@@ -369,6 +370,7 @@ section_helpers()
esac
}
# Handle apt package manager commands
section_apt()
{
USAGE_PREFIX="$SCRIPT apt <command>"
@@ -381,64 +383,69 @@ section_apt()
"clean:Clean apt cache"
)
x-have apt && {
case "$1" in
upkeep)
sudo apt update \
&& sudo apt upgrade -y \
&& sudo apt autoremove -y \
&& sudo apt clean
;;
if ! x-have apt; then
msgr warn "apt not available, skipping"
return 0
fi
install)
# if apt.txt is not found, exit
[ ! -f "$DOTFILES/tools/apt.txt" ] && msgr err "apt.txt not found" && exit 0
case "$1" in
upkeep)
sudo apt update \
&& sudo apt upgrade -y \
&& sudo apt autoremove -y \
&& sudo apt clean
;;
# Load apt.txt, remove comments (even if trailing comment) and empty lines.
#
# Ignoring "Quote this to prevent word splitting."
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 ]] && {
# shellcheck disable=SC2046
sudo apt install \
-y $(
grep -vE '^\s*#' "$DOTFILES/tools/apt.txt" \
| sed -e 's/#.*//' \
| tr '\n' ' '
)
sudo apt install -y $(
grep -vE '^\s*#' "$HOST_APT" \
| 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 ]] && {
# shellcheck disable=SC2046
sudo apt install -y $(
grep -vE '^\s*#' "$HOST_APT" \
| sed -e 's/#.*//' \
| tr '\n' ' '
)
}
# Try this for an alternative way to install packages
# xargs -a <(awk '! /^ *(#|$)/' "$packagelist") -r -- sudo apt-get install -y
;;
# 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"
update) sudo apt update ;;
upgrade) sudo apt upgrade -y ;;
autoremove) sudo apt autoremove -y ;;
clean) sudo apt clean ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
# Handle documentation generation commands
section_docs()
{
USAGE_PREFIX="$SCRIPT docs <command>"
MENU=(
"all:Update all keybindings documentations"
"aerospace:Update aerospace keybindings documentation"
"tmux:Update tmux keybindings documentation"
"nvim:Update nvim keybindings documentation"
"wezterm:Update wezterm keybindings documentation"
@@ -446,12 +453,10 @@ section_docs()
case "$1" in
all)
$0 docs aerospace
$0 docs tmux
$0 docs nvim
$0 docs wezterm
;;
aerospace) bash "$DOTFILES/scripts/create-aerospace-keymaps.php" ;;
tmux) bash "$DOTFILES/local/bin/x-dfm-docs-xterm-keybindings" ;;
nvim) bash "$DOTFILES/scripts/create-nvim-keymaps.sh" ;;
wezterm) bash "$DOTFILES/scripts/create-wezterm-keymaps.sh" ;;
@@ -459,6 +464,7 @@ section_docs()
esac
}
# Handle dotfiles formatting and reset commands
section_dotfiles()
{
USAGE_PREFIX="$SCRIPT dotfiles <command>"
@@ -526,6 +532,7 @@ section_dotfiles()
esac
}
# Handle system check commands (arch, hostname)
section_check()
{
USAGE_PREFIX="$SCRIPT check <command>"
@@ -539,50 +546,36 @@ section_check()
case "$1" in
a | arch)
[[ $2 == "" ]] && echo "$X_ARCH" && exit 0
[[ $X_ARCH == "$2" ]] && exit 0 || exit 1
[[ $2 == "" ]] && echo "$X_ARCH" && return 0
[[ $X_ARCH == "$2" ]] && return 0 || return 1
;;
h | host | hostname)
[[ $2 == "" ]] && echo "$X_HOSTNAME" && exit 0
[[ $X_HOSTNAME == "$2" ]] && exit 0 || exit 1
[[ $2 == "" ]] && echo "$X_HOSTNAME" && return 0
[[ $X_HOSTNAME == "$2" ]] && return 0 || return 1
;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
# Handle install script execution
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
declare -A SCRIPT_MENU
local menu_items=()
for script in "$DOTFILES/scripts/install-"*.sh; do
if [ -f "$script" ]; then
name=$(basename "$script" .sh | sed 's/install-//')
desc=$(get_script_description "$script")
SCRIPT_MENU[$name]="$desc"
menu_items+=("$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[@]}"
;;
*)
@@ -614,7 +607,7 @@ section_tests()
echo " $i"
done
;;
msg)
msgr)
# shellcheck disable=SC1010
msgr done "msgr done"
msgr done_suffix "msgr done_suffix"
@@ -634,11 +627,12 @@ section_tests()
esac
}
# Display main usage information for all sections
usage()
{
echo ""
msgr prompt "Usage: $SCRIPT <section> <command>"
echo $" Empty <command> prints <section> help."
echo " Empty <command> prints <section> help."
echo ""
section_install
echo ""
@@ -657,10 +651,11 @@ usage()
section_helpers
}
# Parse section argument and dispatch to handler
main()
{
SECTION="$1"
shift
SECTION="${1:-}"
[[ $# -gt 0 ]] && shift
# The main loop. The first keyword after $0 triggers section, or help.
case "$SECTION" in
install) section_install "$@" ;;
@@ -672,7 +667,7 @@ main()
docs) section_docs "$@" ;;
scripts) section_scripts "$@" ;;
tests) section_tests "$@" ;;
*) usage && exit 0 ;;
*) usage && return 0 ;;
esac
}

View File

@@ -22,32 +22,37 @@ if [ "$DEBUG" -eq 1 ]; then
set -x
fi
# Output functions
# Print an error message in red
msg_err()
{
echo -e "\e[31m$*\e[0m" >&2
}
# Print a success message in green
msg_success()
{
echo -e "\e[32m$*\e[0m"
}
# Print a warning message in yellow
msg_warn()
{
echo -e "\e[33m$*\e[0m" >&2
}
# Print an info message in blue
msg_info()
{
echo -e "\e[36m$*\e[0m"
}
# Print a debug message when verbose mode is on
msg_debug()
{
[[ $VERBOSE -eq 1 ]] && echo -e "\e[35m$*\e[0m"
}
# Display usage information and examples
show_help()
{
cat << EOF

View File

@@ -90,13 +90,14 @@ declare -A DIR_HAS_REPOS
# Record start time
START_TIME=$(date +%s)
# Logging functions
# Log an error message
log_error()
{
print_color "31" "ERROR:" >&2
echo " $*" >&2
}
# Log an informational message
log_info()
{
if [[ $VERBOSE -eq 1 ]]; then
@@ -105,6 +106,7 @@ log_info()
fi
}
# Log a warning message
log_warn()
{
print_color "33" "WARNING:" >&2
@@ -911,6 +913,7 @@ process_in_parallel()
echo -e "\nProcessed $total repositories in $dur (Total runtime: $runtime)"
}
# Check a directory for git status with progress tracking
check_directory_with_progress()
{
local dir

View File

@@ -23,21 +23,25 @@ CLR_RESET="\033[0m"
# │ Color functions │
# ╰──────────────────────────────────────────────────────────╯
# Wrap text in red color
function __color_red()
{
local MSG="$1"
echo -e "${CLR_RED}${MSG}${CLR_RESET}"
}
# Wrap text in yellow color
function __color_yellow()
{
local MSG="$1"
echo -e "${CLR_YELLOW}${MSG}${CLR_RESET}"
}
# Wrap text in green color
function __color_green()
{
local MSG="$1"
echo -e "${CLR_GREEN}${MSG}${CLR_RESET}"
}
# Wrap text in blue color
function __color_blue()
{
local MSG="$1"
@@ -48,36 +52,43 @@ function __color_blue()
# │ Helpers │
# ╰──────────────────────────────────────────────────────────╯
# Print blue arrow marker
function __log_marker()
{
echo -e "${CLR_BLUE}➜${CLR_RESET}"
}
# Print green checkmark marker
function __log_marker_ok()
{
echo -e "${CLR_GREEN}✔${CLR_RESET}"
}
# Print blue checkmark marker
function __log_marker_ok_blue()
{
echo -e "${CLR_BLUE}✔${CLR_RESET}"
}
# Print yellow warning marker
function __log_marker_warn()
{
echo -e "${CLR_YELLOW}⁕${CLR_RESET}"
}
# Print yellow question marker
function __log_marker_question()
{
echo -e "${CLR_YELLOW}?${CLR_RESET}"
}
# Print red error marker
function __log_marker_err()
{
echo -e "${CLR_RED}⛌${CLR_RESET}"
}
# Print indentation spacing
function __log_indent()
{
echo " "
@@ -87,71 +98,85 @@ function __log_indent()
# │ Log functions │
# ╰──────────────────────────────────────────────────────────╯
# Print a message with arrow marker
function msg()
{
echo -e "$(__log_marker) $1"
}
# Print a celebration message
function msg_yay()
{
echo -e "🎉 $1"
}
# Print a celebration message with checkmark
function msg_yay_done()
{
echo -e "🎉 $1 ...$(__log_marker_ok)"
}
# Print a message with completion checkmark
function msg_done()
{
echo -e "$(__log_marker) $1 ...$(__log_marker_ok)"
}
# Print a completion checkmark suffix
function msg_done_suffix()
{
echo -e "$(__log_marker) ...$(__log_marker_ok)"
}
# Print a prompt-style message
function msg_prompt()
{
echo -e "$(__log_marker_question) $1"
}
# Print a prompt message with checkmark
function msg_prompt_done()
{
echo -e "$(__log_marker_question) $1 ...$(__log_marker_ok)"
}
# Print an indented message
function msg_nested()
{
echo -e "$(__log_indent)$(__log_marker) $1"
}
# Print an indented message with checkmark
function msg_nested_done()
{
echo -e "$(__log_indent)$(__log_marker) $1 ...$(__log_marker_ok)"
}
# Print a running-task message in green
function msg_run()
{
echo -e "${CLR_GREEN}➜ $1${CLR_RESET} $2"
}
# Print a running-task message with checkmark
function msg_run_done()
{
echo -e "${CLR_GREEN}➜ $1${CLR_RESET} $2 ...$(__log_marker_ok)"
}
# Print an ok/success message
function msg_ok()
{
echo -e "$(__log_marker_ok) $1"
}
# Print a warning message
function msg_warn()
{
echo -e "$(__log_marker_warn) $1"
}
# Print an error message
function msg_err()
{
echo -e "$(__log_marker_err) $1"
@@ -174,6 +199,7 @@ ask()
# If this is being sourced, no need to run the next steps.
[ "$sourced" = 1 ] && return
# Run visual tests for all message types
function __tests()
{
msg "[ msg ]"
@@ -192,6 +218,7 @@ function __tests()
msg_yay_done "[ yay_done ]"
}
# Show usage information and examples
function usage()
{
echo "usage: msgr [type] [message] [optional second message]"

View File

@@ -19,7 +19,7 @@ set -euo pipefail # Add error handling
LATEST_VERSION_FORMULA="php" # The formula name for latest PHP version
PHP_VERSION_FILE=".php-version" # File name to look for when auto-switching
# Switch brew php version
# Verify that Homebrew is installed
function check_dependencies()
{
if ! command -v brew > /dev/null 2>&1; then
@@ -28,6 +28,7 @@ function check_dependencies()
fi
}
# Display help message and usage examples
function usage()
{
echo "Brew PHP Switcher - Switch between PHP versions installed via Homebrew"
@@ -53,6 +54,7 @@ function usage()
exit 0
}
# List all PHP versions installed via Homebrew
function list_php_versions()
{
# Check Homebrew's installation path for PHP versions
@@ -185,6 +187,7 @@ function list_php_versions()
done
}
# Convert a version number to a Homebrew formula name
function get_php_formula_for_version()
{
local version="$1"
@@ -199,6 +202,7 @@ function get_php_formula_for_version()
echo "php@$version"
}
# Check if a Homebrew formula is installed
function check_formula_installed()
{
local formula="$1"
@@ -216,6 +220,7 @@ function check_formula_installed()
return 1
}
# Unlink the currently active PHP version
function unlink_current_php()
{
local current_formula=""
@@ -241,6 +246,7 @@ function unlink_current_php()
fi
}
# Link a specific PHP formula as the active version
function link_php_version()
{
local formula="$1"
@@ -265,6 +271,7 @@ function link_php_version()
fi
}
# Display the currently active PHP version
function get_current_version()
{
if ! command -v php > /dev/null 2>&1; then
@@ -300,6 +307,7 @@ function get_current_version()
fi
}
# Validate PHP version format (x.y or latest)
function validate_version()
{
local version="$1"
@@ -312,6 +320,7 @@ function validate_version()
fi
}
# Search for .php-version file in directory hierarchy
function find_php_version_file()
{
local dir="$PWD"
@@ -334,6 +343,7 @@ function find_php_version_file()
return 1
}
# Auto-switch PHP based on .php-version file
function auto_switch_php_version()
{
local version_file
@@ -360,6 +370,7 @@ function auto_switch_php_version()
switch_php_version "$version"
}
# Switch to a specific PHP version
function switch_php_version()
{
local version="$1"
@@ -398,6 +409,7 @@ function switch_php_version()
echo "PHP executable: $(command -v php)"
}
# Parse arguments and dispatch to appropriate action
function main()
{
local version=""

View File

@@ -5,6 +5,7 @@
#
# Modified by Ismo Vuorinen <https://github.com/ivuorinen> 2023
# Display usage information for pushover
__pushover_usage()
{
printf "pushover <options> <message>\n"
@@ -23,6 +24,7 @@ __pushover_usage()
return 1
}
# Format an optional curl form field
__pushover_opt_field()
{
field=$1
@@ -33,6 +35,7 @@ __pushover_opt_field()
fi
}
# Send a pushover notification via curl
__pushover_send_message()
{
device="${1:-}"

View File

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

View File

@@ -7,13 +7,15 @@
# 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
msgr err "Directory $1 does not exist."
echo "Error: Directory $1 does not exist." >&2
exit 1
fi
else
@@ -27,7 +29,7 @@ remove_node_modules_vendor()
# If the directory is a symlink, skip it
if [ -L "$dir" ]; then
msgr msg "Skipping symlink $dir"
echo "Skipping symlink $dir"
return
fi
@@ -35,18 +37,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
msgr run "Removing $dir/node_modules"
echo "Removing $dir/node_modules"
rm -rf "$dir/node_modules"
fi
if [ -d "$dir/vendor" ]; then
msgr run "Removing $dir/vendor"
echo "Removing $dir/vendor"
rm -rf "$dir/vendor"
fi
# Recursively check subdirectories
for item in "$dir"/*; do
remove_node_modules_vendor "$item"
[ -d "$item" ] && remove_node_modules_vendor "$item"
done
fi
}

View File

@@ -10,6 +10,7 @@ VERSION="1.0.0"
LANG_MAP="c:.c,.h|cpp:.cpp,.cc,.cxx,.hpp,.hxx|csharp:.cs|go:.go|java:.java|
javascript:.js,.jsx,.mjs,.ts,.tsx|python:.py|ruby:.rb|swift:.swift"
# Display usage information and options
usage()
{
cat << EOF
@@ -24,22 +25,26 @@ EOF
exit "${1:-0}"
}
# Log a timestamped message to stderr
log()
{
printf '[%s] %s\n' "$(date '+%H:%M:%S')" "$*" >&2
}
# Log an error message and exit
err()
{
log "ERROR: $*"
exit 1
}
# Verify codeql binary is available in PATH
check_codeql()
{
command -v codeql > /dev/null 2>&1 || err "codeql binary not found in PATH"
log "Found codeql: $(codeql version --format=terse)"
}
# Get or create the CodeQL cache directory
get_cache_dir()
{
cache="${XDG_CACHE_HOME:-$HOME/.cache}/codeql"
@@ -47,6 +52,7 @@ get_cache_dir()
printf '%s' "$cache"
}
# Detect supported programming languages in source path
detect_languages()
{
src_path="$1"
@@ -85,6 +91,7 @@ detect_languages()
printf '%s' "$detected" | tr ' ' '\n' | sort -u | tr '\n' ' ' | sed 's/ $//'
}
# Create a CodeQL database for a language
create_database()
{
lang="$1"
@@ -98,6 +105,7 @@ create_database()
--overwrite
}
# Display analysis result statistics from SARIF file
show_results_stats()
{
sarif_file="$1"
@@ -126,6 +134,7 @@ show_results_stats()
return 0
}
# Run CodeQL analysis for a single language
analyze_language()
{
lang="$1"
@@ -172,6 +181,7 @@ analyze_language()
rm -rf "$db_path"
}
# Parse arguments and run CodeQL analysis pipeline
main()
{
src_path="."

View File

@@ -24,7 +24,7 @@ str_to_operator = {
def vercmp(expr):
"""Version Comparison function."""
words = expr.split()
comparisons = [words[i: i + 3] for i in range(0, len(words) - 2, 2)]
comparisons = [words[i : i + 3] for i in range(0, len(words) - 2, 2)]
for left, op_str, right in comparisons:
compare_op = str_to_operator[op_str]
if not compare_op(version.parse(left), version.parse(right)):
@@ -63,7 +63,7 @@ def test():
except KeyError:
pass
else:
assert False, "invalid operator did not raise"
raise AssertionError("invalid operator did not raise")
if __name__ == "__main__":

View File

@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
#
# List environment variables grouped by the first part before underscore
# protecting environment variables that possibly contain sensitive information.
@@ -190,6 +190,7 @@ get_custom_group()
return 1
}
# Check if a key matches the skipped keys list
is_skipped()
{
local key=$1

View File

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

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Python script to find the largest files in a git repository.
# The general method is based on the script in this blog post:
@@ -32,60 +31,59 @@
# vim:tw=120:ts=4:ft=python:norl:
from subprocess import check_output, Popen, PIPE
import argparse
import signal
import sys
from subprocess import PIPE, Popen, check_output
sortByOnDiskSize = False
class Blob(object):
sha1 = ''
size = 0
packed_size = 0
path = ''
def __init__(self, line):
cols = line.split()
self.sha1, self.size, self.packed_size = cols[0], int(cols[2]), int(cols[3])
class Blob:
sha1 = ""
size = 0
packed_size = 0
path = ""
def __repr__(self):
return '{} - {} - {} - {}'.format(
self.sha1, self.size, self.packed_size, self.path)
def __init__(self, line):
cols = line.split()
self.sha1, self.size, self.packed_size = cols[0], int(cols[2]), int(cols[3])
def __lt__(self, other):
if (sortByOnDiskSize):
return self.size < other.size
else:
return self.packed_size < other.packed_size
def __repr__(self):
return f"{self.sha1} - {self.size} - {self.packed_size} - {self.path}"
def csv_line(self):
return "{},{},{},{}".format(
self.size/1024, self.packed_size/1024, self.sha1, self.path)
def __lt__(self, other):
if sortByOnDiskSize:
return self.size < other.size
else:
return self.packed_size < other.packed_size
def csv_line(self):
return f"{self.size / 1024},{self.packed_size / 1024},{self.sha1},{self.path}"
def main():
global sortByOnDiskSize
global sortByOnDiskSize
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGINT, signal_handler)
args = parse_arguments()
sortByOnDiskSize = args.sortByOnDiskSize
size_limit = 1024*args.filesExceeding
args = parse_arguments()
sortByOnDiskSize = args.sortByOnDiskSize
size_limit = 1024 * args.filesExceeding
if args.filesExceeding > 0:
print("Finding objects larger than {}kB…".format(args.filesExceeding))
else:
print("Finding the {} largest objects…".format(args.matchCount))
if args.filesExceeding > 0:
print(f"Finding objects larger than {args.filesExceeding}kB…")
else:
print(f"Finding the {args.matchCount} largest objects…")
blobs = get_top_blobs(args.matchCount, size_limit)
blobs = get_top_blobs(args.matchCount, size_limit)
populate_blob_paths(blobs)
print_out_blobs(blobs)
populate_blob_paths(blobs)
print_out_blobs(blobs)
def get_top_blobs(count, size_limit):
"""Get top blobs from git repository
"""Get top blobs from git repository
Args:
count (int): How many items to return
@@ -93,110 +91,123 @@ def get_top_blobs(count, size_limit):
Returns:
dict: Dictionary of Blobs
"""
sort_column = 4
"""
sort_column = 4
if sortByOnDiskSize:
sort_column = 3
if sortByOnDiskSize:
sort_column = 3
verify_pack = "git verify-pack -v `git rev-parse --git-dir`/objects/pack/pack-*.idx | grep blob | sort -k{}nr".format(sort_column) # noqa: E501
output = check_output(verify_pack, shell=True).decode('utf-8').strip().split("\n")[:-1] # noqa: E501
verify_pack = (
f"git verify-pack -v `git rev-parse --git-dir`/objects/pack/pack-*.idx | grep blob | sort -k{sort_column}nr"
)
output = check_output(verify_pack, shell=True).decode("utf-8").strip().split("\n")[:-1]
blobs = dict()
# use __lt__ to do the appropriate comparison
compare_blob = Blob("a b {} {} c".format(size_limit, size_limit))
for obj_line in output:
blob = Blob(obj_line)
blobs = {}
# use __lt__ to do the appropriate comparison
compare_blob = Blob(f"a b {size_limit} {size_limit} c")
for obj_line in output:
blob = Blob(obj_line)
if size_limit > 0:
if compare_blob < blob:
blobs[blob.sha1] = blob
else:
break
else:
blobs[blob.sha1] = blob
if size_limit > 0:
if compare_blob < blob:
blobs[blob.sha1] = blob
else:
break
else:
blobs[blob.sha1] = blob
if len(blobs) == count:
break
if len(blobs) == count:
break
return blobs
return blobs
def populate_blob_paths(blobs):
"""Populate blob paths that only have a path
"""Populate blob paths that only have a path
Args:
blobs (Blob, dict): Dictionary of Blobs
"""
if len(blobs):
print("Finding object paths…")
Args:
blobs (Blob, dict): Dictionary of Blobs
"""
if len(blobs):
print("Finding object paths…")
# Only include revs which have a path. Other revs aren't blobs.
rev_list = "git rev-list --all --objects | awk '$2 {print}'"
all_object_lines = check_output(rev_list, shell=True).decode('utf-8').strip().split("\n")[:-1] # noqa: E501
outstanding_keys = list(blobs.keys())
# Only include revs which have a path. Other revs aren't blobs.
rev_list = "git rev-list --all --objects | awk '$2 {print}'"
all_object_lines = check_output(rev_list, shell=True).decode("utf-8").strip().split("\n")[:-1]
outstanding_keys = list(blobs.keys())
for line in all_object_lines:
cols = line.split()
sha1, path = cols[0], " ".join(cols[1:])
for line in all_object_lines:
cols = line.split()
sha1, path = cols[0], " ".join(cols[1:])
if (sha1 in outstanding_keys):
outstanding_keys.remove(sha1)
blobs[sha1].path = path
if sha1 in outstanding_keys:
outstanding_keys.remove(sha1)
blobs[sha1].path = path
# short-circuit the search if we're done
if not len(outstanding_keys):
break
# short-circuit the search if we're done
if not len(outstanding_keys):
break
def print_out_blobs(blobs):
if len(blobs):
csv_lines = ["size,pack,hash,path"]
if len(blobs):
csv_lines = ["size,pack,hash,path"]
for blob in sorted(blobs.values(), reverse=True):
csv_lines.append(blob.csv_line())
for blob in sorted(blobs.values(), reverse=True):
csv_lines.append(blob.csv_line())
command = ["column", "-t", "-s", ","]
p = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
command = ["column", "-t", "-s", ","]
p = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
# Encode the input as bytes
input_data = ("\n".join(csv_lines) + "\n").encode()
# Encode the input as bytes
input_data = ("\n".join(csv_lines) + "\n").encode()
stdout, _ = p.communicate(input_data)
stdout, _ = p.communicate(input_data)
print("\nAll sizes in kB. The pack column is the compressed size of the object inside the pack file.\n") # noqa: E501
print("\nAll sizes in kB. The pack column is the compressed size of the object inside the pack file.\n")
print(stdout.decode("utf-8").rstrip('\n'))
else:
print("No files found which match those criteria.")
print(stdout.decode("utf-8").rstrip("\n"))
else:
print("No files found which match those criteria.")
def parse_arguments():
parser = argparse.ArgumentParser(
description='List the largest files in a git repository'
)
parser.add_argument(
'-c', '--match-count', dest='matchCount', type=int, default=10,
help='Files to return. Default is 10. Ignored if --files-exceeding is used.'
)
parser.add_argument(
'--files-exceeding', dest='filesExceeding', type=int, default=0,
help='The cutoff amount, in KB. Files with a pack size (or physical size, with -p) larger than this will be printed.' # noqa: E501
)
parser.add_argument(
'-p', '--physical-sort', dest='sortByOnDiskSize',
action='store_true', default=False,
help='Sort by the on-disk size. Default is to sort by the pack size.'
)
parser = argparse.ArgumentParser(description="List the largest files in a git repository")
parser.add_argument(
"-c",
"--match-count",
dest="matchCount",
type=int,
default=10,
help="Files to return. Default is 10. Ignored if --files-exceeding is used.",
)
parser.add_argument(
"--files-exceeding",
dest="filesExceeding",
type=int,
default=0,
help=(
"The cutoff amount, in KB. Files with a pack size"
" (or physical size, with -p) larger than this will be printed."
),
)
parser.add_argument(
"-p",
"--physical-sort",
dest="sortByOnDiskSize",
action="store_true",
default=False,
help="Sort by the on-disk size. Default is to sort by the pack size.",
)
return parser.parse_args()
return parser.parse_args()
def signal_handler(signal, frame):
print('Caught Ctrl-C. Exiting.')
print("Caught Ctrl-C. Exiting.")
sys.exit(0)
# Default function is main()
if __name__ == '__main__':
main()
if __name__ == "__main__":
main()

View File

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

View File

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

View File

@@ -1,50 +0,0 @@
#!/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 "$@"

Some files were not shown because too many files have changed in this diff Show More