diff options
| author | Junegunn Choi <junegunn.c@gmail.com> | 2022-07-20 12:08:54 +0900 |
|---|---|---|
| committer | Junegunn Choi <junegunn.c@gmail.com> | 2022-07-20 12:08:54 +0900 |
| commit | 82b46726fc9e568e463af184c065fee2bf7045b7 (patch) | |
| tree | 59760f81d9a0587d7218101193747522c449aee7 /src | |
| parent | 8df872a482799377fc03c3ef58f408484bf6b7bf (diff) | |
| download | fzf-82b46726fc9e568e463af184c065fee2bf7045b7.tar.gz | |
Add support for an alternative preview window layout
Close #2804
Close #2844
Related #2277
Diffstat (limited to 'src')
| -rw-r--r-- | src/options.go | 29 | ||||
| -rw-r--r-- | src/terminal.go | 154 |
2 files changed, 112 insertions, 71 deletions
diff --git a/src/options.go b/src/options.go index b0afacda..93178df5 100644 --- a/src/options.go +++ b/src/options.go @@ -89,7 +89,7 @@ const usage = `usage: fzf [options] [,[no]wrap][,[no]cycle][,[no]follow][,[no]hidden] [,border-BORDER_OPT] [,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES] - [,default] + [,default][,<SIZE_THRESHOLD(ALTERNATIVE_LAYOUT)] Scripting -q, --query=STR Start the finder with the given query @@ -175,10 +175,14 @@ type previewOpts struct { follow bool border tui.BorderShape headerLines int + threshold int + alternative *previewOpts } func (a previewOpts) sameLayout(b previewOpts) bool { - return a.size == b.size && a.position == b.position && a.border == b.border && a.hidden == b.hidden + return a.size == b.size && a.position == b.position && a.border == b.border && a.hidden == b.hidden && a.threshold == b.threshold && + (a.alternative != nil && b.alternative != nil && a.alternative.sameLayout(*b.alternative) || + a.alternative == nil && b.alternative == nil) } func (a previewOpts) sameContentLayout(b previewOpts) bool { @@ -247,7 +251,7 @@ type Options struct { } func defaultPreviewOpts(command string) previewOpts { - return previewOpts{command, posRight, sizeSpec{50, true}, "", false, false, false, false, tui.BorderRounded, 0} + return previewOpts{command, posRight, sizeSpec{50, true}, "", false, false, false, false, tui.BorderRounded, 0, 0, nil} } func defaultOptions() *Options { @@ -1169,12 +1173,19 @@ func parseInfoStyle(str string) infoStyle { } func parsePreviewWindow(opts *previewOpts, input string) { - delimRegex := regexp.MustCompile("[:,]") // : for backward compatibility + tokenRegex := regexp.MustCompile(`[:,]*(<([1-9][0-9]*)\(([^)<]+)\)|[^,:]+)`) sizeRegex := regexp.MustCompile("^[0-9]+%?$") offsetRegex := regexp.MustCompile(`^(\+{-?[0-9]+})?([+-][0-9]+)*(-?/[1-9][0-9]*)?$`) headerRegex := regexp.MustCompile("^~(0|[1-9][0-9]*)$") - tokens := delimRegex.Split(input, -1) - for _, token := range tokens { + tokens := tokenRegex.FindAllStringSubmatch(input, -1) + var alternative string + for _, match := range tokens { + if len(match[2]) > 0 { + opts.threshold = atoi(match[2]) + alternative = match[3] + continue + } + token := match[1] switch token { case "": case "default": @@ -1233,6 +1244,12 @@ func parsePreviewWindow(opts *previewOpts, input string) { } } } + if len(alternative) > 0 { + alternativeOpts := *opts + opts.alternative = &alternativeOpts + opts.alternative.alternative = nil + parsePreviewWindow(opts.alternative, alternative) + } } func parseMargin(opt string, margin string) [4]sizeSpec { diff --git a/src/terminal.go b/src/terminal.go index 3c13b373..96bb6411 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -819,12 +819,15 @@ func (t *Terminal) resizeWindows() { } if t.window != nil { t.window.Close() + t.window = nil } if t.pborder != nil { t.pborder.Close() + t.pborder = nil } if t.pwindow != nil { t.pwindow.Close() + t.pwindow = nil } // Reset preview version so that full redraw occurs t.previewed.version = 0 @@ -869,76 +872,97 @@ func (t *Terminal) resizeWindows() { width = screenWidth - marginInt[1] - marginInt[3] height = screenHeight - marginInt[0] - marginInt[2] + // Set up preview window noBorder := tui.MakeBorderStyle(tui.BorderNone, t.unicode) if previewVisible { - createPreviewWindow := func(y int, x int, w int, h int) { - pwidth := w - pheight := h - var previewBorder tui.BorderStyle - if t.previewOpts.border == tui.BorderNone { - previewBorder = tui.MakeTransparentBorder() - } else { - previewBorder = tui.MakeBorderStyle(t.previewOpts.border, t.unicode) + var resizePreviewWindows func(previewOpts previewOpts) + resizePreviewWindows = func(previewOpts previewOpts) { + if previewOpts.hidden { + return + } + hasThreshold := previewOpts.threshold > 0 && previewOpts.alternative != nil + createPreviewWindow := func(y int, x int, w int, h int) { + pwidth := w + pheight := h + var previewBorder tui.BorderStyle + if previewOpts.border == tui.BorderNone { + previewBorder = tui.MakeTransparentBorder() + } else { + previewBorder = tui.MakeBorderStyle(previewOpts.border, t.unicode) + } + t.pborder = t.tui.NewWindow(y, x, w, h, true, previewBorder) + switch previewOpts.border { + case tui.BorderSharp, tui.BorderRounded: + pwidth -= 4 + pheight -= 2 + x += 2 + y += 1 + case tui.BorderLeft: + pwidth -= 2 + x += 2 + case tui.BorderRight: + pwidth -= 2 + case tui.BorderTop: + pheight -= 1 + y += 1 + case tui.BorderBottom: + pheight -= 1 + case tui.BorderHorizontal: + pheight -= 2 + y += 1 + case tui.BorderVertical: + pwidth -= 4 + x += 2 + } + t.pwindow = t.tui.NewWindow(y, x, pwidth, pheight, true, noBorder) } - t.pborder = t.tui.NewWindow(y, x, w, h, true, previewBorder) - switch t.previewOpts.border { - case tui.BorderSharp, tui.BorderRounded: - pwidth -= 4 - pheight -= 2 - x += 2 - y += 1 - case tui.BorderLeft: - pwidth -= 2 - x += 2 - case tui.BorderRight: - pwidth -= 2 - case tui.BorderTop: - pheight -= 1 - y += 1 - case tui.BorderBottom: - pheight -= 1 - case tui.BorderHorizontal: - pheight -= 2 - y += 1 - case tui.BorderVertical: - pwidth -= 4 - x += 2 + verticalPad := 2 + minPreviewHeight := 3 + switch previewOpts.border { + case tui.BorderNone, tui.BorderVertical, tui.BorderLeft, tui.BorderRight: + verticalPad = 0 + minPreviewHeight = 1 + case tui.BorderTop, tui.BorderBottom: + verticalPad = 1 + minPreviewHeight = 2 + } + switch previewOpts.position { + case posUp, posDown: + pheight := calculateSize(height, previewOpts.size, minHeight, minPreviewHeight, verticalPad) + if hasThreshold && pheight < previewOpts.threshold { + resizePreviewWindows(*previewOpts.alternative) + return + } + if previewOpts.position == posUp { + t.window = t.tui.NewWindow( + marginInt[0]+pheight, marginInt[3], width, height-pheight, false, noBorder) + createPreviewWindow(marginInt[0], marginInt[3], width, pheight) + } else { + t.window = t.tui.NewWindow( + marginInt[0], marginInt[3], width, height-pheight, false, noBorder) + createPreviewWindow(marginInt[0]+height-pheight, marginInt[3], width, pheight) + } + case posLeft, posRight: + pwidth := calculateSize(width, previewOpts.size, minWidth, 5, 4) + if hasThreshold && pwidth < previewOpts.threshold { + fmt.Println("Alternative", (*previewOpts.alternative).position == posDown) + resizePreviewWindows(*previewOpts.alternative) + return + } + if previewOpts.position == posLeft { + t.window = t.tui.NewWindow( + marginInt[0], marginInt[3]+pwidth, width-pwidth, height, false, noBorder) + createPreviewWindow(marginInt[0], marginInt[3], pwidth, height) + } else { + t.window = t.tui.NewWindow( + marginInt[0], marginInt[3], width-pwidth, height, false, noBorder) + createPreviewWindow(marginInt[0], marginInt[3]+width-pwidth, pwidth, height) + } } - t.pwindow = t.tui.NewWindow(y, x, pwidth, pheight, true, noBorder) - } - verticalPad := 2 - minPreviewHeight := 3 - switch t.previewOpts.border { - case tui.BorderNone, tui.BorderVertical, tui.BorderLeft, tui.BorderRight: - verticalPad = 0 - minPreviewHeight = 1 - case tui.BorderTop, tui.BorderBottom: - verticalPad = 1 - minPreviewHeight = 2 - } - switch t.previewOpts.position { - case posUp: - pheight := calculateSize(height, t.previewOpts.size, minHeight, minPreviewHeight, verticalPad) - t.window = t.tui.NewWindow( - marginInt[0]+pheight, marginInt[3], width, height-pheight, false, noBorder) - createPreviewWindow(marginInt[0], marginInt[3], width, pheight) - case posDown: - pheight := calculateSize(height, t.previewOpts.size, minHeight, minPreviewHeight, verticalPad) - t.window = t.tui.NewWindow( - marginInt[0], marginInt[3], width, height-pheight, false, noBorder) - createPreviewWindow(marginInt[0]+height-pheight, marginInt[3], width, pheight) - case posLeft: - pwidth := calculateSize(width, t.previewOpts.size, minWidth, 5, 4) - t.window = t.tui.NewWindow( - marginInt[0], marginInt[3]+pwidth, width-pwidth, height, false, noBorder) - createPreviewWindow(marginInt[0], marginInt[3], pwidth, height) - case posRight: - pwidth := calculateSize(width, t.previewOpts.size, minWidth, 5, 4) - t.window = t.tui.NewWindow( - marginInt[0], marginInt[3], width-pwidth, height, false, noBorder) - createPreviewWindow(marginInt[0], marginInt[3]+width-pwidth, pwidth, height) } - } else { + resizePreviewWindows(t.previewOpts) + } + if t.window == nil { t.window = t.tui.NewWindow( marginInt[0], marginInt[3], |
