skillSearchFunc returns a search function for MultiSelectWithSearch that filters skills by case-insensitive substring match on name and description.
(skills []discovery.Skill, descWidth int)
| 838 | // skillSearchFunc returns a search function for MultiSelectWithSearch that |
| 839 | // filters skills by case-insensitive substring match on name and description. |
| 840 | func skillSearchFunc(skills []discovery.Skill, descWidth int) func(string) prompter.MultiSelectSearchResult { |
| 841 | return func(query string) prompter.MultiSelectSearchResult { |
| 842 | var matched []discovery.Skill |
| 843 | if query == "" { |
| 844 | matched = skills |
| 845 | } else { |
| 846 | q := strings.ToLower(query) |
| 847 | for _, s := range skills { |
| 848 | if strings.Contains(strings.ToLower(s.DisplayName()), q) || |
| 849 | strings.Contains(strings.ToLower(s.Description), q) { |
| 850 | matched = append(matched, s) |
| 851 | } |
| 852 | } |
| 853 | } |
| 854 | |
| 855 | more := 0 |
| 856 | if len(matched) > maxSearchResults { |
| 857 | more = len(matched) - maxSearchResults |
| 858 | matched = matched[:maxSearchResults] |
| 859 | } |
| 860 | |
| 861 | keys := make([]string, len(matched)) |
| 862 | labels := make([]string, len(matched)) |
| 863 | for i, s := range matched { |
| 864 | keys[i] = s.DisplayName() |
| 865 | if s.Description != "" { |
| 866 | labels[i] = fmt.Sprintf("%s - %s", s.DisplayName(), truncateDescription(s.Description, descWidth)) |
| 867 | } else { |
| 868 | labels[i] = s.DisplayName() |
| 869 | } |
| 870 | } |
| 871 | |
| 872 | return prompter.MultiSelectSearchResult{ |
| 873 | Keys: keys, |
| 874 | Labels: labels, |
| 875 | MoreResults: more, |
| 876 | } |
| 877 | } |
| 878 | } |
| 879 | |
| 880 | // matchSelectedSkills maps display names back to skill structs. |
| 881 | func matchSelectedSkills(skills []discovery.Skill, selected []string) ([]discovery.Skill, error) { |
no test coverage detected