Unverified Commit 38a80a62 authored by tuckerrrrrrrrrr's avatar tuckerrrrrrrrrr Committed by GitHub

Show similar library names in lib search (#598)

* Show similar library names in lib search

* make similarity threshold for lib search a package variable

* Add library search tests

* Redo name asserts in TestSearchLibrary

Just check that the library names have "Test" in them instead of
checking the names at each index, which won't always be the same
parent e8bb3278
......@@ -88,8 +88,8 @@ func (res result) Data() interface{} {
names := []LibName{}
results := res.results.GetLibraries()
for _, lsr := range results {
names = append(names, LibName{lsr.Name})
for _, lib := range results {
names = append(names, LibName{lib.Name})
}
return NamesOnly{
......@@ -113,9 +113,18 @@ func (res result) String() string {
var out strings.Builder
if res.results.GetStatus() == rpc.LibrarySearchStatus_failed {
out.WriteString("No libraries matching your search.\nDid you mean...\n")
}
for _, lib := range results {
out.WriteString(fmt.Sprintf("Name: \"%s\"\n", lib.Name))
if res.namesOnly {
if res.results.GetStatus() == rpc.LibrarySearchStatus_success {
out.WriteString(fmt.Sprintf("Name: \"%s\"\n", lib.Name))
if res.namesOnly {
continue
}
} else {
out.WriteString(fmt.Sprintf("%s\n", lib.Name))
continue
}
......
......@@ -21,11 +21,15 @@ import (
"strings"
"github.com/arduino/arduino-cli/arduino/libraries/librariesindex"
"github.com/arduino/arduino-cli/arduino/libraries/librariesmanager"
"github.com/arduino/arduino-cli/commands"
rpc "github.com/arduino/arduino-cli/rpc/commands"
"github.com/imjasonmiller/godice"
semver "go.bug.st/relaxed-semver"
)
var similarityThreshold = 0.7
// LibrarySearch FIXMEDOC
func LibrarySearch(ctx context.Context, req *rpc.LibrarySearchReq) (*rpc.LibrarySearchResp, error) {
lm := commands.GetLibraryManager(req.GetInstance().GetId())
......@@ -33,7 +37,12 @@ func LibrarySearch(ctx context.Context, req *rpc.LibrarySearchReq) (*rpc.Library
return nil, errors.New("invalid instance")
}
return searchLibrary(req, lm)
}
func searchLibrary(req *rpc.LibrarySearchReq, lm *librariesmanager.LibrariesManager) (*rpc.LibrarySearchResp, error) {
res := []*rpc.SearchedLibrary{}
status := rpc.LibrarySearchStatus_success
for _, lib := range lm.Index.Libraries {
qry := strings.ToLower(req.GetQuery())
......@@ -46,16 +55,27 @@ func LibrarySearch(ctx context.Context, req *rpc.LibrarySearchReq) (*rpc.Library
}
latest := GetLibraryParameters(lib.Latest)
searchedlib := &rpc.SearchedLibrary{
searchedLib := &rpc.SearchedLibrary{
Name: lib.Name,
Releases: releases,
Latest: latest,
}
res = append(res, searchedlib)
res = append(res, searchedLib)
}
}
if len(res) == 0 {
status = rpc.LibrarySearchStatus_failed
for _, lib := range lm.Index.Libraries {
if godice.CompareString(req.GetQuery(), lib.Name) > similarityThreshold {
res = append(res, &rpc.SearchedLibrary{
Name: lib.Name,
})
}
}
}
return &rpc.LibrarySearchResp{Libraries: res}, nil
return &rpc.LibrarySearchResp{Libraries: res, Status: status}, nil
}
// GetLibraryParameters FIXMEDOC
......
package lib
import (
"strings"
"testing"
"github.com/arduino/arduino-cli/arduino/libraries/librariesmanager"
rpc "github.com/arduino/arduino-cli/rpc/commands"
paths "github.com/arduino/go-paths-helper"
"github.com/stretchr/testify/assert"
)
var customIndexPath = paths.New("testdata")
func TestSearchLibrary(t *testing.T) {
lm := librariesmanager.NewLibraryManager(customIndexPath, nil)
lm.LoadIndex()
req := &rpc.LibrarySearchReq{
Instance: &rpc.Instance{Id: 1},
Query: "test",
}
resp, err := searchLibrary(req, lm)
if err != nil {
t.Fatal(err)
}
assert := assert.New(t)
assert.Equal(resp.GetStatus(), rpc.LibrarySearchStatus_success)
assert.Equal(len(resp.GetLibraries()), 2)
assert.True(strings.Contains(resp.GetLibraries()[0].Name, "Test"))
assert.True(strings.Contains(resp.GetLibraries()[1].Name, "Test"))
}
func TestSearchLibrarySimilar(t *testing.T) {
lm := librariesmanager.NewLibraryManager(customIndexPath, nil)
lm.LoadIndex()
req := &rpc.LibrarySearchReq{
Instance: &rpc.Instance{Id: 1},
Query: "ardino",
}
resp, err := searchLibrary(req, lm)
if err != nil {
t.Fatal(err)
}
assert := assert.New(t)
assert.Equal(resp.GetStatus(), rpc.LibrarySearchStatus_failed)
assert.Equal(len(resp.GetLibraries()), 1)
assert.Equal(resp.GetLibraries()[0].Name, "Arduino")
}
{
"libraries": [
{
"name": "ArduinoTestPackage"
},
{
"name": "Arduino"
},
{
"name": "Test"
}
]
}
......@@ -19,6 +19,7 @@ require (
github.com/gofrs/uuid v3.2.0+incompatible
github.com/golang/protobuf v1.3.3
github.com/h2non/filetype v1.0.8 // indirect
github.com/imjasonmiller/godice v0.1.2
github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5 // indirect
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 // indirect
github.com/juju/testing v0.0.0-20190429233213-dfc56b8c09fc // indirect
......
......@@ -20,6 +20,31 @@ var _ = math.Inf
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type LibrarySearchStatus int32
const (
LibrarySearchStatus_failed LibrarySearchStatus = 0
LibrarySearchStatus_success LibrarySearchStatus = 1
)
var LibrarySearchStatus_name = map[int32]string{
0: "failed",
1: "success",
}
var LibrarySearchStatus_value = map[string]int32{
"failed": 0,
"success": 1,
}
func (x LibrarySearchStatus) String() string {
return proto.EnumName(LibrarySearchStatus_name, int32(x))
}
func (LibrarySearchStatus) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_9feed0d29806df6c, []int{0}
}
type LibraryLayout int32
const (
......@@ -42,7 +67,7 @@ func (x LibraryLayout) String() string {
}
func (LibraryLayout) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_9feed0d29806df6c, []int{0}
return fileDescriptor_9feed0d29806df6c, []int{1}
}
type LibraryLocation int32
......@@ -73,7 +98,7 @@ func (x LibraryLocation) String() string {
}
func (LibraryLocation) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_9feed0d29806df6c, []int{1}
return fileDescriptor_9feed0d29806df6c, []int{2}
}
type LibraryDownloadReq struct {
......@@ -649,10 +674,11 @@ func (m *LibrarySearchReq) GetQuery() string {
}
type LibrarySearchResp struct {
Libraries []*SearchedLibrary `protobuf:"bytes,1,rep,name=libraries,proto3" json:"libraries,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
Libraries []*SearchedLibrary `protobuf:"bytes,1,rep,name=libraries,proto3" json:"libraries,omitempty"`
Status LibrarySearchStatus `protobuf:"varint,2,opt,name=status,proto3,enum=cc.arduino.cli.commands.LibrarySearchStatus" json:"status,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *LibrarySearchResp) Reset() { *m = LibrarySearchResp{} }
......@@ -687,6 +713,13 @@ func (m *LibrarySearchResp) GetLibraries() []*SearchedLibrary {
return nil
}
func (m *LibrarySearchResp) GetStatus() LibrarySearchStatus {
if m != nil {
return m.Status
}
return LibrarySearchStatus_failed
}
type SearchedLibrary struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Releases map[string]*LibraryRelease `protobuf:"bytes,2,rep,name=releases,proto3" json:"releases,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
......@@ -1352,6 +1385,7 @@ func (m *Library) GetLayout() LibraryLayout {
}
func init() {
proto.RegisterEnum("cc.arduino.cli.commands.LibrarySearchStatus", LibrarySearchStatus_name, LibrarySearchStatus_value)
proto.RegisterEnum("cc.arduino.cli.commands.LibraryLayout", LibraryLayout_name, LibraryLayout_value)
proto.RegisterEnum("cc.arduino.cli.commands.LibraryLocation", LibraryLocation_name, LibraryLocation_value)
proto.RegisterType((*LibraryDownloadReq)(nil), "cc.arduino.cli.commands.LibraryDownloadReq")
......
......@@ -82,8 +82,14 @@ message LibrarySearchReq {
string query = 2;
}
enum LibrarySearchStatus {
failed = 0;
success = 1;
}
message LibrarySearchResp {
repeated SearchedLibrary libraries = 1;
LibrarySearchStatus status = 2;
}
message SearchedLibrary {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment