feat(02-02): implement fuzzy match + switch workspace + i3 commander

- FuzzyMatch searches label > branch > cwd (case-insensitive)
- SwitchToWorkspace sends 'workspace number N' via I3Commander interface
- RealI3Commander wraps go.i3wm.org/i3/v4 RunCommand
- 9 tests covering priority, no-match, case-insensitive, errors
This commit is contained in:
Pierre Martin
2026-03-23 17:45:32 +01:00
parent 4a298d5ad0
commit 9427dd3eda

View File

@@ -1,6 +1,9 @@
package main package main
import ( import (
"fmt"
"strings"
i3 "go.i3wm.org/i3/v4" i3 "go.i3wm.org/i3/v4"
) )
@@ -9,13 +12,55 @@ type I3Commander interface {
RunCommand(command string) ([]i3.CommandResult, error) RunCommand(command string) ([]i3.CommandResult, error)
} }
// RealI3Commander utilise go.i3wm.org/i3/v4 directement.
type RealI3Commander struct{}
func (c RealI3Commander) RunCommand(cmd string) ([]i3.CommandResult, error) {
return i3.RunCommand(cmd)
}
// FuzzyMatch trouve la premiere session matchant query dans : label > branche > cwd. // FuzzyMatch trouve la premiere session matchant query dans : label > branche > cwd.
// Case-insensitive. Retourne nil si aucun match. // Case-insensitive. Retourne nil si aucun match.
func FuzzyMatch(query string, sessions []SessionInfo) *SessionInfo { func FuzzyMatch(query string, sessions []SessionInfo) *SessionInfo {
q := strings.ToLower(query)
// Priorite 1 : label
for i := range sessions {
if sessions[i].Label != "" && strings.Contains(strings.ToLower(sessions[i].Label), q) {
return &sessions[i]
}
}
// Priorite 2 : branche git
for i := range sessions {
if strings.Contains(strings.ToLower(sessions[i].GitBranch), q) {
return &sessions[i]
}
}
// Priorite 3 : cwd
for i := range sessions {
if strings.Contains(strings.ToLower(sessions[i].Cwd), q) {
return &sessions[i]
}
}
return nil return nil
} }
// SwitchToWorkspace bascule vers le workspace indique via i3 IPC. // SwitchToWorkspace bascule vers le workspace indique via i3 IPC.
func SwitchToWorkspace(commander I3Commander, wsName string) error { func SwitchToWorkspace(commander I3Commander, wsName string) error {
cmd := fmt.Sprintf("workspace number %s", wsName)
results, err := commander.RunCommand(cmd)
if err != nil {
return fmt.Errorf("i3 RunCommand: %w", err)
}
for _, r := range results {
if !r.Success {
return fmt.Errorf("i3 workspace switch failed: %s", r.Error)
}
}
return nil return nil
} }