From 7ed395cfd5e7a306c1bb3c075b4f66dd36f10243 Mon Sep 17 00:00:00 2001 From: jonnii Date: Thu, 4 Jun 2026 23:30:20 -0400 Subject: [PATCH] refactor(create): route insert's child-select prompt through the Handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit handleInsert prompted the user (tui.PromptSelect) to choose which child branch to move onto a newly inserted branch — importing internal/tui into the action layer. create already has a Handler with prompt methods (PromptStageChanges, PromptScope) implemented by the CLI handlers, so add a PromptChildToMove(children) method the same way: - create.Handler + NullHandler gain PromptChildToMove (null returns "all"). - The CLI SimpleCreateHandler returns "all"; InteractiveCreateHandler builds the select options and calls tui.PromptSelect. - handleInsert takes the handler and calls h.PromptChildToMove, gated on h.IsInteractive() (replacing the inline utils.IsInteractive + tui usage). create/insert.go no longer imports internal/tui or internal/utils (now 9 tui-importing action files). Behavior preserved (lint, create unit tests, integration 494). --- internal/actions/create/create.go | 2 +- internal/actions/create/handler.go | 8 ++++++++ internal/actions/create/insert.go | 15 +++------------ internal/cli/branch/create_handlers.go | 16 ++++++++++++++++ 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/internal/actions/create/create.go b/internal/actions/create/create.go index 8ef566c0b..85830bcb7 100644 --- a/internal/actions/create/create.go +++ b/internal/actions/create/create.go @@ -265,7 +265,7 @@ func Action(ctx *app.Context, opts Options, h Handler) (Result, error) { // Handle insert logic if opts.Insert { h.OnStep(StepInsert, handler.StatusStarted, "Inserting branch into stack") - if err := handleInsert(ctx.Context, branchName, currentBranch, ctx, &opts); err != nil { + if err := handleInsert(ctx.Context, branchName, currentBranch, ctx, &opts, h); err != nil { h.OnStep(StepInsert, handler.StatusFailed, err.Error()) out.Info("Warning: failed to insert branch: %v", err) } else { diff --git a/internal/actions/create/handler.go b/internal/actions/create/handler.go index cbe24a185..e9422ee9a 100644 --- a/internal/actions/create/handler.go +++ b/internal/actions/create/handler.go @@ -48,6 +48,11 @@ type Handler interface { // PromptScope prompts user for a scope value when pattern contains {scope} // The patternHint shows the current branch pattern to the user PromptScope(patternHint string) (string, error) + + // PromptChildToMove asks which of the current branch's children should be + // moved onto a newly inserted branch. Returns "all" to move every child, or + // a specific child name. Only called when IsInteractive() is true. + PromptChildToMove(children []string) (string, error) } // NullHandler is a no-op handler for when nil is passed @@ -67,3 +72,6 @@ func (h *NullHandler) PromptStageChanges() (bool, error) { return false, nil } // PromptScope implements Handler. func (h *NullHandler) PromptScope(_ string) (string, error) { return "", nil } + +// PromptChildToMove implements Handler. Returns "all" (move every child). +func (h *NullHandler) PromptChildToMove(_ []string) (string, error) { return "all", nil } diff --git a/internal/actions/create/insert.go b/internal/actions/create/insert.go index 1fd91fa4f..fa9d94aee 100644 --- a/internal/actions/create/insert.go +++ b/internal/actions/create/insert.go @@ -6,11 +6,9 @@ import ( "github.com/getstackit/stackit/internal/app" "github.com/getstackit/stackit/internal/engine" - "github.com/getstackit/stackit/internal/tui" - "github.com/getstackit/stackit/internal/utils" ) -func handleInsert(ctx context.Context, newBranch, currentBranch string, runtimeCtx *app.Context, opts *Options) error { +func handleInsert(ctx context.Context, newBranch, currentBranch string, runtimeCtx *app.Context, opts *Options, h Handler) error { // Build StackGraph for efficient traversals graph := runtimeCtx.Engine.Graph(engine.SortStrategyAlphabetical) @@ -39,16 +37,9 @@ func handleInsert(ctx context.Context, newBranch, currentBranch string, runtimeC } } } - case len(siblings)> 1 && utils.IsInteractive(): + case len(siblings)> 1 && h.IsInteractive(): runtimeCtx.Output.Info("Current branch has multiple children. Select which should be moved onto the new branch:") - options := []tui.SelectOption{ - {Label: "All children", Value: "all"}, - } - for _, child := range siblings { - options = append(options, tui.SelectOption{Label: child, Value: child}) - } - - selected, err := tui.PromptSelect("Which child should be moved onto the new branch?", options, 0) + selected, err := h.PromptChildToMove(siblings) if err != nil { return err } diff --git a/internal/cli/branch/create_handlers.go b/internal/cli/branch/create_handlers.go index 14e3ce041..80bbf9a0c 100644 --- a/internal/cli/branch/create_handlers.go +++ b/internal/cli/branch/create_handlers.go @@ -82,6 +82,11 @@ func (h *SimpleCreateHandler) PromptScope(_ string) (string, error) { return "", nil } +// PromptChildToMove returns "all" for the simple handler (non-interactive). +func (h *SimpleCreateHandler) PromptChildToMove(_ []string) (string, error) { + return "all", nil +} + func (h *SimpleCreateHandler) printStepCompleted(_ create.Step, _ string) { // Most steps are silent - output is handled in Complete // Only show certain steps for verbose feedback @@ -113,3 +118,14 @@ func (h *InteractiveCreateHandler) PromptScope(patternHint string) (string, erro prompt := fmt.Sprintf("Branch pattern uses {scope}: %s\nEnter scope (or Enter to skip):", patternHint) return tui.PromptTextInput(prompt, "") } + +// PromptChildToMove asks which child branch to move onto the newly inserted +// branch, offering an "All children" option plus each child individually. +func (h *InteractiveCreateHandler) PromptChildToMove(children []string) (string, error) { + options := make([]tui.SelectOption, 0, 1+len(children)) + options = append(options, tui.SelectOption{Label: "All children", Value: "all"}) + for _, child := range children { + options = append(options, tui.SelectOption{Label: child, Value: child}) + } + return tui.PromptSelect("Which child should be moved onto the new branch?", options, 0) +}

AltStyle によって変換されたページ (->オリジナル) /