Support custom separator of inline info

Close #2030
Close #3084
This commit is contained in:
Junegunn Choi 2023-01-24 17:40:08 +09:00
parent ae897c8cdb
commit 618d317803
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627
5 changed files with 43 additions and 17 deletions

View File

@ -3,6 +3,10 @@ CHANGELOG
0.37.0 0.37.0
------ ------
- Added a way to customize the separator of inline info
```sh
fzf --info 'inline: ' --prompt ' ' --color prompt:bright-yellow
```
- New event - New event
- `focus` - Triggered when the focus changes due to a vertical cursor - `focus` - Triggered when the focus changes due to a vertical cursor
movement or a search result update movement or a search result update

View File

@ -337,11 +337,13 @@ e.g.
Determines the display style of finder info (match counters). Determines the display style of finder info (match counters).
.br .br
.BR default " Display on the next line to the prompt" .BR default " Display on the next line to the prompt"
.br .br
.BR inline " Display on the same line" .BR inline " Display on the same line with the default separator ' < '"
.br .br
.BR hidden " Do not display finder info" .BR inline:SEPARATOR " Display on the same line with a non-default separator"
.br
.BR hidden " Do not display finder info"
.br .br
.TP .TP

View File

@ -70,7 +70,7 @@ const usage = `usage: fzf [options]
(default: 0 or center) (default: 0 or center)
--margin=MARGIN Screen margin (TRBL | TB,RL | T,RL,B | T,R,B,L) --margin=MARGIN Screen margin (TRBL | TB,RL | T,RL,B | T,R,B,L)
--padding=PADDING Padding inside border (TRBL | TB,RL | T,RL,B | T,R,B,L) --padding=PADDING Padding inside border (TRBL | TB,RL | T,RL,B | T,R,B,L)
--info=STYLE Finder info style [default|inline|hidden] --info=STYLE Finder info style [default|hidden|inline|inline:SEPARATOR]
--separator=STR String to form horizontal separator on info line --separator=STR String to form horizontal separator on info line
--no-separator Hide info line separator --no-separator Hide info line separator
--scrollbar[=CHAR] Scrollbar character --scrollbar[=CHAR] Scrollbar character
@ -125,6 +125,8 @@ const usage = `usage: fzf [options]
` `
const defaultInfoSep = " < "
// Case denotes case-sensitivity of search // Case denotes case-sensitivity of search
type Case int type Case int
@ -277,6 +279,7 @@ type Options struct {
ScrollOff int ScrollOff int
FileWord bool FileWord bool
InfoStyle infoStyle InfoStyle infoStyle
InfoSep string
Separator *string Separator *string
JumpLabels string JumpLabels string
Prompt string Prompt string
@ -1319,18 +1322,22 @@ func parseLayout(str string) layoutType {
return layoutDefault return layoutDefault
} }
func parseInfoStyle(str string) infoStyle { func parseInfoStyle(str string) (infoStyle, string) {
switch str { switch str {
case "default": case "default":
return infoDefault return infoDefault, ""
case "inline": case "inline":
return infoInline return infoInline, defaultInfoSep
case "hidden": case "hidden":
return infoHidden return infoHidden, ""
default: default:
errorExit("invalid info style (expected: default|inline|hidden)") prefix := "inline:"
if strings.HasPrefix(str, prefix) {
return infoInline, strings.ReplaceAll(str[len(prefix):], "\n", " ")
}
errorExit("invalid info style (expected: default|hidden|inline|inline:SEPARATOR)")
} }
return infoDefault return infoDefault, ""
} }
func parsePreviewWindow(opts *previewOpts, input string) { func parsePreviewWindow(opts *previewOpts, input string) {
@ -1598,12 +1605,13 @@ func parseOptions(opts *Options, allArgs []string) {
case "--no-filepath-word": case "--no-filepath-word":
opts.FileWord = false opts.FileWord = false
case "--info": case "--info":
opts.InfoStyle = parseInfoStyle( opts.InfoStyle, opts.InfoSep = parseInfoStyle(
nextString(allArgs, &i, "info style required")) nextString(allArgs, &i, "info style required"))
case "--no-info": case "--no-info":
opts.InfoStyle = infoHidden opts.InfoStyle = infoHidden
case "--inline-info": case "--inline-info":
opts.InfoStyle = infoInline opts.InfoStyle = infoInline
opts.InfoSep = defaultInfoSep
case "--no-inline-info": case "--no-inline-info":
opts.InfoStyle = infoDefault opts.InfoStyle = infoDefault
case "--separator": case "--separator":
@ -1788,7 +1796,7 @@ func parseOptions(opts *Options, allArgs []string) {
} else if match, value := optString(arg, "--layout="); match { } else if match, value := optString(arg, "--layout="); match {
opts.Layout = parseLayout(value) opts.Layout = parseLayout(value)
} else if match, value := optString(arg, "--info="); match { } else if match, value := optString(arg, "--info="); match {
opts.InfoStyle = parseInfoStyle(value) opts.InfoStyle, opts.InfoSep = parseInfoStyle(value)
} else if match, value := optString(arg, "--separator="); match { } else if match, value := optString(arg, "--separator="); match {
opts.Separator = &value opts.Separator = &value
} else if match, value := optString(arg, "--scrollbar="); match { } else if match, value := optString(arg, "--scrollbar="); match {

View File

@ -147,6 +147,7 @@ type labelPrinter func(tui.Window, int)
type Terminal struct { type Terminal struct {
initDelay time.Duration initDelay time.Duration
infoStyle infoStyle infoStyle infoStyle
infoSep string
separator labelPrinter separator labelPrinter
separatorLen int separatorLen int
spinner []string spinner []string
@ -579,6 +580,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
t := Terminal{ t := Terminal{
initDelay: delay, initDelay: delay,
infoStyle: opts.InfoStyle, infoStyle: opts.InfoStyle,
infoSep: opts.InfoSep,
separator: nil, separator: nil,
spinner: makeSpinner(opts.Unicode), spinner: makeSpinner(opts.Unicode),
queryLen: [2]int{0, 0}, queryLen: [2]int{0, 0},
@ -1393,16 +1395,21 @@ func (t *Terminal) printInfo() {
pos = 2 pos = 2
case infoInline: case infoInline:
pos = t.promptLen + t.queryLen[0] + t.queryLen[1] + 1 pos = t.promptLen + t.queryLen[0] + t.queryLen[1] + 1
if pos+len(" < ") > t.window.Width() { str := t.infoSep
return maxWidth := t.window.Width() - pos
width := runewidth.StringWidth(str)
if width > maxWidth {
trimmed, _ := t.trimRight([]rune(str), maxWidth)
str = string(trimmed)
width = maxWidth
} }
t.move(line, pos, t.separatorLen == 0) t.move(line, pos, t.separatorLen == 0)
if t.reading { if t.reading {
t.window.CPrint(tui.ColSpinner, " < ") t.window.CPrint(tui.ColSpinner, str)
} else { } else {
t.window.CPrint(tui.ColPrompt, " < ") t.window.CPrint(tui.ColPrompt, str)
} }
pos += len(" < ") pos += width
case infoHidden: case infoHidden:
return return
} }

View File

@ -1587,6 +1587,11 @@ class TestGoFZF < TestBase
tmux.until { |lines| assert_equal '> 1', lines[-2] } tmux.until { |lines| assert_equal '> 1', lines[-2] }
end end
def test_info_inline_separator
tmux.send_keys 'seq 10 | fzf --info=inline:___ --no-separator', :Enter
tmux.until { |lines| assert_equal '> ___10/10', lines[-1] }
end
def test_change_first_last def test_change_first_last
tmux.send_keys %(seq 1000 | #{FZF} --bind change:first,alt-Z:last), :Enter tmux.send_keys %(seq 1000 | #{FZF} --bind change:first,alt-Z:last), :Enter
tmux.until { |lines| assert_equal 1000, lines.match_count } tmux.until { |lines| assert_equal 1000, lines.match_count }