junegunn / fzf

:cherry_blossom: A command-line fuzzy finder
https://junegunn.github.io/fzf/
MIT License
65.5k stars 2.41k forks source link

[ubuntu] Fast scroll in fzf leaves garbage on screen #1526

Open suzetmk opened 5 years ago

suzetmk commented 5 years ago

When I preview some quite long contents in fzf such as $ git log --oneline --pretty=format:'%an <%ae> | fzf' and scroll them fast with holding PageDown key down, occasionally 1-2 characters of end part of lines are left on screen. I've confirmed this issue with fzf 0.17.5 (5d16b28). And also confirmed that there is no issue when I scroll same contents in less command.

screenshot: Peek 2019-03-13 15-13

junegunn commented 5 years ago

Thanks for reporting.

Please provide a static (preferably short) text file I can use to reproduce the problem myself.

i.e. fzf < repro.txt

suzetmk commented 5 years ago

Hi @junegunn I've re-confirmed it with fzf < /tmp/git_log_linux.txt. Please use attached one.

git_log_linux.txt.gz

suzetmk commented 5 years ago

I've also confirmed this issue with another terminal emulator (urxvt). So this seems something not terminal-dependent.

junegunn commented 5 years ago

I couldn't reproduce on my system (macOS, iterm2). Are you on tmux? I've noticed that tmux has some issues rendering unicode characters.

suzetmk commented 5 years ago

Thanks @junegunn for testing it.

Are you on tmux?

No I'm on pure bash and using neither tmux nor something similar to it.

I've also found that this doesn't occur on the login console. (i.e. the console not on gnome/gtk but directly on frame buffer console, can be shown hitting Ctrl+Alt+F1 on ubuntu) On this console I'm using exactly same .profile as issue-reproducable ones. So this might be something gnome/gtk-related.

If you have any idea for narrowing down the issue (like: testing some other CLI apps using same library as fzf), please note me.

junegunn commented 5 years ago

fzf does not rely on a library but directly uses low-level control codes to render the screen. So I wouldn't be too surprised to find some visual glitches. Anyway, it's hard to fix the issue without an automated test script that can reliably reproduce the problem. For what it's worth, you can hit CTRL-L to trigger a redraw of the screen.

suzetmk commented 5 years ago

Unfortunately redrawing is not suitable for me since these glitches occurs quite often in my actual usecase of scrolling git-log with ANSI-colorized pretty format.

Anyway, it's hard to fix the issue without an automated test script that can reliably reproduce the problem.

Okay, I'll take a look using my macbook at some early date.

bitterfox commented 3 years ago

Hi,

I also encounter a similar issue to this ticket.

tree | fzf Screenshot from 2021-03-13 17-00-04

Also in preview screen: Screenshot from 2021-03-13 17-11-56

Correct tree: Screenshot from 2021-03-13 17-14-10

I analyzed this issue and figured out that https://github.com/mattn/go-runewidth returns 2 for some Unicode char, but actually it's printed as 1 width char in my terminal.

For example, ━ as tree uses in above:

                fmt.Printf("━ = %v\n", util.RuneWidth('━', 0, 0))
// ━ = 2

But may terminal prints it as: Screenshot from 2021-03-13 17-22-11

Confirmed this in tests with my local docker. https://github.com/bitterfox/fzf/commit/fd2a2a9b7889662921ec8f75910c2013aaaad5ce (sorry for dozen debug prints in the test cases)

This test is failing with the latest master.

Screenshot from 2021-03-13 17-29-30 Screenshot from 2021-03-13 17-29-24 Screenshot from 2021-03-13 17-29-01

When

prevLine: ______EOL
nextLine: ━━━━EOL

prevLine.width returns 6*1(_) + 3(EOL) = 9
nextLine.width returns 4*2(━) + 3(EOL) = 11

So nextLine.width > prevLine.width and it doesn't fill any: https://github.com/junegunn/fzf/blob/34fe5ab1431f8d5b59ef588c20c6d41a708dc6b1/src/terminal.go#L1116-L1119

But my terminal print ━ with 1 width char like -, so actually last 2 char(OL here) will remain

prev: ______EOL
next: ----EOL
--------------------
line: ----EOLOL

For a preview, when print ━━━━EOL, it's move and clear from x=11, but the actual width is 7(4*1+3), so the previous char in 8~10 will remain: https://github.com/junegunn/fzf/blob/34fe5ab1431f8d5b59ef588c20c6d41a708dc6b1/src/tui/light.go#L961-L966

I confirmed my change to clear everything before write fix this issue: https://github.com/bitterfox/fzf/commit/b8c9a3454563f741c12fc80f4605653c06233815

I understand this have a tradeoff between visibility improvement for some environment and less performance(deoptimization). So it might be better to have switch behavior by option.

I'm glad if you can fix this issue in some other way or improve my change :bow:

junegunn commented 3 years ago

@bitterfox Thanks for the investigation. Would it help to update mattn/go-runewidth to the latest (make update)?

junegunn commented 3 years ago

Upgrading the library doesn't seem to help. I didn't know that runewidth.RuneWidth('━') returns different results depending on $LC_ALL.

junegunn commented 3 years ago

@bitterfox Does it help in your case to set RUNEWIDTH_EASTASIAN=0 environment variable as suggest in https://github.com/mattn/go-runewidth/issues/14?

y0ast commented 3 years ago

1620497876_screenshot

This is also a problem for some emoji that can be rendered as text. Mostly ☺️ ☹️ ❤️ , which can be 1 or 2 width.

There is this setting that could help: https://github.com/mattn/go-runewidth/blob/master/runewidth.go#L16

but I am not sure about the implications. It seems like the same underlying problem as the east asian characters.

testing this can be done using:

curl https://raw.githubusercontent.com/LukeSmithxyz/voidrice/master/.local/share/larbs/emoji | fzf

shows up with trailing ;

This is on linux with foot terminal, but I also tested with alacritty and it's the same.

Edit: this reproduces on osx+iterm2.

y0ast commented 3 years ago

I looked into the runewidth code: https://github.com/mattn/go-runewidth/blob/master/runewidth.go#L106

I don't see an option to accommodate everything one's setup in the fzf optimized version. It's not possible to know what exactly the width of a line will be given emoji+east asian characters in a line.

There's a couple of solutions:

  1. Always clear the full line as in @bitterfox
  2. Hacky but preserves speed: add some buffer spaces. Either 5 or 10, and hope that's enough. Or equal to width itself, for guaranteed solution.
  3. Expose a number of cli options to set the appropriate runewidth flags at runtime

It seems that 2 with double width is the nicest solution?

https://github.com/junegunn/fzf/blob/master/src/terminal.go#L1139 ->

        t.window.Print(strings.Repeat(" ", 2 * fillSpaces))

I tested this locally and it fixes the emoji problem at least!

crocket commented 3 years ago

This is reproducible on my laptop, but not on my desktop computer.

On my laptop, if I execute fzf on bash in a tmux session, this issue seems to disappear However, if I execute tmux new-session fzf... < ..., the issue appears again.

crocket commented 3 years ago

After comparing the output of env on my laptop and my desktop computer with diff -u, I figured out that LANG=ko_KR.utf8 caused the issue. Replacing LANG=ko_KR.utf8 with LANG=en_US.utf8 fixed the issue for me.

See if env LANG=en_US.utf8 fzf fixes the issue.