Skip to content

Commit

Permalink
🧹 resolve review comments
Browse files Browse the repository at this point in the history
Signed-off-by: Salim Afiune Maya <[email protected]>
  • Loading branch information
afiune committed Nov 4, 2024
1 parent bc63e5c commit b311ed1
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 20 deletions.
3 changes: 2 additions & 1 deletion apps/cnquery/cmd/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ func StartShell(runtime *providers.Runtime, conf *ShellConfig) error {
connectAsset = filteredAssets[selectedAsset]
}
} else {
fmt.Println(components.List(theme.OperatingSystemTheme, "assets", invAssets))
log.Info().Msgf("discovered %d assets(s)", len(invAssets))
fmt.Println(components.List(theme.OperatingSystemTheme, invAssets))
log.Fatal().Msg("cannot connect to more than one asset, use --platform-id to select a specific asset")
}
}
Expand Down
58 changes: 58 additions & 0 deletions cli/components/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# `components` package

This Go package has interactive helpers used by `cnquery` and `cnspec`.

We use a powerful little TUI framework called [bubbletea](https://github.com/charmbracelet/bubbletea).

## `Select` component

Select is an interactive prompt that displays the provided message and displays a
list of items to be selected.

e.g.
```go
type CustomString string

func (s CustomString) Display() string {
return string(s)
}

func main() {
customStrings := []CustomString{"first", "second", "third"}
selected := components.Select("Choose a string", customStrings)
fmt.Printf("You chose the %s string.\n", customStrings[selected])
}
```

To execute this example:
```
go run cli/components/_examples/selector/main.go
```

## `List` component

List is a non-interactive function that lists items to the user.

e.g.
```go
type CustomString string

func (s CustomString) PrintableKeys() []string {
return []string{"string"}
}
func (s CustomString) PrintableValue(_ int) string {
return string(s)
}

func main() {
customStrings := []CustomString{"first", "second", "third"}
list := components.List(theme.OperatingSystemTheme, customStrings)
fmt.Printf(list)
}
```

To execute this example:
```
go run cli/components/_examples/list/main.go
```

Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ func (s CustomString) PrintableValue(_ int) string {

func main() {
customStrings := []CustomString{"first", "second", "third"}
list := components.List(theme.OperatingSystemTheme, "string", customStrings)
list := components.List(theme.OperatingSystemTheme, customStrings)
fmt.Printf(list)
}
2 changes: 1 addition & 1 deletion cli/components/_examples/selector/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

type CustomString string

func (s CustomString) HumanName() string {
func (s CustomString) Display() string {
return string(s)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,19 @@ import (
"strings"
"text/tabwriter"

"github.com/rs/zerolog/log"
"go.mondoo.com/cnquery/v11/cli/theme"
)

// Object is the interface that a list need to implement so we can display its objects.
type Object interface {
// ListableItem is the interface that a list need to implement so we can display its items.
type ListableItem interface {
// PrintableKeys returns the list of keys that will be printed.
PrintableKeys() []string

// PrintableValue returns the key value based of the provided index.
PrintableValue(index int) string
}

// List is a non-interactive function that lists objects to the user.
// List is a non-interactive function that lists items to the user.
//
// e.g.
// ```go
Expand All @@ -37,17 +36,15 @@ type Object interface {
//
// func main() {
// customStrings := []CustomString{"first", "second", "third"}
// list := components.List(theme.OperatingSystemTheme, "string", customStrings)
// list := components.List(theme.OperatingSystemTheme, customStrings)
// fmt.Printf(list)
// }
//
// ```
func List[O Object](theme *theme.Theme, listType string, list []O) string {
func List[O ListableItem](theme *theme.Theme, list []O) string {
b := &strings.Builder{}
w := tabwriter.NewWriter(b, 1, 1, 1, ' ', tabwriter.TabIndent)

log.Debug().Msgf("discovered %d %s(s)", len(list), listType)

for i := range list {
assetObj := list[i]

Expand Down
16 changes: 8 additions & 8 deletions cli/components/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ import (
"github.com/rs/zerolog/log"
)

// Selector is the interface that items need to implement so that we can select them.
type Selector interface {
HumanName() string
// SelectableItem is the interface that items need to implement so that we can select them.
type SelectableItem interface {
Display() string
}

// Select is an interactive prompt that displays the provided message and displays a
// SelectableItem is an interactive prompt that displays the provided message and displays a
// list of items to be selected.
//
// e.g.
// ```go
//
// type CustomString string
//
// func (s CustomString) HumanName() string {
// func (s CustomString) Display() string {
// return string(s)
// }
//
Expand All @@ -35,11 +35,11 @@ type Selector interface {
// }
//
// ```
func Select[S Selector](msg string, items []S) int {
func Select[S SelectableItem](msg string, items []S) int {
list := make([]string, len(items))

for i := range items {
list[i] = items[i].HumanName()
list[i] = items[i].Display()
}

selection := -1 // make sure we have an invalid index
Expand All @@ -58,7 +58,7 @@ func Select[S Selector](msg string, items []S) int {
selected := items[selection]
log.Debug().
Int("selection", selection).
Str("asset", selected.HumanName()).
Str("item", selected.Display()).
Msg("selected")
return selection
}
7 changes: 6 additions & 1 deletion providers-sdk/v1/inventory/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,19 @@ func (a *Asset) PrintableKeys() []string {
func (a *Asset) PrintableValue(index int) string {
switch assetPrintableKeys[index] {
case "name":
return a.HumanName()
return a.Display()
case "platform-id":
return strings.Join(a.PlatformIds, " ")
default:
return a.String()
}
}

// Display implements SelectableItem from the cli/components package.
func (a *Asset) Display() string {
return a.HumanName()
}

func (a *Asset) HumanName() string {
if a == nil {
return ""
Expand Down

0 comments on commit b311ed1

Please sign in to comment.