Skip to content

Commit 37d508f

Browse files
committed
Add fuzzy search to board listall command
1 parent fb50928 commit 37d508f

File tree

2 files changed

+56
-10
lines changed

2 files changed

+56
-10
lines changed

commands/board/listall.go

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,32 @@ import (
2323
"github.com/arduino/arduino-cli/arduino/cores"
2424
"github.com/arduino/arduino-cli/commands"
2525
rpc "github.com/arduino/arduino-cli/rpc/commands"
26+
"github.com/lithammer/fuzzysearch/fuzzy"
2627
)
2728

29+
// maximumSearchDistance is the maximum Levenshtein distance accepted when using fuzzy search.
30+
// This value is completely arbitrary and picked randomly.
31+
const maximumSearchDistance = 20
32+
2833
// ListAll FIXMEDOC
2934
func ListAll(ctx context.Context, req *rpc.BoardListAllReq) (*rpc.BoardListAllResp, error) {
3035
pm := commands.GetPackageManager(req.GetInstance().GetId())
3136
if pm == nil {
3237
return nil, errors.New("invalid instance")
3338
}
3439

35-
args := req.GetSearchArgs()
36-
match := func(name string) bool {
37-
if len(args) == 0 {
40+
searchArgs := strings.Join(req.SearchArgs, " ")
41+
42+
match := func(toTest []string) bool {
43+
if len(searchArgs) == 0 {
3844
return true
3945
}
40-
name = strings.ToLower(name)
41-
for _, term := range args {
42-
if !strings.Contains(name, strings.ToLower(term)) {
43-
return false
46+
for _, rank := range fuzzy.RankFindNormalizedFold(searchArgs, toTest) {
47+
if rank.Distance < maximumSearchDistance {
48+
return true
4449
}
4550
}
46-
return true
51+
return false
4752
}
4853

4954
list := &rpc.BoardListAllResp{Boards: []*rpc.BoardListItem{}}
@@ -85,13 +90,26 @@ func ListAll(ctx context.Context, req *rpc.BoardListAllReq) (*rpc.BoardListAllRe
8590
platformRelease = latestPlatformRelease
8691
}
8792

93+
toTest := []string{
94+
platform.String(),
95+
platform.Name,
96+
platform.Architecture,
97+
targetPackage.Name,
98+
targetPackage.Maintainer,
99+
}
100+
88101
for _, board := range platformRelease.Boards {
89-
if !match(board.Name()) {
102+
if !req.GetIncludeHiddenBoards() && board.IsHidden() {
90103
continue
91104
}
92-
if !req.GetIncludeHiddenBoards() && board.IsHidden() {
105+
106+
toTest := toTest
107+
toTest = append(toTest, strings.Split(board.Name(), " ")...)
108+
toTest = append(toTest, board.FQBN())
109+
if !match(toTest) {
93110
continue
94111
}
112+
95113
list.Boards = append(list.Boards, &rpc.BoardListItem{
96114
Name: board.Name(),
97115
FQBN: board.FQBN(),

test/test_board.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,34 @@ def test_board_listall_with_manually_installed_platform(run_command, data_dir):
455455
assert "Arduino SAMD (32-bits ARM Cortex-M0+) Boards" == platform["Name"]
456456

457457

458+
def test_board_listall_fuzzy_search(run_command, data_dir):
459+
assert run_command("update")
460+
461+
# Install from platform manager
462+
assert run_command("core install arduino:avr@1.8.3")
463+
464+
# Manually installs a core in sketchbooks hardware folder
465+
git_url = "https://github.com/arduino/ArduinoCore-samd.git"
466+
repo_dir = Path(data_dir, "hardware", "arduino-beta-development", "samd")
467+
assert Repo.clone_from(git_url, repo_dir, multi_options=["-b 1.8.11"])
468+
469+
res = run_command("board listall --format json samd")
470+
assert res.ok
471+
data = json.loads(res.stdout)
472+
boards = {b["FQBN"]: b for b in data["boards"]}
473+
assert len(boards) == 17
474+
assert "arduino-beta-development:samd:mkr1000" in boards
475+
assert "arduino:avr:uno" not in boards
476+
477+
res = run_command("board listall --format json avr")
478+
assert res.ok
479+
data = json.loads(res.stdout)
480+
boards = {b["FQBN"]: b for b in data["boards"]}
481+
assert len(boards) == 26
482+
assert "arduino:avr:uno" in boards
483+
assert "arduino-beta-development:samd:mkr1000" not in boards
484+
485+
458486
def test_board_details(run_command):
459487
run_command("core update-index")
460488
# Download samd core pinned to 1.8.6

0 commit comments

Comments
 (0)