feat: Add C-b n/p keybindings for crew session cycling

When multiple crew sessions exist in the same rig, C-b n cycles to next
and C-b p cycles to previous. Sessions are sorted alphabetically and
wrap around.

Implementation:
- crew_cycle.go: Hidden `gt crew next/prev` commands for tmux to call
- crew_helpers.go: parseCrewSessionName and findRigCrewSessions helpers
- crew_at.go: Calls SetCrewCycleBindings on session creation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-25 11:51:48 -08:00
parent 0095fee81c
commit 62f603bbe1
4 changed files with 16 additions and 43 deletions
+8 -24
View File
@@ -198,33 +198,17 @@ Examples:
} }
var crewNextCmd = &cobra.Command{ var crewNextCmd = &cobra.Command{
Use: "next", Use: "next",
Short: "Switch to next crew session in same rig", Short: "Switch to next crew session in same rig",
Long: `Switch to the next crew session in the same rig. Hidden: true, // Internal command for tmux keybindings
RunE: runCrewNext,
Cycles through crew sessions alphabetically. When you reach the last
crew, wraps around to the first.
This command is bound to C-b n in crew sessions for quick switching.
Examples:
gt crew next # Switch to next crew in same rig`,
RunE: runCrewNext,
} }
var crewPrevCmd = &cobra.Command{ var crewPrevCmd = &cobra.Command{
Use: "prev", Use: "prev",
Short: "Switch to previous crew session in same rig", Short: "Switch to previous crew session in same rig",
Long: `Switch to the previous crew session in the same rig. Hidden: true, // Internal command for tmux keybindings
RunE: runCrewPrev,
Cycles through crew sessions in reverse alphabetical order. When you
reach the first crew, wraps around to the last.
This command is bound to C-b p in crew sessions for quick switching.
Examples:
gt crew prev # Switch to previous crew in same rig`,
RunE: runCrewPrev,
} }
func init() { func init() {
+3
View File
@@ -103,6 +103,9 @@ func runCrewAt(cmd *cobra.Command, args []string) error {
theme := getThemeForRig(r.Name) theme := getThemeForRig(r.Name)
_ = t.ConfigureGasTownSession(sessionID, theme, r.Name, name, "crew") _ = t.ConfigureGasTownSession(sessionID, theme, r.Name, name, "crew")
// Set up C-b n/p keybindings for crew session cycling
_ = t.SetCrewCycleBindings(sessionID)
// Wait for shell to be ready after session creation // Wait for shell to be ready after session creation
if err := t.WaitForShellReady(sessionID, 5*time.Second); err != nil { if err := t.WaitForShellReady(sessionID, 5*time.Second); err != nil {
return fmt.Errorf("waiting for shell: %w", err) return fmt.Errorf("waiting for shell: %w", err)
+5 -3
View File
@@ -11,8 +11,11 @@ import (
// cycleCrewSession switches to the next or previous crew session in the same rig. // cycleCrewSession switches to the next or previous crew session in the same rig.
// direction: 1 for next, -1 for previous // direction: 1 for next, -1 for previous
func cycleCrewSession(direction int) error { func cycleCrewSession(direction int) error {
// Get current session // Get current session (uses existing function from handoff.go)
currentSession := getCurrentTmuxSession() currentSession, err := getCurrentTmuxSession()
if err != nil {
return fmt.Errorf("not in a tmux session: %w", err)
}
if currentSession == "" { if currentSession == "" {
return fmt.Errorf("not in a tmux session") return fmt.Errorf("not in a tmux session")
} }
@@ -55,7 +58,6 @@ func cycleCrewSession(direction int) error {
if targetIdx == currentIdx { if targetIdx == currentIdx {
// Only one session, nothing to switch to // Only one session, nothing to switch to
fmt.Printf("Only one crew session in rig %s\n", rigName)
return nil return nil
} }
-16
View File
@@ -268,22 +268,6 @@ func parseCrewSessionName(sessionName string) (rigName, crewName string, ok bool
return rigName, crewName, true return rigName, crewName, true
} }
// getCurrentTmuxSession returns the current tmux session name.
// Returns empty string if not in tmux.
func getCurrentTmuxSession() string {
if os.Getenv("TMUX") == "" {
return ""
}
cmd := exec.Command("tmux", "display-message", "-p", "#{session_name}")
out, err := cmd.Output()
if err != nil {
return ""
}
return strings.TrimSpace(string(out))
}
// findRigCrewSessions returns all crew sessions for a given rig, sorted alphabetically. // findRigCrewSessions returns all crew sessions for a given rig, sorted alphabetically.
// Uses tmux list-sessions to find sessions matching gt-<rig>-crew-* pattern. // Uses tmux list-sessions to find sessions matching gt-<rig>-crew-* pattern.
func findRigCrewSessions(rigName string) ([]string, error) { func findRigCrewSessions(rigName string) ([]string, error) {