Skip to content

Commit

Permalink
Implement --scroll-off=LINES
Browse files Browse the repository at this point in the history
  • Loading branch information
junegunn committed Nov 2, 2021
1 parent e0dd2be commit 02cee22
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 4 deletions.
8 changes: 6 additions & 2 deletions 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 "Oct 2021" "fzf 0.27.3" "fzf - a command-line fuzzy finder"
.TH fzf 1 "Nov 2021" "fzf 0.27.4" "fzf - a command-line fuzzy finder"

.SH NAME
fzf - a command-line fuzzy finder
Expand Down Expand Up @@ -135,10 +135,14 @@ Enable cyclic scroll
Keep the right end of the line visible when it's too long. Effective only when
the query string is empty.
.TP
.BI "--scroll-off=" "LINES"
Number of screen lines to keep above or below when scrolling to the top or to
the bottom (default: 0).
.TP
.B "--no-hscroll"
Disable horizontal scroll
.TP
.BI "--hscroll-off=" "COL"
.BI "--hscroll-off=" "COLS"
Number of screen columns to keep to the right of the highlighted substring
(default: 10). Setting it to a large value will cause the text to be positioned
on the center of the screen.
Expand Down
14 changes: 13 additions & 1 deletion src/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ const usage = `usage: fzf [options]
--bind=KEYBINDS Custom key bindings. Refer to the man page.
--cycle Enable cyclic scroll
--keep-right Keep the right end of the line visible on overflow
--scroll-off=LINES Number of screen lines to keep above or below when
scrolling to the top or to the bottom (default: 0)
--no-hscroll Disable horizontal scroll
--hscroll-off=COL Number of screen columns to keep to the right of the
--hscroll-off=COLS Number of screen columns to keep to the right of the
highlighted substring (default: 10)
--filepath-word Make word-wise movements respect path separators
--jump-labels=CHARS Label characters for jump and jump-accept
Expand Down Expand Up @@ -200,6 +202,7 @@ type Options struct {
KeepRight bool
Hscroll bool
HscrollOff int
ScrollOff int
FileWord bool
InfoStyle infoStyle
JumpLabels string
Expand Down Expand Up @@ -261,6 +264,7 @@ func defaultOptions() *Options {
KeepRight: false,
Hscroll: true,
HscrollOff: 10,
ScrollOff: 0,
FileWord: false,
InfoStyle: infoDefault,
JumpLabels: defaultJumpLabels,
Expand Down Expand Up @@ -1354,6 +1358,8 @@ func parseOptions(opts *Options, allArgs []string) {
opts.Hscroll = false
case "--hscroll-off":
opts.HscrollOff = nextInt(allArgs, &i, "hscroll offset required")
case "--scroll-off":
opts.ScrollOff = nextInt(allArgs, &i, "scroll offset required")
case "--filepath-word":
opts.FileWord = true
case "--no-filepath-word":
Expand Down Expand Up @@ -1530,6 +1536,8 @@ func parseOptions(opts *Options, allArgs []string) {
opts.Tabstop = atoi(value)
} else if match, value := optString(arg, "--hscroll-off="); match {
opts.HscrollOff = atoi(value)
} else if match, value := optString(arg, "--scroll-off="); match {
opts.ScrollOff = atoi(value)
} else if match, value := optString(arg, "--jump-labels="); match {
opts.JumpLabels = value
validateJumpLabels = true
Expand All @@ -1547,6 +1555,10 @@ func parseOptions(opts *Options, allArgs []string) {
errorExit("hscroll offset must be a non-negative integer")
}

if opts.ScrollOff < 0 {
errorExit("scroll offset must be a non-negative integer")
}

if opts.Tabstop < 1 {
errorExit("tab stop must be a positive integer")
}
Expand Down
21 changes: 20 additions & 1 deletion src/terminal.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ type Terminal struct {
keepRight bool
hscroll bool
hscrollOff int
scrollOff int
wordRubout string
wordNext string
cx int
Expand Down Expand Up @@ -502,6 +503,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
keepRight: opts.KeepRight,
hscroll: opts.Hscroll,
hscrollOff: opts.HscrollOff,
scrollOff: opts.ScrollOff,
wordRubout: wordRubout,
wordNext: wordNext,
cx: len(input),
Expand Down Expand Up @@ -2749,9 +2751,26 @@ func (t *Terminal) constrain() {

t.cy = util.Constrain(t.cy, 0, count-1)

minOffset := t.cy - height + 1
minOffset := util.Max(t.cy-height+1, 0)
maxOffset := util.Max(util.Min(count-height, t.cy), 0)
t.offset = util.Constrain(t.offset, minOffset, maxOffset)
if t.scrollOff == 0 {
return
}

scrollOff := util.Min(height/2, t.scrollOff)
for {
prevOffset := t.offset
if t.cy-t.offset < scrollOff {
t.offset = util.Max(minOffset, t.offset-1)
}
if t.cy-t.offset >= height-scrollOff {
t.offset = util.Min(maxOffset, t.offset+1)
}
if t.offset == prevOffset {
break
}
}
}

func (t *Terminal) vmove(o int, allowCycle bool) {
Expand Down
33 changes: 33 additions & 0 deletions test/test_go.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2076,6 +2076,39 @@ def test_reload_should_update_preview
tmux.send_keys 'C-t'
tmux.until { |lines| assert_includes lines[1], '4' }
end

def test_scroll_off
tmux.send_keys "seq 1000 | #{FZF} --scroll-off=3 --bind l:last", :Enter
tmux.until { |lines| assert_equal 1000, lines.item_count }
height = tmux.until { |lines| lines }.first.to_i
tmux.send_keys :PgUp
tmux.until do |lines|
assert_equal height + 3, lines.first.to_i
assert_equal "> #{height}", lines[3].strip
end
tmux.send_keys :Up
tmux.until { |lines| assert_equal "> #{height + 1}", lines[3].strip }
tmux.send_keys 'l'
tmux.until { |lines| assert_equal '> 1000', lines.first.strip }
tmux.send_keys :PgDn
tmux.until { |lines| assert_equal "> #{1000 - height + 1}", lines.reverse[5].strip }
tmux.send_keys :Down
tmux.until { |lines| assert_equal "> #{1000 - height}", lines.reverse[5].strip }
end

def test_scroll_off_large
tmux.send_keys "seq 1000 | #{FZF} --scroll-off=9999", :Enter
tmux.until { |lines| assert_equal 1000, lines.item_count }
height = tmux.until { |lines| lines }.first.to_i
tmux.send_keys :PgUp
tmux.until { |lines| assert_equal "> #{height}", lines[height / 2].strip }
tmux.send_keys :Up
tmux.until { |lines| assert_equal "> #{height + 1}", lines[height / 2].strip }
tmux.send_keys :Up
tmux.until { |lines| assert_equal "> #{height + 2}", lines[height / 2].strip }
tmux.send_keys :Down
tmux.until { |lines| assert_equal "> #{height + 1}", lines[height / 2].strip }
end
end

module TestShell
Expand Down

0 comments on commit 02cee22

Please sign in to comment.