m/fzf
1
0
mirror of https://github.com/junegunn/fzf.git synced 2025-11-17 15:53:39 -05:00

Advanced preview scroll offset expression to better support fixed header

This commit is contained in:
Junegunn Choi
2021-03-13 02:24:37 +09:00
parent b24a2e2fdc
commit 1b08f43f82
6 changed files with 67 additions and 51 deletions

View File

@@ -84,7 +84,7 @@ const usage = `usage: fzf [options]
[up|down|left|right][:SIZE[%]]
[:[no]wrap][:[no]cycle][:[no]follow][:[no]hidden]
[:rounded|sharp|noborder]
[:+SCROLL[-OFFSET]][:~HEADER_LINES]
[:+SCROLL[OFFSETS][/DENOM]][:~HEADER_LINES]
[:default]
Scripting
@@ -1078,7 +1078,7 @@ func parseInfoStyle(str string) infoStyle {
func parsePreviewWindow(opts *previewOpts, input string) {
tokens := strings.Split(input, ":")
sizeRegex := regexp.MustCompile("^[0-9]+%?$")
offsetRegex := regexp.MustCompile("^\\+([0-9]+|{-?[0-9]+})(-[0-9]+|-/[1-9][0-9]*)?$")
offsetRegex := regexp.MustCompile(`^(\+{-?[0-9]+})?([+-][0-9]+)*(-?/[1-9][0-9]*)?$`)
headerRegex := regexp.MustCompile("^~(0|[1-9][0-9]*)$")
for _, token := range tokens {
switch token {
@@ -1121,7 +1121,7 @@ func parsePreviewWindow(opts *previewOpts, input string) {
} else if sizeRegex.MatchString(token) {
opts.size = parseSize(token, 99, "window size")
} else if offsetRegex.MatchString(token) {
opts.scroll = token[1:]
opts.scroll = token
} else {
errorExit("invalid preview window option: " + token)
}
@@ -1368,7 +1368,7 @@ func parseOptions(opts *Options, allArgs []string) {
opts.Preview.command = ""
case "--preview-window":
parsePreviewWindow(&opts.Preview,
nextString(allArgs, &i, "preview window layout required: [up|down|left|right][:SIZE[%]][:rounded|sharp|noborder][:wrap][:cycle][:hidden][:+SCROLL[-OFFSET]][:~HEADER_LINES][:default]"))
nextString(allArgs, &i, "preview window layout required: [up|down|left|right][:SIZE[%]][:rounded|sharp|noborder][:wrap][:cycle][:hidden][:+SCROLL[OFFSETS][/DENOM]][:~HEADER_LINES][:default]"))
case "--height":
opts.Height = parseHeight(nextString(allArgs, &i, "height required: HEIGHT[%]"))
case "--min-height":

View File

@@ -389,18 +389,18 @@ func TestPreviewOpts(t *testing.T) {
opts.Preview.hidden == true &&
opts.Preview.wrap == true &&
opts.Preview.position == posLeft &&
opts.Preview.scroll == "{1}-/2" &&
opts.Preview.scroll == "+{1}-/2" &&
opts.Preview.size.percent == false &&
opts.Preview.size.size == 15) {
t.Error(opts.Preview)
}
opts = optsFor("--preview-window=up:15:wrap:hidden:+{1}-/2", "--preview-window=down", "--preview-window=cycle")
opts = optsFor("--preview-window=up:15:wrap:hidden:+{1}+3-1-2/2", "--preview-window=down", "--preview-window=cycle")
if !(opts.Preview.command == "" &&
opts.Preview.hidden == true &&
opts.Preview.wrap == true &&
opts.Preview.cycle == true &&
opts.Preview.position == posDown &&
opts.Preview.scroll == "{1}-/2" &&
opts.Preview.scroll == "+{1}+3-1-2/2" &&
opts.Preview.size.percent == false &&
opts.Preview.size.size == 15) {
t.Error(opts.Preview.size.size)

View File

@@ -22,8 +22,9 @@ import (
// import "github.com/pkg/profile"
var placeholder *regexp.Regexp
var numericPrefix *regexp.Regexp
var whiteSuffix *regexp.Regexp
var offsetComponentRegex *regexp.Regexp
var offsetTrimCharsRegex *regexp.Regexp
var activeTempFiles []string
const ellipsis string = ".."
@@ -31,8 +32,9 @@ const clearCode string = "\x1b[2J"
func init() {
placeholder = regexp.MustCompile(`\\?(?:{[+sf]*[0-9,-.]*}|{q}|{\+?f?nf?})`)
numericPrefix = regexp.MustCompile(`^[[:punct:]]*([0-9]+)`)
whiteSuffix = regexp.MustCompile(`\s*$`)
offsetComponentRegex = regexp.MustCompile(`([+-][0-9]+)|(-?/[1-9][0-9]*)`)
offsetTrimCharsRegex = regexp.MustCompile(`[^0-9/+-]`)
activeTempFiles = []string{}
}
@@ -1591,43 +1593,33 @@ func (t *Terminal) replacePlaceholder(template string, forcePlus bool, input str
template, t.ansi, t.delimiter, t.printsep, forcePlus, input, list)
}
// Ascii to positive integer
func atopi(s string) int {
matches := numericPrefix.FindStringSubmatch(s)
if len(matches) < 2 {
return 0
}
n, e := strconv.Atoi(matches[1])
if e != nil || n < 1 {
return 0
}
return n
}
func (t *Terminal) evaluateScrollOffset(list []*Item, height int) int {
offsetExpr := t.replacePlaceholder(t.previewOpts.scroll, false, "", list)
nums := strings.Split(offsetExpr, "-")
switch len(nums) {
case 0:
return 0
case 1, 2:
base := atopi(nums[0])
if base == 0 {
offsetExpr := offsetTrimCharsRegex.ReplaceAllString(
t.replacePlaceholder(t.previewOpts.scroll, false, "", list), "")
atoi := func(s string) int {
n, e := strconv.Atoi(s)
if e != nil {
return 0
} else if len(nums) == 1 {
return base - 1
}
if nums[1][0] == '/' {
denom := atopi(nums[1][1:])
return n
}
base := -1
for _, component := range offsetComponentRegex.FindAllString(offsetExpr, -1) {
if strings.HasPrefix(component, "-/") {
component = component[1:]
}
if component[0] == '/' {
denom := atoi(component[1:])
if denom == 0 {
return base
}
return base - height/denom
}
return base - atopi(nums[1]) - 1
default:
return 0
base += atoi(component)
}
return base
}
func replacePlaceholder(template string, stripAnsi bool, delimiter Delimiter, printsep string, forcePlus bool, query string, allItems []*Item) string {