From 4298c0b1eb31b7563eb608e3fbf4069488ada08d Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Fri, 14 Mar 2025 16:46:23 +0900 Subject: [PATCH] Add `--ghost=TEXT` to display a ghost text when the input is empty --- CHANGELOG.md | 8 ++++++++ man/man1/fzf.1 | 4 ++++ src/options.go | 7 +++++++ src/terminal.go | 7 +++++++ test/test_core.rb | 18 ++++++++++++++++++ 5 files changed, 44 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb883a6c..149574d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ CHANGELOG ========= +0.61.0 +------ +- Added `--ghost=TEXT` to display a ghost text when the input is empty + ```sh + # Display "Type to search" when the input is empty + fzf --ghost "Type to search" + ``` + 0.60.3 ------ - Bug fixes and improvements diff --git a/man/man1/fzf.1 b/man/man1/fzf.1 index 29dd89da..f4c8322c 100644 --- a/man/man1/fzf.1 +++ b/man/man1/fzf.1 @@ -709,6 +709,10 @@ ANSI color codes are supported. Do not display horizontal separator on the info line. A synonym for \fB\-\-separator=''\fB +.TP +.BI "\-\-ghost=" "TEXT" +Ghost text to display when the input is empty + .TP .B "\-\-filepath\-word" Make word-wise movements and actions respect path separators. The following diff --git a/src/options.go b/src/options.go index 8a9e33ff..1f431c45 100644 --- a/src/options.go +++ b/src/options.go @@ -136,6 +136,7 @@ Usage: fzf [options] --separator=STR Draw horizontal separator on info line using the string (default: '─' or '-') --no-separator Hide info line separator + --ghost=TEXT Ghost text to display when the input is empty --filepath-word Make word-wise movements respect path separators --input-border[=STYLE] Draw border around the input section [rounded|sharp|bold|block|thinblock|double|horizontal|vertical| @@ -574,6 +575,7 @@ type Options struct { InfoStyle infoStyle InfoPrefix string InfoCommand string + Ghost string Separator *string JumpLabels string Prompt string @@ -689,6 +691,7 @@ func defaultOptions() *Options { ScrollOff: 3, FileWord: false, InfoStyle: infoDefault, + Ghost: "", Separator: nil, JumpLabels: defaultJumpLabels, Prompt: "> ", @@ -2597,6 +2600,10 @@ func parseOptions(index *int, opts *Options, allArgs []string) error { case "--no-separator": nosep := "" opts.Separator = &nosep + case "--ghost": + if opts.Ghost, err = nextString("ghost text required"); err != nil { + return err + } case "--scrollbar": given, bar := optionalNextString() if given { diff --git a/src/terminal.go b/src/terminal.go index 19230a9d..8f8b800a 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -234,6 +234,7 @@ type Terminal struct { wrap bool wrapSign string wrapSignWidth int + ghost string separator labelPrinter separatorLen int spinner []string @@ -847,6 +848,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor infoCommand: opts.InfoCommand, infoStyle: opts.InfoStyle, infoPrefix: opts.InfoPrefix, + ghost: opts.Ghost, separator: nil, spinner: makeSpinner(opts.Unicode), promptString: opts.Prompt, @@ -2359,6 +2361,11 @@ func (t *Terminal) printPrompt() { t.prompt() before, after := t.updatePromptOffset() + if len(before) == 0 && len(after) == 0 && len(t.ghost) > 0 { + w.CPrint(tui.ColInput.WithAttr(tui.Dim), t.ghost) + return + } + color := tui.ColInput if t.paused { color = tui.ColDisabled diff --git a/test/test_core.rb b/test/test_core.rb index 59cdfac4..882d68c5 100644 --- a/test/test_core.rb +++ b/test/test_core.rb @@ -1813,4 +1813,22 @@ class TestCore < TestInteractive assert_equal ['[0] 1st: foo, 3rd: baz, 2nd: bar'], File.readlines(tempname, chomp: true) end end + + def test_ghost + tmux.send_keys %(seq 100 | #{FZF} --prompt 'X ' --ghost 'Type in query ...'), :Enter + tmux.until do |lines| + assert_equal 100, lines.match_count + assert_includes lines, 'X Type in query ...' + end + tmux.send_keys '100' + tmux.until do |lines| + assert_equal 1, lines.match_count + assert_includes lines, 'X 100' + end + tmux.send_keys 'C-u' + tmux.until do |lines| + assert_equal 100, lines.match_count + assert_includes lines, 'X Type in query ...' + end + end end