2018-04-15 06:06:57 +08:00
|
|
|
// Copyright 2018 Google Inc.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2018-03-30 06:41:22 +08:00
|
|
|
package draw
|
|
|
|
|
2018-06-25 09:49:30 +08:00
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
runewidth "github.com/mattn/go-runewidth"
|
|
|
|
)
|
2018-03-30 06:41:22 +08:00
|
|
|
|
|
|
|
// line_style.go contains the Unicode characters used for drawing lines of
|
|
|
|
// different styles.
|
|
|
|
|
|
|
|
// lineStyleChars maps the line styles to the corresponding component characters.
|
2018-06-25 09:49:30 +08:00
|
|
|
// Source: http://en.wikipedia.org/wiki/Box-drawing_character.
|
2018-03-30 06:41:22 +08:00
|
|
|
var lineStyleChars = map[LineStyle]map[linePart]rune{
|
2018-05-09 01:53:14 +08:00
|
|
|
LineStyleLight: {
|
2018-03-30 06:41:22 +08:00
|
|
|
hLine: '─',
|
|
|
|
vLine: '│',
|
|
|
|
topLeftCorner: '┌',
|
|
|
|
topRightCorner: '┐',
|
|
|
|
bottomLeftCorner: '└',
|
|
|
|
bottomRightCorner: '┘',
|
2018-06-25 09:49:30 +08:00
|
|
|
hAndUp: '┴',
|
|
|
|
hAndDown: '┬',
|
|
|
|
vAndLeft: '┤',
|
|
|
|
vAndRight: '├',
|
|
|
|
vAndH: '┼',
|
2018-03-30 06:41:22 +08:00
|
|
|
},
|
2019-01-24 22:35:39 +08:00
|
|
|
LineStyleDouble: {
|
|
|
|
hLine: '═',
|
|
|
|
vLine: '║',
|
|
|
|
topLeftCorner: '╔',
|
|
|
|
topRightCorner: '╗',
|
|
|
|
bottomLeftCorner: '╚',
|
|
|
|
bottomRightCorner: '╝',
|
|
|
|
hAndUp: '╩',
|
|
|
|
hAndDown: '╦',
|
|
|
|
vAndLeft: '╣',
|
|
|
|
vAndRight: '╠',
|
|
|
|
vAndH: '╬',
|
|
|
|
},
|
2019-01-26 02:57:14 +08:00
|
|
|
LineStyleRound: {
|
|
|
|
hLine: '─',
|
|
|
|
vLine: '│',
|
|
|
|
topLeftCorner: '╭',
|
|
|
|
topRightCorner: '╮',
|
|
|
|
bottomLeftCorner: '╰',
|
|
|
|
bottomRightCorner: '╯',
|
|
|
|
hAndUp: '┴',
|
|
|
|
hAndDown: '┬',
|
|
|
|
vAndLeft: '┤',
|
|
|
|
vAndRight: '├',
|
|
|
|
vAndH: '┼',
|
|
|
|
},
|
2018-03-30 06:41:22 +08:00
|
|
|
}
|
|
|
|
|
2018-06-25 09:49:30 +08:00
|
|
|
// init verifies that all line parts are half-width runes (occupy only one
|
|
|
|
// cell).
|
|
|
|
func init() {
|
|
|
|
for ls, parts := range lineStyleChars {
|
|
|
|
for part, r := range parts {
|
|
|
|
if got := runewidth.RuneWidth(r); got > 1 {
|
|
|
|
panic(fmt.Errorf("line style %v line part %v is a rune %c with width %v, all parts must be half-width runes (width of one)", ls, part, r, got))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-30 06:41:22 +08:00
|
|
|
// lineParts returns the line component characters for the provided line style.
|
|
|
|
func lineParts(ls LineStyle) (map[linePart]rune, error) {
|
|
|
|
parts, ok := lineStyleChars[ls]
|
|
|
|
if !ok {
|
2018-06-25 12:07:33 +08:00
|
|
|
return nil, fmt.Errorf("unsupported line style %d", ls)
|
2018-03-30 06:41:22 +08:00
|
|
|
}
|
|
|
|
return parts, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// LineStyle defines the supported line styles.Q
|
|
|
|
type LineStyle int
|
|
|
|
|
|
|
|
// String implements fmt.Stringer()
|
|
|
|
func (ls LineStyle) String() string {
|
|
|
|
if n, ok := lineStyleNames[ls]; ok {
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
return "LineStyleUnknown"
|
|
|
|
}
|
|
|
|
|
|
|
|
// lineStyleNames maps LineStyle values to human readable names.
|
|
|
|
var lineStyleNames = map[LineStyle]string{
|
2019-01-24 22:35:39 +08:00
|
|
|
LineStyleLight: "LineStyleLight",
|
|
|
|
LineStyleDouble: "LineStyleDouble",
|
2019-01-26 02:57:14 +08:00
|
|
|
LineStyleRound: "LineStyleRound",
|
2018-03-30 06:41:22 +08:00
|
|
|
}
|
|
|
|
|
2018-05-11 23:32:37 +08:00
|
|
|
// Supported line styles.
|
2018-03-30 06:41:22 +08:00
|
|
|
const (
|
2018-04-01 06:57:33 +08:00
|
|
|
LineStyleNone LineStyle = iota
|
2018-03-30 06:41:22 +08:00
|
|
|
LineStyleLight
|
2019-01-24 22:35:39 +08:00
|
|
|
LineStyleDouble
|
2019-01-26 02:57:14 +08:00
|
|
|
LineStyleRound
|
2018-03-30 06:41:22 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
// linePart identifies individual line parts.
|
|
|
|
type linePart int
|
|
|
|
|
|
|
|
// String implements fmt.Stringer()
|
|
|
|
func (lp linePart) String() string {
|
|
|
|
if n, ok := linePartNames[lp]; ok {
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
return "linePartUnknown"
|
|
|
|
}
|
|
|
|
|
|
|
|
// linePartNames maps linePart values to human readable names.
|
|
|
|
var linePartNames = map[linePart]string{
|
|
|
|
vLine: "linePartVLine",
|
|
|
|
topLeftCorner: "linePartTopLeftCorner",
|
|
|
|
topRightCorner: "linePartTopRightCorner",
|
|
|
|
bottomLeftCorner: "linePartBottomLeftCorner",
|
|
|
|
bottomRightCorner: "linePartBottomRightCorner",
|
2018-06-25 09:49:30 +08:00
|
|
|
hAndUp: "linePartHAndUp",
|
|
|
|
hAndDown: "linePartHAndDown",
|
|
|
|
vAndLeft: "linePartVAndLeft",
|
|
|
|
vAndRight: "linePartVAndRight",
|
|
|
|
vAndH: "linePartVAndH",
|
2018-03-30 06:41:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
hLine linePart = iota
|
|
|
|
vLine
|
|
|
|
topLeftCorner
|
|
|
|
topRightCorner
|
|
|
|
bottomLeftCorner
|
|
|
|
bottomRightCorner
|
2018-06-25 09:49:30 +08:00
|
|
|
hAndUp
|
|
|
|
hAndDown
|
|
|
|
vAndLeft
|
|
|
|
vAndRight
|
|
|
|
vAndH
|
2018-03-30 06:41:22 +08:00
|
|
|
)
|