Use ElementStyle as a value instead of pointer, so we can drop all the annoying nil checks

This commit is contained in:
Christian Muehlhaeuser
2019-12-05 18:05:29 +01:00
parent 556c490ac4
commit 78e36a02d0
11 changed files with 147 additions and 176 deletions
+40 -41
View File
@@ -16,27 +16,27 @@ type BaseElement struct {
Token string
Prefix string
Suffix string
Style *ElementStyle
Style ElementStyle
}
func color(c string) (uint8, error) {
if len(c) == 0 {
func color(c *string) (uint8, error) {
if c == nil || len(*c) == 0 {
return 0, errors.New("Invalid color")
}
if c[0] == '#' {
i, err := hexToANSIColor(c)
if (*c)[0] == '#' {
i, err := hexToANSIColor(*c)
return uint8(i), err
}
i, err := strconv.Atoi(c)
i, err := strconv.Atoi(*c)
return uint8(i), err
}
func colorSeq(c string) (string, error) {
if len(c) == 0 {
func colorSeq(c *string) (string, error) {
if c == nil || len(*c) == 0 {
return "", errors.New("Invalid color")
}
col, err := colorful.Hex(c)
col, err := colorful.Hex(*c)
if err != nil {
return "", err
}
@@ -44,13 +44,13 @@ func colorSeq(c string) (string, error) {
return fmt.Sprintf("%d;%d;%dm", uint8(col.R*255), uint8(col.G*255), uint8(col.B*255)), nil
}
func renderText(w io.Writer, rules *ElementStyle, s string) {
func renderText(w io.Writer, rules ElementStyle, s string) {
if len(s) == 0 {
return
}
// FIXME: ugly true-color ANSI support hack
if rules != nil && os.Getenv("COLORTERM") == "truecolor" {
if os.Getenv("COLORTERM") == "truecolor" {
bg, err := colorSeq(rules.BackgroundColor)
if err == nil {
s = "\x1b[48;2;" + bg + s
@@ -63,37 +63,38 @@ func renderText(w io.Writer, rules *ElementStyle, s string) {
out := aurora.Reset(s)
if rules != nil {
if rules.Color != nil {
i, err := color(rules.Color)
if err == nil {
out = out.Index(i)
}
i, err = color(rules.BackgroundColor)
}
if rules.BackgroundColor != nil {
i, err := color(rules.BackgroundColor)
if err == nil {
out = out.BgIndex(i)
}
if rules.Underline != nil && *rules.Underline {
out = out.Underline()
}
if rules.Bold != nil && *rules.Bold {
out = out.Bold()
}
if rules.Italic != nil && *rules.Italic {
out = out.Italic()
}
if rules.CrossedOut != nil && *rules.CrossedOut {
out = out.CrossedOut()
}
if rules.Overlined != nil && *rules.Overlined {
out = out.Overlined()
}
if rules.Inverse != nil && *rules.Inverse {
out = out.Reverse()
}
if rules.Blink != nil && *rules.Blink {
out = out.Blink()
}
}
if rules.Underline != nil && *rules.Underline {
out = out.Underline()
}
if rules.Bold != nil && *rules.Bold {
out = out.Bold()
}
if rules.Italic != nil && *rules.Italic {
out = out.Italic()
}
if rules.CrossedOut != nil && *rules.CrossedOut {
out = out.CrossedOut()
}
if rules.Overlined != nil && *rules.Overlined {
out = out.Overlined()
}
if rules.Inverse != nil && *rules.Inverse {
out = out.Reverse()
}
if rules.Blink != nil && *rules.Blink {
out = out.Blink()
}
_, _ = w.Write([]byte(out.String()))
@@ -106,12 +107,10 @@ func (e *BaseElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error
}()
rules := tr.blockStack.With(e.Style)
if rules != nil {
renderText(w, rules, rules.Prefix)
defer func() {
renderText(w, rules, rules.Suffix)
}()
}
renderText(w, rules, rules.Prefix)
defer func() {
renderText(w, rules, rules.Suffix)
}()
renderText(w, rules, e.Token)
return nil
+4 -4
View File
@@ -6,7 +6,7 @@ import (
type BlockElement struct {
Block *bytes.Buffer
Style *ElementStyle
Style ElementStyle
}
type BlockStack []BlockElement
@@ -29,7 +29,7 @@ func (s BlockStack) Indent() uint {
var i uint
for _, v := range s {
if v.Style == nil || v.Style.Indent == nil {
if v.Style.Indent == nil {
continue
}
i += *v.Style.Indent
@@ -42,7 +42,7 @@ func (s BlockStack) Margin() uint {
var i uint
for _, v := range s {
if v.Style == nil || v.Style.Margin == nil {
if v.Style.Margin == nil {
continue
}
i += *v.Style.Margin
@@ -69,6 +69,6 @@ func (s BlockStack) Current() BlockElement {
return s[len(s)-1]
}
func (s BlockStack) With(child *ElementStyle) *ElementStyle {
func (s BlockStack) With(child ElementStyle) ElementStyle {
return cascadeStyle(s.Current().Style, child, true)
}
+6 -9
View File
@@ -13,19 +13,16 @@ type CodeBlockElement struct {
}
func (e *CodeBlockElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error {
var theme string
var indent uint
var margin uint
rules := tr.style[CodeBlock]
if rules != nil {
if rules.Indent != nil {
indent = *rules.Indent
}
if rules.Margin != nil {
margin = *rules.Margin
}
theme = rules.Theme
if rules.Indent != nil {
indent = *rules.Indent
}
if rules.Margin != nil {
margin = *rules.Margin
}
theme := rules.Theme
iw := &IndentWriter{
Indent: indent + margin,
+8 -12
View File
@@ -18,26 +18,22 @@ func (e *DocumentElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) e
}
tr.blockStack.Push(be)
if rules != nil {
renderText(tr.blockStack.Current().Block, rules, rules.Prefix)
}
renderText(tr.blockStack.Current().Block, rules, rules.Prefix)
return nil
}
func (e *DocumentElement) Finish(w io.Writer, node *bf.Node, tr *TermRenderer) error {
var indent uint
var margin uint
var suffix string
rules := tr.style[Document]
if rules != nil {
if rules.Indent != nil {
indent = *rules.Indent
}
if rules.Margin != nil {
margin = *rules.Margin
}
suffix = rules.Suffix
if rules.Indent != nil {
indent = *rules.Indent
}
if rules.Margin != nil {
margin = *rules.Margin
}
suffix := rules.Suffix
pw := &PaddingWriter{
Padding: uint(tr.WordWrap) - margin,
PadFunc: func(wr io.Writer) {
+3 -3
View File
@@ -21,7 +21,7 @@ type TermRenderer struct {
BaseURL string
WordWrap int
style map[StyleType]*ElementStyle
style map[StyleType]ElementStyle
blockStack BlockStack
table TableElement
}
@@ -56,13 +56,13 @@ func NewTermRenderer(stylePath string) (*TermRenderer, error) {
}
func NewTermRendererFromBytes(b []byte) (*TermRenderer, error) {
e := make(map[string]*ElementStyle)
e := make(map[string]ElementStyle)
err := json.Unmarshal(b, &e)
if err != nil {
return nil, err
}
tr := &TermRenderer{}
tr.style = make(map[StyleType]*ElementStyle)
tr.style = make(map[StyleType]ElementStyle)
for k, v := range e {
t, err := keyToType(k)
+5 -7
View File
@@ -32,13 +32,11 @@ func (e *HeadingElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) er
rules = cascadeStyles(false, rules, tr.style[H6])
}
if rules != nil {
if rules.Indent != nil {
indent = *rules.Indent
}
if rules.Margin != nil {
margin = *rules.Margin
}
if rules.Indent != nil {
indent = *rules.Indent
}
if rules.Margin != nil {
margin = *rules.Margin
}
iw := &IndentWriter{
+2 -2
View File
@@ -35,8 +35,8 @@ func (e *LinkElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error
}
if len(node.LinkData.Destination) > 0 {
style := *tr.style[Link]
pre := " "
style := tr.style[Link]
if !textRendered {
pre = ""
style.Prefix = ""
@@ -46,7 +46,7 @@ func (e *LinkElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error
el := &BaseElement{
Token: resolveRelativeURL(tr.BaseURL, string(node.LinkData.Destination)),
Prefix: pre,
Style: &style,
Style: style,
}
err := el.Render(w, node, tr)
if err != nil {
+6 -9
View File
@@ -29,17 +29,14 @@ func (e *ListElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error
func (e *ListElement) Finish(w io.Writer, node *bf.Node, tr *TermRenderer) error {
var indent uint
var margin uint
var suffix string
rules := tr.blockStack.Current().Style
if rules != nil {
if rules.Indent != nil {
indent = *rules.Indent
}
if rules.Margin != nil {
margin = *rules.Margin
}
suffix = rules.Suffix
if rules.Indent != nil {
indent = *rules.Indent
}
if rules.Margin != nil {
margin = *rules.Margin
}
suffix := rules.Suffix
renderText(tr.blockStack.Current().Block, rules, suffix)
pw := &PaddingWriter{
+8 -13
View File
@@ -13,7 +13,7 @@ type ParagraphElement struct {
}
func (e *ParagraphElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error {
var rules *ElementStyle
var rules ElementStyle
if node.Parent != nil && node.Parent.Type == bf.Item {
// list item
rules = tr.style[List]
@@ -27,31 +27,26 @@ func (e *ParagraphElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer)
tr.blockStack.Push(be)
}
if rules != nil {
renderText(w, tr.blockStack.Current().Style, rules.Prefix)
}
renderText(w, tr.blockStack.Current().Style, rules.Prefix)
return nil
}
func (e *ParagraphElement) Finish(w io.Writer, node *bf.Node, tr *TermRenderer) error {
var indent uint
var margin uint
var suffix string
rules := tr.blockStack.Current().Style
if node.Parent != nil && node.Parent.Type == bf.Item {
// remove indent & margin for list items
rules = tr.blockStack.Current().Style
}
if rules != nil {
if rules.Indent != nil {
indent = *rules.Indent
}
if rules.Margin != nil {
margin = *rules.Margin
}
suffix = rules.Suffix
if rules.Indent != nil {
indent = *rules.Indent
}
if rules.Margin != nil {
margin = *rules.Margin
}
suffix := rules.Suffix
renderText(tr.blockStack.Current().Block, rules, suffix)
pw := &PaddingWriter{
+59 -69
View File
@@ -45,26 +45,26 @@ const (
)
type ElementStyle struct {
Color string `json:"color"`
BackgroundColor string `json:"background_color"`
Underline *bool `json:"underline"`
Bold *bool `json:"bold"`
Italic *bool `json:"italic"`
CrossedOut *bool `json:"crossed_out"`
Faint *bool `json:"faint"`
Conceal *bool `json:"conceal"`
Overlined *bool `json:"overlined"`
Inverse *bool `json:"inverse"`
Blink *bool `json:"blink"`
Indent *uint `json:"indent"`
Margin *uint `json:"margin"`
Theme string `json:"theme"`
Prefix string `json:"prefix"`
Suffix string `json:"suffix"`
Color *string `json:"color"`
BackgroundColor *string `json:"background_color"`
Underline *bool `json:"underline"`
Bold *bool `json:"bold"`
Italic *bool `json:"italic"`
CrossedOut *bool `json:"crossed_out"`
Faint *bool `json:"faint"`
Conceal *bool `json:"conceal"`
Overlined *bool `json:"overlined"`
Inverse *bool `json:"inverse"`
Blink *bool `json:"blink"`
Indent *uint `json:"indent"`
Margin *uint `json:"margin"`
Theme string `json:"theme"`
Prefix string `json:"prefix"`
Suffix string `json:"suffix"`
}
func cascadeStyles(onlyColors bool, s ...*ElementStyle) *ElementStyle {
var r *ElementStyle
func cascadeStyles(onlyColors bool, s ...ElementStyle) ElementStyle {
var r ElementStyle
for _, v := range s {
r = cascadeStyle(r, v, onlyColors)
@@ -72,15 +72,8 @@ func cascadeStyles(onlyColors bool, s ...*ElementStyle) *ElementStyle {
return r
}
func cascadeStyle(parent *ElementStyle, child *ElementStyle, onlyColors bool) *ElementStyle {
if parent == nil {
return child
}
s := ElementStyle{}
if child != nil {
s = *child
}
func cascadeStyle(parent ElementStyle, child ElementStyle, onlyColors bool) ElementStyle {
s := child
s.Color = parent.Color
s.BackgroundColor = parent.BackgroundColor
@@ -99,50 +92,47 @@ func cascadeStyle(parent *ElementStyle, child *ElementStyle, onlyColors bool) *E
s.Blink = parent.Blink
}
if child != nil {
if child.Color != "" {
s.Color = child.Color
}
if child.BackgroundColor != "" {
s.BackgroundColor = child.BackgroundColor
}
if child.Indent != nil {
s.Indent = child.Indent
}
if child.Margin != nil {
s.Margin = child.Margin
}
if child.Underline != nil {
s.Underline = child.Underline
}
if child.Bold != nil {
s.Bold = child.Bold
}
if child.Italic != nil {
s.Italic = child.Italic
}
if child.CrossedOut != nil {
s.CrossedOut = child.CrossedOut
}
if child.Faint != nil {
s.Faint = child.Faint
}
if child.Conceal != nil {
s.Conceal = child.Conceal
}
if child.Overlined != nil {
s.Overlined = child.Overlined
}
if child.Inverse != nil {
s.Inverse = child.Inverse
}
if child.Blink != nil {
s.Blink = child.Blink
}
if child.Color != nil {
s.Color = child.Color
}
if child.BackgroundColor != nil {
s.BackgroundColor = child.BackgroundColor
}
if child.Indent != nil {
s.Indent = child.Indent
}
if child.Margin != nil {
s.Margin = child.Margin
}
if child.Underline != nil {
s.Underline = child.Underline
}
if child.Bold != nil {
s.Bold = child.Bold
}
if child.Italic != nil {
s.Italic = child.Italic
}
if child.CrossedOut != nil {
s.CrossedOut = child.CrossedOut
}
if child.Faint != nil {
s.Faint = child.Faint
}
if child.Conceal != nil {
s.Conceal = child.Conceal
}
if child.Overlined != nil {
s.Overlined = child.Overlined
}
if child.Inverse != nil {
s.Inverse = child.Inverse
}
if child.Blink != nil {
s.Blink = child.Blink
}
return &s
return s
}
func hexToANSIColor(h string) (int, error) {
+6 -7
View File
@@ -26,14 +26,13 @@ func (e *TableElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) erro
var indent uint
var margin uint
rules := tr.style[Table]
if rules != nil {
if rules.Indent != nil {
indent = *rules.Indent
}
if rules.Margin != nil {
margin = *rules.Margin
}
if rules.Indent != nil {
indent = *rules.Indent
}
if rules.Margin != nil {
margin = *rules.Margin
}
iw := &IndentWriter{
Indent: indent + margin,
IndentFunc: func(wr io.Writer) {