-
Notifications
You must be signed in to change notification settings - Fork 442
feat: add --initial option for cursor positioning and fix filter --selected bug #916
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| package choose | ||
|
|
||
| import ( | ||
| "testing" | ||
| ) | ||
|
|
||
| func TestInitialPositioning(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| options []string | ||
| initial string | ||
| expected int // expected starting index | ||
| }{ | ||
| { | ||
| name: "initial option exists", | ||
| options: []string{"Apple", "Banana", "Cherry", "Date"}, | ||
| initial: "Cherry", | ||
| expected: 2, | ||
| }, | ||
| { | ||
| name: "initial option doesn't exist", | ||
| options: []string{"Apple", "Banana", "Cherry", "Date"}, | ||
| initial: "Orange", | ||
| expected: 0, // should default to first item | ||
| }, | ||
| { | ||
| name: "empty initial option", | ||
| options: []string{"Apple", "Banana", "Cherry", "Date"}, | ||
| initial: "", | ||
| expected: 0, // should default to first item | ||
| }, | ||
| { | ||
| name: "initial option is first", | ||
| options: []string{"Apple", "Banana", "Cherry", "Date"}, | ||
| initial: "Apple", | ||
| expected: 0, | ||
| }, | ||
| { | ||
| name: "initial option is last", | ||
| options: []string{"Apple", "Banana", "Cherry", "Date"}, | ||
| initial: "Date", | ||
| expected: 3, | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| // Simulate the logic from command.go | ||
| startingIndex := 0 | ||
| if tt.initial != "" { | ||
| for i, option := range tt.options { | ||
| if option == tt.initial { | ||
| startingIndex = i | ||
| break | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if startingIndex != tt.expected { | ||
| t.Errorf("expected starting index %d, got %d", tt.expected, startingIndex) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,7 @@ type Options struct { | |
| SelectedPrefix string `help:"Prefix to show on selected items (hidden if limit is 1)" default:"✓ " env:"GUM_CHOOSE_SELECTED_PREFIX"` | ||
| UnselectedPrefix string `help:"Prefix to show on unselected items (hidden if limit is 1)" default:"• " env:"GUM_CHOOSE_UNSELECTED_PREFIX"` | ||
| Selected []string `help:"Options that should start as selected (selects all if given *)" default:"" env:"GUM_CHOOSE_SELECTED"` | ||
| Initial string `help:"Option that should start with the cursor positioned on it" default:"" env:"GUM_CHOOSE_INITIAL"` | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I personally feel like |
||
| SelectIfOne bool `help:"Select the given option if there is only one" group:"Selection"` | ||
| InputDelimiter string `help:"Option delimiter when reading from STDIN" default:"\n" env:"GUM_CHOOSE_INPUT_DELIMITER"` | ||
| OutputDelimiter string `help:"Option delimiter when writing to STDOUT" default:"\n" env:"GUM_CHOOSE_OUTPUT_DELIMITER"` | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -132,15 +132,26 @@ func (o Options) Run() error { | |||||||||
| continue | ||||||||||
| } | ||||||||||
| if o.Limit == 1 { | ||||||||||
| // When the user can choose only one option don't select the option but | ||||||||||
| // start with the cursor hovering over it. | ||||||||||
|
Comment on lines
134
to
+136
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Currently
This would be a significant BC break though, because I imagine a lot of people rely on this behavior of |
||||||||||
| m.cursor = i | ||||||||||
| m.selected[option.Str] = struct{}{} | ||||||||||
| } else { | ||||||||||
| currentSelected++ | ||||||||||
| m.selected[option.Str] = struct{}{} | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Handle initial cursor position if specified | ||||||||||
| if o.Initial != "" { | ||||||||||
| for i, match := range matches { | ||||||||||
| if match.Str == o.Initial { | ||||||||||
| m.cursor = i | ||||||||||
| break | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| tm, err := tea.NewProgram(m, options...).Run() | ||||||||||
| if err != nil { | ||||||||||
| return fmt.Errorf("unable to run filter: %w", err) | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this test is very useful as it is, because it doesn't actually test the code running in the command, it just "simulates" it. If the command changes, this test will happily keep reporting a successful test.
Honestly, I would probably just remove both of the tests. There currently aren't many tests in this repo to begin with and adding them in this PR doesn't feel like the right place to start, especially because the structure of the code for the commands makes it kind of difficult to test only small parts of the functionality like this.
There is an open issue regarding adding tests: #818