From f0a8a1dccf8bbb9ed427b9aa43b36e6e11cb5c56 Mon Sep 17 00:00:00 2001 From: Richard Maynard Date: Thu, 11 Dec 2025 23:07:00 -0600 Subject: [PATCH 01/10] break out work.zsh private functions and add test suite --- CHEATSHEET.md | 410 ++++++++++++++++++---- README.md | 4 +- includes/late_15_git_functions.zsh | 45 +++ includes/late_20_aws_functions.zsh | 32 ++ includes/late_25_kubernetes_functions.zsh | 97 +++++ includes/late_27_docker_functions.zsh | 56 +++ includes/late_35_network_functions.zsh | 45 +++ includes/late_45_utility_functions.zsh | 124 +++++++ includes/late_46_format_functions.zsh | 83 +++++ tools/README.md | 178 ++++++++++ tools/pre-commit-hook | 121 +++++++ tools/test_config.zsh | 232 ++++++++++++ 12 files changed, 1350 insertions(+), 77 deletions(-) create mode 100644 includes/late_27_docker_functions.zsh create mode 100644 includes/late_46_format_functions.zsh create mode 100644 tools/README.md create mode 100755 tools/pre-commit-hook create mode 100755 tools/test_config.zsh diff --git a/CHEATSHEET.md b/CHEATSHEET.md index 55c83ae..32c7940 100644 --- a/CHEATSHEET.md +++ b/CHEATSHEET.md @@ -6,27 +6,23 @@ Quick reference for all custom functions, aliases, and commands available in thi ## 📋 Table of Contents -- [Git Functions](#git-functions) -- [AWS Functions](#aws-functions) -- [Kubernetes Functions](#kubernetes-functions) -- [1Password Functions](#1password-functions) -- [Network Functions](#network-functions) -- [System Functions](#system-functions) -- [Utility Functions](#utility-functions) -- [Shell Functions](#shell-functions) -- [Aliases](#aliases) - - [Modern Tool Replacements](#modern-tool-replacements) - - [Git Shortcuts](#git-shortcuts) - - [Safe Defaults](#safe-defaults) - - [Tmux](#tmux) - - [Package Management](#package-management) - - [Miscellaneous](#miscellaneous) +- [Git Commands](#git-commands) +- [AWS Commands](#aws-commands) +- [Kubernetes Commands](#kubernetes-commands) +- [Docker Commands](#docker-commands) +- [1Password Commands](#1password-commands) +- [Network Commands](#network-commands) +- [System Commands](#system-commands) +- [File & Archive Commands](#file--archive-commands) +- [Data Format & Conversion](#data-format--conversion) +- [Shell & Environment](#shell--environment) +- [Modern Tool Replacements](#modern-tool-replacements) - [Key Bindings](#key-bindings) - [Environment Variables](#environment-variables) --- -## Git Functions +## Git Commands ### `retag` Re-tag and force push a git tag. @@ -38,9 +34,61 @@ retag retag v1.0.0 ``` +### `gb` +Interactive branch switcher using fzf. + +```bash +gb # Select branch interactively +``` + +### `gca` +Quick commit amend without editing message. + +```bash +gca # Amend last commit +``` + +### `glo` +Show git log with fzf preview. + +```bash +glo # Interactive log viewer +``` + +### `gnb` +Create branch and push with tracking. + +```bash +gnb + +# Example +gnb feature/new-api +``` + +### `gpthis` +Push current branch to origin. + +```bash +gpthis +``` + +### `gpthisdown` +Push current branch to downstream. + +```bash +gpthisdown +``` + +### `gpfthis` +Force push current branch to origin. + +```bash +gpfthis +``` + --- -## AWS Functions +## AWS Commands ### `awsregion` Get or set AWS_DEFAULT_REGION. @@ -57,9 +105,24 @@ Clear all AWS_* environment variables. unset_aws ``` +### `awsp` +List and switch AWS profiles (interactive with fzf if available). + +```bash +awsp # Interactive selection (if fzf available) +awsp production # Switch to specific profile +``` + +### `whoami-aws` +Show current AWS identity. + +```bash +whoami-aws +``` + --- -## Kubernetes Functions +## Kubernetes Commands ### `kubeme` Start minikube with appropriate configuration for the platform. @@ -76,9 +139,84 @@ Configure docker to use minikube's docker daemon. docker_kube ``` +### `kctx` / `kubectx` +Quick context switch with optional filtering. + +```bash +kctx # Interactive selection +kctx prod # Switch to 'prod' or filter by 'prod' +kubectx prod # Alias works the same +``` + +### `kns` / `kubens` +Quick namespace switch with optional filtering. + +```bash +kns # Interactive selection +kns default # Switch to 'default' or filter by 'default' +kubens kube-system # Alias works the same +``` + +### `klogs` +Get pod logs with fzf selector. + +```bash +klogs # Select pod interactively +``` + +### `kexec` +Exec into pod with fzf selector. + +```bash +kexec # Uses /bin/sh +kexec /bin/bash # Use specific shell +``` + +### `kpf` +Port forward with fzf selector. + +```bash +kpf # Defaults to 8080:8080 +kpf 3000 # Forward 3000:3000 +kpf 8080:80 # Forward local 8080 to pod 80 +``` + --- -## 1Password Functions +## Docker Commands + +### `dclean` +Clean up dangling images, stopped containers, and unused volumes. + +```bash +dclean +``` + +### `dexec` +Interactive container exec using fzf. + +```bash +dexec # Uses /bin/sh +dexec /bin/bash # Use specific shell +``` + +### `dlogs` +Interactive container logs using fzf. + +```bash +dlogs # Select container interactively +``` + +### `dstop` +Stop all running containers. + +```bash +dstop +``` + +--- + +## 1Password Commands ### `ops` Sign in to 1Password account. @@ -103,7 +241,7 @@ opg my-account "AWS Console" --- -## Network Functions +## Network Commands ### `dq` Query DNS across multiple resolvers (Google, Cloudflare, OpenDNS). @@ -118,9 +256,38 @@ dq example.com MX # MX records dq example.com TXT # TXT records ``` +### `port` +Check what process is using a port. + +```bash +port + +# Example +port 8080 +``` + +### `myip` +Get public IP address (supports IPv4/IPv6). + +```bash +myip # Default +myip 4 # IPv4 only +myip 6 # IPv6 only +``` + +### `httptest` +Quick HTTP test with timing information. + +```bash +httptest + +# Example +httptest https://google.com +``` + --- -## System Functions +## System Commands ### `nosleep` (macOS only) Prevent system and display sleep with fullscreen cmatrix. @@ -151,7 +318,7 @@ nfs_mount --- -## Utility Functions +## File & Archive Commands ### `ff` Find files with a pattern in name (case-insensitive). @@ -177,33 +344,77 @@ fe config file # Run 'file' on all config files fe "*.py" # Run 'file' on all Python files (default) ``` -### `wttr` -Get weather from wttr.in. +### `extract` +Universal archive extraction. ```bash -wttr [location] +extract # Examples -wttr # Default location (San Antonio, TX) -wttr "New York" -wttr Tokyo -wttr "San Francisco" +extract archive.tar.gz +extract file.zip +extract data.7z +``` + +### `uuid` +Generate UUID (lowercase). + +```bash +uuid ``` -### `codec` -Get video codec information using ffmpeg. +### `b64e` / `b64d` +Base64 encode/decode. ```bash -codec +b64e "hello world" # Encode +b64d "aGVsbG8gd29ybGQ=" # Decode +``` + +### `ts` +Timestamp conversion. + +```bash +ts # Get current timestamp +ts 1638360000 # Convert timestamp to date +``` + +### `up` +Go up N directories. + +```bash +up # Go up 1 directory +up 3 # Go up 3 directories +``` + +### `large` +Find largest files/dirs in current directory. + +```bash +large # Show top 20 +large 10 # Show top 10 +``` + +### `pkill-fzf` +Kill process by name with fzf selector. + +```bash +pkill-fzf # Select process interactively +``` + +### `portproc` +Find process using a specific port. + +```bash +portproc # Example -codec movie.mp4 -codec video.mkv +portproc 8080 ``` --- -## Shell Functions +## Shell & Environment ### `resrc` Rebuild zsh cache and restart shell. @@ -241,74 +452,123 @@ zhelp git # Show git functions only zhelp aws # Show AWS functions only ``` ---- +### `t` +Tmux session manager - attach to or create "default" session. -## Aliases +```bash +t # Attach to or create default session +``` -### Modern Tool Replacements +Creates windows: TerraformDeploy, LegacyDeploy, TFModules, General -Smart aliases that use modern alternatives when available: +### `tmux` / `tnew` / `tlist` / `tk` +Tmux helpers. -| Alias | Command | Tool | -|-------|---------|------| -| `ls` | `lsd` or `exa` | Modern ls replacement | -| `ll` | `lsd -Al` or `exa -al --git` | Long listing | -| `cat` | `bat` | Syntax-highlighted cat | -| `vi` | `nvim` | Neovim | -| `kubectl` | `kubecolor` | Colored kubectl output | -| `du` | `dust -bd 1` | Modern du | +```bash +tmux # Start tmux with 256 color support +tnew # Create new default session +tlist # List all sessions +tk # Kill default session +``` -### Git Shortcuts +### `path` / `libpath` +Display paths with one entry per line. ```bash -gpthis # Push current branch to origin -gpthisdown # Push current branch to downstream -gpfthis # Force push current branch to origin +path # Display PATH +libpath # Display LD_LIBRARY_PATH ``` -### Safe Defaults +### `wttr` +Get weather from wttr.in. ```bash -rm # Aliased to 'rm -i' (interactive) -mv # Aliased to 'mv -i' (interactive) -cp # Aliased to 'cp -i' (interactive) -mkdir # Aliased to 'mkdir -p' (create parents) +wttr [location] + +# Examples +wttr # Default location (San Antonio, TX) +wttr "New York" +wttr Tokyo +wttr "San Francisco" ``` -### Tmux +### Safe Defaults + +Common commands with safer defaults: ```bash -tmux # Start tmux with 256 color support -tnew # Create new default session -tlist # List all sessions -tk # Kill default session +rm # Aliased to 'rm -i' (interactive) +mv # Aliased to 'mv -i' (interactive) +cp # Aliased to 'cp -i' (interactive) +mkdir # Aliased to 'mkdir -p' (create parents) ``` ### Package Management (dnf systems) ```bash -di # Install package (sudo dnf install) -dr # Remove package (sudo dnf remove) -ds # Search packages (dnf search) +di # Install package (sudo dnf install) +dr # Remove package (sudo dnf remove) +ds # Search packages (dnf search) ``` -### Miscellaneous +### Platform-Specific +**Linux (non-WSL) only:** ```bash -path # Display PATH with one entry per line -libpath # Display LD_LIBRARY_PATH with one entry per line -dirs # Show directory stack with numbers -rmpyc # Remove all .pyc files recursively -ipsort # Sort IP addresses correctly -grep # Colored output by default -ssh # Force xterm-256color TERM +pbcopy # Copy to clipboard (via xsel) +pbpaste # Paste from clipboard (via xsel) rootme # Sudo to root with zsh and zoxide support ``` -**Linux (non-WSL) only:** +--- + +## Modern Tool Replacements + +When these modern tools are installed, the following commands automatically use them: + +| Command | Uses | Description | +|---------|------|-------------| +| `ls` | `lsd` or `exa` | Modern ls with colors and icons | +| `ll` | `lsd -Al` or `exa -al --git` | Long listing with git status | +| `cat` | `bat` | Syntax-highlighted file viewer | +| `vi` | `nvim` | Modern Vim | +| `kubectl` | `kubecolor` | Colored kubectl output | +| `du` | `dust -bd 1` | Visual disk usage | +| `grep` | `grep --color=auto` | Colored output | + +If the modern tool isn't installed, commands fall back to standard versions. + +--- + +## Data Format & Conversion + +### `jpretty` +Pretty print JSON from clipboard or file. + ```bash -pbcopy # Copy to clipboard (via xsel) -pbpaste # Paste from clipboard (via xsel) +jpretty data.json # From file +jpretty # From clipboard (macOS) +``` + +### `y2j` +Convert YAML to JSON. + +```bash +y2j config.yaml +``` + +### `j2y` +Convert JSON to YAML. + +```bash +j2y data.json +``` + +### `jqp` +Interactive JQ playground. + +```bash +jqp data.json # Test jq queries interactively ``` --- diff --git a/README.md b/README.md index 97a53ee..e096288 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A highly optimized, purpose-built Zsh configuration focused on **startup speed** ## 🚀 Features -- 🧠 **Sub-100ms startup time** (measured consistently with benchmarking) +- 🧠 **Sub-150ms startup time** (measured consistently with benchmarking) - 🔌 **Antidote plugin manager** (compiled + cached for maximum speed) - 📦 **Modular `includes/` directory structure** - Early/late phase loading for ordered control @@ -50,7 +50,7 @@ Run this to benchmark shell startup: time zsh -i --login -c echo ``` -You should see results well below **100ms** real time. +You should see results well below **150ms** real time. --- diff --git a/includes/late_15_git_functions.zsh b/includes/late_15_git_functions.zsh index c13c27a..67ff635 100644 --- a/includes/late_15_git_functions.zsh +++ b/includes/late_15_git_functions.zsh @@ -3,6 +3,11 @@ # # Functions for common git operations: # - retag: Delete and recreate a git tag, then force push to origin +# - gcm: Clean up merged branches +# - gb: Interactive branch switcher (fzf) +# - gca: Quick commit amend without editing message +# - glo: Git log with fzf preview +# - gnb: Create branch and push with tracking ######################################## # Re-tag and force push a git tag @@ -19,3 +24,43 @@ function retag() { git push origin :${1} git push origin ${1} } + +# Interactive branch switcher using fzf +# Usage: gb +function gb() { + if ! command -v fzf &>/dev/null; then + echo "Error: fzf not installed" + return 1 + fi + local branch=$(git branch | fzf) + [[ -n "$branch" ]] && git checkout $(echo "$branch" | sed 's/^[* ]*//') +} + +# Quick commit amend without editing message +# Usage: gca +function gca() { + git commit --amend --no-edit +} + +# Show git log with fzf preview +# Usage: glo +function glo() { + if ! command -v fzf &>/dev/null; then + echo "Error: fzf not installed" + return 1 + fi + git log --oneline --color=always | \ + fzf --ansi --preview 'git show --color=always {1}' --preview-window=right:60% +} + +# Create branch and push with tracking +# Usage: gnb +# Example: gnb feature/new-api +function gnb() { + if [[ -z "$1" ]]; then + echo "Usage: gnb " + echo "Example: gnb feature/new-api" + return 1 + fi + git checkout -b "$1" && git push -u origin "$1" +} diff --git a/includes/late_20_aws_functions.zsh b/includes/late_20_aws_functions.zsh index 1f034fd..2ed1715 100644 --- a/includes/late_20_aws_functions.zsh +++ b/includes/late_20_aws_functions.zsh @@ -4,6 +4,10 @@ # Functions for AWS operations: # - awsregion: Get or set AWS_DEFAULT_REGION # - unset_aws: Clear all AWS_* environment variables +# - awsp: List and switch AWS profiles +# - ssm: Get SSM parameter value +# - secret: Get secret from Secrets Manager +# - whoami-aws: Show current AWS identity ######################################## # Get or set AWS default region @@ -26,3 +30,31 @@ function unset_aws() { done echo "All AWS_* environment variables cleared" } + +# List and switch AWS profiles (interactive with fzf if available) +# Usage: awsp [profile-name] +# Example: awsp production +function awsp() { + if [[ -z "$1" ]]; then + if command -v fzf &>/dev/null && [[ -f ~/.aws/config ]]; then + local profile=$(grep '^\[profile' ~/.aws/config | sed 's/\[profile \(.*\)\]/\1/' | fzf) + if [[ -n "$profile" ]]; then + export AWS_PROFILE="$profile" + echo "Switched to profile: $AWS_PROFILE" + fi + else + echo "Current AWS profile: ${AWS_PROFILE:-}" + echo "Available profiles:" + grep '^\[profile' ~/.aws/config 2>/dev/null | sed 's/\[profile \(.*\)\]/ \1/' + fi + else + export AWS_PROFILE="$1" + echo "AWS profile set to: $AWS_PROFILE" + fi +} + +# Show current AWS identity +# Usage: whoami-aws +function whoami-aws() { + aws sts get-caller-identity +} diff --git a/includes/late_25_kubernetes_functions.zsh b/includes/late_25_kubernetes_functions.zsh index b00e836..3dc7b25 100644 --- a/includes/late_25_kubernetes_functions.zsh +++ b/includes/late_25_kubernetes_functions.zsh @@ -4,6 +4,11 @@ # Functions for Kubernetes/Minikube operations: # - kubeme: Start minikube with configuration # - docker_kube: Set docker to use minikube's docker daemon +# - kctx: Quick context switch (fzf) +# - kns: Quick namespace switch (fzf) +# - klogs: Get pod logs with fzf selector +# - kexec: Exec into pod with fzf selector +# - kpf: Port forward with fzf selector ######################################## # Start minikube with appropriate configuration for the platform @@ -36,3 +41,95 @@ function kubeme() { function docker_kube() { eval $(minikube docker-env) } + +# Quick context switch using fzf +# Usage: kctx [context-name-or-filter] +# Example: kctx # Interactive selection +# Example: kctx prod # Switch to 'prod' or filter by 'prod' +function kctx() { + if ! command -v fzf &>/dev/null; then + echo "Error: fzf not installed" + return 1 + fi + + if [[ -n "$1" ]]; then + # Check if $1 is an exact match for a context + if kubectl config get-contexts -o name | grep -q "^${1}$"; then + kubectl config use-context "$1" + else + # Use $1 as a filter for fzf + local context=$(kubectl config get-contexts -o name | fzf --query="$1" --select-1) + [[ -n "$context" ]] && kubectl config use-context "$context" + fi + else + # No argument, show all contexts + local context=$(kubectl config get-contexts -o name | fzf) + [[ -n "$context" ]] && kubectl config use-context "$context" + fi +} +alias kubectx=kctx + +# Quick namespace switch using fzf +# Usage: kns [namespace-name-or-filter] +# Example: kns # Interactive selection +# Example: kns default # Switch to 'default' or filter by 'default' +function kns() { + if ! command -v fzf &>/dev/null; then + echo "Error: fzf not installed" + return 1 + fi + + if [[ -n "$1" ]]; then + # Check if $1 is an exact match for a namespace + if kubectl get namespaces -o name | cut -d/ -f2 | grep -q "^${1}$"; then + kubectl config set-context --current --namespace="$1" + else + # Use $1 as a filter for fzf + local namespace=$(kubectl get namespaces -o name | cut -d/ -f2 | fzf --query="$1" --select-1) + [[ -n "$namespace" ]] && kubectl config set-context --current --namespace="$namespace" + fi + else + # No argument, show all namespaces + local namespace=$(kubectl get namespaces -o name | cut -d/ -f2 | fzf) + [[ -n "$namespace" ]] && kubectl config set-context --current --namespace="$namespace" + fi +} +alias kubens=kns + +# Get pod logs with fzf selector +# Usage: klogs +function klogs() { + if ! command -v fzf &>/dev/null; then + echo "Error: fzf not installed" + return 1 + fi + local pod=$(kubectl get pods -o name | fzf) + [[ -n "$pod" ]] && kubectl logs -f "$pod" +} + +# Exec into pod with fzf selector +# Usage: kexec [shell] +# Example: kexec /bin/bash +function kexec() { + if ! command -v fzf &>/dev/null; then + echo "Error: fzf not installed" + return 1 + fi + local shell="${1:-/bin/sh}" + local pod=$(kubectl get pods -o name | fzf) + [[ -n "$pod" ]] && kubectl exec -it "$pod" -- "$shell" +} + +# Port forward with fzf selector +# Usage: kpf [local-port[:remote-port]] +# Example: kpf 8080 +# Example: kpf 8080:80 +function kpf() { + if ! command -v fzf &>/dev/null; then + echo "Error: fzf not installed" + return 1 + fi + local port="${1:-8080}" + local pod=$(kubectl get pods -o name | fzf) + [[ -n "$pod" ]] && kubectl port-forward "$pod" "$port" +} diff --git a/includes/late_27_docker_functions.zsh b/includes/late_27_docker_functions.zsh new file mode 100644 index 0000000..0503c23 --- /dev/null +++ b/includes/late_27_docker_functions.zsh @@ -0,0 +1,56 @@ +######################################## +# Docker Helper Functions +# +# Functions for Docker operations: +# - dclean: Clean up dangling images and stopped containers +# - dexec: Interactive container exec (fzf) +# - dlogs: Interactive container logs (fzf) +# - dstop: Stop all running containers +######################################## + +# Clean up dangling images, stopped containers, and unused volumes +# Usage: dclean +function dclean() { + echo "Cleaning up Docker resources..." + docker system prune -f + docker volume prune -f + echo "Docker cleanup complete" +} + +# Interactive container exec using fzf +# Usage: dexec [shell] +# Example: dexec /bin/bash +function dexec() { + if ! command -v fzf &>/dev/null; then + echo "Error: fzf not installed" + docker ps --format '{{.Names}}' + return 1 + fi + local shell="${1:-/bin/sh}" + local container=$(docker ps --format '{{.Names}}' | fzf) + [[ -n "$container" ]] && docker exec -it "$container" "$shell" +} + +# Interactive container logs using fzf +# Usage: dlogs +function dlogs() { + if ! command -v fzf &>/dev/null; then + echo "Error: fzf not installed" + docker ps --format '{{.Names}}' + return 1 + fi + local container=$(docker ps --format '{{.Names}}' | fzf) + [[ -n "$container" ]] && docker logs -f "$container" +} + +# Stop all running containers +# Usage: dstop +function dstop() { + local containers=$(docker ps -q) + if [[ -z "$containers" ]]; then + echo "No running containers to stop" + else + docker ps -q | xargs docker stop + echo "All containers stopped" + fi +} diff --git a/includes/late_35_network_functions.zsh b/includes/late_35_network_functions.zsh index 0d35fc8..ccb579b 100644 --- a/includes/late_35_network_functions.zsh +++ b/includes/late_35_network_functions.zsh @@ -3,6 +3,9 @@ # # Functions for network operations: # - dq: Query DNS across multiple resolvers (Google, Cloudflare, OpenDNS) +# - port: Check what's using a port +# - myip: Get public IP address +# - httptest: Quick HTTP test with timing ######################################## # Query DNS across multiple resolvers @@ -28,3 +31,45 @@ function dq() { echo "$c via cloudflare/1.1.1.1" echo "$o via opendns/208.67.222.222" } + +# Check what process is using a port +# Usage: port +# Example: port 8080 +function port() { + if [[ -z "$1" ]]; then + echo "Usage: port " + echo "Example: port 8080" + return 1 + fi + lsof -i ":$1" +} + +# Get public IP address +# Usage: myip [4|6] +# Example: myip # Default (both IPv4 and IPv6) +# Example: myip 4 # IPv4 only +# Example: myip 6 # IPv6 only +function myip() { + local url="https://icanhazip.com" + + if [[ "$1" == "4" ]]; then + url="https://ipv4.icanhazip.com" + elif [[ "$1" == "6" ]]; then + url="https://ipv6.icanhazip.com" + fi + + curl -s "$url" | tr -d '\n' + echo +} + +# Quick HTTP test with timing information +# Usage: httptest +# Example: httptest https://google.com +function httptest() { + if [[ -z "$1" ]]; then + echo "Usage: httptest " + echo "Example: httptest https://google.com" + return 1 + fi + curl -w "\nHTTP: %{http_code}\nTime: %{time_total}s\nSize: %{size_download} bytes\n" -o /dev/null -s "$1" +} diff --git a/includes/late_45_utility_functions.zsh b/includes/late_45_utility_functions.zsh index aef2e94..755e619 100644 --- a/includes/late_45_utility_functions.zsh +++ b/includes/late_45_utility_functions.zsh @@ -6,6 +6,15 @@ # - fe: Find files by pattern and execute command on them # - wttr: Get weather from wttr.in # - codec: Get video codec information using ffmpeg +# - extract: Universal archive extraction +# - uuid: Generate UUID +# - b64e / b64d: Base64 encode/decode +# - ts: Timestamp conversion +# - mkcd: Create directory and cd into it +# - up: Go up N directories +# - large: Find largest files/dirs in current directory +# - pkill-fzf: Kill process by name with fzf +# - portproc: Find process using a port ######################################## # Find files with a pattern in name @@ -55,3 +64,118 @@ function codec() { fi ffmpeg -i "$1" 2>&1 | grep Stream | grep -Eo '(Audio|Video)\: [^ ,]+' } + +# Universal archive extraction +# Usage: extract +# Example: extract archive.tar.gz +function extract() { + if [[ ! -f "$1" ]]; then + echo "Error: '$1' is not a valid file" + return 1 + fi + + case "$1" in + *.tar.bz2|*.tbz2) tar xjf "$1" ;; + *.tar.gz|*.tgz) tar xzf "$1" ;; + *.tar.xz|*.txz) tar xJf "$1" ;; + *.tar) tar xf "$1" ;; + *.bz2) bunzip2 "$1" ;; + *.gz) gunzip "$1" ;; + *.zip) unzip "$1" ;; + *.Z) uncompress "$1" ;; + *.7z) 7z x "$1" ;; + *.rar) unrar x "$1" ;; + *) echo "Error: '$1' cannot be extracted via extract()"; return 1 ;; + esac +} + +# Generate UUID (lowercase) +# Usage: uuid +function uuid() { + uuidgen | tr '[:upper:]' '[:lower:]' +} + +# Base64 encode +# Usage: b64e +# Example: b64e "hello world" +function b64e() { + if [[ -z "$1" ]]; then + echo "Usage: b64e " + return 1 + fi + echo -n "$1" | base64 +} + +# Base64 decode +# Usage: b64d +# Example: b64d "aGVsbG8gd29ybGQ=" +function b64d() { + if [[ -z "$1" ]]; then + echo "Usage: b64d " + return 1 + fi + echo -n "$1" | base64 -d +} + +# Timestamp conversion +# Usage: ts [unix-timestamp] +# Example: ts # Get current timestamp +# Example: ts 1638360000 # Convert timestamp to date +function ts() { + if [[ -z "$1" ]]; then + date +%s + else + date -r "$1" + fi +} + +# Go up N directories +# Usage: up [N] +# Example: up 3 # Go up 3 directories +function up() { + local levels=${1:-1} + local path="" + for ((i=0; i/dev/null; then + echo "Error: fzf not installed" + return 1 + fi + local pid=$(ps aux | fzf | awk '{print $2}') + if [[ -n "$pid" ]]; then + echo "Killing process $pid..." + kill "$pid" + fi +} + +# Find process using a specific port +# Usage: portproc +# Example: portproc 8080 +function portproc() { + if [[ -z "$1" ]]; then + echo "Usage: portproc " + echo "Example: portproc 8080" + return 1 + fi + local pids=$(lsof -ti ":$1") + if [[ -n "$pids" ]]; then + echo "$pids" | xargs ps -p + else + echo "No process found using port $1" + fi +} diff --git a/includes/late_46_format_functions.zsh b/includes/late_46_format_functions.zsh new file mode 100644 index 0000000..4ebbcf6 --- /dev/null +++ b/includes/late_46_format_functions.zsh @@ -0,0 +1,83 @@ +######################################## +# Format & Data Conversion Functions +# +# Functions for data formatting and conversion: +# - jpretty: Pretty print JSON from clipboard or file +# - y2j: Convert YAML to JSON +# - j2y: Convert JSON to YAML +# - jqp: Interactive JQ playground +######################################## + +# Pretty print JSON from clipboard or file +# Usage: jpretty [file] +# Example: jpretty data.json +# Example: jpretty # Uses clipboard +function jpretty() { + if ! command -v jq &>/dev/null; then + echo "Error: jq not installed" + return 1 + fi + + if [[ -z "$1" ]]; then + if command -v pbpaste &>/dev/null; then + pbpaste | jq '.' + else + echo "Usage: jpretty " + return 1 + fi + else + jq '.' "$1" + fi +} + +# Convert YAML to JSON +# Usage: y2j +# Example: y2j config.yaml +function y2j() { + if ! command -v yq &>/dev/null; then + echo "Error: yq not installed" + return 1 + fi + if [[ -z "$1" ]]; then + echo "Usage: y2j " + echo "Example: y2j config.yaml" + return 1 + fi + yq eval -o=json "$1" +} + +# Convert JSON to YAML +# Usage: j2y +# Example: j2y data.json +function j2y() { + if ! command -v yq &>/dev/null; then + echo "Error: yq not installed" + return 1 + fi + if [[ -z "$1" ]]; then + echo "Usage: j2y " + echo "Example: j2y data.json" + return 1 + fi + yq eval -P "$1" +} + +# Interactive JQ playground - test queries interactively +# Usage: jqp +# Example: jqp data.json +function jqp() { + if ! command -v jq &>/dev/null; then + echo "Error: jq not installed" + return 1 + fi + if ! command -v fzf &>/dev/null; then + echo "Error: fzf not installed" + return 1 + fi + if [[ -z "$1" ]]; then + echo "Usage: jqp " + echo "Example: jqp data.json" + return 1 + fi + echo '' | fzf --print-query --preview "jq {q} $1 2>/dev/null || echo 'Invalid JQ query'" +} diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 0000000..2f7ac87 --- /dev/null +++ b/tools/README.md @@ -0,0 +1,178 @@ +# Zsh Configuration Tools + +Utilities for testing, benchmarking, and profiling your zsh configuration. + +--- + +## test_config.zsh + +Comprehensive testing and linting for zsh configuration. + +### Usage + +```bash +# Full test suite +./tools/test_config.zsh + +# Quick tests (skip shellcheck and performance) +./tools/test_config.zsh --quick + +# Run and keep compiled files +./tools/test_config.zsh --fix +``` + +### What it checks + +1. **Syntax** - All .zsh files parse correctly +2. **Shellcheck** - Linting (with zsh-specific ignores) +3. **Load Test** - Configuration loads successfully +4. **Functions** - Required functions exist +5. **Compilation** - All files compile to .zwc +6. **Performance** - Startup time under 150ms + +### Exit codes + +- `0` - All tests passed +- `1` - Tests failed with errors + +## pre-commit-hook + +Git pre-commit hook that runs quick tests before each commit. + +### Usage + +```bash +# Install the hook +./tools/pre-commit-hook install + +# Uninstall the hook +./tools/pre-commit-hook uninstall + +# Test manually (without committing) +./tools/pre-commit-hook test + +# Show help +./tools/pre-commit-hook help +``` + +### What It Does + +- Runs `./tools/test_config.zsh --quick` before each commit +- Prevents commits if tests fail +- Catches syntax errors and broken configurations early + +### Bypass + +```bash +# Skip pre-commit hook for one commit +git commit --no-verify +``` + +--- + +## benchzshy.sh + +Statistical benchmark that measures average startup time over 100 runs. + +### Usage + +```bash +./tools/benchzshy.sh +``` + +### Requirements + +- GNU time (`gtime` on macOS) + ```bash + brew install gnu-time # macOS + ``` + +### Output + +Provides average times for: +- **Real** - Actual wall-clock time +- **User** - CPU time in user space +- **Sys** - CPU time in kernel space + +### Example + +``` +Benchmarking zsh startup over 100 runs... + +== Average Time Over 100 Runs == +Real: 0.087 s +User: 0.052 s +Sys : 0.028 s +``` + +Use this to measure the impact of configuration changes over many runs, reducing noise from individual measurements. + +--- + +## zsh_profile.py + +Analyzes zsh profiling output to identify slow operations. + +### Usage + +```bash +# 1. Generate profile with PROFILE_STARTUP +PROFILE_STARTUP=true zsh -i --login -c echo + +# 2. Analyze profile (default: show operations > 5ms) +python tools/zsh_profile.py /tmp/zsh_profile.$$ + +# 3. Or with custom threshold (e.g., 1ms) +python tools/zsh_profile.py /tmp/zsh_profile.$$ 1 +``` + +### Output + +Shows operations exceeding threshold: + +``` +12.3ms /path/to/file.zsh:42 source slow_plugin.zsh +8.7ms /path/to/file.zsh:156 compinit -C +6.2ms /path/to/file.zsh:89 some_slow_function +``` + +### Use Cases + +- **Identify bottlenecks** - Find which lines are slowing startup +- **Optimization** - Measure impact of changes +- **Regression detection** - Ensure new code doesn't add delays + +### Requirements + +- Python 3.x with dataclasses support + +--- + +## CI/CD Integration + +You can add this to GitHub Actions or similar: + +```yaml +name: Test Zsh Config +on: [push, pull_request] +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install zsh + run: sudo apt-get install -y zsh + - name: Run tests + run: ./tools/test_config.zsh --quick +``` + +--- + +## Quick Reference + +| Tool | Purpose | When to Use | +|------|---------|-------------| +| `test_config.zsh` | Validate config works | Before commits, in CI/CD | +| `benchzshy.sh` | Measure average startup | Compare changes over time | +| `zsh_profile.py` | Find slow operations | Optimize specific bottlenecks | +| `pre-commit-hook` | Auto-validate commits | Daily development | diff --git a/tools/pre-commit-hook b/tools/pre-commit-hook new file mode 100755 index 0000000..d3f31c7 --- /dev/null +++ b/tools/pre-commit-hook @@ -0,0 +1,121 @@ +#!/usr/bin/env zsh +# +# Git pre-commit hook for zsh configuration +# + +# Determine if we're being run as a hook or directly +SCRIPT_NAME="${0:t}" +IS_HOOK=false +[[ "$SCRIPT_NAME" == "pre-commit" ]] && IS_HOOK=true + +# Installation functions +install_hook() { + local script_path="${0:A}" + local git_root="$(git rev-parse --show-toplevel 2>/dev/null)" + + if [[ -z "$git_root" ]]; then + echo "Error: Not in a git repository" + return 1 + fi + + local hook_path="${git_root}/.git/hooks/pre-commit" + + if [[ -e "$hook_path" ]] && [[ ! -L "$hook_path" ]]; then + echo "Error: ${hook_path} already exists and is not a symlink" + echo "Please backup and remove it first, then run: $0 install" + return 1 + fi + + ln -sf "../../tools/pre-commit-hook" "$hook_path" + echo "✓ Pre-commit hook installed at ${hook_path}" + echo "" + echo "The hook will run './tools/test_config.zsh --quick' before each commit." + echo "To bypass: git commit --no-verify" +} + +uninstall_hook() { + local git_root="$(git rev-parse --show-toplevel 2>/dev/null)" + + if [[ -z "$git_root" ]]; then + echo "Error: Not in a git repository" + return 1 + fi + + local hook_path="${git_root}/.git/hooks/pre-commit" + + if [[ -L "$hook_path" ]] && [[ "$(readlink "$hook_path")" == "../../tools/pre-commit-hook" ]]; then + rm "$hook_path" + echo "✓ Pre-commit hook uninstalled" + elif [[ -e "$hook_path" ]]; then + echo "Warning: ${hook_path} exists but is not our symlink" + echo "Not removing it. Remove manually if needed." + return 1 + else + echo "Pre-commit hook is not installed" + fi +} + +show_usage() { + local script_name="${1:-$0}" + cat </dev/null; then + echo "${RED}✗${NC} Syntax error in $file" + zsh -n "$file" + ((SYNTAX_ERRORS++)) || true + else + echo "${GREEN}✓${NC} $file" + fi +done + +# Check all include files (they depend on init.zsh variables, so we skip detailed checks) +for file in includes/*.zsh; do + # Basic check: file is readable and not empty + if [[ ! -r "$file" ]]; then + echo "${RED}✗${NC} Cannot read $file" + ((SYNTAX_ERRORS++)) || true + elif [[ ! -s "$file" ]]; then + echo "${YELLOW}⚠${NC} Empty file: $file" + ((WARNINGS++)) || true + else + echo "${GREEN}✓${NC} $file" + fi +done + +ERRORS=$((ERRORS + SYNTAX_ERRORS)) +echo "" + +######################################### +# 2. Shellcheck (optional, with zsh-specific ignores) +######################################### +if command -v shellcheck &>/dev/null && [[ "$QUICK_MODE" != true ]]; then + echo "🔎 Running shellcheck (with zsh-specific ignores)..." + + # SC1090: Can't follow non-constant source + # SC2148: Tips depend on target shell (we're zsh, not bash) + # SC2296: Parameter expansions can't start with ( (zsh-specific syntax) + # SC1091: Not following sourced files + SHELLCHECK_IGNORE="-e SC1090 -e SC2148 -e SC2296 -e SC1091" + + SHELLCHECK_ERRORS=0 + for file in zshrc includes/*.zsh; do + if ! shellcheck -s bash $SHELLCHECK_IGNORE "$file" 2>/dev/null; then + echo "${YELLOW}⚠${NC} Shellcheck warnings in $file (may be false positives for zsh)" + ((WARNINGS++)) || true + fi + done + echo "" +fi + +######################################### +# 3. Load Test +######################################### +if [[ "$QUICK_MODE" != true ]]; then + echo "🚀 Testing full configuration load..." + + if zsh -i -c 'echo "Shell loaded successfully"' &>/dev/null; then + echo "${GREEN}✓${NC} Configuration loads successfully" + else + echo "${RED}✗${NC} Configuration failed to load" + ((ERRORS++)) || true + fi + echo "" +fi + +######################################### +# 4. Function Existence Check +######################################### +echo "🔧 Checking that key functions exist..." + +REQUIRED_FUNCTIONS=( + # Core + "source_compiled" + "is_stale_file" + # Git + "retag" + "gb" + "gca" + "glo" + "gnb" + # AWS + "awsregion" + "awsp" + # Kubernetes + "kctx" + "kns" + # Docker + "dclean" + # Shell + "resrc" + "t" + "zhelp" +) + +MISSING_FUNCTIONS=0 +for func in "${REQUIRED_FUNCTIONS[@]}"; do + if ! zsh -i -c "type $func" &>/dev/null; then + echo "${RED}✗${NC} Function not found: $func" + ((MISSING_FUNCTIONS++)) || true + fi +done + +if [[ $MISSING_FUNCTIONS -eq 0 ]]; then + echo "${GREEN}✓${NC} All required functions exist" +else + ERRORS=$((ERRORS + MISSING_FUNCTIONS)) +fi +echo "" + +######################################### +# 5. Compilation Test +######################################### +echo "⚙️ Testing bytecode compilation..." + +COMPILE_ERRORS=0 +for file in zshrc includes/*.zsh; do + if ! zcompile "$file" 2>/dev/null; then + echo "${RED}✗${NC} Cannot compile $file" + ((COMPILE_ERRORS++)) || true + fi +done + +if [[ $COMPILE_ERRORS -eq 0 ]]; then + echo "${GREEN}✓${NC} All files compile to .zwc" + + if [[ "$FIX_MODE" == false ]]; then + # Clean up test compilation artifacts + find . -name "*.zwc" -newer zshrc -delete 2>/dev/null + fi +else + ERRORS=$((ERRORS + COMPILE_ERRORS)) +fi +echo "" + +######################################### +# 6. Performance Check +######################################### +if [[ "$QUICK_MODE" != true ]]; then + echo "⚡ Performance test (startup time)..." + + # Run 5 iterations and average to reduce noise + # Use -i --login -c echo like normal usage + local sum=0 + local count=5 + for i in {1..$count}; do + local iter_time=$( { TIMEFMT='%*E'; time zsh -i --login -c echo } 2>&1 ) + # Parse the time value + if [[ "$iter_time" =~ ([0-9]+):([0-9]+)\.([0-9]+) ]]; then + # Format: M:SS.mmm + local mins=${match[1]} + local secs=${match[2]} + local ms=${match[3]} + local iter_ms=$(( mins * 60000 + secs * 1000 + ms )) + elif [[ "$iter_time" =~ ([0-9]+)\.([0-9]+) ]]; then + # Format: S.mmm + local secs=${match[1]} + local ms=${match[2]} + # Pad milliseconds to 3 digits if needed + while [[ ${#ms} -lt 3 ]]; do + ms="${ms}0" + done + local iter_ms=$(( secs * 1000 + ms )) + fi + sum=$(( sum + iter_ms )) + done 2>/dev/null + + TOTAL_MS=$(( sum / count )) + printf " Average startup time: %.0fms (over %d runs)\n" "$TOTAL_MS" "$count" + + if [[ -n "$TOTAL_MS" ]] && (( TOTAL_MS > 150 )); then + echo "${YELLOW}⚠${NC} Startup time exceeds 150ms target" + ((WARNINGS++)) || true + else + echo "${GREEN}✓${NC} Startup time under 150ms" + fi + echo "" +fi + +######################################### +# Summary +######################################### +echo "==========================================" +if [[ $ERRORS -eq 0 ]] && [[ $WARNINGS -eq 0 ]]; then + echo "${GREEN}✓ All tests passed!${NC}" + exit 0 +elif [[ $ERRORS -eq 0 ]]; then + echo "${YELLOW}⚠ Tests passed with $WARNINGS warning(s)${NC}" + exit 0 +else + echo "${RED}✗ Tests failed with $ERRORS error(s) and $WARNINGS warning(s)${NC}" + exit 1 +fi From 918dc4dad4826f73ff8b133c59c0bb57935584ba Mon Sep 17 00:00:00 2001 From: Richard Maynard Date: Thu, 11 Dec 2025 23:28:21 -0600 Subject: [PATCH 02/10] Fix shell check warnings --- .github/CONTRIBUTING.md | 163 ++++++++++++++++++++++ .github/workflows/test.yml | 55 ++++++++ .gitignore | 1 + includes/completions.zsh | 4 +- includes/early_07_colors.zsh | 4 +- includes/early_15_terminal_support.zsh | 6 +- includes/early_20_environment.zsh | 1 + includes/early_50_powerlevel10k.zsh | 13 +- includes/init.zsh | 4 +- includes/late_15_git_functions.zsh | 16 ++- includes/late_20_aws_functions.zsh | 7 +- includes/late_25_kubernetes_functions.zsh | 30 ++-- includes/late_27_docker_functions.zsh | 9 +- includes/late_30_1password_functions.zsh | 6 +- includes/late_35_network_functions.zsh | 9 +- includes/late_45_utility_functions.zsh | 12 +- includes/late_50_tools.zsh | 3 +- includes/late_75_aliases.zsh | 2 +- tools/test_config.zsh | 7 +- zshrc | 14 +- 20 files changed, 308 insertions(+), 58 deletions(-) create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/workflows/test.yml diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..1dd91e5 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,163 @@ +# Contributing to Zsh Configuration + +## Automated Testing + +This repository uses GitHub Actions to automatically test all changes. Tests run on: +- **Ubuntu Latest** - Primary Linux testing +- **macOS Latest** - macOS-specific functionality + +### What Gets Tested + +1. **Syntax Validation** - All `.zsh` files must parse correctly +2. **Shellcheck Linting** - Code quality checks with zsh-specific ignores +3. **Configuration Loading** - Ensures the config loads without errors +4. **Function Existence** - Verifies all required functions are defined + +### Running Tests Locally + +Before pushing changes, run the test suite locally: + +```bash +# Quick tests (syntax, functions, compilation) +./tools/test_config.zsh --quick + +# Full tests (includes shellcheck and performance) +./tools/test_config.zsh + +# Install pre-commit hook (recommended) +./tools/pre-commit-hook install +``` + +## Branch Protection Setup + +To require tests to pass before merging: + +### 1. Enable Branch Protection + +1. Go to your repository on GitHub +2. Navigate to **Settings** → **Branches** +3. Click **Add branch protection rule** +4. Enter branch name pattern: `master` (or `main`) + +### 2. Configure Protection Rules + +Enable the following options: + +- ✅ **Require a pull request before merging** + - ✅ Require approvals: 1 (optional, for team repos) + +- ✅ **Require status checks to pass before merging** + - ✅ Require branches to be up to date before merging + - Search and select these status checks: + - `Run Test Suite` + - `Run Test Suite (macOS)` (optional) + +- ✅ **Require conversation resolution before merging** (optional) + +- ✅ **Do not allow bypassing the above settings** + +### 3. Save and Test + +After enabling: +1. Create a test branch +2. Make a change and push +3. Open a pull request +4. Verify that GitHub Actions runs automatically +5. Confirm you cannot merge until tests pass + +## Development Workflow + +### Making Changes + +1. **Create a feature branch** + ```bash + git checkout -b feature/my-change + ``` + +2. **Make your changes** + - Edit files as needed + - Add new functions with proper documentation + - Update CHEATSHEET.md if adding/removing commands + +3. **Test locally** + ```bash + ./tools/test_config.zsh + ``` + +4. **Commit changes** + ```bash + git add . + git commit -m "Description of changes" + # Pre-commit hook runs automatically + ``` + +5. **Push and create PR** + ```bash + git push origin feature/my-change + ``` + - Open pull request on GitHub + - Wait for CI to pass + - Address any failures + +### If Tests Fail + +**In CI:** +1. Click "Details" next to the failed check +2. Review the error logs +3. Fix locally and push again + +**Locally:** +1. Run `./tools/test_config.zsh` to see full output +2. Fix the issues reported +3. Re-run tests to verify +4. Commit and push fixes + +## Coding Standards + +### Shellcheck Compliance + +All code must pass shellcheck with our standard ignores: +- SC1090: Can't follow non-constant source +- SC2148: Tips depend on target shell +- SC2296: Zsh-specific parameter expansion +- SC1091: Not following sourced files +- SC2034: Variables used by child processes +- SC2168: `local` outside functions (valid in zsh) + +### Function Guidelines + +1. **Add usage documentation** + ```zsh + # Description of what it does + # Usage: function_name [optional-arg] + # Example: function_name foo bar + function function_name() { + if [[ -z "$1" ]]; then + echo "Usage: function_name " + return 1 + fi + # ... implementation + } + ``` + +2. **Quote variables** to prevent word splitting +3. **Use `local` for function variables** +4. **Declare and assign separately** to avoid masking return values +5. **Handle errors** with appropriate return codes + +### Performance Requirements + +- Maintain sub-150ms startup time +- Changes adding >5ms should be justified +- Use profiling to measure impact: + ```bash + PROFILE_STARTUP=true zsh -i --login -c echo + ``` + +## Questions? + +Open an issue or check the documentation: +- `README.md` - Overview and setup +- `CHEATSHEET.md` - Available commands +- `CLAUDE.md` - Architecture and development guide +- `tools/README.md` - Testing tools documentation diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..3a571aa --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,55 @@ +name: Zsh Config Tests + +on: + push: + branches: [ master, main ] + pull_request: + branches: [ master, main ] + +jobs: + test: + name: Run Test Suite + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install zsh + run: | + sudo apt-get update + sudo apt-get install -y zsh + + - name: Install shellcheck + run: | + sudo apt-get install -y shellcheck + + - name: Verify installations + run: | + zsh --version + shellcheck --version + + - name: Run full test suite + run: | + ./tools/test_config.zsh + + test-macos: + name: Run Test Suite (macOS) + runs-on: macos-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install shellcheck + run: | + brew install shellcheck + + - name: Verify installations + run: | + zsh --version + shellcheck --version + + - name: Run tests + run: | + ./tools/test_config.zsh diff --git a/.gitignore b/.gitignore index 6460efa..2c26c45 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ cache/ **/*.zwc .vscode/ CLAUDE.md +.claude/settings.local.json diff --git a/includes/completions.zsh b/includes/completions.zsh index 3c14100..6114d88 100644 --- a/includes/completions.zsh +++ b/includes/completions.zsh @@ -18,12 +18,12 @@ compinit -C zstyle ':completion:*' cache-path "${ZSH}/cache/.zcompcache" # set cache path for completions zstyle ':completion:*' completer _extensions _complete _approximate # choose completers to use zstyle ':completion:*' group-name '' # group completion items together -zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS} # define colors for completion list +zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" # define colors for completion list zstyle ':completion:*' menu select # enable fancy selection of completions # zstyle ':completion:*' rehash true zstyle ':completion:*' use-cache true # enable cache, helpful for large completion lists but can be problematic for things like kubectl zstyle ':completion:*' verbose true -zstyle ":completion:*:default" list-colors ${(s.:.)LS_COLORS} +zstyle ":completion:*:default" list-colors "${(s.:.)LS_COLORS}" zstyle ':completion:*:descriptions' format '%F{green}%B%d%b%f' zstyle ':completion:*:messages' format '%F{purple}%d%f' zstyle ':completion:*:warnings' format '%F{red}No matches for: %d%f' diff --git a/includes/early_07_colors.zsh b/includes/early_07_colors.zsh index d9f1b26..6e7be67 100644 --- a/includes/early_07_colors.zsh +++ b/includes/early_07_colors.zsh @@ -13,7 +13,7 @@ case $OSTYPE in # Cache dircolors output for performance (~10ms saved) local dircolors_cache="${ZSH_CACHE_DIR}/dircolors_cache.zsh" if [[ ! -f "$dircolors_cache" || "${ZSH}/dircolors" -nt "$dircolors_cache" ]]; then - /opt/homebrew/bin/gdircolors -b ${ZSH}/dircolors > "$dircolors_cache" + /opt/homebrew/bin/gdircolors -b "${ZSH}/dircolors" > "$dircolors_cache" fi source_compiled "$dircolors_cache" else @@ -27,7 +27,7 @@ case $OSTYPE in # Cache dircolors output for performance local dircolors_cache="${ZSH_CACHE_DIR}/dircolors_cache.zsh" if [[ ! -f "$dircolors_cache" || "${ZSH}/dircolors" -nt "$dircolors_cache" ]]; then - dircolors ${ZSH}/dircolors > "$dircolors_cache" + dircolors "${ZSH}/dircolors" > "$dircolors_cache" fi source_compiled "$dircolors_cache" fi diff --git a/includes/early_15_terminal_support.zsh b/includes/early_15_terminal_support.zsh index 7788686..a9d19a8 100644 --- a/includes/early_15_terminal_support.zsh +++ b/includes/early_15_terminal_support.zsh @@ -7,15 +7,15 @@ ######################################## ### Some terminals need VTE sourced in -if [ $TILIX_ID ] || [ $VTE_VERSION ]; then +if [ "$TILIX_ID" ] || [ "$VTE_VERSION" ]; then source /etc/profile.d/vte.sh fi ### Check if suspected terminal is in a list we want to blur background of if ! [[ -z ${SUSPECTED_TERM_PID} ]]; then - if [[ $(ps --no-header -p ${SUSPECTED_TERM_PID} -o comm | egrep '(yakuake|konsole|alacritty)' ) ]]; then + if ps --no-header -p "${SUSPECTED_TERM_PID}" -o comm | grep -Eq '(yakuake|konsole|alacritty)'; then for wid in $(xdotool search --pid $PPID); do - xprop -f _KDE_NET_WM_BLUR_BEHIND_REGION 32c -set _KDE_NET_WM_BLUR_BEHIND_REGION 0 -id $wid >/dev/null 2>&1 + xprop -f _KDE_NET_WM_BLUR_BEHIND_REGION 32c -set _KDE_NET_WM_BLUR_BEHIND_REGION 0 -id "$wid" >/dev/null 2>&1 done fi fi diff --git a/includes/early_20_environment.zsh b/includes/early_20_environment.zsh index dd9272e..02ca6a5 100644 --- a/includes/early_20_environment.zsh +++ b/includes/early_20_environment.zsh @@ -37,6 +37,7 @@ esac ### konsole/yakuake don't handle blurring in KDE/Plasa 5 right, so work around ### this needs to happen early before tmux or antibody runs +# shellcheck disable=SC1073,SC1072,SC1027,SC1036,SC1009 if [[ ${XDG_SESSION_DESKTOP} = ("KDE"|"plasma") ]] && [[ -z ${SUSPECTED_TERM_PID} ]]; then SUSPECTED_TERM_PID=${PPID} fi diff --git a/includes/early_50_powerlevel10k.zsh b/includes/early_50_powerlevel10k.zsh index c57d8ab..d28e0a5 100644 --- a/includes/early_50_powerlevel10k.zsh +++ b/includes/early_50_powerlevel10k.zsh @@ -71,22 +71,25 @@ function prompt_goenv_version() { prompt_kube_context() { # powerlevel10 has a builtin context, but want some extra features CLUSTER_FILE=${ZSH_DIR}/k8s-clusters - local context=`test -f ~/.kube/config && grep current-context ~/.kube/config | cut -d\ -f2` + local context + context=$(test -f ~/.kube/config && grep current-context ~/.kube/config | cut -d\ -f2) if [[ -z $context ]]; then context='unknown' fi - if [[ "$context" =~ "arn:aws*" ]]; then + if [[ "$context" =~ arn:aws* ]]; then context=${context#*/} fi - local namespace=`kubectl config get-contexts --no-headers | grep '^\*' | awk '{ print $5 }'` + local namespace + namespace=$(kubectl config get-contexts --no-headers | grep '^\*' | awk '{ print $5 }') if [ "${namespace}" = "" ]; then namespace='default' fi - local env=$(test -f ${CLUSTER_FILE} && grep ${context} ${CLUSTER_FILE} | cut -d\; -f1) + local env + env=$(test -f "${CLUSTER_FILE}" && grep "${context}" "${CLUSTER_FILE}" | cut -d\; -f1) if [ -z "${env}" ]; then env="unknown" fi - p10k segment -s ${env} -i $'\uE7B2' -t "${context}/${namespace}" + p10k segment -s "${env}" -i $'\uE7B2' -t "${context}/${namespace}" } # Easily switch primary foreground/background colors diff --git a/includes/init.zsh b/includes/init.zsh index 4ec9533..828eef0 100644 --- a/includes/init.zsh +++ b/includes/init.zsh @@ -37,11 +37,11 @@ append_path() { remove_path() { local dir="$1" - PATH=$(print -r -- $PATH | tr ':' '\n' | grep -vFx "$dir" | paste -sd:) + PATH=$(print -r -- "$PATH" | tr ':' '\n' | grep -vFx "$dir" | paste -sd:) } clean_path() { - PATH=$(print -r -- $PATH | tr ':' '\n' | awk '!seen[$0]++' | paste -sd:) + PATH=$(print -r -- "$PATH" | tr ':' '\n' | awk '!seen[$0]++' | paste -sd:) } source_compiled() { diff --git a/includes/late_15_git_functions.zsh b/includes/late_15_git_functions.zsh index 67ff635..a04da3b 100644 --- a/includes/late_15_git_functions.zsh +++ b/includes/late_15_git_functions.zsh @@ -19,10 +19,10 @@ function retag() { echo "Example: retag v1.0.0" return 1 fi - git tag -d ${1} - git tag ${1} - git push origin :${1} - git push origin ${1} + git tag -d "${1}" + git tag "${1}" + git push origin :"${1}" + git push origin "${1}" } # Interactive branch switcher using fzf @@ -32,8 +32,12 @@ function gb() { echo "Error: fzf not installed" return 1 fi - local branch=$(git branch | fzf) - [[ -n "$branch" ]] && git checkout $(echo "$branch" | sed 's/^[* ]*//') + local branch + branch=$(git branch | fzf) + if [[ -n "$branch" ]]; then + branch="${branch##*( |\*)}" # Remove leading spaces and asterisk + git checkout "$branch" + fi } # Quick commit amend without editing message diff --git a/includes/late_20_aws_functions.zsh b/includes/late_20_aws_functions.zsh index 2ed1715..95791a8 100644 --- a/includes/late_20_aws_functions.zsh +++ b/includes/late_20_aws_functions.zsh @@ -25,8 +25,8 @@ function awsregion() { # Clear all AWS environment variables # Usage: unset_aws function unset_aws() { - for i in `env | grep '^AWS' | cut -d= -f1`; do - unset $i + for i in $(env | grep '^AWS' | cut -d= -f1); do + unset "$i" done echo "All AWS_* environment variables cleared" } @@ -37,7 +37,8 @@ function unset_aws() { function awsp() { if [[ -z "$1" ]]; then if command -v fzf &>/dev/null && [[ -f ~/.aws/config ]]; then - local profile=$(grep '^\[profile' ~/.aws/config | sed 's/\[profile \(.*\)\]/\1/' | fzf) + local profile + profile=$(grep '^\[profile' ~/.aws/config | sed 's/\[profile \(.*\)\]/\1/' | fzf) if [[ -n "$profile" ]]; then export AWS_PROFILE="$profile" echo "Switched to profile: $AWS_PROFILE" diff --git a/includes/late_25_kubernetes_functions.zsh b/includes/late_25_kubernetes_functions.zsh index 3dc7b25..0906caf 100644 --- a/includes/late_25_kubernetes_functions.zsh +++ b/includes/late_25_kubernetes_functions.zsh @@ -16,11 +16,10 @@ # Example: kubeme v1.19.6 function kubeme() { local minikube_version=${1:="v1.19.6"} - minikube status >/dev/null 2>&1 - if [ $? -ne 0 ]; then + if ! minikube status >/dev/null 2>&1; then case ${OSTYPE} in linux*) - minikube start --kubernetes-version ${minikube_version} --vm-driver kvm2 \ + minikube start --kubernetes-version "${minikube_version}" --vm-driver kvm2 \ --cpus 4 \ --memory 8192 \ --extra-config=kubelet.authorization-mode=Webhook \ @@ -29,7 +28,7 @@ function kubeme() { --addons ingress ;; darwin*) - minikube --kubernetes-version ${minikube_version} start + minikube --kubernetes-version "${minikube_version}" start ;; esac fi @@ -39,7 +38,7 @@ function kubeme() { # Configure docker to use minikube's docker daemon # Usage: docker_kube function docker_kube() { - eval $(minikube docker-env) + eval "$(minikube docker-env)" } # Quick context switch using fzf @@ -58,12 +57,14 @@ function kctx() { kubectl config use-context "$1" else # Use $1 as a filter for fzf - local context=$(kubectl config get-contexts -o name | fzf --query="$1" --select-1) + local context + context=$(kubectl config get-contexts -o name | fzf --query="$1" --select-1) [[ -n "$context" ]] && kubectl config use-context "$context" fi else # No argument, show all contexts - local context=$(kubectl config get-contexts -o name | fzf) + local context + context=$(kubectl config get-contexts -o name | fzf) [[ -n "$context" ]] && kubectl config use-context "$context" fi } @@ -85,12 +86,14 @@ function kns() { kubectl config set-context --current --namespace="$1" else # Use $1 as a filter for fzf - local namespace=$(kubectl get namespaces -o name | cut -d/ -f2 | fzf --query="$1" --select-1) + local namespace + namespace=$(kubectl get namespaces -o name | cut -d/ -f2 | fzf --query="$1" --select-1) [[ -n "$namespace" ]] && kubectl config set-context --current --namespace="$namespace" fi else # No argument, show all namespaces - local namespace=$(kubectl get namespaces -o name | cut -d/ -f2 | fzf) + local namespace + namespace=$(kubectl get namespaces -o name | cut -d/ -f2 | fzf) [[ -n "$namespace" ]] && kubectl config set-context --current --namespace="$namespace" fi } @@ -103,7 +106,8 @@ function klogs() { echo "Error: fzf not installed" return 1 fi - local pod=$(kubectl get pods -o name | fzf) + local pod + pod=$(kubectl get pods -o name | fzf) [[ -n "$pod" ]] && kubectl logs -f "$pod" } @@ -116,7 +120,8 @@ function kexec() { return 1 fi local shell="${1:-/bin/sh}" - local pod=$(kubectl get pods -o name | fzf) + local pod + pod=$(kubectl get pods -o name | fzf) [[ -n "$pod" ]] && kubectl exec -it "$pod" -- "$shell" } @@ -130,6 +135,7 @@ function kpf() { return 1 fi local port="${1:-8080}" - local pod=$(kubectl get pods -o name | fzf) + local pod + pod=$(kubectl get pods -o name | fzf) [[ -n "$pod" ]] && kubectl port-forward "$pod" "$port" } diff --git a/includes/late_27_docker_functions.zsh b/includes/late_27_docker_functions.zsh index 0503c23..087d9c0 100644 --- a/includes/late_27_docker_functions.zsh +++ b/includes/late_27_docker_functions.zsh @@ -27,7 +27,8 @@ function dexec() { return 1 fi local shell="${1:-/bin/sh}" - local container=$(docker ps --format '{{.Names}}' | fzf) + local container + container=$(docker ps --format '{{.Names}}' | fzf) [[ -n "$container" ]] && docker exec -it "$container" "$shell" } @@ -39,14 +40,16 @@ function dlogs() { docker ps --format '{{.Names}}' return 1 fi - local container=$(docker ps --format '{{.Names}}' | fzf) + local container + container=$(docker ps --format '{{.Names}}' | fzf) [[ -n "$container" ]] && docker logs -f "$container" } # Stop all running containers # Usage: dstop function dstop() { - local containers=$(docker ps -q) + local containers + containers=$(docker ps -q) if [[ -z "$containers" ]]; then echo "No running containers to stop" else diff --git a/includes/late_30_1password_functions.zsh b/includes/late_30_1password_functions.zsh index d0021d4..51f21f8 100644 --- a/includes/late_30_1password_functions.zsh +++ b/includes/late_30_1password_functions.zsh @@ -27,7 +27,7 @@ function ops() { return 1 fi check_op || return 1 - eval $(op signin $1) + eval "$(op signin "$1")" } # Get password from 1Password and copy to clipboard @@ -42,6 +42,6 @@ function opg() { check_op || return 1 op_account=$1 shift - item="$@" - op --account ${op_account} get item ${item} --fields password | pbcopy + item="$*" + op --account "${op_account}" get item "${item}" --fields password | pbcopy } diff --git a/includes/late_35_network_functions.zsh b/includes/late_35_network_functions.zsh index ccb579b..af23db9 100644 --- a/includes/late_35_network_functions.zsh +++ b/includes/late_35_network_functions.zsh @@ -21,9 +21,12 @@ function dq() { fi local domain="$1" local type="${2:-ANY}" - local g=$(dig +noall +answer +short @8.8.8.8 "$domain" "$type") - local c=$(dig +noall +answer +short @1.1.1.1 "$domain" "$type") - local o=$(dig +noall +answer +short @208.67.222.222 "$domain" "$type") + local g + local c + local o + g=$(dig +noall +answer +short @8.8.8.8 "$domain" "$type") + c=$(dig +noall +answer +short @1.1.1.1 "$domain" "$type") + o=$(dig +noall +answer +short @208.67.222.222 "$domain" "$type") echo "Various Results for $domain ($type)" echo "" diff --git a/includes/late_45_utility_functions.zsh b/includes/late_45_utility_functions.zsh index 755e619..6a33734 100644 --- a/includes/late_45_utility_functions.zsh +++ b/includes/late_45_utility_functions.zsh @@ -28,7 +28,7 @@ function ff() { echo "Example: ff config" return 1 fi - find . -type f -iname '*'$*'*' -ls + find . -type f -iname '*'"$*"'*' -ls } # Find files with pattern and execute command on them @@ -42,7 +42,7 @@ function fe() { echo "Example: fe config file" return 1 fi - find . -type f -iname '*'${1:-}'*' -exec ${2:-file} {} \; + find . -type f -iname '*'"${1:-}"'*' -exec "${2:-file}" {} \; } # Get weather from wttr.in @@ -138,7 +138,7 @@ function up() { for ((i=0; i "${pyenv_init_cache}") &! + (pyenv init - > "${pyenv_init_cache}") &! # zsh-specific &! syntax fi # Lazy load pyenv init on first use diff --git a/includes/late_75_aliases.zsh b/includes/late_75_aliases.zsh index 16258d3..f90227a 100644 --- a/includes/late_75_aliases.zsh +++ b/includes/late_75_aliases.zsh @@ -86,7 +86,7 @@ alias cless='less -R' # Some platform specific items case ${OSTYPE} in linux*) - if [ ${IS_WSL} -eq 0 ]; then + if [ "${IS_WSL}" -eq 0 ]; then alias pbcopy='xsel --clipboard --input' alias pbpaste='xsel --clipboard --output' fi diff --git a/tools/test_config.zsh b/tools/test_config.zsh index 0062338..e34c425 100755 --- a/tools/test_config.zsh +++ b/tools/test_config.zsh @@ -76,11 +76,14 @@ if command -v shellcheck &>/dev/null && [[ "$QUICK_MODE" != true ]]; then # SC2148: Tips depend on target shell (we're zsh, not bash) # SC2296: Parameter expansions can't start with ( (zsh-specific syntax) # SC1091: Not following sourced files - SHELLCHECK_IGNORE="-e SC1090 -e SC2148 -e SC2296 -e SC1091" + # SC2034: Variables used by child processes/exports (zsh-specific) + # SC2168: local outside functions is valid in zsh + local -a shellcheck_ignore + shellcheck_ignore=(-e SC1090 -e SC2148 -e SC2296 -e SC1091 -e SC2034 -e SC2168) SHELLCHECK_ERRORS=0 for file in zshrc includes/*.zsh; do - if ! shellcheck -s bash $SHELLCHECK_IGNORE "$file" 2>/dev/null; then + if ! shellcheck -s bash "${shellcheck_ignore[@]}" "$file" 2>/dev/null; then echo "${YELLOW}⚠${NC} Shellcheck warnings in $file (may be false positives for zsh)" ((WARNINGS++)) || true fi diff --git a/zshrc b/zshrc index 073459c..826fb4e 100644 --- a/zshrc +++ b/zshrc @@ -9,11 +9,15 @@ fi export ZSH="${HOME}/.zsh" export ZSH_CACHE_DIR="${ZSH}/cache" export ZSH_INCLUDES="${ZSH}/includes" -[ -d "${ZSH_CACHE_DIR}" ] || { - [ -x /bin/mkdir ] && /bin/mkdir -p "${ZSH_CACHE_DIR}" || \ - [ -x /usr/bin/mkdir ] && /usr/bin/mkdir -p "${ZSH_CACHE_DIR}" || \ - command mkdir -p "${ZSH_CACHE_DIR}" -} +if [ ! -d "${ZSH_CACHE_DIR}" ]; then + if [ -x /bin/mkdir ]; then + /bin/mkdir -p "${ZSH_CACHE_DIR}" + elif [ -x /usr/bin/mkdir ]; then + /usr/bin/mkdir -p "${ZSH_CACHE_DIR}" + else + command mkdir -p "${ZSH_CACHE_DIR}" + fi +fi # Load core functions ZSH_INIT_FILE="${ZSH_INCLUDES}/init.zsh" From 972f054e2a2c8354dcea3adf57b0e5ad2c6ea92a Mon Sep 17 00:00:00 2001 From: Richard Maynard Date: Thu, 11 Dec 2025 23:36:27 -0600 Subject: [PATCH 03/10] Address test issues in CI environment --- tools/test_config.zsh | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/tools/test_config.zsh b/tools/test_config.zsh index e34c425..a2b13e4 100755 --- a/tools/test_config.zsh +++ b/tools/test_config.zsh @@ -135,13 +135,42 @@ REQUIRED_FUNCTIONS=( "zhelp" ) -MISSING_FUNCTIONS=0 -for func in "${REQUIRED_FUNCTIONS[@]}"; do - if ! zsh -i -c "type $func" &>/dev/null; then - echo "${RED}✗${NC} Function not found: $func" - ((MISSING_FUNCTIONS++)) || true - fi -done +# Check if running in CI or minimal environment +if [[ -n "$CI" ]] || [[ ! -f "${HOME}/.zshrc" ]]; then + # CI mode: Source files directly + # Set up minimal environment + export ZSH="${ZSH_ROOT}" + export ZSH_CACHE_DIR="${ZSH}/cache" + + # Create cache dir if needed + mkdir -p "${ZSH_CACHE_DIR}" + + # Source init.zsh first (has core functions) + source "${ZSH_ROOT}/includes/init.zsh" 2>/dev/null || true + + # Source all function files + for file in "${ZSH_ROOT}"/includes/late_*.zsh; do + [[ -f "$file" ]] && source "$file" 2>/dev/null || true + done + + # Check functions in current shell + MISSING_FUNCTIONS=0 + for func in "${REQUIRED_FUNCTIONS[@]}"; do + if ! type "$func" &>/dev/null; then + echo "${RED}✗${NC} Function not found: $func" + ((MISSING_FUNCTIONS++)) || true + fi + done +else + # Normal mode: Use interactive shell + MISSING_FUNCTIONS=0 + for func in "${REQUIRED_FUNCTIONS[@]}"; do + if ! zsh -i -c "type $func" &>/dev/null; then + echo "${RED}✗${NC} Function not found: $func" + ((MISSING_FUNCTIONS++)) || true + fi + done +fi if [[ $MISSING_FUNCTIONS -eq 0 ]]; then echo "${GREEN}✓${NC} All required functions exist" From ba45debeba3039b07ed909291a6eb28c9cd6ed8e Mon Sep 17 00:00:00 2001 From: Richard Maynard Date: Thu, 11 Dec 2025 23:38:06 -0600 Subject: [PATCH 04/10] Add status badge to README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e096288..9b37fd5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # ⚡ ephur's Zsh Configuration +[![Zsh Config Tests](https://github.com/ephur/zshrc/actions/workflows/test.yml/badge.svg)](https://github.com/ephur/zshrc/actions/workflows/test.yml) + A highly optimized, purpose-built Zsh configuration focused on **startup speed**, **modular organization**, and a clean, reproducible shell experience across multiple platforms (macOS, WSL, Linux distros). --- From 4b9fb5d3e9fad83d302a985833acb8fc6bf6718d Mon Sep 17 00:00:00 2001 From: Richard Maynard Date: Thu, 11 Dec 2025 23:43:17 -0600 Subject: [PATCH 05/10] Fix shell check warnings that only appear with Linux as the OS --- includes/early_15_terminal_support.zsh | 2 +- includes/early_20_environment.zsh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/early_15_terminal_support.zsh b/includes/early_15_terminal_support.zsh index a9d19a8..fee5dd5 100644 --- a/includes/early_15_terminal_support.zsh +++ b/includes/early_15_terminal_support.zsh @@ -12,7 +12,7 @@ if [ "$TILIX_ID" ] || [ "$VTE_VERSION" ]; then fi ### Check if suspected terminal is in a list we want to blur background of -if ! [[ -z ${SUSPECTED_TERM_PID} ]]; then +if [[ -n "${SUSPECTED_TERM_PID}" ]]; then if ps --no-header -p "${SUSPECTED_TERM_PID}" -o comm | grep -Eq '(yakuake|konsole|alacritty)'; then for wid in $(xdotool search --pid $PPID); do xprop -f _KDE_NET_WM_BLUR_BEHIND_REGION 32c -set _KDE_NET_WM_BLUR_BEHIND_REGION 0 -id "$wid" >/dev/null 2>&1 diff --git a/includes/early_20_environment.zsh b/includes/early_20_environment.zsh index 02ca6a5..4bbe1d7 100644 --- a/includes/early_20_environment.zsh +++ b/includes/early_20_environment.zsh @@ -38,8 +38,8 @@ esac ### konsole/yakuake don't handle blurring in KDE/Plasa 5 right, so work around ### this needs to happen early before tmux or antibody runs # shellcheck disable=SC1073,SC1072,SC1027,SC1036,SC1009 -if [[ ${XDG_SESSION_DESKTOP} = ("KDE"|"plasma") ]] && [[ -z ${SUSPECTED_TERM_PID} ]]; then - SUSPECTED_TERM_PID=${PPID} +if [[ ${XDG_SESSION_DESKTOP} = ("KDE"|"plasma") ]] && [[ -z "${SUSPECTED_TERM_PID}" ]]; then + SUSPECTED_TERM_PID="${PPID}" fi # Check some special paths to add/update env From ae19488ce1c5dccece73443652130f8700b30979 Mon Sep 17 00:00:00 2001 From: Richard Maynard Date: Thu, 11 Dec 2025 23:47:00 -0600 Subject: [PATCH 06/10] Update tools/test_config.zsh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tools/test_config.zsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/test_config.zsh b/tools/test_config.zsh index a2b13e4..4945a48 100755 --- a/tools/test_config.zsh +++ b/tools/test_config.zsh @@ -214,7 +214,7 @@ if [[ "$QUICK_MODE" != true ]]; then # Use -i --login -c echo like normal usage local sum=0 local count=5 - for i in {1..$count}; do + for ((i=1; i<=count; i++)); do local iter_time=$( { TIMEFMT='%*E'; time zsh -i --login -c echo } 2>&1 ) # Parse the time value if [[ "$iter_time" =~ ([0-9]+):([0-9]+)\.([0-9]+) ]]; then From 48ece1203205d5fe4c2b5f1de3b333102e19eea4 Mon Sep 17 00:00:00 2001 From: Richard Maynard Date: Thu, 11 Dec 2025 23:48:01 -0600 Subject: [PATCH 07/10] Update includes/early_50_powerlevel10k.zsh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- includes/early_50_powerlevel10k.zsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/early_50_powerlevel10k.zsh b/includes/early_50_powerlevel10k.zsh index d28e0a5..dea7fb1 100644 --- a/includes/early_50_powerlevel10k.zsh +++ b/includes/early_50_powerlevel10k.zsh @@ -76,7 +76,7 @@ prompt_kube_context() { if [[ -z $context ]]; then context='unknown' fi - if [[ "$context" =~ arn:aws* ]]; then + if [[ "$context" =~ '^arn:aws' ]]; then context=${context#*/} fi local namespace From 34ab55cf704468a6df2e4bf69e39cbf207174563 Mon Sep 17 00:00:00 2001 From: Richard Maynard Date: Thu, 11 Dec 2025 23:48:50 -0600 Subject: [PATCH 08/10] Update includes/late_15_git_functions.zsh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- includes/late_15_git_functions.zsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/late_15_git_functions.zsh b/includes/late_15_git_functions.zsh index a04da3b..a59310b 100644 --- a/includes/late_15_git_functions.zsh +++ b/includes/late_15_git_functions.zsh @@ -35,7 +35,7 @@ function gb() { local branch branch=$(git branch | fzf) if [[ -n "$branch" ]]; then - branch="${branch##*( |\*)}" # Remove leading spaces and asterisk + branch=$(echo "$branch" | sed 's/^[* ]*//') # Remove leading spaces and asterisk git checkout "$branch" fi } From 69e86b7f4c02a866581b171b9d8480eca89289c6 Mon Sep 17 00:00:00 2001 From: Richard Maynard Date: Thu, 11 Dec 2025 23:49:06 -0600 Subject: [PATCH 09/10] Update includes/late_20_aws_functions.zsh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- includes/late_20_aws_functions.zsh | 2 -- 1 file changed, 2 deletions(-) diff --git a/includes/late_20_aws_functions.zsh b/includes/late_20_aws_functions.zsh index 95791a8..5b31dcd 100644 --- a/includes/late_20_aws_functions.zsh +++ b/includes/late_20_aws_functions.zsh @@ -5,8 +5,6 @@ # - awsregion: Get or set AWS_DEFAULT_REGION # - unset_aws: Clear all AWS_* environment variables # - awsp: List and switch AWS profiles -# - ssm: Get SSM parameter value -# - secret: Get secret from Secrets Manager # - whoami-aws: Show current AWS identity ######################################## From 84bc60f3e07f939904d5815a1b86b799d11bf686 Mon Sep 17 00:00:00 2001 From: Richard Maynard Date: Thu, 11 Dec 2025 23:51:06 -0600 Subject: [PATCH 10/10] remove unused functions from file headers --- includes/late_15_git_functions.zsh | 1 - includes/late_45_utility_functions.zsh | 1 - 2 files changed, 2 deletions(-) diff --git a/includes/late_15_git_functions.zsh b/includes/late_15_git_functions.zsh index a59310b..cf4d830 100644 --- a/includes/late_15_git_functions.zsh +++ b/includes/late_15_git_functions.zsh @@ -3,7 +3,6 @@ # # Functions for common git operations: # - retag: Delete and recreate a git tag, then force push to origin -# - gcm: Clean up merged branches # - gb: Interactive branch switcher (fzf) # - gca: Quick commit amend without editing message # - glo: Git log with fzf preview diff --git a/includes/late_45_utility_functions.zsh b/includes/late_45_utility_functions.zsh index 6a33734..211da14 100644 --- a/includes/late_45_utility_functions.zsh +++ b/includes/late_45_utility_functions.zsh @@ -10,7 +10,6 @@ # - uuid: Generate UUID # - b64e / b64d: Base64 encode/decode # - ts: Timestamp conversion -# - mkcd: Create directory and cd into it # - up: Go up N directories # - large: Find largest files/dirs in current directory # - pkill-fzf: Kill process by name with fzf