Skip to content

Refactor string match util #1415

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 25 additions & 10 deletions arduino/utils/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,35 @@ func removeDiatrics(s string) (string, error) {
// Both str and substrings are transforms to lower case and have their
// accents and other unicode diatrics removed.
// If strings transformation fails an error is returned.
func Match(str string, substrings []string) (bool, error) {
str, err := removeDiatrics(strings.ToLower(str))
if err != nil {
return false, err
func Match(str string, substrings []string) bool {
clean := func(s string) string {
s = strings.ToLower(s)
if s2, err := removeDiatrics(s); err == nil {
return s2
}
return s
}

str = clean(str)
for _, sub := range substrings {
cleanSub, err := removeDiatrics(strings.ToLower(sub))
if err != nil {
return false, err
if !strings.Contains(str, clean(sub)) {
return false
}
if !strings.Contains(str, cleanSub) {
return false, nil
}
return true
}

// MatchAny checks if query matches at least one of the
// string in arrayToMatch using the utils.Match function.
func MatchAny(query string, arrayToMatch []string) bool {
queryArgs := strings.Split(strings.TrimSpace(query), " ")
if len(queryArgs) == 0 {
return true
}
for _, t := range arrayToMatch {
if Match(t, queryArgs) {
return true
}
}
return true, nil
return false
}
2 changes: 0 additions & 2 deletions commands/board/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"regexp"
"sort"
"strings"
"sync"
"time"

"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
Expand All @@ -39,7 +38,6 @@ import (
var (
// ErrNotFound is returned when the API returns 404
ErrNotFound = errors.New(tr("board not found"))
m sync.Mutex
vidPidURL = "https://builder.arduino.cc/v3/boards/byVidPid"
validVidPid = regexp.MustCompile(`0[xX][a-fA-F\d]{4}`)
)
Expand Down
30 changes: 2 additions & 28 deletions commands/board/listall.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,38 +25,14 @@ import (
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
)

// maximumSearchDistance is the maximum Levenshtein distance accepted when using fuzzy search.
// This value is completely arbitrary and picked randomly.
const maximumSearchDistance = 20

// ListAll FIXMEDOC
func ListAll(ctx context.Context, req *rpc.BoardListAllRequest) (*rpc.BoardListAllResponse, error) {
pm := commands.GetPackageManager(req.GetInstance().GetId())
if pm == nil {
return nil, errors.New(tr("invalid instance"))
}

searchArgs := []string{}
for _, s := range req.SearchArgs {
searchArgs = append(searchArgs, strings.Trim(s, " "))
}

match := func(toTest []string) (bool, error) {
if len(searchArgs) == 0 {
return true, nil
}

for _, t := range toTest {
matches, err := utils.Match(t, searchArgs)
if err != nil {
return false, err
}
if matches {
return matches, nil
}
}
return false, nil
}
searchArgs := strings.Join(req.GetSearchArgs(), " ")

list := &rpc.BoardListAllResponse{Boards: []*rpc.BoardListItem{}}
for _, targetPackage := range pm.Packages {
Expand Down Expand Up @@ -100,9 +76,7 @@ func ListAll(ctx context.Context, req *rpc.BoardListAllRequest) (*rpc.BoardListA

toTest := append(toTest, board.Name())
toTest = append(toTest, board.FQBN())
if ok, err := match(toTest); err != nil {
return nil, err
} else if !ok {
if !utils.MatchAny(searchArgs, toTest) {
continue
}

Expand Down
27 changes: 2 additions & 25 deletions commands/board/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,6 @@ func Search(ctx context.Context, req *rpc.BoardSearchRequest) (*rpc.BoardSearchR
return nil, errors.New(tr("invalid instance"))
}

searchArgs := strings.Split(strings.Trim(req.SearchArgs, " "), " ")

match := func(toTest []string) (bool, error) {
if len(searchArgs) == 0 {
return true, nil
}

for _, t := range toTest {
matches, err := utils.Match(t, searchArgs)
if err != nil {
return false, err
}
if matches {
return matches, nil
}
}
return false, nil
}

res := &rpc.BoardSearchResponse{Boards: []*rpc.BoardListItem{}}
for _, targetPackage := range pm.Packages {
for _, platform := range targetPackage.Platforms {
Expand Down Expand Up @@ -93,9 +74,7 @@ func Search(ctx context.Context, req *rpc.BoardSearchRequest) (*rpc.BoardSearchR
}

toTest := append(strings.Split(board.Name(), " "), board.Name(), board.FQBN())
if ok, err := match(toTest); err != nil {
return nil, err
} else if !ok {
if !utils.MatchAny(req.GetSearchArgs(), toTest) {
continue
}

Expand All @@ -109,9 +88,7 @@ func Search(ctx context.Context, req *rpc.BoardSearchRequest) (*rpc.BoardSearchR
} else if latestPlatformRelease != nil {
for _, board := range latestPlatformRelease.BoardsManifest {
toTest := append(strings.Split(board.Name, " "), board.Name)
if ok, err := match(toTest); err != nil {
return nil, err
} else if !ok {
if !utils.MatchAny(req.GetSearchArgs(), toTest) {
continue
}

Expand Down
25 changes: 2 additions & 23 deletions commands/core/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const maximumSearchDistance = 20

// PlatformSearch FIXMEDOC
func PlatformSearch(req *rpc.PlatformSearchRequest) (*rpc.PlatformSearchResponse, error) {
searchArgs := strings.Trim(req.SearchArgs, " ")
searchArgs := strings.TrimSpace(req.SearchArgs)
allVersions := req.AllVersions
pm := commands.GetPackageManager(req.Instance.Id)
if pm == nil {
Expand All @@ -46,25 +46,6 @@ func PlatformSearch(req *rpc.PlatformSearchRequest) (*rpc.PlatformSearchResponse
res = pm.FindPlatformReleaseProvidingBoardsWithVidPid(vid, pid)
} else {

searchArgs := strings.Split(searchArgs, " ")

match := func(toTest []string) (bool, error) {
if len(searchArgs) == 0 {
return true, nil
}

for _, t := range toTest {
matches, err := utils.Match(t, searchArgs)
if err != nil {
return false, err
}
if matches {
return matches, nil
}
}
return false, nil
}

for _, targetPackage := range pm.Packages {
for _, platform := range targetPackage.Platforms {
// discard invalid platforms
Expand Down Expand Up @@ -95,9 +76,7 @@ func PlatformSearch(req *rpc.PlatformSearchRequest) (*rpc.PlatformSearchResponse
}

// Search
if ok, err := match(toTest); err != nil {
return nil, err
} else if !ok {
if !utils.MatchAny(searchArgs, toTest) {
continue
}

Expand Down
25 changes: 1 addition & 24 deletions commands/lib/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package lib
import (
"context"
"errors"
"strings"

"github.com/arduino/arduino-cli/arduino/libraries/librariesindex"
"github.com/arduino/arduino-cli/arduino/libraries/librariesmanager"
Expand All @@ -39,34 +38,12 @@ func LibrarySearch(ctx context.Context, req *rpc.LibrarySearchRequest) (*rpc.Lib
}

func searchLibrary(req *rpc.LibrarySearchRequest, lm *librariesmanager.LibrariesManager) (*rpc.LibrarySearchResponse, error) {
query := req.GetQuery()
res := []*rpc.SearchedLibrary{}
status := rpc.LibrarySearchStatus_LIBRARY_SEARCH_STATUS_SUCCESS

searchArgs := strings.Split(strings.Trim(query, " "), " ")

match := func(toTest []string) (bool, error) {
if len(searchArgs) == 0 {
return true, nil
}

for _, t := range toTest {
matches, err := utils.Match(t, searchArgs)
if err != nil {
return false, err
}
if matches {
return matches, nil
}
}
return false, nil
}

for _, lib := range lm.Index.Libraries {
toTest := []string{lib.Name, lib.Latest.Paragraph, lib.Latest.Sentence}
if ok, err := match(toTest); err != nil {
return nil, err
} else if !ok {
if !utils.MatchAny(req.GetQuery(), toTest) {
continue
}
res = append(res, indexLibraryToRPCSearchLibrary(lib))
Expand Down
26 changes: 13 additions & 13 deletions i18n/data/en.po
Original file line number Diff line number Diff line change
Expand Up @@ -1035,15 +1035,15 @@ msgstr "Invalid output format: %s"
msgid "Invalid parameter %s: version not allowed"
msgstr "Invalid parameter %s: version not allowed"

#: commands/board/list.go:53
#: commands/board/list.go:51
msgid "Invalid pid value: '%s'"
msgstr "Invalid pid value: '%s'"

#: legacy/builder/phases/sizer.go:150
msgid "Invalid size regexp: %s"
msgstr "Invalid size regexp: %s"

#: commands/board/list.go:50
#: commands/board/list.go:48
msgid "Invalid vid value: '%s'"
msgstr "Invalid vid value: '%s'"

Expand Down Expand Up @@ -2093,7 +2093,7 @@ msgstr "binary file not found in %s"
msgid "board %s:%s not found"
msgstr "board %s:%s not found"

#: commands/board/list.go:41
#: commands/board/list.go:40
msgid "board not found"
msgstr "board not found"

Expand Down Expand Up @@ -2358,7 +2358,7 @@ msgstr "downloading tool %[1]s: %[2]s"
msgid "encoding sketch metadata: %s"
msgstr "encoding sketch metadata: %s"

#: commands/board/list.go:142
#: commands/board/list.go:140
msgid "error getting board info from Arduino Cloud"
msgstr "error getting board info from Arduino Cloud"

Expand All @@ -2378,11 +2378,11 @@ msgstr "error parsing FQBN"
msgid "error parsing value: %v"
msgstr "error parsing value: %v"

#: commands/board/list.go:83
#: commands/board/list.go:81
msgid "error processing response from server"
msgstr "error processing response from server"

#: commands/board/list.go:98
#: commands/board/list.go:96
msgid "error querying Arduino Cloud Api"
msgstr "error querying Arduino Cloud Api"

Expand Down Expand Up @@ -2411,7 +2411,7 @@ msgstr "extracting archive: %w"
msgid "failed to compute hash of file \"%s\""
msgstr "failed to compute hash of file \"%s\""

#: commands/board/list.go:66
#: commands/board/list.go:64
msgid "failed to initialize http client"
msgstr "failed to initialize http client"

Expand Down Expand Up @@ -2626,8 +2626,8 @@ msgstr "invalid hash '%[1]s': %[2]s"

#: commands/board/attach.go:42
#: commands/board/details.go:33
#: commands/board/list.go:187
#: commands/board/listall.go:36
#: commands/board/list.go:185
#: commands/board/listall.go:32
#: commands/board/search.go:36
#: commands/compile/compile.go:93
#: commands/core/download.go:36
Expand All @@ -2640,7 +2640,7 @@ msgstr "invalid hash '%[1]s': %[2]s"
#: commands/instances.go:589
#: commands/lib/list.go:41
#: commands/lib/list.go:46
#: commands/lib/search.go:35
#: commands/lib/search.go:34
#: commands/upload/upload.go:51
msgid "invalid instance"
msgstr "invalid instance"
Expand Down Expand Up @@ -3203,7 +3203,7 @@ msgstr "start syncing discovery %[1]s: %[2]w"
msgid "starting discovery %[1]s: %[2]w"
msgstr "starting discovery %[1]s: %[2]w"

#: commands/board/list.go:279
#: commands/board/list.go:277
msgid "stopping discoveries: %s"
msgstr "stopping discoveries: %s"

Expand Down Expand Up @@ -3235,7 +3235,7 @@ msgstr "text section exceeds available space in board"
msgid "the library name is different from the set (%[1]s != %[2]s)"
msgstr "the library name is different from the set (%[1]s != %[2]s)"

#: commands/board/list.go:74
#: commands/board/list.go:72
msgid "the server responded with status %s"
msgstr "the server responded with status %s"

Expand Down Expand Up @@ -3397,7 +3397,7 @@ msgstr "writing library_index.json.sig"
msgid "writing sketch metadata %[1]s: %[2]s"
msgstr "writing sketch metadata %[1]s: %[2]s"

#: commands/board/list.go:90
#: commands/board/list.go:88
msgid "wrong format in server response"
msgstr "wrong format in server response"

Expand Down
14 changes: 7 additions & 7 deletions i18n/rice-box.go

Large diffs are not rendered by default.