summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2021-03-13 02:24:37 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2021-03-13 02:26:41 +0900
commit1b08f43f82af507165ec773922f4793da3cd9b4b (patch)
tree7c553c96917437a5953d0901e1151eeefe4e7858 /src
parentb24a2e2fdcf15b3d0d353795f4bfa3d0b0fc06e6 (diff)
Advanced preview scroll offset expression to better support fixed header
Diffstat (limited to 'src')
-rw-r--r--src/options.go8
-rw-r--r--src/options_test.go6
-rw-r--r--src/terminal.go52
3 files changed, 29 insertions, 37 deletions
diff --git a/src/options.go b/src/options.go
index 29c90373..8d0afe06 100644
--- a/src/options.go
+++ b/src/options.go
@@ -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":
diff --git a/src/options_test.go b/src/options_test.go
index 791b55d4..ce135413 100644
--- a/src/options_test.go
+++ b/src/options_test.go
@@ -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)
diff --git a/src/terminal.go b/src/terminal.go
index 9fa11212..53a32769 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -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 {