diff --git a/README.md b/README.md index a0862d1..da52587 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,8 @@ source ~/.bashrc # or source ~/.zshrc ## Usage ``` -tmux-ws create [--detach|-d] Create and attach to a workspace +tmux-ws create [--detach|-d] [--force|-f] Create and attach to a workspace +tmux-ws attach Attach to a running workspace tmux-ws list List available and running workspaces tmux-ws kill Kill a workspace session tmux-ws edit Open workspace config in $EDITOR diff --git a/bin/tmux-ws b/bin/tmux-ws index 9e17c6e..bebeb54 100755 --- a/bin/tmux-ws +++ b/bin/tmux-ws @@ -17,36 +17,36 @@ NC='\033[0m' # --- Usage --- usage() { - cat < [--detach|-d] Create and attach to a workspace - $SCRIPT_NAME list List available and running workspaces - $SCRIPT_NAME kill Kill a workspace session - $SCRIPT_NAME edit Open workspace config in \$EDITOR - $SCRIPT_NAME init Create config directory structure - $SCRIPT_NAME help Show this help - -${BOLD}Options:${NC} - --detach, -d Create workspace without attaching - --force, -f Kill existing session before creating - -${BOLD}Config:${NC} - $CONFIG_DIR//workspace.conf - $CONFIG_DIR/_templates/default.conf Base template (auto-inherited) - -${BOLD}Config format:${NC} - # workspace.conf — EXECUTED as shell code. Do not untrusted sources. - _BASE="default" - DEFAULT_DIR="\$HOME/projects/myapp" - WINDOWS=( - "editor::vim" - "server::npm run dev" - "logs::tail -f /var/log/app.log" - "scratch::" - ) -EOF + echo -e "${BOLD}$SCRIPT_NAME${NC} — tmux workspace manager" + echo -e "" + echo -e "${BOLD}Usage:${NC}" + echo -e " $SCRIPT_NAME create [--detach|-d] Create and attach to a workspace" + echo -e " $SCRIPT_NAME attach Attach to a running workspace" + echo -e " $SCRIPT_NAME list List available and running workspaces" + echo -e " $SCRIPT_NAME kill Kill a workspace session" + echo -e " $SCRIPT_NAME edit Open workspace config in \$EDITOR" + echo -e " $SCRIPT_NAME init Create config directory structure" + echo -e " $SCRIPT_NAME version Show version" + echo -e " $SCRIPT_NAME help Show this help" + echo -e "" + echo -e "${BOLD}Options:${NC}" + echo -e " --detach, -d Create workspace without attaching" + echo -e " --force, -f Kill existing session before creating" + echo -e "" + echo -e "${BOLD}Config:${NC}" + echo -e " $CONFIG_DIR//workspace.conf" + echo -e " $CONFIG_DIR/_templates/default.conf Base template (auto-inherited)" + echo -e "" + echo -e "${BOLD}Config format:${NC}" + echo -e " # workspace.conf — EXECUTED as shell code. Do not untrusted sources." + echo -e " _BASE=\"default\"" + echo -e " DEFAULT_DIR=\"\$HOME/projects/myapp\"" + echo -e " WINDOWS=(" + echo -e " \"editor::vim\"" + echo -e " \"server::npm run dev\"" + echo -e " \"logs::tail -f /var/log/app.log\"" + echo -e " \"scratch::\"" + echo -e " )" } # --- Logging --- @@ -345,6 +345,22 @@ cmd_edit() { "${EDITOR:-vim}" "$config_file" } +cmd_attach() { + local name="${1:-}" + if [[ -z "$name" ]]; then + error "Workspace name required" + exit 1 + fi + + if ! tmux has-session -t "$name" 2>/dev/null; then + error "Session '$name' is not running" + echo " Create it with: $SCRIPT_NAME create $name" + exit 1 + fi + + tmux attach -t "$name" +} + cmd_init() { if [[ -d "$CONFIG_DIR" ]] && [[ "$(ls -A "$CONFIG_DIR" 2>/dev/null)" ]]; then warn "Config directory already exists at $CONFIG_DIR" @@ -416,6 +432,7 @@ main() { case "$command" in create) cmd_create "$@" ;; + attach) cmd_attach "$@" ;; list) cmd_list ;; kill) cmd_kill "$@" ;; edit) cmd_edit "$@" ;; diff --git a/tests/test_tmux_ws.bats b/tests/test_tmux_ws.bats index 04738bb..d63431f 100644 --- a/tests/test_tmux_ws.bats +++ b/tests/test_tmux_ws.bats @@ -96,6 +96,7 @@ EOF tmux kill-session -t bad-format 2>/dev/null || true tmux kill-session -t no-template 2>/dev/null || true tmux kill-session -t fail-hook 2>/dev/null || true + tmux kill-session -t test-attach 2>/dev/null || true } teardown() { @@ -104,6 +105,7 @@ teardown() { tmux kill-session -t bad-format 2>/dev/null || true tmux kill-session -t no-template 2>/dev/null || true tmux kill-session -t fail-hook 2>/dev/null || true + tmux kill-session -t test-attach 2>/dev/null || true rm -rf "$TEST_CONFIG_DIR" rm -rf "$BATS_TEST_TMPDIR/test-workspace-dir" rm -rf "$BATS_TEST_TMPDIR/myapp-dir" @@ -272,6 +274,28 @@ teardown() { [[ "${output}" == *"not running"* ]] } +# --- Attach --- + +@test "attach requires a name" { + run tmux-ws attach + [ "$status" -eq 1 ] + [[ "${output}" == *"Workspace name required"* ]] +} + +@test "attach fails for nonexistent session" { + run tmux-ws attach nonexistent + [ "$status" -eq 1 ] + [[ "${output}" == *"not running"* ]] +} + +@test "attach passes validation for running session" { + tmux new-session -d -s test-attach + # tmux attach requires a tty, so we can't test the actual attach. + # Verify the session exists (would pass the has-session check). + run tmux has-session -t test-attach + [ "$status" -eq 0 ] +} + # --- Edit --- @test "edit requires a name" {