Skip to content

Commit cc41fe7

Browse files
committed
fix: duplicates, cursor positioning
1 parent ce4b3c2 commit cc41fe7

File tree

2 files changed

+63
-17
lines changed

2 files changed

+63
-17
lines changed

cli/cliui/select.go

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ type multiSelectModel struct {
378378
message string
379379
canceled bool
380380
selected bool
381-
isInputMode bool // New field to track if we're adding a custom option
381+
isCustomInputMode bool // New field to track if we're adding a custom option
382382
customInput string // New field to store custom input
383383
enableCustomInput bool // New field to control whether custom input is allowed
384384
}
@@ -391,7 +391,7 @@ func (multiSelectModel) Init() tea.Cmd {
391391
func (m multiSelectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
392392
var cmd tea.Cmd
393393

394-
if m.isInputMode {
394+
if m.isCustomInputMode {
395395
return m.handleCustomInputMode(msg)
396396
}
397397

@@ -409,7 +409,7 @@ func (m multiSelectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
409409
case tea.KeyEnter:
410410
// Switch to custom input mode if we're on the "+ Add custom value:" option
411411
if m.enableCustomInput && m.cursor == len(m.filteredOptions()) {
412-
m.isInputMode = true
412+
m.isCustomInputMode = true
413413
return m, nil
414414
}
415415
if len(m.options) != 0 {
@@ -427,17 +427,15 @@ func (m multiSelectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
427427
return m, nil
428428

429429
case tea.KeyUp:
430-
options := m.filteredOptions()
431-
maxIndex := len(options)
430+
maxIndex := m.getMaxIndex()
432431
if m.cursor > 0 {
433432
m.cursor--
434433
} else {
435434
m.cursor = maxIndex
436435
}
437436

438437
case tea.KeyDown:
439-
options := m.filteredOptions()
440-
maxIndex := len(options)
438+
maxIndex := m.getMaxIndex()
441439
if m.cursor < maxIndex {
442440
m.cursor++
443441
} else {
@@ -473,6 +471,16 @@ func (m multiSelectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
473471
return m, cmd
474472
}
475473

474+
func (m multiSelectModel) getMaxIndex() int {
475+
options := m.filteredOptions()
476+
if m.enableCustomInput {
477+
// Include the "+ Add custom value" entry
478+
return len(options)
479+
}
480+
// Includes only the actual options
481+
return len(options) - 1
482+
}
483+
476484
// handleCustomInputMode manages keyboard interactions when in custom input mode
477485
func (m *multiSelectModel) handleCustomInputMode(msg tea.Msg) (tea.Model, tea.Cmd) {
478486
keyMsg, ok := msg.(tea.KeyMsg)
@@ -499,15 +507,44 @@ func (m *multiSelectModel) handleCustomInputMode(msg tea.Msg) (tea.Model, tea.Cm
499507

500508
// handleCustomInputSubmission processes the submission of custom input
501509
func (m *multiSelectModel) handleCustomInputSubmission() (tea.Model, tea.Cmd) {
502-
if m.customInput != "" {
503-
m.options = append(m.options, &multiSelectOption{
504-
option: m.customInput,
505-
chosen: true,
506-
})
510+
if m.customInput == "" {
511+
m.isCustomInputMode = false
512+
return m, nil
513+
}
514+
515+
// Clear search to ensure option is visible and cursor points to the new option
516+
m.search.SetValue("")
517+
518+
// Check for duplicates
519+
for i, opt := range m.options {
520+
if strings.EqualFold(opt.option, m.customInput) {
521+
// If the option exists but isn't chosen, select it
522+
if !opt.chosen {
523+
opt.chosen = true
524+
}
525+
526+
// Point cursor to the new option
527+
m.cursor = i
528+
529+
// Reset custom input mode to disabled
530+
m.isCustomInputMode = false
531+
m.customInput = ""
532+
return m, nil
533+
}
507534
}
508-
// Reset input state regardless of whether input was empty
535+
536+
// Add new unique option
537+
m.options = append(m.options, &multiSelectOption{
538+
option: m.customInput,
539+
chosen: true,
540+
})
541+
542+
// Point cursor to the newly added option
543+
m.cursor = len(m.options) - 1
544+
545+
// Reset custom input mode to disabled
509546
m.customInput = ""
510-
m.isInputMode = false
547+
m.isCustomInputMode = false
511548
return m, nil
512549
}
513550

@@ -531,7 +568,7 @@ func (m multiSelectModel) View() string {
531568
return s.String()
532569
}
533570

534-
if m.isInputMode {
571+
if m.isCustomInputMode {
535572
_, _ = s.WriteString(fmt.Sprintf("%s\nEnter custom value: %s\n", msg, m.customInput))
536573
return s.String()
537574
}

cli/prompts.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ func (RootCmd) promptExample() *serpent.Command {
4141
Default: "",
4242
Value: serpent.StringArrayOf(&multiSelectValues),
4343
}
44+
45+
enableCustomInput bool
46+
enableCustomInputOption = serpent.Option{
47+
Name: "enable-custom-input",
48+
Description: "Enable custom input option in multi-select.",
49+
Required: false,
50+
Flag: "enable-custom-input",
51+
Value: serpent.BoolOf(&enableCustomInput),
52+
}
4453
)
4554
cmd := &serpent.Command{
4655
Use: "prompt-example",
@@ -159,12 +168,12 @@ func (RootCmd) promptExample() *serpent.Command {
159168
"Code", "Chairs", "Whale", "Diamond", "Carrot",
160169
},
161170
Defaults: []string{"Code"},
162-
EnableCustomInput: true,
171+
EnableCustomInput: enableCustomInput,
163172
})
164173
}
165174
_, _ = fmt.Fprintf(inv.Stdout, "%q are nice choices.\n", strings.Join(multiSelectValues, ", "))
166175
return multiSelectError
167-
}, useThingsOption),
176+
}, useThingsOption, enableCustomInputOption),
168177
promptCmd("rich-parameter", func(inv *serpent.Invocation) error {
169178
value, err := cliui.RichSelect(inv, cliui.RichSelectOptions{
170179
Options: []codersdk.TemplateVersionParameterOption{

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy