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

View File

@@ -198,33 +198,17 @@ Examples:
}
var crewNextCmd = &cobra.Command{
Use: "next",
Short: "Switch to next crew session in same rig",
Long: `Switch to the next crew session in the same rig.
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,
Use: "next",
Short: "Switch to next crew session in same rig",
Hidden: true, // Internal command for tmux keybindings
RunE: runCrewNext,
}
var crewPrevCmd = &cobra.Command{
Use: "prev",
Short: "Switch to previous crew session in same rig",
Long: `Switch to the previous crew session in the same rig.
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,
Use: "prev",
Short: "Switch to previous crew session in same rig",
Hidden: true, // Internal command for tmux keybindings
RunE: runCrewPrev,
}
func init() {

View File

@@ -103,6 +103,9 @@ func runCrewAt(cmd *cobra.Command, args []string) error {
theme := getThemeForRig(r.Name)
_ = 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
if err := t.WaitForShellReady(sessionID, 5*time.Second); err != nil {
return fmt.Errorf("waiting for shell: %w", err)

View File

@@ -11,8 +11,11 @@ import (
// cycleCrewSession switches to the next or previous crew session in the same rig.
// direction: 1 for next, -1 for previous
func cycleCrewSession(direction int) error {
// Get current session
currentSession := getCurrentTmuxSession()
// Get current session (uses existing function from handoff.go)
currentSession, err := getCurrentTmuxSession()
if err != nil {
return fmt.Errorf("not in a tmux session: %w", err)
}
if currentSession == "" {
return fmt.Errorf("not in a tmux session")
}
@@ -55,7 +58,6 @@ func cycleCrewSession(direction int) error {
if targetIdx == currentIdx {
// Only one session, nothing to switch to
fmt.Printf("Only one crew session in rig %s\n", rigName)
return nil
}

View File

@@ -268,22 +268,6 @@ func parseCrewSessionName(sessionName string) (rigName, crewName string, ok bool
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.
// Uses tmux list-sessions to find sessions matching gt-<rig>-crew-* pattern.
func findRigCrewSessions(rigName string) ([]string, error) {