Commit 4754c31975d8

Vincent Demeester <vincent@sbr.pm>
2026-02-18 10:15:54
feat(zsh): add smart path shortening to prompt
Replaced raw %~ with _prompt_dir() that applies context-aware abbreviations: worktrees (๐ŸŒฟ org/repo), desktop (๐Ÿ–ฅ๏ธ), forges (gh:/gl:/cb:), and middle-segment truncation for paths over 50 chars. Org names shortened to 3 chars, branch stripped from worktree paths since git prompt already shows it.
1 parent f4a4eb9
Changed files (1)
home
common
shell
home/common/shell/zsh/prompt.zsh
@@ -1,5 +1,85 @@
-# Simple, fast zsh prompt configuration
-# Based on TODO: Small zsh configuration
+# shellcheck shell=bash disable=SC2296,SC2076,SC2154,SC2004,SC2016,SC2155
+# Simple, fast zsh prompt configuration (zsh-only, not bash-compatible)
+# Smart path shortening for long directories
+
+# Shorten path by abbreviating middle segments to first letter
+# $1: path string, $2: max length, $3: number of leading segments to keep (default 1)
+_shorten_path() {
+  local p="$1" max="$2" keep="${3:-1}"
+  local parts=("${(@s:/:)p}")
+  local len=${#parts[@]}
+
+  # Need enough segments to shorten
+  if (( len < keep + 2 )); then
+    echo "$p"
+    return
+  fi
+
+  # Shorten segments after the kept ones, up to second-to-last
+  local i
+  for (( i=keep+1; i < len; i++ )); do
+    (( ${#p} <= max )) && break
+    parts[$i]="${parts[$i]:0:1}"
+    p="${(j:/:)parts}"
+  done
+  echo "$p"
+}
+
+# Smart directory display
+# - Worktrees:  ~/.local/share/worktrees/<org>/<repo>/<branch>[/...] โ†’ ๐ŸŒฟ <org(3)>/<repo>[/...]
+# - Desktop:    ~/desktop/...                                       โ†’ ๐Ÿ–ฅ๏ธ .../...
+# - Forges:     ~/src/github.com/org/repo/...                       โ†’ gh:org/repo/...
+#               ~/src/gitlab.com/org/repo/...                       โ†’ gl:org/repo/...
+#               ~/src/codeberg.org/org/repo/...                     โ†’ cb:org/repo/...
+# - Long paths: middle segments abbreviated to first letter
+_prompt_dir() {
+  local dir="${PWD/#$HOME/~}"
+
+  # Worktrees: ~/.local/share/worktrees/<org>/<repo>/<branch>[/subdir...]
+  #   โ†’ ๐ŸŒฟ <org(3)>/<repo>[/subdir...] (branch already shown by git prompt)
+  if [[ "$dir" =~ '^~/.local/share/worktrees/([^/]+)/([^/]+)/[^/]+(/.*)?$' ]]; then
+    local org="${match[1]:0:3}"
+    local repo="${match[2]}"
+    local subdir="${match[3]}"
+    dir="๐ŸŒฟ ${org}/${repo}${subdir}"
+    if (( ${#dir} > 50 )); then
+      # Keep "๐ŸŒฟ org/repo" (first 2 real segments after emoji+space)
+      dir=$(_shorten_path "$dir" 50 2)
+    fi
+    echo "$dir"
+    return
+  fi
+
+  # Desktop: ~/desktop/... โ†’ ๐Ÿ–ฅ๏ธ ...
+  if [[ "$dir" =~ '^~/desktop(/.*)?$' ]]; then
+    local rest="${match[1]#/}"
+    if [[ -n "$rest" ]]; then
+      dir="๐Ÿ–ฅ๏ธ ${rest}"
+    else
+      dir="๐Ÿ–ฅ๏ธ"
+    fi
+    if (( ${#dir} > 50 )); then
+      dir=$(_shorten_path "$dir" 50)
+    fi
+    echo "$dir"
+    return
+  fi
+
+  # Forges: ~/src/<forge>/org/repo/... โ†’ prefix:org/repo/...
+  if [[ "$dir" =~ '^~/src/github\.com/(.*)$' ]]; then
+    dir="gh:${match[1]}"
+  elif [[ "$dir" =~ '^~/src/gitlab\.com/(.*)$' ]]; then
+    dir="gl:${match[1]}"
+  elif [[ "$dir" =~ '^~/src/codeberg\.org/(.*)$' ]]; then
+    dir="cb:${match[1]}"
+  fi
+
+  # General: shorten if too long (keep prefix:org/repo = 2 segments for forges)
+  if (( ${#dir} > 50 )); then
+    dir=$(_shorten_path "$dir" 50 2)
+  fi
+  echo "$dir"
+}
 
 # Helper function to get git branch
 _prompt_git_branch() {
@@ -34,4 +114,4 @@ _prompt_kubeconfig() {
 # Format: hostname:directory [git-branch] [nix-shell] [kubeconfig] $
 # Colors: 111=light blue (hostname), 2=green (directory), 76=green (git), yellow (nix), 134=orange (k8s)
 setopt PROMPT_SUBST
-export PROMPT='%F{111}%m%f:%F{2}%~%f$(_prompt_git_branch)$(_prompt_nix_shell)$(_prompt_kubeconfig) %(!.#.$) '
+export PROMPT='%F{111}%m%f:%F{2}$(_prompt_dir)%f$(_prompt_git_branch)$(_prompt_nix_shell)$(_prompt_kubeconfig) %(!.#.$) '