Skip to content

Commit 14bdcc4

Browse files
committed
Enhanced SwiftCommitGen Command Processing and Configuration
This commit introduces significant improvements to SwiftCommitGen by adding new command processing capabilities and configuration options. The addition of ConfigCommand.swift enhances batch processing of SwiftCommitGen commands, improving efficiency and scalability. UserConfiguration.swift now includes a 'defaultGenerationMode' property, enhancing configuration flexibility. GenerateCommand.swift introduces a new flag for processing each file independently, providing granular control over commit generation. These changes collectively increase flexibility, control, and efficiency in managing multiple files and configurations within SwiftCommitGen.
1 parent 5697e5e commit 14bdcc4

File tree

3 files changed

+142
-2
lines changed

3 files changed

+142
-2
lines changed

Sources/SwiftCommitGen/ConfigCommand.swift

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,20 @@ import Foundation
88
#endif
99

1010
struct ConfigCommand: ParsableCommand {
11+
enum GenerationModeOption: String, ExpressibleByArgument, Codable {
12+
case automatic
13+
case perFile = "per-file"
14+
15+
var mode: CommitGenOptions.GenerationMode {
16+
switch self {
17+
case .automatic:
18+
return .automatic
19+
case .perFile:
20+
return .perFile
21+
}
22+
}
23+
}
24+
1125
struct Dependencies {
1226
var makeStore: () -> any ConfigCommandStore
1327
var makeIO: () -> any ConfigCommandIO
@@ -49,6 +63,12 @@ struct ConfigCommand: ParsableCommand {
4963
@Flag(name: .customLong("clear-quiet"), help: "Remove the stored quiet preference.")
5064
var clearQuiet: Bool = false
5165

66+
@Option(name: .long, help: "Set the default generation mode (automatic|per-file).")
67+
var mode: GenerationModeOption?
68+
69+
@Flag(name: .customLong("clear-mode"), help: "Remove the stored generation mode preference.")
70+
var clearMode: Bool = false
71+
5272
func run() throws {
5373
try validateOptions()
5474
let dependencies = ConfigCommand.resolveDependencies()
@@ -97,6 +117,9 @@ struct ConfigCommand: ParsableCommand {
97117
if let verboseSetting = verbose, let quietSetting = quiet, verboseSetting && quietSetting {
98118
throw ValidationError("Cannot set both --verbose true and --quiet true.")
99119
}
120+
if mode != nil && clearMode {
121+
throw ValidationError("Cannot use --mode together with --clear-mode.")
122+
}
100123
}
101124

102125
private var shouldRunInteractively: Bool {
@@ -107,6 +130,8 @@ struct ConfigCommand: ParsableCommand {
107130
&& !clearVerbose
108131
&& quiet == nil
109132
&& !clearQuiet
133+
&& mode == nil
134+
&& !clearMode
110135
}
111136

112137
private func applyDirectUpdates(to configuration: inout UserConfiguration) -> Bool {
@@ -159,6 +184,27 @@ struct ConfigCommand: ParsableCommand {
159184
}
160185
}
161186

187+
if clearMode {
188+
if configuration.defaultGenerationMode != nil {
189+
configuration.defaultGenerationMode = nil
190+
changed = true
191+
}
192+
}
193+
if let modeSelection = mode?.mode {
194+
switch modeSelection {
195+
case .automatic:
196+
if configuration.defaultGenerationMode != nil {
197+
configuration.defaultGenerationMode = nil
198+
changed = true
199+
}
200+
case .perFile:
201+
if configuration.defaultGenerationMode != .perFile {
202+
configuration.defaultGenerationMode = .perFile
203+
changed = true
204+
}
205+
}
206+
}
207+
162208
return changed
163209
}
164210

@@ -208,6 +254,23 @@ struct ConfigCommand: ParsableCommand {
208254
],
209255
theme: theme
210256
)
257+
258+
let currentMode = configuration.defaultGenerationMode ?? .automatic
259+
let automaticNote =
260+
currentMode == .automatic && configuration.defaultGenerationMode == nil ? "(default)" : nil
261+
printPreference(
262+
title: "Generation mode",
263+
choices: [
264+
DisplayChoice(
265+
name: "automatic",
266+
isCurrent: currentMode == .automatic,
267+
isRecommended: true,
268+
note: automaticNote
269+
),
270+
DisplayChoice(name: "per-file", isCurrent: currentMode == .perFile),
271+
],
272+
theme: theme
273+
)
211274
}
212275
}
213276

@@ -365,10 +428,22 @@ struct ConfigInteractiveEditor {
365428
}
366429
}
367430

431+
if let modeChoice = promptForGenerationMode(current: configuration.defaultGenerationMode) {
432+
switch modeChoice {
433+
case .automatic:
434+
updated.defaultGenerationMode = nil
435+
case .perFile:
436+
updated.defaultGenerationMode = .perFile
437+
case .clear:
438+
updated.defaultGenerationMode = nil
439+
}
440+
}
441+
368442
let changed =
369443
updated.autoStageIfNoStaged != original.autoStageIfNoStaged
370444
|| updated.defaultVerbose != original.defaultVerbose
371445
|| updated.defaultQuiet != original.defaultQuiet
446+
|| updated.defaultGenerationMode != original.defaultGenerationMode
372447

373448
return (updated, changed)
374449
}
@@ -474,6 +549,61 @@ struct ConfigInteractiveEditor {
474549
)
475550
}
476551

552+
private func promptForGenerationMode(
553+
current: CommitGenOptions.GenerationMode?
554+
) -> GenerationModeChoice? {
555+
let currentMode = current ?? .automatic
556+
let description: String = {
557+
switch currentMode {
558+
case .automatic:
559+
return "automatic"
560+
case .perFile:
561+
return "per-file"
562+
}
563+
}()
564+
565+
let choices: [Choice<GenerationModeChoice>] = [
566+
Choice(
567+
label: "1",
568+
tokens: ["1", "automatic", "auto", "a"],
569+
description: "automatic",
570+
value: .automatic,
571+
isRecommended: true
572+
),
573+
Choice(
574+
label: "2",
575+
tokens: ["2", "per-file", "perfile", "p"],
576+
description: "per-file",
577+
value: .perFile
578+
),
579+
Choice(
580+
label: "",
581+
tokens: ["clear", "reset"],
582+
description: "",
583+
value: .clear,
584+
isVisible: false
585+
),
586+
]
587+
588+
return promptChoice(
589+
title: "Generation mode",
590+
currentDescription: description,
591+
choices: choices,
592+
keepMessage: "Press Enter to keep current generation mode.",
593+
isCurrent: { choiceValue in
594+
switch (choiceValue, currentMode) {
595+
case (.automatic, .automatic), (.perFile, .perFile):
596+
return true
597+
default:
598+
return false
599+
}
600+
},
601+
additionalInstructions: [
602+
"Type 'clear' to remove the stored preference and fall back to automatic mode."
603+
]
604+
)
605+
}
606+
477607
private func promptChoice<Value>(
478608
title: String,
479609
currentDescription: String,
@@ -545,4 +675,10 @@ struct ConfigInteractiveEditor {
545675
case verbose
546676
case quiet
547677
}
678+
679+
private enum GenerationModeChoice {
680+
case automatic
681+
case perFile
682+
case clear
683+
}
548684
}

Sources/SwiftCommitGen/Core/UserConfiguration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ struct UserConfiguration: Codable {
44
var autoStageIfNoStaged: Bool?
55
var defaultVerbose: Bool?
66
var defaultQuiet: Bool?
7+
var defaultGenerationMode: CommitGenOptions.GenerationMode?
78
}
89

910
struct UserConfigurationStore {

Sources/SwiftCommitGen/GenerateCommand.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ struct GenerateCommand: AsyncParsableCommand {
5050

5151
@Flag(
5252
name: .customLong("single-file"),
53-
help: "Process each file independently before combining the drafts into a single commit message."
53+
help:
54+
"Process each file independently before combining the drafts into a single commit message."
5455
)
5556
private var singleFile: Bool = false
5657

@@ -86,7 +87,9 @@ struct GenerateCommand: AsyncParsableCommand {
8687
quietPreference = nil
8788
}
8889

89-
let generationMode: CommitGenOptions.GenerationMode = singleFile ? .perFile : .automatic
90+
let configuredGenerationMode = userConfig.defaultGenerationMode ?? .automatic
91+
let generationMode: CommitGenOptions.GenerationMode =
92+
singleFile ? .perFile : configuredGenerationMode
9093

9194
let autoCommit = commit
9295
let stageAllBeforeGenerating = stagePreference ?? false

0 commit comments

Comments
 (0)