Workspace Manager
Ce script m'a permis d'ajouter des commandes à mon terminal pour naviguer rapidement entre mes projets, les ouvrir dans mon IDE et lancer des actions contextuelles, avec le support de la recherche floue (fuzzy-search) et de l'autocomplétion.
Il est construit sur une architecture modulaire et agnostique : un Core universel gère les déplacements, et des Handlers spécifiques gèrent les commandes propres à chaque environnement.
Prérequis⚓︎
Pour que ce script fonctionne, les éléments suivants sont nécessaires :
- Zsh : Le shell par défaut sur macOS.
- fzf : L'outil de recherche floue interactif.
brew install fzf - PhpStorm (ou autre IDE) : L'application doit être installée dans le dossier
Applicationset correctement nommée "PhpStorm" (le script utilise la commande native macOSopen -a).
Arborescence⚓︎
Pour garder un système propre, j'ai séparé l'interface (couleurs et fonction d'affichage de message) de la logique métier dans un dossier personnalisé à la racine (~) :
.zsh_custom
├── ui.zsh
└── workspace.zsh
1. Le module d'interface (UI)⚓︎
Le fichier ~/.zsh_custom/ui.zsh contient :
# UI et Helpers CLI
RED="\033[0;31m"
GREEN="\033[0;32m"
YELLOW="\033[0;33m"
BLUE="\033[0;34m"
CYAN="\033[0;36m"
RESET="\033[0m"
msg() {
local color="$1"
shift
echo -e "${color}$*${RESET}"
}
2. Le script⚓︎
Le fichier ~/.zsh_custom/workspace.zsh contient la logique de gestion et de déplacement au sein des workspaces :
# CLI Workspace Manager
source "$HOME/.zsh_custom/ui.zsh"
select_project() {
local workspace="$1"
if ! command -v fzf >/dev/null 2>&1; then
msg "$RED" "Aucun projet fourni et fzf introuvable."
return 1
fi
# `! -name ".*"` pour exclure les dossiers cachés
local selection=$(find "$workspace" -mindepth 1 -maxdepth 1 -type d ! -name ".*" -exec basename {} \; | fzf --height 40% --reverse --prompt="> ")
echo "$selection"
}
_core_workspace_manager() {
local cmd_name="$1"
local workspace="$2"
local ide_name="$3"
local custom_handler="$4" # fonction qui gère les actions spécifiques
shift 4
local open_ide=false
local project=""
local custom_flags=() # tableau pour stocker les flags inconnus du core
while [[ "$#" -gt 0 ]]; do
case "$1" in
-i|--ide)
open_ide=true; shift
;;
-h|--help)
msg "$CYAN" "Usage: $cmd_name [options] [project]"
echo
msg "$CYAN" "Options globales :"
echo " -i, --ide Ouvre le projet dans $ide_name"
echo " -h, --help Affiche ce message"
# On demande au handler d'afficher ses propres options d'aide
if command -v "$custom_handler" >/dev/null 2>&1; then
echo
msg "$CYAN" "Options spécifiques :"
"$custom_handler" "--help"
fi
return 0
;;
-*)
# si le flag est inconnu du core, on le garde pour le handler
custom_flags+=("$1")
shift
;;
*)
project="$1"
shift
;;
esac
done
# logique commune
if [[ -z "$project" ]]; then
project=$(select_project "$workspace") || return 1
fi
local dir="$workspace/$project"
if [[ ! -d "$dir" ]]; then
msg "$RED" "Projet introuvable: $project"
return 1
fi
cd "$dir" || return
msg "$CYAN" "Déplacement vers $(pwd)"
if $open_ide; then
msg "$CYAN" "Ouverture de $ide_name..."
command -v open >/dev/null 2>&1 && open -a "$ide_name" "$dir" >/dev/null 2>&1 &
fi
# délégation des actions spécifiques restantes au handler
if [[ ${#custom_flags[@]} -gt 0 ]] && command -v "$custom_handler" >/dev/null 2>&1; then
"$custom_handler" "${custom_flags[@]}"
fi
}
_work_handler() {
for flag in "$@"; do
case "$flag" in
--help) echo " -s, --sync Synchronise le code (ex: git pull)" ;;
-s|--sync) msg "$CYAN" "Sync en cours..."; sync ;;
*) msg "$YELLOW" "Option ignorée par 'work': $flag" ;;
esac
done
}
work() { _core_workspace_manager "work" "/Volumes/Workspace" "PhpStorm" "_work_handler" "$@"; }
compdef '_files -W /Volumes/Workspace -/' work # (1)!
_dev_handler() {
for flag in "$@"; do
case "$flag" in
--help)
echo " -u, --up Monte l'environnement Docker"
echo " -s, --sync Met à jour les packages NPM"
;;
-u|--up)
msg "$CYAN" "Démarrage du projet..."; make up
;;
*)
msg "$YELLOW" "Option ignorée par 'dev': $flag"
;;
esac
done
}
dev() { _core_workspace_manager "dev" "/Users/evan/dev" "PhpStorm" "_dev_handler" "$@"; }
compdef '_files -W /Users/evan/dev -/' dev # (1)!
- fonction native de
Zshqui signifie "Completion Define" (définir une complétion). Elle sert à lier une règle d'autocomplétion à une commande spécifique. En l'occurrence,_filesest un utilitaire intégré àZshconçu spécialement pour générer des suggestions basées sur le système de fichiers.
3. Activation⚓︎
Il suffit de charger ce script dans le fichier de configuration principal de Zsh :
# ... reste du code
source "$HOME/.zsh_custom/workspace.zsh"
Finalement, on recharge la configuration configuration :
source ~/.zshrc
Ajouter une nouvelle commande⚓︎
Grâce à l'architecture ouverte, il est possible de créer de nouvelles commandes en 3 étapes directement dans workspace.zsh, sans jamais toucher au cœur du script (_core_workspace_manager) :
- Créez une fonction handler
_test_handler() { ... }pour définir les options spécifiques (voir ci-dessus). - Déclarez la commande :
test() { _core_workspace_manager "test" "/Chemin/Vers/Dossier" "NomIDE" "_test_handler" "$@"; } - Ajoutez l'autocomplétion :
compdef '_files -W /Chemin/Vers/Dossier -/' test
Utilisation⚓︎
L'outil fusionne des commandes globales (communes à tous les espaces) et des commandes spécifiques (propres au contexte).
Exemples d'utilisation :⚓︎
work: ouvre le menu interactiffzfpour choisir un projet.work mon-projet: déplace directement dans le projet.work -i mon-projet: déplace et ouvre le projet dans PhpStorm (Option Globale).
Options contextuelles :⚓︎
Les options varient selon la commande parente :
work -s mon-projet: Lance la fonctionsyncde l'espace de travail.dev -u mon-projet: Lance une commande pour démarrer le server local de mon projet.dev -s mon-projet: Refusera de lancer la fonctionsync(puisque non définie ou différente dans le handlerdev).
L'option --help (ou -h) affiche la liste des commandes universelles et spécifiques.