| 691 | var errSkillsListed = errors.New("skills listed") |
| 692 | |
| 693 | func selectSkillsWithSelector(opts *InstallOptions, skills []discovery.Skill, canPrompt bool, sel skillSelector) ([]discovery.Skill, error) { |
| 694 | checkCollisions := func(ss []discovery.Skill) error { |
| 695 | if err := collisionError(ss); err != nil { |
| 696 | fmt.Fprintf(opts.IO.ErrOut, "Hint: install individually using the full name: gh skill install %s namespace/skill-name\n", sel.sourceHint) |
| 697 | return err |
| 698 | } |
| 699 | return nil |
| 700 | } |
| 701 | |
| 702 | if opts.All { |
| 703 | if err := checkCollisions(skills); err != nil { |
| 704 | return nil, err |
| 705 | } |
| 706 | return skills, nil |
| 707 | } |
| 708 | |
| 709 | if opts.SkillName != "" { |
| 710 | return sel.matchByName(opts, skills) |
| 711 | } |
| 712 | |
| 713 | if !canPrompt { |
| 714 | if err := listAvailableSkills(opts, skills, sel); err != nil { |
| 715 | return nil, err |
| 716 | } |
| 717 | return nil, errSkillsListed |
| 718 | } |
| 719 | |
| 720 | if sel.fetchDescriptions != nil { |
| 721 | sel.fetchDescriptions() |
| 722 | } |
| 723 | |
| 724 | tw := opts.IO.TerminalWidth() |
| 725 | descWidth := tw - 35 |
| 726 | if descWidth < 20 { |
| 727 | descWidth = 20 |
| 728 | } |
| 729 | |
| 730 | selected, err := opts.Prompter.MultiSelectWithSearch( |
| 731 | "Select skill(s) to install:", |
| 732 | "Filter skills", |
| 733 | nil, |
| 734 | []string{allSkillsKey}, |
| 735 | skillSearchFunc(skills, descWidth), |
| 736 | ) |
| 737 | if err != nil { |
| 738 | return nil, err |
| 739 | } |
| 740 | |
| 741 | if len(selected) == 0 { |
| 742 | return nil, fmt.Errorf("must select at least one skill") |
| 743 | } |
| 744 | |
| 745 | for _, s := range selected { |
| 746 | if s == allSkillsKey { |
| 747 | if err := checkCollisions(skills); err != nil { |
| 748 | return nil, err |
| 749 | } |
| 750 | return skills, nil |