Skip to content

Commit

Permalink
add: proposal option to change checkmarks in the intercactive multise…
Browse files Browse the repository at this point in the history
…cect
  • Loading branch information
KarolosLykos committed Jan 3, 2023
1 parent b03ed07 commit f5d4818
Show file tree
Hide file tree
Showing 7 changed files with 264 additions and 2 deletions.
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,44 @@ func main() {

</details>

### interactive_multiselect/custom-checkmarks

![Animation](https://raw.githubusercontent.com/pterm/pterm/master/_examples/interactive_multiselect/custom-checkmarks/animation.svg)

<details>

<summary>SHOW SOURCE</summary>

```go
package main

import (
"fmt"

"atomicgo.dev/keyboard/keys"
"github.com/pterm/pterm"
)

func main() {
var options []string

for i := 0; i < 5; i++ {
options = append(options, fmt.Sprintf("Option %d", i))
}

printer := pterm.DefaultInteractiveMultiselect.WithOptions(options)
printer.Filter = false
printer.KeyConfirm = keys.Enter
printer.KeySelect = keys.Space
printer.Checkmarks = pterm.Checkmarks{Selected: "+", NotSelected: "-"}
selectedOptions, _ := printer.Show()
pterm.Info.Printfln("Selected options: %s", pterm.Green(selectedOptions))
}

```

</details>

### interactive_multiselect/custom-keys

![Animation](https://raw.githubusercontent.com/pterm/pterm/master/_examples/interactive_multiselect/custom-keys/animation.svg)
Expand Down
38 changes: 38 additions & 0 deletions _examples/interactive_multiselect/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
### interactive_multiselect/custom-checkmarks

![Animation](https://raw.githubusercontent.com/pterm/pterm/master/_examples/interactive_multiselect/custom-checkmarks/animation.svg)

<details>

<summary>SHOW SOURCE</summary>

```go
package main

import (
"fmt"

"atomicgo.dev/keyboard/keys"
"github.com/pterm/pterm"
)

func main() {
var options []string

for i := 0; i < 5; i++ {
options = append(options, fmt.Sprintf("Option %d", i))
}

printer := pterm.DefaultInteractiveMultiselect.WithOptions(options)
printer.Filter = false
printer.KeyConfirm = keys.Enter
printer.KeySelect = keys.Space
printer.Checkmarks = pterm.Checkmarks{Selected: "+", NotSelected: "-"}
selectedOptions, _ := printer.Show()
pterm.Info.Printfln("Selected options: %s", pterm.Green(selectedOptions))
}

```

</details>

### interactive_multiselect/custom-keys

![Animation](https://raw.githubusercontent.com/pterm/pterm/master/_examples/interactive_multiselect/custom-keys/animation.svg)
Expand Down
32 changes: 32 additions & 0 deletions _examples/interactive_multiselect/custom-checkmarks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# interactive_multiselect/custom-checkmarks

![Animation](animation.svg)

```go
package main

import (
"fmt"

"atomicgo.dev/keyboard/keys"

"github.com/pterm/pterm"
)

func main() {
var options []string

for i := 0; i < 5; i++ {
options = append(options, fmt.Sprintf("Option %d", i))
}

printer := pterm.DefaultInteractiveMultiselect.WithOptions(options)
printer.Filter = false
printer.KeyConfirm = keys.Enter
printer.KeySelect = keys.Space
printer.Checkmarks = pterm.Checkmarks{Selected: "+", NotSelected: "-"}
selectedOptions, _ := printer.Show()
pterm.Info.Printfln("Selected options: %s", pterm.Green(selectedOptions))
}

```
44 changes: 44 additions & 0 deletions _examples/interactive_multiselect/custom-checkmarks/ci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"os"
"time"

"atomicgo.dev/keyboard"
"atomicgo.dev/keyboard/keys"
)

// ------ Automation for CI ------
// You can ignore this function, it is used to automatically run the demo and generate the example animation in our CI system.
func init() {
if os.Getenv("CI") == "true" {
go func() {
time.Sleep(time.Second)
for i := 0; i < 10; i++ {
keyboard.SimulateKeyPress(keys.Down)
if i%2 == 0 {
time.Sleep(time.Millisecond * 100)
keyboard.SimulateKeyPress(keys.Enter)
}
time.Sleep(time.Millisecond * 500)
}
time.Sleep(time.Second)

for _, s := range "fuzzy" {
keyboard.SimulateKeyPress(s)
time.Sleep(time.Millisecond * 150)
}

time.Sleep(time.Second)

for i := 0; i < 2; i++ {
keyboard.SimulateKeyPress(keys.Down)
time.Sleep(time.Millisecond * 300)
}

keyboard.SimulateKeyPress(keys.Enter)
time.Sleep(time.Millisecond * 350)
keyboard.SimulateKeyPress(keys.Tab)
}()
}
}
25 changes: 25 additions & 0 deletions _examples/interactive_multiselect/custom-checkmarks/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import (
"fmt"

"atomicgo.dev/keyboard/keys"

"github.com/pterm/pterm"
)

func main() {
var options []string

for i := 0; i < 5; i++ {
options = append(options, fmt.Sprintf("Option %d", i))
}

printer := pterm.DefaultInteractiveMultiselect.WithOptions(options)
printer.Filter = false
printer.KeyConfirm = keys.Enter
printer.KeySelect = keys.Space
printer.Checkmarks = pterm.Checkmarks{Selected: "+", NotSelected: "-"}
selectedOptions, _ := printer.Show()
pterm.Info.Printfln("Selected options: %s", pterm.Green(selectedOptions))
}
21 changes: 19 additions & 2 deletions interactive_multiselect_printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"atomicgo.dev/keyboard"
"atomicgo.dev/keyboard/keys"
"github.com/lithammer/fuzzysearch/fuzzy"

"github.com/pterm/pterm/internal"
)

Expand All @@ -25,9 +26,18 @@ var (
Filter: true,
KeySelect: keys.Enter,
KeyConfirm: keys.Tab,
Checkmarks: Checkmarks{
Selected: "✓",
NotSelected: "✗",
},
}
)

type Checkmarks struct {
Selected string
NotSelected string
}

// InteractiveMultiselectPrinter is a printer for interactive multiselect menus.
type InteractiveMultiselectPrinter struct {
DefaultText string
Expand All @@ -39,6 +49,7 @@ type InteractiveMultiselectPrinter struct {
Selector string
SelectorStyle *Style
Filter bool
Checkmarks Checkmarks

selectedOption int
selectedOptions []int
Expand Down Expand Up @@ -95,6 +106,12 @@ func (p InteractiveMultiselectPrinter) WithKeyConfirm(keyConfirm keys.KeyCode) *
return &p
}

// WithCheckmarks sets the checkmark
func (p InteractiveMultiselectPrinter) WithCheckmarks(checkmarks Checkmarks) *InteractiveMultiselectPrinter {
p.Checkmarks = checkmarks
return &p
}

// Show shows the interactive multiselect menu and returns the selected entry.
func (p *InteractiveMultiselectPrinter) Show(text ...string) ([]string, error) {
// should be the first defer statement to make sure it is executed last
Expand Down Expand Up @@ -345,9 +362,9 @@ func (p *InteractiveMultiselectPrinter) renderSelectMenu() string {
}
var checkmark string
if p.isSelected(option) {
checkmark = fmt.Sprintf("[%s]", Green("✓"))
checkmark = fmt.Sprintf("[%s]", Green(p.Checkmarks.Selected))
} else {
checkmark = fmt.Sprintf("[%s]", Red("✗"))
checkmark = fmt.Sprintf("[%s]", Red(p.Checkmarks.NotSelected))
}
if i == p.selectedOption {
content += Sprintf("%s %s %s\n", p.renderSelector(), checkmark, option)
Expand Down
68 changes: 68 additions & 0 deletions interactive_multiselect_printer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package pterm_test

import (
"testing"

"atomicgo.dev/keyboard"
"atomicgo.dev/keyboard/keys"
"github.com/MarvinJWendt/testza"

"github.com/pterm/pterm"
)

func TestInteractiveMultiselectPrinter_Show(t *testing.T) {
go func() {
keyboard.SimulateKeyPress(keys.Down)
keyboard.SimulateKeyPress(keys.Down)
keyboard.SimulateKeyPress(keys.Enter)
keyboard.SimulateKeyPress(keys.Tab)
}()
result, _ := pterm.DefaultInteractiveMultiselect.WithOptions([]string{"a", "b", "c", "d", "e"}).WithDefaultOptions([]string{"b"}).Show()
testza.AssertEqual(t, []string{"b", "c"}, result)
}

func TestInteractiveMultiselectPrinter_Show_MaxHeightSlidingWindow(t *testing.T) {
go func() {
keyboard.SimulateKeyPress(keys.Up)
keyboard.SimulateKeyPress(keys.Up)
keyboard.SimulateKeyPress(keys.Enter)
keyboard.SimulateKeyPress(keys.Tab)
}()
result, _ := pterm.DefaultInteractiveMultiselect.WithOptions([]string{"a", "b", "c", "d", "e", "f"}).WithDefaultOptions([]string{"b"}).Show()
testza.AssertEqual(t, []string{"b", "e"}, result)
}

func TestInteractiveMultiselectPrinter_WithDefaultText(t *testing.T) {
p := pterm.DefaultInteractiveMultiselect.WithDefaultText("default")
testza.AssertEqual(t, p.DefaultText, "default")
}

func TestInteractiveMultiselectPrinter_WithDefaultOption(t *testing.T) {
p := pterm.DefaultInteractiveMultiselect.WithDefaultOptions([]string{"default"})
testza.AssertEqual(t, p.DefaultOptions, []string{"default"})
}

func TestInteractiveMultiselectPrinter_WithOptions(t *testing.T) {
p := pterm.DefaultInteractiveMultiselect.WithOptions([]string{"a", "b", "c"})
testza.AssertEqual(t, p.Options, []string{"a", "b", "c"})
}

func TestInteractiveMultiselectPrinter_WithMaxHeight(t *testing.T) {
p := pterm.DefaultInteractiveMultiselect.WithMaxHeight(1337)
testza.AssertEqual(t, p.MaxHeight, 1337)
}

func TestInteractiveMultiselectPrinter_WithKeySelect(t *testing.T) {
p := pterm.DefaultInteractiveMultiselect.WithKeySelect(keys.Left).WithOptions([]string{"a", "b", "c"})
testza.AssertEqual(t, p.KeySelect, keys.Left)
}

func TestInteractiveMultiselectPrinter_WithKeyConfirm(t *testing.T) {
p := pterm.DefaultInteractiveMultiselect.WithKeyConfirm(keys.Left).WithOptions([]string{"a", "b", "c"})
testza.AssertEqual(t, p.KeyConfirm, keys.Left)
}

func TestInteractiveMultiselectPrinter_WithCheckmarks(t *testing.T) {
p := pterm.DefaultInteractiveMultiselect.WithCheckmarks(pterm.Checkmarks{Selected: "+", NotSelected: "-"}).WithOptions([]string{"a", "b", "c"})
testza.AssertEqual(t, p.Checkmarks, pterm.Checkmarks{Selected: "+", NotSelected: "-"})
}

0 comments on commit f5d4818

Please sign in to comment.