- Frame CSI by parameter and final byte ranges, string sequences (OSC,
DCS, APC) by ST or BEL terminator
- Consume framed sequence whole. Partial consumption left remainder to be
read as input: CTRL-A as \e[97;5u typed "97;5u" into query
- BEL-terminated OSC reply was worse than junk. Payload typed, then BEL
read as CTRL-G, aborting fzf. \e]0;title\a was enough
- Wait for string terminator in read loop, as already done for CSI
- Take second-chance read only while sequence unfinished. Re-reading after
complete one blocked until next keystroke, holding back what followed
- Leave unterminated sequences alone. That is how ALT-[ and ALT-] arrive
- Skip SOS and PM. Nothing sends them, and waiting for a terminator that
never comes would delay ALT-X and ALT-^
- When the cursor is not at column 0, Init() makes space so fzf draws on
the next line and the prompt line is left intact
- Close() undid that: it moved up onto the prompt line before ESC[J, so
the erase wiped a line fzf never wrote on
- Shells repaint afterwards, so it showed as a flicker of the last prompt
line. Reported on fish, also seen on bash and nushell. zsh erases the
same line but repaints fast enough to hide it
- Erase our own area first, then step back and restore the column, so
nothing on that line is touched, RPROMPT included
Fix#4913
- getch() charged EINTR against a 100 iteration limit meant for read
attempts, and the count only reset once a byte was read
- So signals arriving during an idle prompt drained it, and running out
returned getCharError, which became Event{Fatal} and exit status 2
- Only the cancellable path is affected, hence only --listen
- select() is not restarted by SA_RESTART, unlike the blocking read on
the non-cancellable path, so it is the only one that sees EINTR
- waitReadable() already retries EINTR without a limit
Fix#4917
ESCDELAY=0 makes the retry count zero, so the wait added in d0377ed had
no effect and the reply still leaked. Past the introducer these bytes
cannot be the ESC key, so waiting for them adds no Escape latency.
- Wait at least defaultEscDelay, honour a larger ESCDELAY
- Lone ESC still honours ESCDELAY=0, measured 3ms to exit either way
Fix#4899
Read loop dropped its escDelay retry budget after every successful byte,
so a sequence split across reads reached the parser as a fragment, parsed
as ALT-[ with the remainder left behind as query text.
- fzf queries DECRQM at startup since dab626b, so a terminal answering
late leaked "?2004;2$y" into the query
- Same split leaked modified keys and mouse sequences: CTRL-UP left "5A",
SGR mouse left "0;1;1M"
- Bound unchanged, a stall longer than escDelay still falls back to ALT
Fix#4899
Ask the terminal whether the mode is already on (DECRQM) and put it back
that way on exit. Forcing it off broke pasting in shells that run fzf
from a line editor widget, which enable the mode only when the editor
starts. Terminals that do not answer fall back to disabling it.
- Startup queries go out in one write, cursor position last. Every
terminal answers DSR, so its reply bounds the wait: a paste reply
still missing by then means the terminal does not know the query.
- Bound the first read with select(2). Terminals that never answer
escape sequences, such as FreeBSD virtual terminals, blocked startup
until a key was pressed, and that keystroke was then discarded.
Fix#4887Fix#2860Fix#976
The display sanitizer already stripped raw 8-bit C1 bytes (0x80-0x9F)
because they decode to RuneError as standalone bytes. Their valid UTF-8
encodings (0xC2 0x80 .. 0xC2 0x9F) decode to the same code points but
were passed through, allowing a filename or input line containing CSI
(U+009B), OSC (U+009D), or DCS (U+0090) to inject terminal control
sequences when rendered.
New BorderShape that embeds the section inside the --list-border
frame, joined to the list content by a horizontal separator with
T-junctions where the list shape has side borders. Requires a list
border with both top and bottom segments; falls back to 'line'
otherwise. Stacks when multiple sections are inline.
Sections inherit --color list-border by default and are colored as a
uniform block via their own --color *-border and *-bg.
Incompatible with --header-first. --header-border=inline requires
--header-lines-border to be inline or unset.
Support double, curly, dotted, and dashed underline styles via --color
(e.g. underline-curly) and ANSI passthrough (SGR 4:N, 58, 59) with --ansi.
Close#4633Close#4678
Thanks to @shtse8 for the test cases.
Fix#4652
Code was reorganized so that it doesn't delete the current line if the
cursor is not at the front. This should be acceptable in almost all
cases.
Thanks to @phanen for reporting the issue and suggesting the fix.
- Fix parsing in escSequence so 7-byte CSI forms (e.g. ESC [ 5 ; 10 ~) set *sz = 7 and the entire sequence is consumed.
- Prevents trailing bytes (like 10~) from remaining in the input buffer and being printed as stray characters.
* Added tests for `LightRenderer`
* Added common SHIFT, ALT and ALT+SHIFT key sequences
* Added common CTRL key sequences
* Added common CTRL+ALT, CTRL+SHIFT, CTRL+ALT+SHIFT key sequences
* Added proper xterm META modifier handling
according to https://github.com/joejulian/xterm/blob/defc6dd5684a12dc8e56cb6973ef973e7a32caa3/input.c#L357-L375
* Fix `ctrl-backspace` and `ctrl-alt-backspace`
* Fix broken tcell tests on windows by swallowing Resize events
* Added tests for FullscreenRenderer
* Removed own fork of tcell and updated tcell to 2.9.0
tcell 2.9.0 is needed for `Ctrl-Alt-*` and `Ctrl-Alt-Shift-*` shortcuts in Windows
* Replace conditional checks with switch statements to improve readability
* Replace long conditionals with constant slices to improve readability
* Bind `ctrl-bspace` (`ctrl-h`) to `backward-delete-char` by default
Since we now distinguish between Backspace and Ctrl-Backspace, Ctrl-Backspace should trigger the same action as Backspace by default. In that way nothing changes for the user but you can bind other actions to Ctrl-Backspace when desired.
Options:
--footer=STR String to print as footer
--footer-border[=STYLE] Draw border around the footer section
[rounded|sharp|bold|block|thinblock|double|horizontal|vertical|
top|bottom|left|right|line|none] (default: line)
--footer-label=LABEL Label to print on the footer border
--footer-label-pos=COL Position of the footer label
[POSITIVE_INTEGER: columns from left|
NEGATIVE_INTEGER: columns from right][:bottom]
(default: 0 or center)
The default border type for footer is 'line', which draws a single
separator between the footer and the list. It changes its position
depending on `--layout`, so you don't have to manually switch between
'top' and 'bottom'
The 'line' style is now supported by other border types as well.
`--list-border` is the only exception.
Close#2890Close#1396
You can't type in queries in this mode, and the only way to trigger an
fzf search is to use `search(...)` action.
# Click header to trigger search
fzf --header '[src] [test]' --no-input --layout reverse \
--header-border bottom --input-border \
--bind 'click-header:transform-search:echo ${FZF_CLICK_HEADER_WORD:1:-1}'
If you do not want 'current-fg' to inherit attributes of 'fg', prefix it
with 'regular:' to reset them.
# italic and underline
fzf --color fg:italic,current-fg:underline
# only underline
fzf --color fg:italic,current-fg:regular:underline