Skip to content

Commit 08af76b

Browse files
committed
Change lib search command to use fuzzy search
1 parent 59b6277 commit 08af76b

File tree

5 files changed

+75
-42
lines changed

5 files changed

+75
-42
lines changed

commands/lib/search.go

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
"github.com/arduino/arduino-cli/arduino/libraries/librariesmanager"
2525
"github.com/arduino/arduino-cli/commands"
2626
rpc "github.com/arduino/arduino-cli/rpc/commands"
27-
"github.com/imjasonmiller/godice"
27+
"github.com/lithammer/fuzzysearch/fuzzy"
2828
semver "go.bug.st/relaxed-semver"
2929
)
3030

@@ -44,42 +44,45 @@ func searchLibrary(req *rpc.LibrarySearchReq, lm *librariesmanager.LibrariesMana
4444
res := []*rpc.SearchedLibrary{}
4545
status := rpc.LibrarySearchStatus_success
4646

47-
for _, lib := range lm.Index.Libraries {
48-
qry := strings.ToLower(req.GetQuery())
49-
if strings.Contains(strings.ToLower(lib.Name), qry) ||
50-
strings.Contains(strings.ToLower(lib.Latest.Paragraph), qry) ||
51-
strings.Contains(strings.ToLower(lib.Latest.Sentence), qry) {
52-
releases := map[string]*rpc.LibraryRelease{}
53-
for str, rel := range lib.Releases {
54-
releases[str] = GetLibraryParameters(rel)
55-
}
56-
latest := GetLibraryParameters(lib.Latest)
57-
58-
searchedLib := &rpc.SearchedLibrary{
59-
Name: lib.Name,
60-
Releases: releases,
61-
Latest: latest,
62-
}
63-
res = append(res, searchedLib)
47+
// If the query is empty all libraries are returned
48+
if strings.Trim(req.GetQuery(), " ") == "" {
49+
for _, lib := range lm.Index.Libraries {
50+
res = append(res, indexLibraryToRPCSearchLibrary(lib))
6451
}
52+
return &rpc.LibrarySearchResp{Libraries: res, Status: status}, nil
6553
}
6654

67-
if len(res) == 0 {
68-
status = rpc.LibrarySearchStatus_failed
69-
for _, lib := range lm.Index.Libraries {
70-
if godice.CompareString(req.GetQuery(), lib.Name) > similarityThreshold {
71-
res = append(res, &rpc.SearchedLibrary{
72-
Name: lib.Name,
73-
})
55+
for _, lib := range lm.Index.Libraries {
56+
words := strings.Split(req.GetQuery(), " ")
57+
toTest := []string{lib.Name, lib.Latest.Paragraph, lib.Latest.Sentence}
58+
59+
for _, word := range words {
60+
if len(fuzzy.FindNormalizedFold(word, toTest)) > 0 {
61+
res = append(res, indexLibraryToRPCSearchLibrary(lib))
7462
}
7563
}
7664
}
7765

7866
return &rpc.LibrarySearchResp{Libraries: res, Status: status}, nil
7967
}
8068

81-
// GetLibraryParameters FIXMEDOC
82-
func GetLibraryParameters(rel *librariesindex.Release) *rpc.LibraryRelease {
69+
// indexLibraryToRPCSearchLibrary converts a librariindex.Library to rpc.SearchLibrary
70+
func indexLibraryToRPCSearchLibrary(lib *librariesindex.Library) *rpc.SearchedLibrary {
71+
releases := map[string]*rpc.LibraryRelease{}
72+
for str, rel := range lib.Releases {
73+
releases[str] = getLibraryParameters(rel)
74+
}
75+
latest := getLibraryParameters(lib.Latest)
76+
77+
return &rpc.SearchedLibrary{
78+
Name: lib.Name,
79+
Releases: releases,
80+
Latest: latest,
81+
}
82+
}
83+
84+
// getLibraryParameters FIXMEDOC
85+
func getLibraryParameters(rel *librariesindex.Release) *rpc.LibraryRelease {
8386
return &rpc.LibraryRelease{
8487
Author: rel.Author,
8588
Version: rel.Version.String(),

commands/lib/search_test.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,12 @@ func TestSearchLibrarySimilar(t *testing.T) {
4848
}
4949

5050
assert := assert.New(t)
51-
assert.Equal(resp.GetStatus(), rpc.LibrarySearchStatus_failed)
52-
assert.Equal(len(resp.GetLibraries()), 1)
53-
assert.Equal(resp.GetLibraries()[0].Name, "Arduino")
51+
assert.Equal(resp.GetStatus(), rpc.LibrarySearchStatus_success)
52+
assert.Equal(len(resp.GetLibraries()), 2)
53+
libs := map[string]*rpc.SearchedLibrary{}
54+
for _, l := range resp.GetLibraries() {
55+
libs[l.Name] = l
56+
}
57+
assert.Contains(libs, "ArduinoTestPackage")
58+
assert.Contains(libs, "Arduino")
5459
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ require (
1919
github.com/gofrs/uuid v3.2.0+incompatible
2020
github.com/golang/protobuf v1.4.2
2121
github.com/h2non/filetype v1.0.8 // indirect
22-
github.com/imjasonmiller/godice v0.1.2
2322
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 // indirect
2423
github.com/kr/text v0.2.0 // indirect
2524
github.com/leonelquinteros/gotext v1.4.0
25+
github.com/lithammer/fuzzysearch v1.1.1 // indirect
2626
github.com/mattn/go-colorable v0.1.2
2727
github.com/mattn/go-isatty v0.0.8
2828
github.com/mattn/go-runewidth v0.0.9 // indirect

go.sum

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
22
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
33
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
4-
github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg=
54
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
65
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
76
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
@@ -117,8 +116,6 @@ github.com/h2non/filetype v1.0.8 h1:le8gpf+FQA0/DlDABbtisA1KiTS0Xi+YSC/E8yY3Y14=
117116
github.com/h2non/filetype v1.0.8/go.mod h1:isekKqOuhMj+s/7r3rIeTErIRy4Rub5uBWHfvMusLMU=
118117
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
119118
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
120-
github.com/imjasonmiller/godice v0.1.2 h1:T1/sW/HoDzFeuwzOOuQjmeMELz9CzZ53I2CnD+08zD4=
121-
github.com/imjasonmiller/godice v0.1.2/go.mod h1:8cTkdnVI+NglU2d6sv+ilYcNaJ5VSTBwvMbFULJd/QQ=
122119
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
123120
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
124121
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
@@ -155,6 +152,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
155152
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
156153
github.com/leonelquinteros/gotext v1.4.0 h1:2NHPCto5IoMXbrT0bldPrxj0qM5asOCwtb1aUQZ1tys=
157154
github.com/leonelquinteros/gotext v1.4.0/go.mod h1:yZGXREmoGTtBvZHNcc+Yfug49G/2spuF/i/Qlsvz1Us=
155+
github.com/lithammer/fuzzysearch v1.1.1 h1:8F9OAV2xPuYblToVohjanztdnPjbtA0MLgMvDKQ0Z08=
156+
github.com/lithammer/fuzzysearch v1.1.1/go.mod h1:H2bng+w5gsR7NlfIJM8ElGZI0sX6C/9uzGqicVXGU6c=
158157
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
159158
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
160159
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -215,7 +214,6 @@ github.com/segmentio/objconv v1.0.1 h1:QjfLzwriJj40JibCV3MGSEiAoXixbp4ybhwfTB8RX
215214
github.com/segmentio/objconv v1.0.1/go.mod h1:auayaH5k3137Cl4SoXTgrzQcuQDmvuVtZgS0fb1Ahys=
216215
github.com/segmentio/stats/v4 v4.5.3 h1:Y/DSUWZ4c8ICgqJ9rQohzKvGqGWbLPWad5zmxVoKN+Y=
217216
github.com/segmentio/stats/v4 v4.5.3/go.mod h1:LsaahUJR7iiSs8mnkvQvdQ/RLHAS5adGLxuntg0ydGo=
218-
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
219217
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
220218
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
221219
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
@@ -281,7 +279,6 @@ golang.org/x/crypto v0.0.0-20180214000028-650f4a345ab4/go.mod h1:6SG95UA2DQfeDnf
281279
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
282280
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
283281
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
284-
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
285282
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
286283
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+UgTgQZ4pMLzXxi1pSt+/Y=
287284
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -334,7 +331,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
334331
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
335332
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
336333
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
337-
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a h1:mEQZbbaBjWyLNy0tmZmgEuQAR8XOQ3hL8GYi3J/NG64=
338334
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
339335
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
340336
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

test/test_lib.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -383,11 +383,11 @@ def test_search(run_command):
383383
libs_json = json.loads(result.stdout)
384384
assert len(libs) == len(libs_json.get("libraries"))
385385

386-
result = run_command("lib search")
386+
result = run_command("lib search --names")
387387
assert result.ok
388388

389389
# Search for a specific target
390-
result = run_command("lib search ArduinoJson --format json")
390+
result = run_command("lib search --names ArduinoJson --format json")
391391
assert result.ok
392392
libs_json = json.loads(result.stdout)
393393
assert len(libs_json.get("libraries")) >= 1
@@ -399,10 +399,39 @@ def test_search_paragraph(run_command):
399399
within the index file.
400400
"""
401401
assert run_command("lib update-index")
402-
result = run_command('lib search "A simple and efficient JSON library" --format json')
402+
result = run_command('lib search "A simple and efficient JSON library" --names --format json')
403403
assert result.ok
404-
libs_json = json.loads(result.stdout)
405-
assert 1 == len(libs_json.get("libraries"))
404+
data = json.loads(result.stdout)
405+
libraries = [l["name"] for l in data["libraries"]]
406+
assert "ArduinoJson" in libraries
407+
408+
409+
def test_lib_search_fuzzy(run_command):
410+
run_command("update")
411+
412+
def run_search(search_args, expected_libraries):
413+
res = run_command(f"lib search --names --format json {search_args}")
414+
assert res.ok
415+
data = json.loads(res.stdout)
416+
libraries = [l["name"] for l in data["libraries"]]
417+
for l in expected_libraries:
418+
assert l in libraries
419+
420+
run_search("Arduino_MKRIoTCarrier", ["Arduino_MKRIoTCarrier"])
421+
run_search("Arduino mkr iot carrier", ["Arduino_MKRIoTCarrier"])
422+
run_search("Arduinomkriotcarrier", ["Arduino_MKRIoTCarrier"])
423+
424+
run_search(
425+
"dht",
426+
["DHT sensor library", "DHT sensor library for ESPx", "DHT12", "SimpleDHT", "TinyDHT sensor library", "SDHT"],
427+
)
428+
run_search(
429+
"dht11", ["DHT sensor library", "DHT sensor library for ESPx", "SimpleDHT", "TinyDHT sensor library", "SDHT"]
430+
)
431+
run_search("dht12", ["AM232X", "DHT12", "DHT12 sensor library", "SDHT"])
432+
run_search("dht22", ["DHT sensor library", "DHT sensor library for ESPx", "SimpleDHT", "SDHT"])
433+
run_search("dht sensor", ["DHT sensor library", "DHT sensor library for ESPx", "SimpleDHT", "SDHT"])
434+
run_search("sensor dht", ["DHT sensor library", "DHT sensor library for ESPx", "SimpleDHT", "SDHT"])
406435

407436

408437
def test_lib_list_with_updatable_flag(run_command):

0 commit comments

Comments
 (0)