listAvailableSkills prints discovered skills as a table for non-interactive callers, mirroring the information shown in the interactive picker so the output can be browsed or piped into tools like grep.
(opts *InstallOptions, skills []discovery.Skill, sel skillSelector)
| 763 | // callers, mirroring the information shown in the interactive picker so the |
| 764 | // output can be browsed or piped into tools like grep. |
| 765 | func listAvailableSkills(opts *InstallOptions, skills []discovery.Skill, sel skillSelector) error { |
| 766 | if len(skills) == 0 { |
| 767 | return fmt.Errorf("no skills found in %s", sel.sourceHint) |
| 768 | } |
| 769 | |
| 770 | if sel.fetchDescriptions != nil { |
| 771 | sel.fetchDescriptions() |
| 772 | } |
| 773 | |
| 774 | if opts.IO.IsStdoutTTY() { |
| 775 | fmt.Fprintf(opts.IO.ErrOut, "Showing %s from %s. Re-run with a skill name to install.\n\n", |
| 776 | text.Pluralize(len(skills), "skill"), sel.sourceHint) |
| 777 | } |
| 778 | |
| 779 | tw := opts.IO.TerminalWidth() |
| 780 | descWidth := max(tw-40, 20) |
| 781 | isTTY := opts.IO.IsStdoutTTY() |
| 782 | |
| 783 | table := tableprinter.New(opts.IO, tableprinter.WithHeader("SKILL", "DESCRIPTION")) |
| 784 | for _, s := range skills { |
| 785 | table.AddField(s.DisplayName()) |
| 786 | desc := s.Description |
| 787 | if isTTY { |
| 788 | desc = text.Truncate(descWidth, desc) |
| 789 | } |
| 790 | table.AddField(desc) |
| 791 | table.EndRow() |
| 792 | } |
| 793 | return table.Render() |
| 794 | } |
| 795 | |
| 796 | func matchSkillByName(opts *InstallOptions, skills []discovery.Skill) ([]discovery.Skill, error) { |
| 797 | for _, s := range skills { |
no test coverage detected