summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2020-03-05 20:15:15 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2020-03-05 20:56:15 +0900
commitd9b12111912a43e62f61051d40897a378a020cf5 (patch)
tree741fe6d7141c0e2837bbec13e6ec1e4fc1ace80d
parent99f1e02766fab9ca95ba72b34f36e2d8ce398042 (diff)
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)
-rw-r--r--man/man1/fzf.114
-rw-r--r--src/options.go39
-rw-r--r--src/terminal.go139
-rw-r--r--src/tui/light.go18
-rw-r--r--src/tui/tcell.go6
-rw-r--r--src/tui/tui.go24
6 files changed, 150 insertions, 90 deletions
diff --git a/man/man1/fzf.1 b/man/man1/fzf.1
index 0486b033..d9186517 100644
--- a/man/man1/fzf.1
+++ b/man/man1/fzf.1
@@ -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"
diff --git a/src/options.go b/src/options.go
index 69ff7d4c..b87e85c2 100644
--- a/src/options.go
+++ b/src/options.go
@@ -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 {
diff --git a/src/terminal.go b/src/terminal.go
index bd41bdb8..a6a5c5ba 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -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() {
diff --git a/src/tui/light.go b/src/tui/light.go
index 05f87e6f..fbc76f59 100644
--- a/src/tui/light.go
+++ b/src/tui/light.go
@@ -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))
}
diff --git a/src/tui/tcell.go b/src/tui/tcell.go
index 79b4944e..db891655 100644
--- a/src/tui/tcell.go
+++ b/src/tui/tcell.go
@@ -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)
diff --git a/src/tui/tui.go b/src/tui/tui.go
index 179adfd5..4968b366 100644
--- a/src/tui/tui.go
+++ b/src/tui/tui.go
@@ -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: ' ',