Add --no-unicode option to draw borders in ASCII characters

Close ##1533
This commit is contained in:
Junegunn Choi 2019-03-29 02:11:03 +09:00
parent e7d60aac9c
commit 75972d59a8
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627
6 changed files with 87 additions and 38 deletions

View File

@ -174,6 +174,11 @@ A synonym for \fB--layout=reverse\fB
.TP
.B "--border"
Draw border above and below the finder
.TP
.B "--no-unicode"
Use ASCII characters instead of Unicode box drawing characters to draw border
.TP
.BI "--margin=" MARGIN
Comma-separated expression for margins around the finder.

View File

@ -195,6 +195,7 @@ type Options struct {
HeaderLines int
Margin [4]sizeSpec
Bordered bool
Unicode bool
Tabstop int
ClearOnExit bool
Version bool
@ -244,6 +245,7 @@ func defaultOptions() *Options {
Header: make([]string, 0),
HeaderLines: 0,
Margin: defaultMargin(),
Unicode: true,
Tabstop: 8,
ClearOnExit: true,
Version: false}
@ -1152,6 +1154,10 @@ func parseOptions(opts *Options, allArgs []string) {
opts.Bordered = false
case "--border":
opts.Bordered = true
case "--no-unicode":
opts.Unicode = false
case "--unicode":
opts.Unicode = true
case "--margin":
opts.Margin = parseMargin(
nextString(allArgs, &i, "margin required (TRBL / TB,RL / T,RL,B / T,R,B,L)"))

View File

@ -88,6 +88,7 @@ type Terminal struct {
tabstop int
margin [4]sizeSpec
strong tui.Attr
unicode bool
bordered bool
cleanExit bool
border tui.Window
@ -391,6 +392,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
printQuery: opts.PrintQuery,
history: opts.History,
margin: opts.Margin,
unicode: opts.Unicode,
bordered: opts.Bordered,
cleanExit: opts.ClearOnExit,
strong: strongAttr,
@ -600,11 +602,12 @@ func (t *Terminal) resizeWindows() {
marginInt[0]-1,
marginInt[3],
width,
height+2, tui.BorderHorizontal)
height+2, tui.MakeBorderStyle(tui.BorderHorizontal, t.unicode))
}
noBorder := tui.MakeBorderStyle(tui.BorderNone, t.unicode)
if previewVisible {
createPreviewWindow := func(y int, x int, w int, h int) {
t.pborder = t.tui.NewWindow(y, x, w, h, tui.BorderAround)
t.pborder = t.tui.NewWindow(y, x, w, h, tui.MakeBorderStyle(tui.BorderAround, t.unicode))
pwidth := w - 4
// ncurses auto-wraps the line when the cursor reaches the right-end of
// the window. To prevent unintended line-wraps, we use the width one
@ -612,28 +615,28 @@ func (t *Terminal) resizeWindows() {
if !t.preview.wrap && t.tui.DoesAutoWrap() {
pwidth += 1
}
t.pwindow = t.tui.NewWindow(y+1, x+2, pwidth, h-2, tui.BorderNone)
t.pwindow = t.tui.NewWindow(y+1, x+2, pwidth, h-2, noBorder)
}
switch t.preview.position {
case posUp:
pheight := calculateSize(height, t.preview.size, minHeight, 3)
t.window = t.tui.NewWindow(
marginInt[0]+pheight, marginInt[3], width, height-pheight, tui.BorderNone)
marginInt[0]+pheight, marginInt[3], width, height-pheight, noBorder)
createPreviewWindow(marginInt[0], marginInt[3], width, pheight)
case posDown:
pheight := calculateSize(height, t.preview.size, minHeight, 3)
t.window = t.tui.NewWindow(
marginInt[0], marginInt[3], width, height-pheight, tui.BorderNone)
marginInt[0], marginInt[3], width, height-pheight, noBorder)
createPreviewWindow(marginInt[0]+height-pheight, marginInt[3], width, pheight)
case posLeft:
pwidth := calculateSize(width, t.preview.size, minWidth, 5)
t.window = t.tui.NewWindow(
marginInt[0], marginInt[3]+pwidth, width-pwidth, height, tui.BorderNone)
marginInt[0], marginInt[3]+pwidth, width-pwidth, height, noBorder)
createPreviewWindow(marginInt[0], marginInt[3], pwidth, height)
case posRight:
pwidth := calculateSize(width, t.preview.size, minWidth, 5)
t.window = t.tui.NewWindow(
marginInt[0], marginInt[3], width-pwidth, height, tui.BorderNone)
marginInt[0], marginInt[3], width-pwidth, height, noBorder)
createPreviewWindow(marginInt[0], marginInt[3]+width-pwidth, pwidth, height)
}
} else {
@ -641,7 +644,7 @@ func (t *Terminal) resizeWindows() {
marginInt[0],
marginInt[3],
width,
height, tui.BorderNone)
height, noBorder)
}
for i := 0; i < t.window.Height(); i++ {
t.window.MoveAndClear(i, 0)

View File

@ -163,9 +163,9 @@ func (r *LightRenderer) findOffset() (row int, col int) {
return -1, -1
}
func repeat(s string, times int) string {
func repeat(r rune, times int) string {
if times > 0 {
return strings.Repeat(s, times)
return strings.Repeat(string(r), times)
}
return ""
}
@ -676,7 +676,7 @@ func (r *LightRenderer) NewWindow(top int, left int, width int, height int, bord
}
func (w *LightWindow) drawBorder() {
switch w.border {
switch w.border.shape {
case BorderAround:
w.drawBorderAround()
case BorderHorizontal:
@ -686,22 +686,24 @@ func (w *LightWindow) drawBorder() {
func (w *LightWindow) drawBorderHorizontal() {
w.Move(0, 0)
w.CPrint(ColBorder, AttrRegular, repeat("─", w.width))
w.CPrint(ColBorder, AttrRegular, repeat(w.border.horizontal, w.width))
w.Move(w.height-1, 0)
w.CPrint(ColBorder, AttrRegular, repeat("─", w.width))
w.CPrint(ColBorder, AttrRegular, repeat(w.border.horizontal, w.width))
}
func (w *LightWindow) drawBorderAround() {
w.Move(0, 0)
w.CPrint(ColBorder, AttrRegular, "┌"+repeat("─", w.width-2)+"┐")
w.CPrint(ColBorder, 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(ColBorder, AttrRegular, "│")
w.cprint2(colDefault, w.bg, AttrRegular, repeat(" ", w.width-2))
w.CPrint(ColBorder, AttrRegular, "│")
w.CPrint(ColBorder, AttrRegular, string(w.border.vertical))
w.cprint2(colDefault, w.bg, AttrRegular, repeat(' ', w.width-2))
w.CPrint(ColBorder, AttrRegular, string(w.border.vertical))
}
w.Move(w.height-1, 0)
w.CPrint(ColBorder, AttrRegular, "└"+repeat("─", w.width-2)+"┘")
w.CPrint(ColBorder, AttrRegular,
string(w.border.bottomLeft)+repeat(w.border.horizontal, w.width-2)+string(w.border.bottomRight))
}
func (w *LightWindow) csi(code string) {
@ -762,7 +764,7 @@ func (w *LightWindow) MoveAndClear(y int, x int) {
w.Move(y, x)
// We should not delete preview window on the right
// csi("K")
w.Print(repeat(" ", w.width-x))
w.Print(repeat(' ', w.width-x))
w.Move(y, x)
}
@ -858,7 +860,7 @@ func wrapLine(input string, prefixLength int, max int, tabstop int) []wrappedLin
width += w
str := string(r)
if r == '\t' {
str = repeat(" ", w)
str = repeat(' ', w)
}
if prefixLength+width <= max {
line += str

View File

@ -61,12 +61,8 @@ func (w *TcellWindow) Refresh() {
}
w.lastX = 0
w.lastY = 0
switch w.borderStyle {
case BorderAround:
w.drawBorder(true)
case BorderHorizontal:
w.drawBorder(false)
}
w.drawBorder()
}
func (w *TcellWindow) FinishFill() {
@ -570,7 +566,11 @@ func (w *TcellWindow) CFill(fg Color, bg Color, a Attr, str string) FillReturn {
return w.fillString(str, NewColorPair(fg, bg), a)
}
func (w *TcellWindow) drawBorder(around bool) {
func (w *TcellWindow) drawBorder() {
if w.borderStyle.shape == BorderNone {
return
}
left := w.left
right := left + w.width
top := w.top
@ -584,19 +584,19 @@ func (w *TcellWindow) drawBorder(around bool) {
}
for x := left; x < right; x++ {
_screen.SetContent(x, top, tcell.RuneHLine, nil, style)
_screen.SetContent(x, bot-1, tcell.RuneHLine, nil, style)
_screen.SetContent(x, top, w.borderStyle.horizontal, nil, style)
_screen.SetContent(x, bot-1, w.borderStyle.horizontal, nil, style)
}
if around {
if w.borderStyle.shape == BorderAround {
for y := top; y < bot; y++ {
_screen.SetContent(left, y, tcell.RuneVLine, nil, style)
_screen.SetContent(right-1, y, tcell.RuneVLine, nil, style)
_screen.SetContent(left, y, w.borderStyle.vertical, nil, style)
_screen.SetContent(right-1, y, w.borderStyle.vertical, nil, style)
}
_screen.SetContent(left, top, tcell.RuneULCorner, nil, style)
_screen.SetContent(right-1, top, tcell.RuneURCorner, nil, style)
_screen.SetContent(left, bot-1, tcell.RuneLLCorner, nil, style)
_screen.SetContent(right-1, bot-1, tcell.RuneLRCorner, nil, style)
_screen.SetContent(left, top, w.borderStyle.topLeft, nil, style)
_screen.SetContent(right-1, top, w.borderStyle.topRight, nil, style)
_screen.SetContent(left, bot-1, w.borderStyle.bottomLeft, nil, style)
_screen.SetContent(right-1, bot-1, w.borderStyle.bottomRight, nil, style)
}
}

View File

@ -201,14 +201,47 @@ type MouseEvent struct {
Mod bool
}
type BorderStyle int
type BorderShape int
const (
BorderNone BorderStyle = iota
BorderNone BorderShape = iota
BorderAround
BorderHorizontal
)
type BorderStyle struct {
shape BorderShape
horizontal rune
vertical rune
topLeft rune
topRight rune
bottomLeft rune
bottomRight rune
}
func MakeBorderStyle(shape BorderShape, unicode bool) BorderStyle {
if unicode {
return BorderStyle{
shape: shape,
horizontal: '─',
vertical: '│',
topLeft: '┌',
topRight: '┐',
bottomLeft: '└',
bottomRight: '┘',
}
}
return BorderStyle{
shape: shape,
horizontal: '-',
vertical: '|',
topLeft: '+',
topRight: '+',
bottomLeft: '+',
bottomRight: '+',
}
}
type Renderer interface {
Init()
Pause(clear bool)