Commit 57d2ef5087ad

Vincent Demeester <vincent@sbr.pm>
2026-02-18 10:37:50
feat(zsh): add smart path shortening to prompt
Replaced raw %~ with _prompt_dir() that shortens long paths by abbreviating segments to first letter, keeping last two intact. Added icon prefixes for worktrees (๐ŸŒณ) and desktop (๐Ÿ–ฅ๏ธ). Dotfiles preserve dot prefix (.local โ†’ .l).
1 parent 4149698
Changed files (1)
home
common
shell
home/common/shell/zsh/prompt.zsh
@@ -1,84 +1,53 @@
 # 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
+# Smart path shortening for prompt
 
-# 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 a path by abbreviating all segments except the last to first letter
+# $1: path string, $2: max length (default 50)
 _shorten_path() {
-  local p="$1" max="$2" keep="${3:-1}"
+  local p="$1" max="${2:-50}"
+  (( ${#p} <= max )) && { echo "$p"; return; }
+
   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
+  # Shorten from the first segment toward the last, keeping last 2 intact
   local i
-  for (( i=keep+1; i < len; i++ )); do
+  for (( i=1; i <= len - 2; i++ )); do
     (( ${#p} <= max )) && break
-    parts[$i]="${parts[$i]:0:1}"
+    # Don't shorten segments that are already 1-2 chars
+    (( ${#parts[$i]} <= 2 )) && continue
+    # Keep dot prefix for hidden dirs (e.g. .local โ†’ .l)
+    if [[ "${parts[$i]}" == .* ]]; then
+      parts[$i]=".${parts[$i]:1:1}"
+    else
+      parts[$i]="${parts[$i]:0:1}"
+    fi
     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
+# Smart directory display with path shortening
+# - All paths are shortened when > 50 chars (middle segments โ†’ first letter)
+# - Worktrees get a ๐ŸŒฒ prefix
+# - Desktop gets a ๐Ÿ–ฅ๏ธ prefix
 _prompt_dir() {
   local dir="${PWD/#$HOME/~}"
+  local prefix=""
 
-  # 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
+  # Worktrees: add ๐ŸŒฒ prefix
+  if [[ "$dir" =~ '^~/.local/share/worktrees/' ]]; then
+    prefix="๐ŸŒณ "
+  # Desktop: add ๐Ÿ–ฅ๏ธ prefix
+  elif [[ "$dir" =~ '^~/desktop' ]]; then
+    prefix="๐Ÿ–ฅ๏ธ "
   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)
+    dir=$(_shorten_path "$dir" 50)
   fi
-  echo "$dir"
+  echo "${prefix}${dir}"
 }
 
 # Helper function to get git branch
@@ -104,8 +73,8 @@ _prompt_nix_shell() {
 # Helper function to show KUBECONFIG
 _prompt_kubeconfig() {
   if [[ -n $KUBECONFIG ]]; then
-    # Extract just the filename from the path for brevity
-    local kube_name=$(basename "$KUBECONFIG" .yaml)
+    local kube_name
+    kube_name=$(basename "$KUBECONFIG" .yaml)
     echo " %F{134}k8s:$kube_name%f"
   fi
 }