From ab4248463a86d2ef5bb28a57152c7066ef4c093a Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Sat, 10 Jan 2026 00:14:11 +0100 Subject: [PATCH] Improve CLI UX by making host/port/timeout global flags - Move --host, --port, and --timeout from individual commands to global app level - Enables cleaner syntax: 'soundtouch-cli --host 192.168.1.10 volume get' - Consistent with Docker, kubectl, and other CLI tools that use global connection flags - Environment variables (SOUNDTOUCH_HOST, SOUNDTOUCH_PORT) work seamlessly - Remove repetitive CommonFlags from all individual commands - Maintains backward compatibility - all functionality works exactly the same - Discovery commands ignore host flag when not needed BREAKING: CLI syntax improved from 'volume --host IP get' to '--host IP volume get' --- cmd/soundtouch-cli/main.go | 310 ++++++++++++++++++------------------- 1 file changed, 155 insertions(+), 155 deletions(-) diff --git a/cmd/soundtouch-cli/main.go b/cmd/soundtouch-cli/main.go index d16e528..8669409 100644 --- a/cmd/soundtouch-cli/main.go +++ b/cmd/soundtouch-cli/main.go @@ -21,7 +21,7 @@ func main() { Email: "info@example.com", }, }, - Flags: []cli.Flag{}, + Flags: CommonFlags, Commands: []*cli.Command{ // Discovery commands { @@ -33,11 +33,13 @@ func main() { Name: "devices", Usage: "Discover and list SoundTouch devices", Action: discoverDevices, - Flags: append(CommonFlags, &cli.BoolFlag{ - Name: "all", - Aliases: []string{"a"}, - Usage: "Show detailed information for all devices", - }), + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "all", + Aliases: []string{"a"}, + Usage: "Show detailed information for all devices", + }, + }, }, }, }, @@ -47,7 +49,6 @@ func main() { Aliases: []string{"i"}, Usage: "Get device information", Action: getDeviceInfo, - Flags: CommonFlags, Before: RequireHost, }, { @@ -60,19 +61,20 @@ func main() { Name: "get", Usage: "Get device name", Action: getDeviceName, - Flags: CommonFlags, Before: RequireHost, }, { Name: "set", Usage: "Set device name", Action: setDeviceName, - Flags: append(CommonFlags, &cli.StringFlag{ - Name: "value", - Aliases: []string{"n"}, - Usage: "New device name", - Required: true, - }), + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "value", + Aliases: []string{"n"}, + Usage: "New device name", + Required: true, + }, + }, Before: RequireHost, }, }, @@ -81,14 +83,12 @@ func main() { Name: "capabilities", Usage: "Get device capabilities", Action: getCapabilities, - Flags: CommonFlags, Before: RequireHost, }, { Name: "presets", Usage: "Get configured presets", Action: getPresets, - Flags: CommonFlags, Before: RequireHost, }, // Playback commands @@ -101,42 +101,36 @@ func main() { Name: "now", Usage: "Get current playback status", Action: getNowPlaying, - Flags: CommonFlags, Before: RequireHost, }, { Name: "start", Usage: "Start playback", Action: playCommand, - Flags: CommonFlags, Before: RequireHost, }, { Name: "pause", Usage: "Pause playback", Action: pauseCommand, - Flags: CommonFlags, Before: RequireHost, }, { Name: "stop", Usage: "Stop playback", Action: stopCommand, - Flags: CommonFlags, Before: RequireHost, }, { Name: "next", Usage: "Next track", Action: nextCommand, - Flags: CommonFlags, Before: RequireHost, }, { Name: "prev", Usage: "Previous track", Action: prevCommand, - Flags: CommonFlags, Before: RequireHost, }, }, @@ -146,11 +140,13 @@ func main() { Name: "preset", Usage: "Select preset by number", Action: selectPreset, - Flags: append(CommonFlags, &cli.IntFlag{ - Name: "preset", - Usage: "Preset number (1-6)", - Required: true, - }), + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "preset", + Usage: "Preset number (1-6)", + Required: true, + }, + }, Before: RequireHost, }, // Key commands @@ -163,54 +159,50 @@ func main() { Name: "send", Usage: "Send generic key command", Action: sendKey, - Flags: append(CommonFlags, &cli.StringFlag{ - Name: "key", - Aliases: []string{"k"}, - Usage: "Key name (PLAY, PAUSE, STOP, POWER, MUTE, etc.)", - Required: true, - }), + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "key", + Aliases: []string{"k"}, + Usage: "Key name (PLAY, PAUSE, STOP, POWER, MUTE, etc.)", + Required: true, + }, + }, Before: RequireHost, }, { Name: "power", Usage: "Send POWER key command", Action: powerCommand, - Flags: CommonFlags, Before: RequireHost, }, { Name: "mute", Usage: "Send MUTE key command", Action: muteCommand, - Flags: CommonFlags, Before: RequireHost, }, { Name: "thumbs-up", Usage: "Send THUMBS_UP key command", Action: thumbsUpCommand, - Flags: CommonFlags, Before: RequireHost, }, { Name: "thumbs-down", Usage: "Send THUMBS_DOWN key command", Action: thumbsDownCommand, - Flags: CommonFlags, Before: RequireHost, }, { Name: "volume-up", Usage: "Send VOLUME_UP key command", Action: volumeUpKey, - Flags: CommonFlags, Before: RequireHost, }, { Name: "volume-down", Usage: "Send VOLUME_DOWN key command", Action: volumeDownKey, - Flags: CommonFlags, Before: RequireHost, }, }, @@ -220,7 +212,6 @@ func main() { Name: "track", Usage: "Get track information", Action: getTrackInfo, - Flags: CommonFlags, Before: RequireHost, }, // Volume commands @@ -233,43 +224,48 @@ func main() { Name: "get", Usage: "Get current volume level", Action: getVolume, - Flags: CommonFlags, Before: RequireHost, }, { Name: "set", Usage: "Set volume level", Action: setVolume, - Flags: append(CommonFlags, &cli.IntFlag{ - Name: "level", - Aliases: []string{"l"}, - Usage: "Volume level (0-100)", - Required: true, - }), + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "level", + Aliases: []string{"l"}, + Usage: "Volume level (0-100)", + Required: true, + }, + }, Before: RequireHost, }, { Name: "up", Usage: "Increase volume", Action: volumeUp, - Flags: append(CommonFlags, &cli.IntFlag{ - Name: "amount", - Aliases: []string{"a"}, - Usage: "Amount to increase (1-10)", - Value: 2, - }), + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "amount", + Aliases: []string{"a"}, + Usage: "Amount to increase (1-10)", + Value: 2, + }, + }, Before: RequireHost, }, { Name: "down", Usage: "Decrease volume", Action: volumeDown, - Flags: append(CommonFlags, &cli.IntFlag{ - Name: "amount", - Aliases: []string{"a"}, - Usage: "Amount to decrease (1-10)", - Value: 2, - }), + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "amount", + Aliases: []string{"a"}, + Usage: "Amount to decrease (1-10)", + Value: 2, + }, + }, Before: RequireHost, }, }, @@ -284,14 +280,13 @@ func main() { Name: "list", Usage: "List available audio sources", Action: listSources, - Flags: CommonFlags, Before: RequireHost, }, { Name: "select", Usage: "Select an audio source", Action: selectSource, - Flags: append(CommonFlags, + Flags: []cli.Flag{ &cli.StringFlag{ Name: "source", Aliases: []string{"s"}, @@ -303,28 +298,25 @@ func main() { Aliases: []string{"a"}, Usage: "Source account for streaming services (optional)", }, - ), + }, Before: RequireHost, }, { Name: "spotify", Usage: "Select Spotify source", Action: selectSpotify, - Flags: CommonFlags, Before: RequireHost, }, { Name: "bluetooth", Usage: "Select Bluetooth source", Action: selectBluetooth, - Flags: CommonFlags, Before: RequireHost, }, { Name: "aux", Usage: "Select AUX input source", Action: selectAux, - Flags: CommonFlags, Before: RequireHost, }, }, @@ -339,50 +331,54 @@ func main() { Name: "get", Usage: "Get current bass level", Action: getBass, - Flags: CommonFlags, Before: RequireHost, }, { Name: "set", Usage: "Set bass level", Action: setBass, - Flags: append(CommonFlags, &cli.IntFlag{ - Name: "level", - Aliases: []string{"l"}, - Usage: "Bass level (-9 to 9)", - Required: true, - }), + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "level", + Aliases: []string{"l"}, + Usage: "Bass level (-9 to 9)", + Required: true, + }, + }, Before: RequireHost, }, { Name: "up", Usage: "Increase bass", Action: bassUp, - Flags: append(CommonFlags, &cli.IntFlag{ - Name: "amount", - Aliases: []string{"a"}, - Usage: "Amount to increase (1-5)", - Value: 1, - }), + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "amount", + Aliases: []string{"a"}, + Usage: "Amount to increase (1-5)", + Value: 1, + }, + }, Before: RequireHost, }, { Name: "down", Usage: "Decrease bass", Action: bassDown, - Flags: append(CommonFlags, &cli.IntFlag{ - Name: "amount", - Aliases: []string{"a"}, - Usage: "Amount to decrease (1-5)", - Value: 1, - }), + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "amount", + Aliases: []string{"a"}, + Usage: "Amount to decrease (1-5)", + Value: 1, + }, + }, Before: RequireHost, }, { Name: "capabilities", Usage: "Get bass capabilities", Action: getBassCapabilities, - Flags: CommonFlags, Before: RequireHost, }, }, @@ -397,50 +393,54 @@ func main() { Name: "get", Usage: "Get current balance level", Action: getBalance, - Flags: CommonFlags, Before: RequireHost, }, { Name: "set", Usage: "Set balance level", Action: setBalance, - Flags: append(CommonFlags, &cli.IntFlag{ - Name: "level", - Aliases: []string{"l"}, - Usage: "Balance level (-50 to 50, negative=left, positive=right)", - Required: true, - }), + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "level", + Aliases: []string{"l"}, + Usage: "Balance level (-50 to 50, negative=left, positive=right)", + Required: true, + }, + }, Before: RequireHost, }, { Name: "left", Usage: "Shift balance to the left", Action: balanceLeft, - Flags: append(CommonFlags, &cli.IntFlag{ - Name: "amount", - Aliases: []string{"a"}, - Usage: "Amount to shift left (1-10, default: 5)", - Value: 5, - }), + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "amount", + Aliases: []string{"a"}, + Usage: "Amount to shift left (1-10, default: 5)", + Value: 5, + }, + }, Before: RequireHost, }, { Name: "right", Usage: "Shift balance to the right", Action: balanceRight, - Flags: append(CommonFlags, &cli.IntFlag{ - Name: "amount", - Aliases: []string{"a"}, - Usage: "Amount to shift right (1-10, default: 5)", - Value: 5, - }), + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "amount", + Aliases: []string{"a"}, + Usage: "Amount to shift right (1-10, default: 5)", + Value: 5, + }, + }, Before: RequireHost, }, { Name: "center", Usage: "Center the balance", Action: balanceCenter, - Flags: CommonFlags, Before: RequireHost, }, }, @@ -455,26 +455,26 @@ func main() { Name: "get", Usage: "Get current time", Action: getClockTime, - Flags: CommonFlags, Before: RequireHost, }, { Name: "set", Usage: "Set clock time", Action: setClockTime, - Flags: append(CommonFlags, &cli.StringFlag{ - Name: "time", - Aliases: []string{"t"}, - Usage: "Time in HH:MM format or 'now' for current time", - Required: true, - }), + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "time", + Aliases: []string{"t"}, + Usage: "Time in HH:MM format or 'now' for current time", + Required: true, + }, + }, Before: RequireHost, }, { Name: "now", Usage: "Set clock to current system time", Action: setClockTimeNow, - Flags: CommonFlags, Before: RequireHost, }, { @@ -485,45 +485,46 @@ func main() { Name: "get", Usage: "Get display settings", Action: getClockDisplay, - Flags: CommonFlags, Before: RequireHost, }, { Name: "enable", Usage: "Enable clock display", Action: enableClockDisplay, - Flags: CommonFlags, Before: RequireHost, }, { Name: "disable", Usage: "Disable clock display", Action: disableClockDisplay, - Flags: CommonFlags, Before: RequireHost, }, { Name: "brightness", Usage: "Set display brightness", Action: setClockDisplayBrightness, - Flags: append(CommonFlags, &cli.StringFlag{ - Name: "brightness", - Aliases: []string{"b"}, - Usage: "Brightness level (low, medium, high, off)", - Required: true, - }), + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "brightness", + Aliases: []string{"b"}, + Usage: "Brightness level (low, medium, high, off)", + Required: true, + }, + }, Before: RequireHost, }, { Name: "format", Usage: "Set display format", Action: setClockDisplayFormat, - Flags: append(CommonFlags, &cli.StringFlag{ - Name: "format", - Aliases: []string{"f"}, - Usage: "Time format (12 or 24)", - Required: true, - }), + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "format", + Aliases: []string{"f"}, + Usage: "Time format (12 or 24)", + Required: true, + }, + }, Before: RequireHost, }, }, @@ -540,21 +541,18 @@ func main() { Name: "info", Usage: "Get network information", Action: getNetworkInfo, - Flags: CommonFlags, Before: RequireHost, }, { Name: "ping", Usage: "Ping the device", Action: pingDevice, - Flags: CommonFlags, Before: RequireHost, }, { Name: "url", Usage: "Get device base URL", Action: getDeviceURL, - Flags: CommonFlags, Before: RequireHost, }, }, @@ -569,71 +567,73 @@ func main() { Name: "get", Usage: "Get current zone configuration", Action: getZone, - Flags: CommonFlags, Before: RequireHost, }, { Name: "status", Usage: "Get zone status", Action: getZoneStatus, - Flags: CommonFlags, Before: RequireHost, }, { Name: "members", Usage: "List zone members", Action: getZoneMembers, - Flags: CommonFlags, Before: RequireHost, }, { Name: "create", Usage: "Create a new zone", Action: createZone, - Flags: append(CommonFlags, &cli.StringSliceFlag{ - Name: "members", - Aliases: []string{"m"}, - Usage: "Member IP addresses", - Required: true, - }), + Flags: []cli.Flag{ + &cli.StringSliceFlag{ + Name: "members", + Aliases: []string{"m"}, + Usage: "Member IP addresses", + Required: true, + }, + }, Before: RequireHost, }, { Name: "add", Usage: "Add device to zone", Action: addToZone, - Flags: append(CommonFlags, &cli.StringFlag{ - Name: "member", - Aliases: []string{"m"}, - Usage: "Member IP address to add", - Required: true, - }), + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "member", + Aliases: []string{"m"}, + Usage: "Member IP address to add", + Required: true, + }, + }, Before: RequireHost, }, { Name: "remove", Usage: "Remove device from zone", Action: removeFromZone, - Flags: append(CommonFlags, &cli.StringFlag{ - Name: "member", - Aliases: []string{"m"}, - Usage: "Member IP address to remove", - Required: true, - }), + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "member", + Aliases: []string{"m"}, + Usage: "Member IP address to remove", + Required: true, + }, + }, Before: RequireHost, }, { Name: "dissolve", Usage: "Dissolve the current zone", Action: dissolveZone, - Flags: CommonFlags, Before: RequireHost, }, { Name: "set", Usage: "Set zone configuration", Action: setZoneConfig, - Flags: append(CommonFlags, + Flags: []cli.Flag{ &cli.StringFlag{ Name: "master", Usage: "Master device IP address", @@ -644,7 +644,7 @@ func main() { Aliases: []string{"m"}, Usage: "Member IP addresses", }, - ), + }, Before: RequireHost, }, },