-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ make
components.Select()
generic (#4811)
The Go `components` 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) HumanName() 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/rawlist/main.go ``` --------- Signed-off-by: Salim Afiune Maya <afiune@mondoo.com>
- Loading branch information
Showing
9 changed files
with
257 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright (c) Mondoo, Inc. | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
|
||
package main | ||
|
||
import ( | ||
"fmt" | ||
|
||
"go.mondoo.com/cnquery/v11/cli/components" | ||
"go.mondoo.com/cnquery/v11/cli/theme" | ||
) | ||
|
||
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// Copyright (c) Mondoo, Inc. | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
|
||
package main | ||
|
||
import ( | ||
"fmt" | ||
|
||
"go.mondoo.com/cnquery/v11/cli/components" | ||
) | ||
|
||
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]) | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright (c) Mondoo, Inc. | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
|
||
package components | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
"text/tabwriter" | ||
|
||
"go.mondoo.com/cnquery/v11/cli/theme" | ||
) | ||
|
||
// 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 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) | ||
// } | ||
// | ||
// ``` | ||
func List[O ListableItem](theme *theme.Theme, list []O) string { | ||
b := &strings.Builder{} | ||
w := tabwriter.NewWriter(b, 1, 1, 1, ' ', tabwriter.TabIndent) | ||
|
||
for i := range list { | ||
assetObj := list[i] | ||
|
||
for i, key := range assetObj.PrintableKeys() { | ||
fmt.Fprint(w, theme.Primary(key, ":\t")) | ||
fmt.Fprintln(w, assetObj.PrintableValue(i)) | ||
} | ||
|
||
fmt.Fprintln(w, "") | ||
} | ||
|
||
w.Flush() | ||
|
||
return b.String() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// Copyright (c) Mondoo, Inc. | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
|
||
package components | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
tea "github.com/charmbracelet/bubbletea" | ||
"github.com/rs/zerolog/log" | ||
) | ||
|
||
// SelectableItem is the interface that items need to implement so that we can select them. | ||
type SelectableItem interface { | ||
Display() string | ||
} | ||
|
||
// 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) 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]) | ||
// } | ||
// | ||
// ``` | ||
func Select[S SelectableItem](msg string, items []S) int { | ||
list := make([]string, len(items)) | ||
|
||
for i := range items { | ||
list[i] = items[i].Display() | ||
} | ||
|
||
selection := -1 // make sure we have an invalid index | ||
model := NewListModel(msg, list, func(s int) { | ||
selection = s | ||
}) | ||
_, err := tea.NewProgram(model, tea.WithInputTTY()).Run() | ||
if err != nil { | ||
fmt.Println("Error running program:", err) | ||
os.Exit(1) | ||
} | ||
|
||
if selection == -1 { | ||
return -1 | ||
} | ||
selected := items[selection] | ||
log.Debug(). | ||
Int("selection", selection). | ||
Str("item", selected.Display()). | ||
Msg("selected") | ||
return selection | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters