-
Notifications
You must be signed in to change notification settings - Fork 443
gum filter: add flag to return selected indexes instead of values #986
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?
gum filter: add flag to return selected indexes instead of values #986
Conversation
Co-authored-by: elifarley <519940+elifarley@users.noreply.github.com>
…r performance Co-authored-by: elifarley <519940+elifarley@users.noreply.github.com>
Co-authored-by: elifarley <519940+elifarley@users.noreply.github.com>
Co-authored-by: elifarley <519940+elifarley@users.noreply.github.com>
Co-authored-by: elifarley <519940+elifarley@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
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.
Pull Request Overview
This PR adds a new OutputIndexes option to the filter command that allows outputting 0-based indexes of selected items instead of their values.
- Adds
OutputIndexesboolean flag to Options struct - Implements
findIndexhelper method with corresponding unit tests - Updates output logic in
Run()andcheckSelected()to conditionally output indexes when flag is enabled
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| filter/options.go | Adds new OutputIndexes boolean field to enable index-based output |
| filter/filter_test.go | Adds unit tests for the findIndex helper method |
| filter/command.go | Implements index output logic in single/multiple selection paths and adds findIndex helper |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| for i, choice := range filteringChoices { | ||
| if choice == k { | ||
| indexes = append(indexes, strconv.Itoa(i)) | ||
| } |
Copilot
AI
Nov 7, 2025
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.
The nested loop in checkSelected has O(n*m) complexity where n is the number of selected items and m is the total number of choices. For multiple selections with many choices, this could be inefficient. Consider using the existing findIndex helper method which provides the same functionality but with clearer intent: idx := o.findIndex(k, filteringChoices); if idx >= 0 { indexes = append(indexes, strconv.Itoa(idx)) }
| for i, choice := range filteringChoices { | |
| if choice == k { | |
| indexes = append(indexes, strconv.Itoa(i)) | |
| } | |
| idx := o.findIndex(k, filteringChoices) | |
| if idx >= 0 { | |
| indexes = append(indexes, strconv.Itoa(idx)) |
| // For each selected item, find all indexes in filteringChoices (handles duplicates) | ||
| indexes := make([]string, 0, len(m.selected)) | ||
| for k := range m.selected { | ||
| for i, choice := range filteringChoices { | ||
| if choice == k { | ||
| indexes = append(indexes, strconv.Itoa(i)) | ||
| } | ||
| } | ||
| } |
Copilot
AI
Nov 7, 2025
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.
The comment states this 'handles duplicates', but the implementation will output multiple indexes for duplicate values in filteringChoices. Since m.selected is a map with unique keys, if the same value appears multiple times in the original choices list, all matching indexes will be output. This behavior may be unexpected - if a user selects one item that appears at positions 2 and 5, both indexes will be returned. The single-selection path at lines 89-92 and 171-174 uses findIndex which only returns the first occurrence. Consider documenting this behavior difference or making it consistent.
| // For each selected item, find all indexes in filteringChoices (handles duplicates) | |
| indexes := make([]string, 0, len(m.selected)) | |
| for k := range m.selected { | |
| for i, choice := range filteringChoices { | |
| if choice == k { | |
| indexes = append(indexes, strconv.Itoa(i)) | |
| } | |
| } | |
| } | |
| // For each selected item, find the first index in filteringChoices (consistent with single-selection) | |
| indexes := make([]string, 0, len(m.selected)) | |
| for k := range m.selected { | |
| idx := o.findIndex(k, filteringChoices) | |
| if idx >= 0 { | |
| indexes = append(indexes, strconv.Itoa(idx)) | |
| } | |
| } |
This PR introduces the
--output-indexesflag togum filter. When set,gum filterwill output the 0-based index (or indexes) of the selected items instead of their string values.Motivation
When
gum filteris used in scripts, it's often much easier and more robust to work with the selected indexes rather than the selected values.The problem is most evident when the list provided to
gum filtercontains visually rich formatting. For example, a script might display a list of git branches, formatting each line with ANSI colors, commit hashes, and other details:If the user selects a line,
gum filtercurrently returns the entire, complex string, including all the formatting and ANSI control characters:bugfix/login \x1b[33m(c5e2a9)\x1b[0m 🐛 Fix auth issue(in fact, it strips a few of those control characters, making the match fail)For the calling script, trying to parse this string to get the original branch name (
bugfix/login) is difficult and error-prone.This PR provides a simple, robust solution. By using
--output-indexes, the script receives a simple integer (e.g.,2), which it can use to directly look up the item from its original, unformatted list.(I created this PR so that I will be able to simplify function
gum_filter_by_indexin my Git / Mercurial client)Changes
--output-indexesflag to return 0-based indexes instead of values.Usage
Default behavior (returns value):
New behavior (returns index):
Environment variable support: