@@ -43,6 +43,32 @@ type AdvanceCreateFlowOptions = {
4343 readonly quickCreate ?: boolean
4444}
4545
46+ /**
47+ * Direction over the finite ordered set of unresolved Create settings rows.
48+ *
49+ * @pure true
50+ * @effect none
51+ * @invariant value ∈ {"up", "down"}
52+ * @precondition n/a
53+ * @postcondition navigation direction is total for settings rows
54+ * @complexity O(1)
55+ */
56+ export type CreateSettingsNavigationDirection = "up" | "down"
57+
58+ /**
59+ * User-facing key guide shown only after Create leaves the repo URL step.
60+ *
61+ * @pure true
62+ * @effect none
63+ * @invariant hint contains the complete settings-mode key contract
64+ * @precondition CreateFlowView.step > 0
65+ * @postcondition no repo-step quick-create guidance is rendered from this value
66+ * @complexity O(1)
67+ */
68+ export const createSettingsHint = "↑ - up, ↓ - down, Enter - apply"
69+
70+ const firstCreateSettingsStepIndex = 1
71+
4672const trimLeftSlash = ( value : string ) : string => {
4773 let start = 0
4874 while ( start < value . length && value [ start ] === "/" ) {
@@ -462,6 +488,65 @@ const continueCreateFlow = (
462488 }
463489} )
464490
491+ const clampCreateSettingsStep = (
492+ step : number ,
493+ lastStep : number
494+ ) : number => Math . min ( Math . max ( step , firstCreateSettingsStepIndex ) , lastStep )
495+
496+ const nextCreateSettingsStep = (
497+ step : number ,
498+ lastStep : number ,
499+ direction : CreateSettingsNavigationDirection
500+ ) : number =>
501+ Match . value ( direction ) . pipe (
502+ Match . when ( "up" , ( ) => step === firstCreateSettingsStepIndex ? lastStep : step - 1 ) ,
503+ Match . when ( "down" , ( ) => step === lastStep ? firstCreateSettingsStepIndex : step + 1 ) ,
504+ Match . exhaustive
505+ )
506+
507+ /**
508+ * Moves the selected Create settings row without applying the current buffer.
509+ *
510+ * @pure true
511+ * @effect none
512+ * @invariant view.step = 0 -> result = null
513+ * @invariant result != null -> 1 <= result.step < |resolveCreateFlowSteps(result.values)|
514+ * @invariant result != null && result.step != view.step -> result.buffer = ""
515+ * @precondition view is a CreateFlowView snapshot
516+ * @postcondition result values are identical to the input values
517+ * @complexity O(n) where n is the number of unresolved Create steps
518+ */
519+ export const moveCreateSettingsStep = (
520+ view : CreateFlowView ,
521+ direction : CreateSettingsNavigationDirection
522+ ) : CreateFlowView | null => {
523+ const steps = resolveCreateFlowSteps ( view . values )
524+ const lastStep = steps . length - 1
525+ if ( view . step < firstCreateSettingsStepIndex || lastStep < firstCreateSettingsStepIndex ) {
526+ return null
527+ }
528+
529+ const currentStep = clampCreateSettingsStep ( view . step , lastStep )
530+ const step = nextCreateSettingsStep ( currentStep , lastStep , direction )
531+ if ( step === view . step ) {
532+ return view
533+ }
534+ return {
535+ ...view ,
536+ step,
537+ buffer : ""
538+ }
539+ }
540+
541+ const resolveNextCreateFlowStep = (
542+ currentStep : CreateStep ,
543+ currentStepIndex : number ,
544+ nextSteps : ReadonlyArray < CreateStep >
545+ ) : number =>
546+ currentStep === "repoUrl"
547+ ? firstCreateSettingsStepIndex
548+ : clampCreateSettingsStep ( currentStepIndex , nextSteps . length - 1 )
549+
465550export const advanceCreateFlow = (
466551 contextOrCwd : string | CreateFlowContext ,
467552 view : CreateFlowView ,
@@ -499,8 +584,8 @@ export const advanceCreateFlow = (
499584 }
500585
501586 const nextSteps = resolveCreateFlowSteps ( nextValues )
502- const nextStep = step === "repoUrl" ? 1 : view . step
503- if ( nextStep < nextSteps . length ) {
587+ const nextStep = resolveNextCreateFlowStep ( step , view . step , nextSteps )
588+ if ( nextSteps . length > firstCreateSettingsStepIndex && nextStep < nextSteps . length ) {
504589 return continueCreateFlow ( nextStep , nextValues )
505590 }
506591
0 commit comments