@@ -23,7 +23,6 @@ import (
2323 "github.com/arduino/arduino-cli/arduino"
2424 "github.com/arduino/arduino-cli/arduino/libraries/librariesindex"
2525 "github.com/arduino/arduino-cli/arduino/libraries/librariesmanager"
26- "github.com/arduino/arduino-cli/arduino/utils"
2726 "github.com/arduino/arduino-cli/commands/internal/instances"
2827 rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
2928 semver "go.bug.st/relaxed-semver"
@@ -38,128 +37,14 @@ func LibrarySearch(ctx context.Context, req *rpc.LibrarySearchRequest) (*rpc.Lib
3837 return searchLibrary (req , lm ), nil
3938}
4039
41- // matcherTokensFromQueryString parses the query string into tokens of interest
42- // for the qualifier-value pattern matching.
43- func matcherTokensFromQueryString (query string ) []string {
44- escaped := false
45- quoted := false
46- tokens := []string {}
47- sb := & strings.Builder {}
48-
49- for _ , r := range query {
50- // Short circuit the loop on backslash so that all other paths can clear
51- // the escaped flag.
52- if ! escaped && r == '\\' {
53- escaped = true
54- continue
55- }
56-
57- if r == '"' {
58- if ! escaped {
59- quoted = ! quoted
60- } else {
61- sb .WriteRune (r )
62- }
63- } else if ! quoted && r == ' ' {
64- tokens = append (tokens , strings .ToLower (sb .String ()))
65- sb .Reset ()
66- } else {
67- sb .WriteRune (r )
68- }
69- escaped = false
70- }
71- if sb .Len () > 0 {
72- tokens = append (tokens , strings .ToLower (sb .String ()))
73- }
74-
75- return tokens
76- }
77-
78- // defaulLibraryMatchExtractor returns a string describing the library that
79- // is used for the simple search.
80- func defaultLibraryMatchExtractor (lib * librariesindex.Library ) string {
81- res := lib .Name + " " +
82- lib .Latest .Paragraph + " " +
83- lib .Latest .Sentence + " " +
84- lib .Latest .Author + " "
85- for _ , include := range lib .Latest .ProvidesIncludes {
86- res += include + " "
87- }
88- return res
89- }
90-
91- var qualifiers map [string ]func (lib * librariesindex.Library ) string = map [string ]func (lib * librariesindex.Library ) string {
92- "name" : func (lib * librariesindex.Library ) string { return lib .Name },
93- "architectures" : func (lib * librariesindex.Library ) string { return strings .Join (lib .Latest .Architectures , " " ) },
94- "author" : func (lib * librariesindex.Library ) string { return lib .Latest .Author },
95- "category" : func (lib * librariesindex.Library ) string { return lib .Latest .Category },
96- "dependencies" : func (lib * librariesindex.Library ) string {
97- names := make ([]string , len (lib .Latest .Dependencies ))
98- for i , dep := range lib .Latest .Dependencies {
99- names [i ] = dep .GetName ()
100- }
101- return strings .Join (names , " " )
102- },
103- "maintainer" : func (lib * librariesindex.Library ) string { return lib .Latest .Maintainer },
104- "paragraph" : func (lib * librariesindex.Library ) string { return lib .Latest .Paragraph },
105- "sentence" : func (lib * librariesindex.Library ) string { return lib .Latest .Sentence },
106- "types" : func (lib * librariesindex.Library ) string { return strings .Join (lib .Latest .Types , " " ) },
107- "version" : func (lib * librariesindex.Library ) string { return lib .Latest .Version .String () },
108- "website" : func (lib * librariesindex.Library ) string { return lib .Latest .Website },
109- }
110-
111- // matcherFromQueryString returns a closure that takes a library as a
112- // parameter and returns true if the library matches the query.
113- func matcherFromQueryString (query string ) func (* librariesindex.Library ) bool {
114- // A qv-query is one using <qualifier>[:=]<value> syntax.
115- qvQuery := strings .Contains (query , ":" ) || strings .Contains (query , "=" )
116-
117- if ! qvQuery {
118- queryTerms := utils .SearchTermsFromQueryString (query )
119- return func (lib * librariesindex.Library ) bool {
120- return utils .Match (defaultLibraryMatchExtractor (lib ), queryTerms )
121- }
122- }
123-
124- queryTerms := matcherTokensFromQueryString (query )
125-
126- return func (lib * librariesindex.Library ) bool {
127- matched := true
128- for _ , term := range queryTerms {
129-
130- if sepIdx := strings .IndexAny (term , "=:" ); sepIdx != - 1 {
131- potentialKey := term [:sepIdx ]
132- separator := term [sepIdx ]
133-
134- extractor , ok := qualifiers [potentialKey ]
135- if ok {
136- target := term [sepIdx + 1 :]
137- if separator == ':' {
138- matched = (matched && utils .Match (extractor (lib ), []string {target }))
139- } else { // "="
140- matched = (matched && strings .ToLower (extractor (lib )) == target )
141- }
142- } else {
143- // Unknown qualifier names revert to basic search terms.
144- matched = (matched && utils .Match (defaultLibraryMatchExtractor (lib ), []string {term }))
145- }
146- } else {
147- // Terms that do not use qv-syntax are handled as usual.
148- matched = (matched && utils .Match (defaultLibraryMatchExtractor (lib ), []string {term }))
149- }
150- }
151- return matched
152- }
153- }
154-
15540func searchLibrary (req * rpc.LibrarySearchRequest , lm * librariesmanager.LibrariesManager ) * rpc.LibrarySearchResponse {
15641 res := []* rpc.SearchedLibrary {}
15742 query := req .GetSearchArgs ()
15843 if query == "" {
15944 query = req .GetQuery ()
16045 }
16146
162- matcher := matcherFromQueryString (query )
47+ matcher := MatcherFromQueryString (query )
16348
16449 for _ , lib := range lm .Index .Libraries {
16550 if matcher (lib ) {
0 commit comments