Skip to content
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

Feature request: Ability to display current line position and matched item count in fzf info #3866

Closed
5 of 10 tasks
LangLangBart opened this issue Jun 15, 2024 · 7 comments
Closed
5 of 10 tasks
Labels

Comments

@LangLangBart
Copy link
Contributor

Checklist

  • I have read through the manual page (man fzf)
  • I have searched through the existing issues
  • For bug reports, I have checked if the bug is reproducible in the latest version of fzf

Output of fzf --version

0.53.0 (brew)

OS

  • Linux
  • macOS
  • Windows
  • Etc.

Shell

  • bash
  • zsh
  • fish

Problem / Steps to reproduce

Intro

Currently, the info looks like in the image below, displaying the matched count and the total count, as well as the number of selections in multi mode.

---

Feature Description

Ability to display the current line position and the number of matched items.

The request can be hacked together with the current flags by using the --border or the --header to display the desired infos.

FZF_DEFAULT_COMMAND= FZF_DEFAULT_OPTS="" fzf \
  --bind 'result:transform-border-label:echo "[$FZF_POS/$FZF_MATCH_COUNT] ($FZF_SELECT_COUNT)"' \
  --bind 'focus:transform-border-label:echo "[$FZF_POS/$FZF_MATCH_COUNT] ($FZF_SELECT_COUNT)"' \
  --border-label-pos 3 \
  --border bottom \
  --multi \
  --no-info \
  --no-separator \
  --prompt 'Filter: '

Note

The above image is just to better illustrate the request and not a good solution, as the matched count doesn't incrementally update itself in batches in the same way as the current info does on large inputs.

The name of the flag could be --info2=STYLE.

Related

Projects which inspired this request.

@junegunn
Copy link
Owner

junegunn commented Jun 17, 2024

matched count doesn't incrementally update itself in batches in the same way as the current info does on large inputs.

This made me realize that we're not firing result event if the input stream is not complete.

fzf/src/terminal.go

Lines 1241 to 1259 in ed12925

if !t.reading {
switch t.merger.Length() {
case 0:
zero := tui.Zero.AsEvent()
if _, prs := t.keymap[zero]; prs {
t.eventChan <- zero
}
// --sync, only 'focus' is bound, but no items to focus
needActivation = t.suppress && !t.hasResultActions && !t.hasLoadActions && t.hasFocusActions
case 1:
one := tui.One.AsEvent()
if _, prs := t.keymap[one]; prs {
t.eventChan <- one
}
}
if t.hasResultActions {
t.eventChan <- tui.Result.AsEvent()
}
}

But there's no reason that it should be this way. I can't remember why I made that decision. Maybe I was worried about ending up with too many events? Maybe it was just an oversight.

The name of the flag could be --info2=STYLE.

While I agree that an alternative representation is desirable in some cases, we should think through how to implement it and
not rush into a decision.

Something like --info-format="#{match_count}/#{total_count} #{sort} #{track} [#{multi}] (#{progress})" (similar to git format and tmux format) would give the maximum flexibility, but obviously, it isn't simple to get it right.

e.g. How to hide surrounding parentheses and brackets when the inner element evaluates to an empty string? We don't want to see () or []. And how to handle leading and trailing spaces around an empty element, etc.

junegunn added a commit that referenced this issue Jun 17, 2024
@LangLangBart
Copy link
Contributor Author

LangLangBart commented Jun 17, 2024

junegunn added the feature label yesterday

Thanks for considering this a feature.

How to hide surrounding parentheses and brackets when the inner element evaluates to an empty string?

So, some kind of conditional syntax would be needed? Below are some syntax examples for conditionals:

zsh: ternary expression

In zsh, the syntax for a conditional string would be %(x.true-text.false-text). For example:

# Display a different string based on whether the hour is six
print -Pr -- "%(6T.Breakfast is ready.No Breakfast)"
# Print a Thumbs Up emoji or a Cross Mark emoji based on the exit status of the last command
print -Pr -- "%(?.👍.❌)"

go: if…end

Or maybe go1 templates, but the syntax is a bit more uncommon, because of the double curly braces. The gh tool has a --template flag that allows writing go templates, for example, to show me the stargazers_count of a repo only when it is not private.

gh api repos/junegunn/fzf \
  --template '{{ if not .private }}Stars: {{ .stargazers_count }}{{ end }}'

(similar to git format and tmux format)

git

git also has some if…end construct

git for-each-ref --sort=-creatordate \
  --format='%(if)%(HEAD)%(then)%(color:magenta)%(refname:short)%(color:reset)%(else)%(color:yellow)%(refname)%(color:reset)%(end)' 'refs/heads'

But a state for multi mode would be needed to check if it is enabled or not. However, the longer and more complex it becomes to write, the less likely anyone will actually use it. What do you think about some kind of conditional syntax for strings as seen above?

Footnotes

  1. template package - text/template - Go Packages

@junegunn
Copy link
Owner

On second thought, I'm afraid we would end up with a very complex solution for little demand. Shelling out seems like the most practical solution for now. Now that the result event is fixed, one can use transform-border-label or transform-header to display more information on screen, but yeah, it's not an exact substitute for the info panel.

How about adding something like --info-command='echo "[$FZF_POS/$FZF_MATCH_COUNT] ($FZF_SELECT_COUNT)"', and exposing more information? An alternative would be transform-info action. In either way, we can pass the default info line as $FZF_INFO so that the user can extract information from it.

@LangLangBart
Copy link
Contributor Author

LangLangBart commented Jun 18, 2024

How about adding something like --info-command='echo "[$FZF_POS/$FZF_MATCH_COUNT] ($FZF_SELECT_COUNT)"'

It would allow for customizing the info, and the syntax is straightforward and easy to use. I like it.

@junegunn
Copy link
Owner

Added --info-command. It supports ANSI color codes in the output and $FZF_INFO is exported to the command. I've tested it with all info layouts (default, inline, right, inline-right) and everything seems to work as expected. Please test it and let me know if there's a problem.

@LangLangBart
Copy link
Contributor Author

everything seems to work as expected.

Works well. Thank you for your effort in implementing it.

It allows for some custom info commands, as described in the issue, and even some less common ones, such as transforming numbers into Roman numerals.


Please test it

Should there be an additional sentence in the man page under the --info-command option? This sentence could direct the user to another section containing a list of variables. For instance:

For additional environment variables available to the command, see the section ENVIRONMENT VARIABLES EXPORTED TO CHILD PROCESSES.

If a user hasn't read the man page and assigns a loop to it, the typical ⌃ Control + C keybind has no effect to cancel it. One has to close the tab. An issue or user fault ?

fzf --info-command='while : ;do echo "Time: $(date +%H:%M:%S), Matches: $FZF_MATCH_COUNT"; sleep 1;done'

@junegunn
Copy link
Owner

the typical ⌃ Control + C keybind has no effect to cancel it.

All transform actions have the same problem. To allow CTRL-C, we should restore the terminal state to receive user input, but immediately doing so would cause unwanted artifacts to be rendered on screen during the execution. For example, if you hold down CTRL-K or up arrow during a transform action, you would see:

> ^K^K^K^[[A^[[A^[[A

One idea is to receive user input when a certain amount of time has elapsed, e.g. 1 second, assuming that most transform commands finish within the period.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants