@@ -8,6 +8,20 @@ import Foundation
88#endif
99
1010struct 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}
0 commit comments