From ad25bd76715cbb35c0d179d69ffd6167f65c5697 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 15:39:27 +0000 Subject: [PATCH] feat(cli): add interactive platform selection to `exfig init` Improves the UX of `exfig init` by: 1. Making the `--platform` argument optional. 2. Prompting the user to select a platform interactively if the argument is missing and the session is TTY. 3. Added `CaseIterable` to `Platform` enum in `ExFigCore` to support listing options. This resolves the issue where running `exfig init` without arguments would immediately fail with a missing argument error, making it friendlier for new users. --- .../Subcommands/GenerateConfigFile.swift | 38 ++++++++++++++++++- Sources/ExFigCore/Platform.swift | 2 +- mise.lock | 5 +++ mise.toml | 1 + 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/Sources/ExFig/Subcommands/GenerateConfigFile.swift b/Sources/ExFig/Subcommands/GenerateConfigFile.swift index f73039a5..01c741e6 100644 --- a/Sources/ExFig/Subcommands/GenerateConfigFile.swift +++ b/Sources/ExFig/Subcommands/GenerateConfigFile.swift @@ -22,13 +22,15 @@ extension ExFigCommand { var globalOptions: GlobalOptions @Option(name: .shortAndLong, help: "Platform: ios or android.") - var platform: Platform + var platform: Platform? func run() async throws { ExFigCommand.initializeTerminalUI(verbose: globalOptions.verbose, quiet: globalOptions.quiet) let ui = ExFigCommand.terminalUI! - let fileContents: String = switch platform { + let selectedPlatform = try resolvePlatform(ui: ui) + + let fileContents: String = switch selectedPlatform { case .android: androidConfigFileContents case .ios: @@ -51,6 +53,38 @@ extension ExFigCommand { try writeConfigFile(contents: fileContents, to: destination, ui: ui) } + private func resolvePlatform(ui: TerminalUI) throws -> Platform { + if let platform { + return platform + } + + if !TTYDetector.isTTY { + throw ExFigError + .custom(errorString: "Missing expected argument '--platform '") + } + + ui.info("Select a platform:") + let platforms = Platform.allCases + for (index, p) in platforms.enumerated() { + ui.info("\(index + 1). \(p.rawValue)") + } + + TerminalOutputManager.shared.writeDirect("Enter number or name: ") + ANSICodes.flushStdout() + + guard let input = readLine()?.trimmingCharacters(in: .whitespacesAndNewlines) else { + throw ExFigError.custom(errorString: "Operation cancelled") + } + + if let index = Int(input), index > 0, index <= platforms.count { + return platforms[index - 1] + } else if let p = Platform(rawValue: input.lowercased()) { + return p + } else { + throw ExFigError.custom(errorString: "Invalid selection") + } + } + /// Handles existing file: prompts for confirmation and removes if approved. /// - Returns: `true` to proceed with overwrite, `false` if user cancelled private func handleExistingFile(at destination: String, ui: TerminalUI) throws -> Bool { diff --git a/Sources/ExFigCore/Platform.swift b/Sources/ExFigCore/Platform.swift index ebe298ba..f3af2d39 100644 --- a/Sources/ExFigCore/Platform.swift +++ b/Sources/ExFigCore/Platform.swift @@ -4,7 +4,7 @@ import Foundation /// /// ExFig supports exporting to both iOS (Xcode) and Android (Android Studio) projects. /// The platform affects naming conventions, output formats, and generated code. -public enum Platform: String, Sendable { +public enum Platform: String, Sendable, CaseIterable { /// iOS/iPadOS/macOS platform (Xcode projects). /// Generates xcassets, Swift extensions for UIKit and SwiftUI. case ios diff --git a/mise.lock b/mise.lock index e8d8b629..4dc7ba36 100644 --- a/mise.lock +++ b/mise.lock @@ -41,6 +41,11 @@ backend = "aqua:apple/pkl" "platforms.macos-x64" = { checksum = "sha256:5f62ae7a7a34c15b3a83af17bda8e6b98516953f383a492340d4aa090caaa6d9", url = "https://github.com/apple/pkl/releases/download/0.30.2/pkl-macos-amd64"} "platforms.windows-x64" = { checksum = "sha256:19e92aa59bcf4e54963b6e3b419af7e1b939f5793b44f4a08d60bab1217106f4", url = "https://github.com/apple/pkl/releases/download/0.30.2/pkl-windows-amd64.exe"} +[[tools.swift]] +version = "6.2.3" +backend = "core:swift" +"platforms.linux-x64" = { checksum = "blake3:0857a2267c52dc00ff1b59b93530a4316d3f99884744f4f75661fcbbea8a414b"} + [[tools.swiftformat]] version = "0.58.7" backend = "asdf:swiftformat" diff --git a/mise.toml b/mise.toml index cbffebf3..1238464d 100644 --- a/mise.toml +++ b/mise.toml @@ -38,6 +38,7 @@ git-cliff = "2.10.1" # Changelog generation # --- Configuration --- pkl = "0.30.2" # Configuration language (for hk.pkl) +swift = "6.2.3" # ============================================================================= # Tasks