Skip to content

Commit

Permalink
Add board search command and gRPC interface function (#1210)
Browse files Browse the repository at this point in the history
* Add board search command

* board search now searches only on board name and results are sorted alphabetically

* Remove fuzzy search from board search command
  • Loading branch information
silvanocerza authored Mar 10, 2021
1 parent d35a3c9 commit 13c6edf
Show file tree
Hide file tree
Showing 12 changed files with 902 additions and 311 deletions.
66 changes: 66 additions & 0 deletions arduino/utils/search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// This file is part of arduino-cli.
//
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to [email protected].

package utils

import (
"strings"
"unicode"

"golang.org/x/text/runes"
"golang.org/x/text/transform"
"golang.org/x/text/unicode/norm"
)

// removeDiatrics removes accents and similar diatrics from unicode characters.
// An empty string is returned in case of errors.
// This might not be the best solution but it works well enough for our usecase,
// in the future we might want to use the golang.org/x/text/secure/precis package
// when its API will be finalized.
// From https://stackoverflow.com/a/26722698
func removeDiatrics(s string) (string, error) {
transformer := transform.Chain(
norm.NFD,
runes.Remove(runes.In(unicode.Mn)),
norm.NFC,
)
s, _, err := transform.String(transformer, s)
if err != nil {
return "", err
}
return s, nil
}

// Match returns true if all substrings are contained in str.
// 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
}

for _, sub := range substrings {
cleanSub, err := removeDiatrics(strings.ToLower(sub))
if err != nil {
return false, err
}
if !strings.Contains(str, cleanSub) {
return false, nil
}
}
return true, nil
}
1 change: 1 addition & 0 deletions cli/board/board.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func NewCommand() *cobra.Command {
boardCommand.AddCommand(initDetailsCommand())
boardCommand.AddCommand(initListCommand())
boardCommand.AddCommand(initListAllCommand())
boardCommand.AddCommand(initSearchCommand())

return boardCommand
}
99 changes: 99 additions & 0 deletions cli/board/search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// This file is part of arduino-cli.
//
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to [email protected].

package board

import (
"context"
"os"
"sort"
"strings"

"github.com/arduino/arduino-cli/cli/errorcodes"
"github.com/arduino/arduino-cli/cli/feedback"
"github.com/arduino/arduino-cli/cli/instance"
"github.com/arduino/arduino-cli/commands/board"
rpc "github.com/arduino/arduino-cli/rpc/commands"
"github.com/arduino/arduino-cli/table"
"github.com/spf13/cobra"
)

func initSearchCommand() *cobra.Command {
var searchCommand = &cobra.Command{
Use: "search [boardname]",
Short: "List all known boards and their corresponding FQBN.",
Long: "" +
"List all boards that have the support platform installed. You can search\n" +
"for a specific board if you specify the board name",
Example: "" +
" " + os.Args[0] + " board search\n" +
" " + os.Args[0] + " board search zero",
Args: cobra.ArbitraryArgs,
Run: runSearchCommand,
}
searchCommand.Flags().BoolVarP(&searchFlags.showHiddenBoard, "show-hidden", "a", false, "Show also boards marked as 'hidden' in the platform")
return searchCommand
}

var searchFlags struct {
showHiddenBoard bool
}

func runSearchCommand(cmd *cobra.Command, args []string) {
inst, err := instance.CreateInstance()
if err != nil {
feedback.Errorf("Error searching boards: %v", err)
os.Exit(errorcodes.ErrGeneric)
}

res, err := board.Search(context.Background(), &rpc.BoardSearchReq{
Instance: inst,
SearchArgs: strings.Join(args, " "),
IncludeHiddenBoards: searchFlags.showHiddenBoard,
})
if err != nil {
feedback.Errorf("Error searching boards: %v", err)
os.Exit(errorcodes.ErrGeneric)
}

feedback.PrintResult(searchResults{res.Boards})
}

// output from this command requires special formatting so we create a dedicated
// feedback.Result implementation
type searchResults struct {
boards []*rpc.BoardListItem
}

func (r searchResults) Data() interface{} {
return r.boards
}

func (r searchResults) String() string {
sort.Slice(r.boards, func(i, j int) bool {
return r.boards[i].GetName() < r.boards[j].GetName()
})

t := table.New()
t.SetHeader("Board Name", "FQBN", "Platform ID", "")
for _, item := range r.boards {
hidden := ""
if item.IsHidden {
hidden = "(hidden)"
}
t.AddRow(item.GetName(), item.GetFQBN(), item.Platform.ID, hidden)
}
return t.Render()
}
Loading

0 comments on commit 13c6edf

Please sign in to comment.