Add more --border options; default changed to "rounded"

--border option now takes an optional argument that defines the style

  - rounded (new default)
  - sharp
  - horizontal (previous default)
pull/1921/head
Junegunn Choi 4 years ago
parent 99f1e02766
commit d9b1211191
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627

@ -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 "Feb 2020" "fzf 0.21.0" "fzf - a command-line fuzzy finder"
.TH fzf 1 "Mar 2020" "fzf 0.21.0" "fzf - a command-line fuzzy finder"
.SH NAME
fzf - a command-line fuzzy finder
@ -178,8 +178,16 @@ Choose the layout (default: default)
A synonym for \fB--layout=reverse\fB
.TP
.B "--border"
Draw border above and below the finder
.BI "--border" [=STYLE]
Draw border around the finder
.br
.BR rounded " Border with rounded corners (default)"
.br
.BR sharp " Border with sharp corners"
.br
.BR horizontal " Horizontal lines above and below the finder"
.br
.TP
.B "--no-unicode"

@ -57,7 +57,8 @@ const usage = `usage: fzf [options]
--min-height=HEIGHT Minimum height when --height is given in percent
(default: 10)
--layout=LAYOUT Choose layout: [default|reverse|reverse-list]
--border Draw border above and below the finder
--border[=STYLE] Draw border around the finder
[rounded|sharp|horizontal] (default: rounded)
--margin=MARGIN Screen margin (TRBL / TB,RL / T,RL,B / T,R,B,L)
--info=STYLE Finder info style [default|inline|hidden]
--prompt=STR Input prompt (default: '> ')
@ -212,7 +213,7 @@ type Options struct {
Header []string
HeaderLines int
Margin [4]sizeSpec
Bordered bool
BorderShape tui.BorderShape
Unicode bool
Tabstop int
ClearOnExit bool
@ -301,12 +302,12 @@ func nextString(args []string, i *int, message string) string {
return args[*i]
}
func optionalNextString(args []string, i *int) string {
if len(args) > *i+1 && !strings.HasPrefix(args[*i+1], "-") {
func optionalNextString(args []string, i *int) (bool, string) {
if len(args) > *i+1 && !strings.HasPrefix(args[*i+1], "-") && !strings.HasPrefix(args[*i+1], "+") {
*i++
return args[*i]
return true, args[*i]
}
return ""
return false, ""
}
func atoi(str string) int {
@ -400,6 +401,23 @@ func parseAlgo(str string) algo.Algo {
return algo.FuzzyMatchV2
}
func parseBorder(str string, optional bool) tui.BorderShape {
switch str {
case "rounded":
return tui.BorderRounded
case "sharp":
return tui.BorderSharp
case "horizontal":
return tui.BorderHorizontal
default:
if optional && str == "" {
return tui.BorderRounded
}
errorExit("invalid border style (expected: rounded|sharp|horizontal)")
}
return tui.BorderNone
}
func parseKeyChords(str string, message string) map[int]string {
if len(str) == 0 {
errorExit(message)
@ -1098,7 +1116,7 @@ func parseOptions(opts *Options, allArgs []string) {
case "--bind":
parseKeymap(opts.Keymap, nextString(allArgs, &i, "bind expression required"))
case "--color":
spec := optionalNextString(allArgs, &i)
_, spec := optionalNextString(allArgs, &i)
if len(spec) == 0 {
opts.Theme = tui.EmptyTheme()
} else {
@ -1246,9 +1264,10 @@ func parseOptions(opts *Options, allArgs []string) {
case "--no-margin":
opts.Margin = defaultMargin()
case "--no-border":
opts.Bordered = false
opts.BorderShape = tui.BorderNone
case "--border":
opts.Bordered = true
hasArg, arg := optionalNextString(allArgs, &i)
opts.BorderShape = parseBorder(arg, !hasArg)
case "--no-unicode":
opts.Unicode = false
case "--unicode":
@ -1273,6 +1292,8 @@ func parseOptions(opts *Options, allArgs []string) {
opts.Filter = &value
} else if match, value := optString(arg, "-d", "--delimiter="); match {
opts.Delimiter = delimiterRegexp(value)
} else if match, value := optString(arg, "--border="); match {
opts.BorderShape = parseBorder(value, false)
} else if match, value := optString(arg, "--prompt="); match {
opts.Prompt = value
} else if match, value := optString(arg, "--pointer="); match {

@ -100,7 +100,7 @@ type Terminal struct {
margin [4]sizeSpec
strong tui.Attr
unicode bool
bordered bool
borderShape tui.BorderShape
cleanExit bool
border tui.Window
window tui.Window
@ -370,9 +370,9 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
effectiveMinHeight *= 2
}
if opts.InfoStyle != infoDefault {
effectiveMinHeight -= 1
effectiveMinHeight--
}
if opts.Bordered {
if opts.BorderShape != tui.BorderNone {
effectiveMinHeight += 2
}
return util.Min(termHeight, util.Max(maxHeight, effectiveMinHeight))
@ -391,62 +391,62 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
spinner = []string{`-`, `\`, `|`, `/`, `-`, `\`, `|`, `/`}
}
t := Terminal{
initDelay: delay,
infoStyle: opts.InfoStyle,
spinner: spinner,
queryLen: [2]int{0, 0},
layout: opts.Layout,
fullscreen: fullscreen,
hscroll: opts.Hscroll,
hscrollOff: opts.HscrollOff,
wordRubout: wordRubout,
wordNext: wordNext,
cx: len(input),
cy: 0,
offset: 0,
xoffset: 0,
yanked: []rune{},
input: input,
multi: opts.Multi,
sort: opts.Sort > 0,
toggleSort: opts.ToggleSort,
delimiter: opts.Delimiter,
expect: opts.Expect,
keymap: opts.Keymap,
pressed: "",
printQuery: opts.PrintQuery,
history: opts.History,
margin: opts.Margin,
unicode: opts.Unicode,
bordered: opts.Bordered,
cleanExit: opts.ClearOnExit,
strong: strongAttr,
cycle: opts.Cycle,
header: header,
header0: header,
ansi: opts.Ansi,
tabstop: opts.Tabstop,
reading: true,
failed: nil,
jumping: jumpDisabled,
jumpLabels: opts.JumpLabels,
printer: opts.Printer,
printsep: opts.PrintSep,
merger: EmptyMerger,
selected: make(map[int32]selectedItem),
reqBox: util.NewEventBox(),
preview: opts.Preview,
previewer: previewer{"", 0, 0, previewBox != nil && !opts.Preview.hidden, false},
previewBox: previewBox,
eventBox: eventBox,
mutex: sync.Mutex{},
suppress: true,
slab: util.MakeSlab(slab16Size, slab32Size),
theme: opts.Theme,
startChan: make(chan bool, 1),
killChan: make(chan int),
tui: renderer,
initFunc: func() { renderer.Init() }}
initDelay: delay,
infoStyle: opts.InfoStyle,
spinner: spinner,
queryLen: [2]int{0, 0},
layout: opts.Layout,
fullscreen: fullscreen,
hscroll: opts.Hscroll,
hscrollOff: opts.HscrollOff,
wordRubout: wordRubout,
wordNext: wordNext,
cx: len(input),
cy: 0,
offset: 0,
xoffset: 0,
yanked: []rune{},
input: input,
multi: opts.Multi,
sort: opts.Sort > 0,
toggleSort: opts.ToggleSort,
delimiter: opts.Delimiter,
expect: opts.Expect,
keymap: opts.Keymap,
pressed: "",
printQuery: opts.PrintQuery,
history: opts.History,
margin: opts.Margin,
unicode: opts.Unicode,
borderShape: opts.BorderShape,
cleanExit: opts.ClearOnExit,
strong: strongAttr,
cycle: opts.Cycle,
header: header,
header0: header,
ansi: opts.Ansi,
tabstop: opts.Tabstop,
reading: true,
failed: nil,
jumping: jumpDisabled,
jumpLabels: opts.JumpLabels,
printer: opts.Printer,
printsep: opts.PrintSep,
merger: EmptyMerger,
selected: make(map[int32]selectedItem),
reqBox: util.NewEventBox(),
preview: opts.Preview,
previewer: previewer{"", 0, 0, previewBox != nil && !opts.Preview.hidden, false},
previewBox: previewBox,
eventBox: eventBox,
mutex: sync.Mutex{},
suppress: true,
slab: util.MakeSlab(slab16Size, slab32Size),
theme: opts.Theme,
startChan: make(chan bool, 1),
killChan: make(chan int),
tui: renderer,
initFunc: func() { renderer.Init() }}
t.prompt, t.promptLen = t.processTabs([]rune(opts.Prompt), 0)
t.pointer, t.pointerLen = t.processTabs([]rune(opts.Pointer), 0)
t.marker, t.markerLen = t.processTabs([]rune(opts.Marker), 0)
@ -595,8 +595,11 @@ func (t *Terminal) resizeWindows() {
} else {
marginInt[idx] = int(sizeSpec.size)
}
if t.bordered && idx%2 == 0 {
marginInt[idx] += 1
switch t.borderShape {
case tui.BorderHorizontal:
marginInt[idx] += 1 - idx%2
case tui.BorderRounded, tui.BorderSharp:
marginInt[idx] += 1 + idx%2
}
}
adjust := func(idx1 int, idx2 int, max int, min int) {
@ -636,18 +639,26 @@ func (t *Terminal) resizeWindows() {
width := screenWidth - marginInt[1] - marginInt[3]
height := screenHeight - marginInt[0] - marginInt[2]
if t.bordered {
switch t.borderShape {
case tui.BorderHorizontal:
t.border = t.tui.NewWindow(
marginInt[0]-1,
marginInt[3],
width,
height+2,
false, tui.MakeBorderStyle(tui.BorderHorizontal, t.unicode))
case tui.BorderRounded, tui.BorderSharp:
t.border = t.tui.NewWindow(
marginInt[0]-1,
marginInt[3]-2,
width+4,
height+2,
false, tui.MakeBorderStyle(t.borderShape, t.unicode))
}
noBorder := tui.MakeBorderStyle(tui.BorderNone, t.unicode)
if previewVisible {
createPreviewWindow := func(y int, x int, w int, h int) {
previewBorder := tui.MakeBorderStyle(tui.BorderAround, t.unicode)
previewBorder := tui.MakeBorderStyle(tui.BorderRounded, t.unicode)
if !t.preview.border {
previewBorder = tui.MakeTransparentBorder()
}
@ -1146,7 +1157,7 @@ func (t *Terminal) refresh() {
t.placeCursor()
if !t.suppress {
windows := make([]tui.Window, 0, 4)
if t.bordered {
if t.borderShape != tui.BorderNone {
windows = append(windows, t.border)
}
if t.hasPreviewWindow() {

@ -105,6 +105,7 @@ type LightRenderer struct {
type LightWindow struct {
renderer *LightRenderer
colored bool
preview bool
border BorderStyle
top int
left int
@ -681,6 +682,7 @@ func (r *LightRenderer) NewWindow(top int, left int, width int, height int, prev
w := &LightWindow{
renderer: r,
colored: r.theme != nil,
preview: preview,
border: borderStyle,
top: top,
left: left,
@ -704,7 +706,7 @@ func (r *LightRenderer) NewWindow(top int, left int, width int, height int, prev
func (w *LightWindow) drawBorder() {
switch w.border.shape {
case BorderAround:
case BorderRounded, BorderSharp:
w.drawBorderAround()
case BorderHorizontal:
w.drawBorderHorizontal()
@ -720,16 +722,20 @@ func (w *LightWindow) drawBorderHorizontal() {
func (w *LightWindow) drawBorderAround() {
w.Move(0, 0)
w.CPrint(ColPreviewBorder, AttrRegular,
color := ColBorder
if w.preview {
color = ColPreviewBorder
}
w.CPrint(color, AttrRegular,
string(w.border.topLeft)+repeat(w.border.horizontal, w.width-2)+string(w.border.topRight))
for y := 1; y < w.height-1; y++ {
w.Move(y, 0)
w.CPrint(ColPreviewBorder, AttrRegular, string(w.border.vertical))
w.CPrint(ColPreviewBorder, AttrRegular, repeat(' ', w.width-2))
w.CPrint(ColPreviewBorder, AttrRegular, string(w.border.vertical))
w.CPrint(color, AttrRegular, string(w.border.vertical))
w.CPrint(color, AttrRegular, repeat(' ', w.width-2))
w.CPrint(color, AttrRegular, string(w.border.vertical))
}
w.Move(w.height-1, 0)
w.CPrint(ColPreviewBorder, AttrRegular,
w.CPrint(color, AttrRegular,
string(w.border.bottomLeft)+repeat(w.border.horizontal, w.width-2)+string(w.border.bottomRight))
}

@ -28,6 +28,7 @@ type Attr tcell.Style
type TcellWindow struct {
color bool
preview bool
top int
left int
width int
@ -418,6 +419,7 @@ func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int,
}
return &TcellWindow{
color: r.theme != nil,
preview: preview,
top: top,
left: left,
width: width,
@ -591,7 +593,7 @@ func (w *TcellWindow) drawBorder() {
var style tcell.Style
if w.color {
if w.borderStyle.shape == BorderAround {
if w.preview {
style = ColPreviewBorder.style()
} else {
style = ColBorder.style()
@ -605,7 +607,7 @@ func (w *TcellWindow) drawBorder() {
_screen.SetContent(x, bot-1, w.borderStyle.horizontal, nil, style)
}
if w.borderStyle.shape == BorderAround {
if w.borderStyle.shape != BorderHorizontal {
for y := top; y < bot; y++ {
_screen.SetContent(left, y, w.borderStyle.vertical, nil, style)
_screen.SetContent(right-1, y, w.borderStyle.vertical, nil, style)

@ -210,7 +210,8 @@ type BorderShape int
const (
BorderNone BorderShape = iota
BorderAround
BorderRounded
BorderSharp
BorderHorizontal
)
@ -228,14 +229,25 @@ type BorderCharacter int
func MakeBorderStyle(shape BorderShape, unicode bool) BorderStyle {
if unicode {
if shape == BorderRounded {
return BorderStyle{
shape: shape,
horizontal: '─',
vertical: '│',
topLeft: '╭',
topRight: '╮',
bottomLeft: '╰',
bottomRight: '╯',
}
}
return BorderStyle{
shape: shape,
horizontal: '─',
vertical: '│',
topLeft: '╭',
topRight: '╮',
bottomLeft: '╰',
bottomRight: '╯',
topLeft: '',
topRight: '',
bottomLeft: '',
bottomRight: '',
}
}
return BorderStyle{
@ -251,7 +263,7 @@ func MakeBorderStyle(shape BorderShape, unicode bool) BorderStyle {
func MakeTransparentBorder() BorderStyle {
return BorderStyle{
shape: BorderAround,
shape: BorderRounded,
horizontal: ' ',
vertical: ' ',
topLeft: ' ',

Loading…
Cancel
Save