| 382 | } |
| 383 | |
| 384 | func MultiSelect(inv *serpent.Invocation, opts MultiSelectOptions) ([]string, error) { |
| 385 | // Similar hack is applied to Select() |
| 386 | if flag.Lookup("test.v") != nil { |
| 387 | return opts.Defaults, nil |
| 388 | } |
| 389 | |
| 390 | options := make([]*multiSelectOption, len(opts.Options)) |
| 391 | for i, option := range opts.Options { |
| 392 | chosen := false |
| 393 | for _, d := range opts.Defaults { |
| 394 | if option == d { |
| 395 | chosen = true |
| 396 | break |
| 397 | } |
| 398 | } |
| 399 | |
| 400 | options[i] = &multiSelectOption{ |
| 401 | option: option, |
| 402 | chosen: chosen, |
| 403 | } |
| 404 | } |
| 405 | |
| 406 | initialModel := multiSelectModel{ |
| 407 | search: textinput.New(), |
| 408 | options: options, |
| 409 | message: opts.Message, |
| 410 | enableCustomInput: opts.EnableCustomInput, |
| 411 | } |
| 412 | |
| 413 | initialModel.search.Prompt = "" |
| 414 | initialModel.search.Focus() |
| 415 | |
| 416 | p := tea.NewProgram( |
| 417 | initialModel, |
| 418 | tea.WithoutSignalHandler(), |
| 419 | tea.WithContext(inv.Context()), |
| 420 | tea.WithInput(inv.Stdin), |
| 421 | tea.WithOutput(inv.Stdout), |
| 422 | ) |
| 423 | |
| 424 | closeSignalHandler := installSignalHandler(p) |
| 425 | defer closeSignalHandler() |
| 426 | |
| 427 | m, err := p.Run() |
| 428 | if err != nil { |
| 429 | return nil, err |
| 430 | } |
| 431 | |
| 432 | model, ok := m.(multiSelectModel) |
| 433 | if !ok { |
| 434 | return nil, xerrors.New(fmt.Sprintf("unknown model found %T (%+v)", m, m)) |
| 435 | } |
| 436 | |
| 437 | if model.canceled { |
| 438 | return nil, ErrCanceled |
| 439 | } |
| 440 | |
| 441 | return model.selectedOptions(), nil |