Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .assets/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,12 @@ def process_tape(tape: Path) -> str:


def main() -> None:
tapes = sorted(ASSETS_DIR.glob("*.tape"))
selector = (
"*.tape" if sys.argv == 0 else sys.argv[1].removesuffix(".tape") + ".tape"
)
print(selector)

tapes = sorted(ASSETS_DIR.glob(selector))
if not tapes:
print("No .tape files found in", ASSETS_DIR)
sys.exit(1)
Expand Down
Binary file modified .assets/multi_selection_custom.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion .assets/multi_selection_custom.tape
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Set Height 600
Type@30ms "./examples/multi_selection_custom"
Sleep 100ms Enter
Sleep 1s
Space
Down Sleep 250ms
Down Sleep 250ms
Space
Sleep 1
Expand Down
3 changes: 2 additions & 1 deletion examples/multi_selection_custom/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ func main() {
}

choices := []lang{
{name: "Python", icon: "🐍"},
{name: "Go", icon: "🐹"},
{name: "Rust", icon: "🦀"},
{name: "Python", icon: "🐍"},
{name: "TypeScript", icon: "📘"},
{name: "Haskell", icon: "λ"},
}
Expand All @@ -44,6 +44,7 @@ func main() {
sp.MinSelections = 2
sp.MaxSelections = 4
sp.LoopCursor = true
sp.PreSelected = selection.PreSelect(choices[1])

// Custom styling with emoji icons.
sp.UnmarkedChoiceStyle = func(c *selection.Choice[lang]) string {
Expand Down
9 changes: 9 additions & 0 deletions selection/multi_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,16 @@ func (m *MultiModel[T]) Init() tea.Cmd {
}

m.filterInput = m.initFilterInput()

m.selectedChoices = make(map[int]bool)
if m.PreSelected != nil {
for _, c := range m.choices {
if m.PreSelected(c) {
m.selectedChoices[c.idx] = true
}
}
}

m.currentChoices, m.availableChoices = m.filteredAndPagedChoices()
m.requestedPageSize = m.PageSize

Expand Down
27 changes: 27 additions & 0 deletions selection/multi_model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,33 @@ func TestMultiZeroMinSelections(t *testing.T) {
}
}

func TestMultiPreSelect(t *testing.T) {
t.Parallel()

m := selection.NewMultiModel(selection.NewMulti("foo:", []string{"a", "b", "c"}))
m.ColorProfile = termenv.TrueColor
m.PageSize = 2
m.PreSelected = selection.PreSelect("b", "c")

test.Run(t, m)
test.AssertGoldenView(t, m, "multi_preselect_pre.golden")

values := getValues(t, m)
if len(values) != 2 || values[0] != "b" || values[1] != "c" {
t.Fatalf("selected values are not b and c: %#v", values)
}

test.Update(t, m, keySpace)

values = getValues(t, m)
if len(values) != 3 || values[0] != "a" || values[1] != "b" || values[2] != "c" {
t.Fatalf("selected values are not a, b and c: %#v", values)
}

test.Update(t, m, keyEnter)
test.AssertGoldenView(t, m, "multi_preselect_post.golden")
}

var keyEsc = tea.KeyPressMsg{Code: tea.KeyEsc}

func getValues[T any](tb testing.TB, m *selection.MultiModel[T]) []T {
Expand Down
21 changes: 21 additions & 0 deletions selection/multi_prompt.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ type MultiSelection[T any] struct {
// disabled and FilterPlaceholder does nothing.
FilterPlaceholder string

// PreSelected is an optional function that decided whether an option should
// be pre-selected. It can easily be populated from a single choice value or
// a slice of choice values using the selection.PreSelected helper.
PreSelected func(c *Choice[T]) bool

// PageSize is the number of choices that are displayed at once. If
// PageSize is smaller than the number of choices, pagination is enabled.
// If PageSize is 0, pagination is disabled. Regardless of the value of
Expand Down Expand Up @@ -286,3 +291,19 @@ func (s *MultiSelection[T]) RunPrompt() ([]T, error) {

return m.Values()
}

func PreSelect[T comparable](preSelectedValues ...T) func(c *Choice[T]) bool {
if len(preSelectedValues) == 0 {
return nil
}

preSelectedMap := map[T]bool{}

for _, v := range preSelectedValues {
preSelectedMap[v] = true
}

return func(c *Choice[T]) bool {
return preSelectedMap[c.Value]
}
}
1 change: 1 addition & 0 deletions selection/testdata/multi_preselect_post.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo: a, b, c
5 changes: 5 additions & 0 deletions selection/testdata/multi_preselect_pre.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
foo:
Filter: Type to filter choices 
▸ ☐ a
⇣ ☑ b
 ☑ c
Loading