Skip to content

Commit

Permalink
Add --header-first option to display header before prompt line
Browse files Browse the repository at this point in the history
  • Loading branch information
junegunn committed Nov 3, 2021
1 parent ffd8bef commit 7bff466
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 11 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
CHANGELOG
=========

0.27.4
0.28.0
------
- Added `--header-first` option to print header before the prompt line
```sh
fzf --header $'Welcome to fzf\n▔▔▔▔▔▔▔▔▔▔▔▔▔▔' --reverse --height 30% --border --header-first
```
- Added `--scroll-off=LINES` option (similar to `scrolloff` option of Vim)
- You can set it to a very large number so that the cursor stays in the
middle of the screen while scrolling
Expand Down
5 changes: 4 additions & 1 deletion man/man1/fzf.1
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
..
.TH fzf 1 "Nov 2021" "fzf 0.27.4" "fzf - a command-line fuzzy finder"
.TH fzf 1 "Nov 2021" "fzf 0.28.0" "fzf - a command-line fuzzy finder"

.SH NAME
fzf - a command-line fuzzy finder
Expand Down Expand Up @@ -299,6 +299,9 @@ are not affected by \fB--with-nth\fR. ANSI color codes are processed even when
The first N lines of the input are treated as the sticky header. When
\fB--with-nth\fR is set, the lines are transformed just like the other
lines that follow.
.TP
.B "--header-first"
Print header before the prompt line
.SS Display
.TP
.B "--ansi"
Expand Down
7 changes: 7 additions & 0 deletions src/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const usage = `usage: fzf [options]
--marker=STR Multi-select marker (default: '>')
--header=STR String to print as header
--header-lines=N The first N lines of the input are treated as header
--header-first Print header before the prompt line
Display
--ansi Enable processing of ANSI color codes
Expand Down Expand Up @@ -225,6 +226,7 @@ type Options struct {
History *History
Header []string
HeaderLines int
HeaderFirst bool
Margin [4]sizeSpec
Padding [4]sizeSpec
BorderShape tui.BorderShape
Expand Down Expand Up @@ -287,6 +289,7 @@ func defaultOptions() *Options {
History: nil,
Header: make([]string, 0),
HeaderLines: 0,
HeaderFirst: false,
Margin: defaultMargin(),
Padding: defaultMargin(),
Unicode: true,
Expand Down Expand Up @@ -1427,6 +1430,10 @@ func parseOptions(opts *Options, allArgs []string) {
case "--header-lines":
opts.HeaderLines = atoi(
nextString(allArgs, &i, "number of header lines required"))
case "--header-first":
opts.HeaderFirst = true
case "--no-header-first":
opts.HeaderFirst = false
case "--preview":
opts.Preview.command = nextString(allArgs, &i, "preview command required")
case "--no-preview":
Expand Down
43 changes: 34 additions & 9 deletions src/terminal.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ type Terminal struct {
printQuery bool
history *History
cycle bool
headerFirst bool
headerLines int
header []string
header0 []string
ansi bool
Expand Down Expand Up @@ -529,6 +531,8 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
paused: opts.Phony,
strong: strongAttr,
cycle: opts.Cycle,
headerFirst: opts.HeaderFirst,
headerLines: opts.HeaderLines,
header: header,
header0: header,
ansi: opts.Ansi,
Expand Down Expand Up @@ -976,12 +980,23 @@ func (t *Terminal) updatePromptOffset() ([]rune, []rune) {
return before, after
}

func (t *Terminal) promptLine() int {
if t.headerFirst {
max := t.window.Height() - 1
if !t.noInfoLine() {
max--
}
return util.Min(len(t.header0)+t.headerLines, max)
}
return 0
}

func (t *Terminal) placeCursor() {
t.move(0, t.promptLen+t.queryLen[0], false)
t.move(t.promptLine(), t.promptLen+t.queryLen[0], false)
}

func (t *Terminal) printPrompt() {
t.move(0, 0, true)
t.move(t.promptLine(), 0, true)
t.prompt()

before, after := t.updatePromptOffset()
Expand All @@ -1003,22 +1018,23 @@ func (t *Terminal) trimMessage(message string, maxWidth int) string {

func (t *Terminal) printInfo() {
pos := 0
line := t.promptLine()
switch t.infoStyle {
case infoDefault:
t.move(1, 0, true)
t.move(line+1, 0, true)
if t.reading {
duration := int64(spinnerDuration)
idx := (time.Now().UnixNano() % (duration * int64(len(t.spinner)))) / duration
t.window.CPrint(tui.ColSpinner, t.spinner[idx])
}
t.move(1, 2, false)
t.move(line+1, 2, false)
pos = 2
case infoInline:
pos = t.promptLen + t.queryLen[0] + t.queryLen[1] + 1
if pos+len(" < ") > t.window.Width() {
return
}
t.move(0, pos, true)
t.move(line, pos, true)
if t.reading {
t.window.CPrint(tui.ColSpinner, " < ")
} else {
Expand Down Expand Up @@ -1061,11 +1077,20 @@ func (t *Terminal) printHeader() {
return
}
max := t.window.Height()
if t.headerFirst {
max--
if !t.noInfoLine() {
max--
}
}
var state *ansiState
for idx, lineStr := range t.header {
line := idx + 2
if t.noInfoLine() {
line--
line := idx
if !t.headerFirst {
line++
if !t.noInfoLine() {
line++
}
}
if line >= max {
continue
Expand Down Expand Up @@ -2644,7 +2669,7 @@ func (t *Terminal) Loop() {
}
}
} else if me.Down {
if my == 0 && mx >= 0 {
if my == t.promptLine() && mx >= 0 {
// Prompt
t.cx = mx + t.xoffset
} else if my >= min {
Expand Down
33 changes: 33 additions & 0 deletions test/test_go.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2109,6 +2109,39 @@ def test_scroll_off_large
tmux.send_keys :Down
tmux.until { |lines| assert_equal "> #{height + 1}", lines[height / 2].strip }
end

def test_header_first
tmux.send_keys "seq 1000 | #{FZF} --header foobar --header-lines 3 --header-first", :Enter
tmux.until do |lines|
expected = <<~OUTPUT
> 4
997/997
>
3
2
1
foobar
OUTPUT

assert_equal expected.chomp, lines.reverse.take(7).reverse.join("\n")
end
end

def test_header_first_reverse
tmux.send_keys "seq 1000 | #{FZF} --header foobar --header-lines 3 --header-first --reverse --inline-info", :Enter
tmux.until do |lines|
expected = <<~OUTPUT
foobar
1
2
3
> < 997/997
> 4
OUTPUT

assert_equal expected.chomp, lines.take(6).join("\n")
end
end
end

module TestShell
Expand Down

0 comments on commit 7bff466

Please sign in to comment.