Skip to content

Commit 13c6edf

Browse files
authored
Add board search command and gRPC interface function (#1210)
* Add board search command * board search now searches only on board name and results are sorted alphabetically * Remove fuzzy search from board search command
1 parent d35a3c9 commit 13c6edf

File tree

12 files changed

+902
-311
lines changed

12 files changed

+902
-311
lines changed

Diff for: arduino/utils/search.go

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-cli.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to [email protected].
15+
16+
package utils
17+
18+
import (
19+
"strings"
20+
"unicode"
21+
22+
"golang.org/x/text/runes"
23+
"golang.org/x/text/transform"
24+
"golang.org/x/text/unicode/norm"
25+
)
26+
27+
// removeDiatrics removes accents and similar diatrics from unicode characters.
28+
// An empty string is returned in case of errors.
29+
// This might not be the best solution but it works well enough for our usecase,
30+
// in the future we might want to use the golang.org/x/text/secure/precis package
31+
// when its API will be finalized.
32+
// From https://stackoverflow.com/a/26722698
33+
func removeDiatrics(s string) (string, error) {
34+
transformer := transform.Chain(
35+
norm.NFD,
36+
runes.Remove(runes.In(unicode.Mn)),
37+
norm.NFC,
38+
)
39+
s, _, err := transform.String(transformer, s)
40+
if err != nil {
41+
return "", err
42+
}
43+
return s, nil
44+
}
45+
46+
// Match returns true if all substrings are contained in str.
47+
// Both str and substrings are transforms to lower case and have their
48+
// accents and other unicode diatrics removed.
49+
// If strings transformation fails an error is returned.
50+
func Match(str string, substrings []string) (bool, error) {
51+
str, err := removeDiatrics(strings.ToLower(str))
52+
if err != nil {
53+
return false, err
54+
}
55+
56+
for _, sub := range substrings {
57+
cleanSub, err := removeDiatrics(strings.ToLower(sub))
58+
if err != nil {
59+
return false, err
60+
}
61+
if !strings.Contains(str, cleanSub) {
62+
return false, nil
63+
}
64+
}
65+
return true, nil
66+
}

Diff for: cli/board/board.go

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func NewCommand() *cobra.Command {
3737
boardCommand.AddCommand(initDetailsCommand())
3838
boardCommand.AddCommand(initListCommand())
3939
boardCommand.AddCommand(initListAllCommand())
40+
boardCommand.AddCommand(initSearchCommand())
4041

4142
return boardCommand
4243
}

Diff for: cli/board/search.go

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-cli.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to [email protected].
15+
16+
package board
17+
18+
import (
19+
"context"
20+
"os"
21+
"sort"
22+
"strings"
23+
24+
"github.com/arduino/arduino-cli/cli/errorcodes"
25+
"github.com/arduino/arduino-cli/cli/feedback"
26+
"github.com/arduino/arduino-cli/cli/instance"
27+
"github.com/arduino/arduino-cli/commands/board"
28+
rpc "github.com/arduino/arduino-cli/rpc/commands"
29+
"github.com/arduino/arduino-cli/table"
30+
"github.com/spf13/cobra"
31+
)
32+
33+
func initSearchCommand() *cobra.Command {
34+
var searchCommand = &cobra.Command{
35+
Use: "search [boardname]",
36+
Short: "List all known boards and their corresponding FQBN.",
37+
Long: "" +
38+
"List all boards that have the support platform installed. You can search\n" +
39+
"for a specific board if you specify the board name",
40+
Example: "" +
41+
" " + os.Args[0] + " board search\n" +
42+
" " + os.Args[0] + " board search zero",
43+
Args: cobra.ArbitraryArgs,
44+
Run: runSearchCommand,
45+
}
46+
searchCommand.Flags().BoolVarP(&searchFlags.showHiddenBoard, "show-hidden", "a", false, "Show also boards marked as 'hidden' in the platform")
47+
return searchCommand
48+
}
49+
50+
var searchFlags struct {
51+
showHiddenBoard bool
52+
}
53+
54+
func runSearchCommand(cmd *cobra.Command, args []string) {
55+
inst, err := instance.CreateInstance()
56+
if err != nil {
57+
feedback.Errorf("Error searching boards: %v", err)
58+
os.Exit(errorcodes.ErrGeneric)
59+
}
60+
61+
res, err := board.Search(context.Background(), &rpc.BoardSearchReq{
62+
Instance: inst,
63+
SearchArgs: strings.Join(args, " "),
64+
IncludeHiddenBoards: searchFlags.showHiddenBoard,
65+
})
66+
if err != nil {
67+
feedback.Errorf("Error searching boards: %v", err)
68+
os.Exit(errorcodes.ErrGeneric)
69+
}
70+
71+
feedback.PrintResult(searchResults{res.Boards})
72+
}
73+
74+
// output from this command requires special formatting so we create a dedicated
75+
// feedback.Result implementation
76+
type searchResults struct {
77+
boards []*rpc.BoardListItem
78+
}
79+
80+
func (r searchResults) Data() interface{} {
81+
return r.boards
82+
}
83+
84+
func (r searchResults) String() string {
85+
sort.Slice(r.boards, func(i, j int) bool {
86+
return r.boards[i].GetName() < r.boards[j].GetName()
87+
})
88+
89+
t := table.New()
90+
t.SetHeader("Board Name", "FQBN", "Platform ID", "")
91+
for _, item := range r.boards {
92+
hidden := ""
93+
if item.IsHidden {
94+
hidden = "(hidden)"
95+
}
96+
t.AddRow(item.GetName(), item.GetFQBN(), item.Platform.ID, hidden)
97+
}
98+
return t.Render()
99+
}

0 commit comments

Comments
 (0)