leo-arch / fnf

A simple fuzzy finder for the terminal
MIT License
20 stars 2 forks source link

fnf resets bash terminal wrapping settings #2

Open jjhart opened 3 months ago

jjhart commented 3 months ago

I run my terminal with wrapping disabled (so long lines just get truncated at the width of my current terminal window, rather than wrapping).

I recently switched from fzf to fnf for my f*f needs, and it resets my terminal to "wrapping enabled" each time it runs. Here's an example, with a 50-character wide terminal:

# nowrap - expected output
$ echo {0..25}
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 195

$ find . type f | fnf -q foo
foo

# wraps
$ echo {0..25}
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25

# disable wrap
$ tput rmam

# nowrap
$ echo {0..25}
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 195

(note that find, above, is not to blame; this is verified independently).

I can workaround this trivially by adding tput rmam to my bash functions that I use to call fnf, so it's not a big deal for me. Note that fzf does not exhibit this behavior.

A quick glance around the code doesn't show anything obvious in the tty interactions that do this, but I'm not a tty expert. I note there is a tty_getwidth function defined but it is never called.

leo-arch commented 3 months ago

Hi @jjhart, and thanks for reporting. Yes, it seems fnf isn´t restoring (at exit) terminal attributes in some cases. I'll take a look at it.

leo-arch commented 3 months ago

Tested as follows:

tput rmam

echo {0..100}
# output properly unwrapped

ls | fnf

echo {0..100}
# output is now wrapped

What I observed:

  1. fnf is actually restoring the original terminal attributes at exit (via tcsetattr(3)). See tty_init() and tty_reset() in tty.c.
  2. I get the same behavior with fzf (0.53.0).
  3. Tried also other terminal applications (vifm, nnn, lf, fff, ranger, nano) and got the same results (which is quite interesting). Some others, tough, like vim and mc, do keep terminal attributes.
jjhart commented 3 months ago

Interesting, thanks. I did note that fnf -? does not reset the wrapping setting (ie, is benign). tty wizardy is a dark art! I've tried commenting out a few things in tty.c (including the entire new_termios stanza in init) but haven't found any smoking guns.

In any event, all my usage of fnf is wrapped within bash functions, so I've added tput rmam > /dev/null 2>&1 into each of them and my workflow is effectively back to what it was before (I always run unwrapped, so I didn't bother trying to save/restore my current setting).

Thanks!

leo-arch commented 3 months ago

I did note that fnf -? does not reset the wrapping setting

There's no such -? option in fnf. What do you mean exactly?

jjhart commented 3 months ago

There's no such -? option in fnf. What do you mean exactly?

Sorry, it functioned exactly as I expected (print usage) but did so because -? isn't an option. I didn't notice the "invalid option" line. All I'm saying here is that "just launching fnf, by itself, doesn't trigger the behavior". No big surprise there - printing usage to STDERR shouldn't be doing anything out of the ordinary.

$ fnf -?
fnf: invalid option -- ?
Usage: fnf [OPTION]...
 -l, --lines=LINES        Specify how many lines of results to show (default 10)
 -m, --multi              Enable multi-selection
 -p, --prompt=PROMPT      Input prompt (default '> ')
 -P, --pad=NUM            Left pad the list of matches NUM places (default 0)
 -q, --query=QUERY        Use QUERY as the initial search string
 -e, --show-matches=QUERY Output the sorted matches of QUERY
 -t, --tty=TTY            Specify file to use as TTY device (default /dev/tty)
 -s, --show-scores        Show the scores of each match
 -0, --read-null          Read input delimited by ASCII NUL characters
 -j, --workers NUM        Use NUM workers for searching. (default is # of CPUs)
 -i, --show-info          Show selection info line
 -h, --help               Display this help and exit
 -v, --version            Output version information and exit
     --pointer            Pointer to highlighted match (default '>')
     --marker             Multi-select marker (default '*')
     --cycle              Enable cyclic scrolling
     --tab-accepts        TAB accepts
     --right-accepts      Right arrow key accepts
     --left-aborts        Left arrow key aborts
     --reverse            Display from top, prompt at bottom
     --no-color           Run colorless
leo-arch commented 3 months ago

Ok, I get it. I'm still intrigued about this however (mostly because it's seen in other good projects too). So, I'll keep an eye on it.