From 43436e48e0dacb51f9ab3da84b4c1ec697b744da Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Tue, 16 May 2023 23:45:31 +0900 Subject: [PATCH] Add new border style: 'block' --- CHANGELOG.md | 2 ++ src/options.go | 8 +++++-- src/terminal.go | 10 ++++----- src/tui/light.go | 24 ++++++++++---------- src/tui/tui.go | 58 ++++++++++++++++++++++++++++++++++++------------ 5 files changed, 69 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07555840..b67cc726 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ CHANGELOG 0.41.0 ------ +- Added color name `preview-border` and `preview-scrollbar` +- Added new border style `block` which uses [block elements](https://en.wikipedia.org/wiki/Block_Elements) - Bug fixes and improvements 0.40.0 diff --git a/src/options.go b/src/options.go index ba84c8b4..e50c1fcc 100644 --- a/src/options.go +++ b/src/options.go @@ -63,7 +63,7 @@ const usage = `usage: fzf [options] (default: 10) --layout=LAYOUT Choose layout: [default|reverse|reverse-list] --border[=STYLE] Draw border around the finder - [rounded|sharp|horizontal|vertical| + [rounded|sharp|bold|block|double|horizontal|vertical| top|bottom|left|right|none] (default: rounded) --border-label=LABEL Label to print on the border --border-label-pos=COL Position of the border label @@ -544,6 +544,8 @@ func parseBorder(str string, optional bool) tui.BorderShape { return tui.BorderSharp case "bold": return tui.BorderBold + case "block": + return tui.BorderBlock case "double": return tui.BorderDouble case "horizontal": @@ -564,7 +566,7 @@ func parseBorder(str string, optional bool) tui.BorderShape { if optional && str == "" { return tui.DefaultBorderShape } - errorExit("invalid border style (expected: rounded|sharp|bold|double|horizontal|vertical|top|bottom|left|right|none)") + errorExit("invalid border style (expected: rounded|sharp|bold|block|double|horizontal|vertical|top|bottom|left|right|none)") } return tui.BorderNone } @@ -1430,6 +1432,8 @@ func parsePreviewWindowImpl(opts *previewOpts, input string, exit func(string)) opts.border = tui.BorderSharp case "border-bold": opts.border = tui.BorderBold + case "border-block": + opts.border = tui.BorderBlock case "border-double": opts.border = tui.BorderDouble case "noborder", "border-none": diff --git a/src/terminal.go b/src/terminal.go index fadfd6c4..c8e2791c 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -717,7 +717,7 @@ func (t *Terminal) environ() []string { func borderLines(shape tui.BorderShape) int { switch shape { - case tui.BorderHorizontal, tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderDouble: + case tui.BorderHorizontal, tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderBlock, tui.BorderDouble: return 2 case tui.BorderTop, tui.BorderBottom: return 1 @@ -1073,7 +1073,7 @@ func (t *Terminal) adjustMarginAndPadding() (int, int, [4]int, [4]int) { if idx == 3 { extraMargin[idx] += 1 + bw } - case tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderDouble: + case tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderBlock, tui.BorderDouble: extraMargin[idx] += 1 + bw*(idx%2) } marginInt[idx] = sizeSpecToInt(idx, sizeSpec) + extraMargin[idx] @@ -1166,7 +1166,7 @@ func (t *Terminal) resizeWindows(forcePreview bool) { t.border = t.tui.NewWindow( marginInt[0], marginInt[3], width+(1+bw), height, false, tui.MakeBorderStyle(tui.BorderRight, t.unicode)) - case tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderDouble: + case tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderBlock, tui.BorderDouble: t.border = t.tui.NewWindow( marginInt[0]-1, marginInt[3]-(1+bw), width+(1+bw)*2, height+2, false, tui.MakeBorderStyle(t.borderShape, t.unicode)) @@ -1200,7 +1200,7 @@ func (t *Terminal) resizeWindows(forcePreview bool) { } t.pborder = t.tui.NewWindow(y, x, w, h, true, previewBorder) switch previewOpts.border { - case tui.BorderSharp, tui.BorderRounded, tui.BorderBold, tui.BorderDouble: + case tui.BorderSharp, tui.BorderRounded, tui.BorderBold, tui.BorderBlock, tui.BorderDouble: pwidth -= (1 + bw) * 2 pheight -= 2 x += 1 + bw @@ -1342,7 +1342,7 @@ func (t *Terminal) printLabel(window tui.Window, render labelPrinter, opts label } switch borderShape { - case tui.BorderHorizontal, tui.BorderTop, tui.BorderBottom, tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderDouble: + case tui.BorderHorizontal, tui.BorderTop, tui.BorderBottom, tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderBlock, tui.BorderDouble: if redrawBorder { window.DrawHBorder() } diff --git a/src/tui/light.go b/src/tui/light.go index 411238d4..bc44b4f8 100644 --- a/src/tui/light.go +++ b/src/tui/light.go @@ -745,7 +745,7 @@ func (w *LightWindow) DrawHBorder() { func (w *LightWindow) drawBorder(onlyHorizontal bool) { switch w.border.shape { - case BorderRounded, BorderSharp, BorderBold, BorderDouble: + case BorderRounded, BorderSharp, BorderBold, BorderBlock, BorderDouble: w.drawBorderAround(onlyHorizontal) case BorderHorizontal: w.drawBorderHorizontal(true, true) @@ -776,14 +776,14 @@ func (w *LightWindow) drawBorderHorizontal(top, bottom bool) { if w.preview { color = ColPreviewBorder } - hw := runewidth.RuneWidth(w.border.horizontal) + hw := runewidth.RuneWidth(w.border.top) if top { w.Move(0, 0) - w.CPrint(color, repeat(w.border.horizontal, w.width/hw)) + w.CPrint(color, repeat(w.border.top, w.width/hw)) } if bottom { w.Move(w.height-1, 0) - w.CPrint(color, repeat(w.border.horizontal, w.width/hw)) + w.CPrint(color, repeat(w.border.bottom, w.width/hw)) } } @@ -799,11 +799,11 @@ func (w *LightWindow) drawBorderVertical(left, right bool) { for y := 0; y < w.height; y++ { w.Move(y, 0) if left { - w.CPrint(color, string(w.border.vertical)) + w.CPrint(color, string(w.border.left)) } w.CPrint(color, repeat(' ', width)) if right { - w.CPrint(color, string(w.border.vertical)) + w.CPrint(color, string(w.border.right)) } } } @@ -814,23 +814,23 @@ func (w *LightWindow) drawBorderAround(onlyHorizontal bool) { if w.preview { color = ColPreviewBorder } - hw := runewidth.RuneWidth(w.border.horizontal) + hw := runewidth.RuneWidth(w.border.top) tcw := runewidth.RuneWidth(w.border.topLeft) + runewidth.RuneWidth(w.border.topRight) bcw := runewidth.RuneWidth(w.border.bottomLeft) + runewidth.RuneWidth(w.border.bottomRight) rem := (w.width - tcw) % hw - w.CPrint(color, string(w.border.topLeft)+repeat(w.border.horizontal, (w.width-tcw)/hw)+repeat(' ', rem)+string(w.border.topRight)) + w.CPrint(color, string(w.border.topLeft)+repeat(w.border.top, (w.width-tcw)/hw)+repeat(' ', rem)+string(w.border.topRight)) if !onlyHorizontal { - vw := runewidth.RuneWidth(w.border.vertical) + vw := runewidth.RuneWidth(w.border.left) for y := 1; y < w.height-1; y++ { w.Move(y, 0) - w.CPrint(color, string(w.border.vertical)) + w.CPrint(color, string(w.border.left)) w.CPrint(color, repeat(' ', w.width-vw*2)) - w.CPrint(color, string(w.border.vertical)) + w.CPrint(color, string(w.border.right)) } } w.Move(w.height-1, 0) rem = (w.width - bcw) % hw - w.CPrint(color, string(w.border.bottomLeft)+repeat(w.border.horizontal, (w.width-bcw)/hw)+repeat(' ', rem)+string(w.border.bottomRight)) + w.CPrint(color, string(w.border.bottomLeft)+repeat(w.border.bottom, (w.width-bcw)/hw)+repeat(' ', rem)+string(w.border.bottomRight)) } func (w *LightWindow) csi(code string) string { diff --git a/src/tui/tui.go b/src/tui/tui.go index 5fd27d0f..63bdfa83 100644 --- a/src/tui/tui.go +++ b/src/tui/tui.go @@ -312,6 +312,7 @@ const ( BorderRounded BorderSharp BorderBold + BorderBlock BorderDouble BorderHorizontal BorderVertical @@ -339,8 +340,10 @@ func (s BorderShape) HasTop() bool { type BorderStyle struct { shape BorderShape - horizontal rune - vertical rune + top rune + bottom rune + left rune + right rune topLeft rune topRight rune bottomLeft rune @@ -353,8 +356,10 @@ func MakeBorderStyle(shape BorderShape, unicode bool) BorderStyle { if !unicode { return BorderStyle{ shape: shape, - horizontal: '-', - vertical: '|', + top: '-', + bottom: '-', + left: '|', + right: '|', topLeft: '+', topRight: '+', bottomLeft: '+', @@ -365,8 +370,10 @@ func MakeBorderStyle(shape BorderShape, unicode bool) BorderStyle { case BorderSharp: return BorderStyle{ shape: shape, - horizontal: '─', - vertical: '│', + top: '─', + bottom: '─', + left: '│', + right: '│', topLeft: '┌', topRight: '┐', bottomLeft: '└', @@ -375,18 +382,37 @@ func MakeBorderStyle(shape BorderShape, unicode bool) BorderStyle { case BorderBold: return BorderStyle{ shape: shape, - horizontal: '━', - vertical: '┃', + top: '━', + bottom: '━', + left: '┃', + right: '┃', topLeft: '┏', topRight: '┓', bottomLeft: '┗', bottomRight: '┛', } + case BorderBlock: + // ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜ + // ▌ ▐ + // ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟ + return BorderStyle{ + shape: shape, + top: '▀', + bottom: '▄', + left: '▌', + right: '▐', + topLeft: '▛', + topRight: '▜', + bottomLeft: '▙', + bottomRight: '▟', + } case BorderDouble: return BorderStyle{ shape: shape, - horizontal: '═', - vertical: '║', + top: '═', + bottom: '═', + left: '║', + right: '║', topLeft: '╔', topRight: '╗', bottomLeft: '╚', @@ -395,8 +421,10 @@ func MakeBorderStyle(shape BorderShape, unicode bool) BorderStyle { } return BorderStyle{ shape: shape, - horizontal: '─', - vertical: '│', + top: '─', + bottom: '─', + left: '│', + right: '│', topLeft: '╭', topRight: '╮', bottomLeft: '╰', @@ -407,8 +435,10 @@ func MakeBorderStyle(shape BorderShape, unicode bool) BorderStyle { func MakeTransparentBorder() BorderStyle { return BorderStyle{ shape: BorderRounded, - horizontal: ' ', - vertical: ' ', + top: ' ', + bottom: ' ', + left: ' ', + right: ' ', topLeft: ' ', topRight: ' ', bottomLeft: ' ',