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

Cursor and prompt control in function to avoid prompt flick #1814

Closed
1 task done
tmpm697 opened this issue May 22, 2024 · 10 comments
Closed
1 task done

Cursor and prompt control in function to avoid prompt flick #1814

tmpm697 opened this issue May 22, 2024 · 10 comments

Comments

@tmpm697
Copy link

tmpm697 commented May 22, 2024

What happened, and what did you expect to happen?

set-env FZF_DEFAULT_OPTS "--height=40%"
set-env FZF_DEFAULT_COMMAND ""
fn flick-test {
  echo "1\n2\n3\n4\n5\n" | fzf --reverse
  sleep 3
  edit:redraw &full=$true
}
set edit:insert:binding[Ctrl-T] = { flick-test >$os:dev-tty 2>&1 }
github-flick.mov

expecting: after select candidate in fzf and exit fzf cleanly, sleep 3 will not drop cursor to next line while sleep 3 is running --> should keep cursor and prompt as before trigger ctrl-t

so i think a flag that on/off prompt manually by user would solve this issue.

idk if this is bug or feature request, but it looks like a bug to me.

Output of "elvish -version"

0.20.1

Code of Conduct

@krader1961
Copy link
Contributor

expecting: after select candidate in fzf and exit fzf cleanly, sleep 3 will not drop cursor to next line while sleep 3 is running --> should keep cursor and prompt as before trigger ctrl-t

What you describe isn't possible. The fzf command has already written the text followed by a newline. The newline written by fzf is causing the terminal to move the cursor to the line after the selection. This isn't due to anything Elvish is doing.

It's not clear what you expect. Try doing the same thing, by adding the following to the end of you ~/.bashrc:

export FZF_DEFAULT_OPTS="--height=40%"
export FZF_DEFAULT_COMMAND=""
flick-test() {
  echo $'1\n2\n3\n4\n5' | fzf --reverse
  sleep 3
}
bind -x '"\C-t":"flick-test"'

The only difference is that bash will move the cursor to the line following the prompt in effect when you press Ctrl-T. Both Elvish and Bash will redraw the prompt, including anything you might have typed (e.g., "echo") before pressing Ctrl-T. Personally, I prefer the Elvish behavior.

@tmpm697
Copy link
Author

tmpm697 commented May 23, 2024

You can try to remove sleep 3 --> fzf will exit and return prompt super fast, you're including fzf in this case but it's minor. The issue is sleep command holding prompt.

It's ideal if user can also instruct fzf that it should keep prompt intact, just draw its list and redraw its own list below only

Holding prompt is reasonable when you're in interactive mode, in which shell waiting for user to type smth and then let the command change the prompt and wait for it to return result.

But in a function, especially when trigger keybinding to call a function, the interactive behavior causes flick issue which should be a voided.

@krader1961
Copy link
Contributor

I still don't understand what the problem is. There is no way to tell an external program like fzf it should keep the Elvish prompt intact. Elvish could be modified to behave like Bash but it's not clear that is preferable. On the contrary, I like the Elvish behavior of letting the external command use the line containing the current prompt. I also suspect you are using the word "flicker" in a manner different from how the rest of us who have engaged with you on this issue use the term because none of us consider what you are describing to be an example of "flicker". So like @MiLk on the discussion channel I'm going to bow out of this discussion because, despite trying really hard, I still don't understand what the problem is.

@iandol
Copy link
Contributor

iandol commented May 23, 2024

Thanks @krader1961 for the bash version, indeed the same thing happens (except as you say, bash moves the cursor position down so the old prompt is not affected by fzf output). In bash the partially entered text stays on screen (i.e. in bash type 3 then ctrl+t then select 5 and you'll see the 3 and 5 on the screen), very confusing! Elvish removes the partial text so this doesn't happen, I would assume this is a deliberate design choice.

@tmpm697 -- if you use a two line prompt (I use starship) in elvish then it looks more similar to bash...

@krader1961
Copy link
Contributor

@iandol I agree with your analysis. What is unclear to me is whether that difference in behavior is what @tmpm697 is complaining about. That's because their original problem statement is ambiguous. Specifically, this statement:

expecting: after select candidate in fzf and exit fzf cleanly, sleep 3 will not drop cursor to next line while sleep 3 is running --> should keep cursor and prompt as before trigger ctrl-t

@tmpm697 It might help if you (a) commented on how the Bash behavior differs from the Elvish behavior, and (b) provided a mockup of the Elvish behavior you prefer. Regarding point (a) does Bash behave as you prefer? Obviously you can't run Elvish to address my point (b) but it should be straightforward to create a simulated output using the markdown triple-quote mechanism to create a mockup of the output you expect to see.

@iandol
Copy link
Contributor

iandol commented May 25, 2024

What is unclear to me is whether that difference in behavior is what @tmpm697 is complaining about

I am pretty sure it is. For him the prompt is "flickering", which is visible in his first video as a single frame where the Elvish prompt disappears then reappears, causing a "flash". The behaviour is best described as prompt flicker (a fluctuation in brightness caused by the temporary removal of the prompt). He wants the Elvish prompt to remain on screen during the sleep, so that when it returns from sleep there is no flicker on that line.

Here is what Elvish is doing. FRAME C is the critical one, where line 1 prompt disappears.

FRAME A:

~/.config/test>



FRAME B:

~/.config/test>
> |
6/6------------------------------
> 1
  2

FRAME C:

1
|


FRAME D:

1
~/.config/test>


I think he would want FRAME C to be like this (line 1 keeps the prompt, it is line 2 that now holds the fzf output during the sleep):

FRAME C-ALT:

~/.config/test>
1
|

How FRAME D would then be drawn I think is not the issue, the point is the prompt disappears then reappears...

@iandol
Copy link
Contributor

iandol commented May 25, 2024

As I said above, using a two-line prompt you don't see this as most of the prompt is on the first line.

@tmpm697
Copy link
Author

tmpm697 commented May 25, 2024

@iandol thanks, it seems to be like that, when fzf is called -> move cursor where it's needed (in this case drop cursor next line and hold where user can type input)

my idea is simple, hold the cursor/prompt until a program need it or user explicitly allow it, i.e: when fzf needs cursor, gives it, but it should not need prompt until user want to update current dir or current-command which is often after fzf exit.

surprisingly fzf has option --no-clear which instructs fzf not to redraw when it exits but currently aik, if use it prompt will be swallowed by fzf fuzzy menu.

so fzf redraw a lot and it hold the prompt and current-command also while it's running which it shouldn't be, it should hold only area below prompt for its fuzzy menu.

@tmpm697
Copy link
Author

tmpm697 commented May 25, 2024

more info if someone stumble by this issue, this flick issue with fzf and terminal will be reduced if you set fzf --height 100% --> fzf take full terminal screen and display fuzzy list at top

or fzf --layout=default --height 100% --> fzf takes full terminal screen and display fuzzy list at bottom.

or you proactively drop new line for fzf echo "", fzf

or you use two lines prompt which @iandol mentioned above.

but they are not what i want :)

@tmpm697
Copy link
Author

tmpm697 commented Jul 12, 2024

After a while battling with this issue, I think it's not shells in general to blame but mostly terminals.

As general shell users, you use pipe and whatever commands to achieve your purpose, but this is not the case when you deal with script that every call cost you the time to return back to your interactive mode,

which mean the more you're exposed to have a prompt flick,

the close one is writing your script which cost free or instantly return back to your shell which is a bit challenge as you need to understand your shells.

@tmpm697 tmpm697 closed this as completed Jul 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants