From 618d3178033d80fbe13b70e6387c3f0673a1bf7a Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Tue, 24 Jan 2023 17:40:08 +0900 Subject: [PATCH] Support custom separator of inline info Close #2030 Close #3084 --- CHANGELOG.md | 4 ++++ man/man1/fzf.1 | 8 +++++--- src/options.go | 26 +++++++++++++++++--------- src/terminal.go | 17 ++++++++++++----- test/test_go.rb | 5 +++++ 5 files changed, 43 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6233f19..4bd358c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ CHANGELOG 0.37.0 ------ +- Added a way to customize the separator of inline info + ```sh + fzf --info 'inline: ╱ ' --prompt '╱ ' --color prompt:bright-yellow + ``` - New event - `focus` - Triggered when the focus changes due to a vertical cursor movement or a search result update diff --git a/man/man1/fzf.1 b/man/man1/fzf.1 index a2e8c41..8329fd5 100644 --- a/man/man1/fzf.1 +++ b/man/man1/fzf.1 @@ -337,11 +337,13 @@ e.g. Determines the display style of finder info (match counters). .br -.BR default " Display on the next line to the prompt" +.BR default " Display on the next line to the prompt" .br -.BR inline " Display on the same line" +.BR inline " Display on the same line with the default separator ' < '" .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 .TP diff --git a/src/options.go b/src/options.go index 393f580..deff0c8 100644 --- a/src/options.go +++ b/src/options.go @@ -70,7 +70,7 @@ const usage = `usage: fzf [options] (default: 0 or center) --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) - --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 --no-separator Hide info line separator --scrollbar[=CHAR] Scrollbar character @@ -125,6 +125,8 @@ const usage = `usage: fzf [options] ` +const defaultInfoSep = " < " + // Case denotes case-sensitivity of search type Case int @@ -277,6 +279,7 @@ type Options struct { ScrollOff int FileWord bool InfoStyle infoStyle + InfoSep string Separator *string JumpLabels string Prompt string @@ -1319,18 +1322,22 @@ func parseLayout(str string) layoutType { return layoutDefault } -func parseInfoStyle(str string) infoStyle { +func parseInfoStyle(str string) (infoStyle, string) { switch str { case "default": - return infoDefault + return infoDefault, "" case "inline": - return infoInline + return infoInline, defaultInfoSep case "hidden": - return infoHidden + return infoHidden, "" 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) { @@ -1598,12 +1605,13 @@ func parseOptions(opts *Options, allArgs []string) { case "--no-filepath-word": opts.FileWord = false case "--info": - opts.InfoStyle = parseInfoStyle( + opts.InfoStyle, opts.InfoSep = parseInfoStyle( nextString(allArgs, &i, "info style required")) case "--no-info": opts.InfoStyle = infoHidden case "--inline-info": opts.InfoStyle = infoInline + opts.InfoSep = defaultInfoSep case "--no-inline-info": opts.InfoStyle = infoDefault case "--separator": @@ -1788,7 +1796,7 @@ func parseOptions(opts *Options, allArgs []string) { } else if match, value := optString(arg, "--layout="); match { opts.Layout = parseLayout(value) } 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 { opts.Separator = &value } else if match, value := optString(arg, "--scrollbar="); match { diff --git a/src/terminal.go b/src/terminal.go index 62e8043..b09c47d 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -147,6 +147,7 @@ type labelPrinter func(tui.Window, int) type Terminal struct { initDelay time.Duration infoStyle infoStyle + infoSep string separator labelPrinter separatorLen int spinner []string @@ -579,6 +580,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal { t := Terminal{ initDelay: delay, infoStyle: opts.InfoStyle, + infoSep: opts.InfoSep, separator: nil, spinner: makeSpinner(opts.Unicode), queryLen: [2]int{0, 0}, @@ -1393,16 +1395,21 @@ func (t *Terminal) printInfo() { pos = 2 case infoInline: pos = t.promptLen + t.queryLen[0] + t.queryLen[1] + 1 - if pos+len(" < ") > t.window.Width() { - return + str := t.infoSep + 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) if t.reading { - t.window.CPrint(tui.ColSpinner, " < ") + t.window.CPrint(tui.ColSpinner, str) } else { - t.window.CPrint(tui.ColPrompt, " < ") + t.window.CPrint(tui.ColPrompt, str) } - pos += len(" < ") + pos += width case infoHidden: return } diff --git a/test/test_go.rb b/test/test_go.rb index 67207fb..3dd6357 100755 --- a/test/test_go.rb +++ b/test/test_go.rb @@ -1587,6 +1587,11 @@ class TestGoFZF < TestBase tmux.until { |lines| assert_equal '> 1', lines[-2] } 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 tmux.send_keys %(seq 1000 | #{FZF} --bind change:first,alt-Z:last), :Enter tmux.until { |lines| assert_equal 1000, lines.match_count }