Use already parsed events for replies if possible

This commit is contained in:
Tulir Asokan
2019-04-10 21:06:19 +03:00
parent 9132e2b750
commit db0e24ccc2
18 changed files with 245 additions and 23 deletions

View File

@ -18,6 +18,7 @@ package html
import (
"fmt"
"strings"
"maunium.net/go/mauview"
)
@ -37,6 +38,10 @@ func NewBlockquoteEntity(children []Entity) *BlockquoteEntity {
}}
}
func (be *BlockquoteEntity) Clone() Entity {
return &BlockquoteEntity{BaseEntity: be.BaseEntity.Clone().(*BaseEntity)}
}
func (be *BlockquoteEntity) Draw(screen mauview.Screen) {
be.BaseEntity.Draw(screen)
for y := 0; y < be.height; y++ {
@ -44,6 +49,33 @@ func (be *BlockquoteEntity) Draw(screen mauview.Screen) {
}
}
func (be *BlockquoteEntity) PlainText() string {
if len(be.Children) == 0 {
return ""
}
var buf strings.Builder
newlined := false
for i, child := range be.Children {
if i != 0 && child.IsBlock() && !newlined {
buf.WriteRune('\n')
}
newlined = false
for i, row := range strings.Split(child.PlainText(), "\n") {
if i != 0 {
buf.WriteRune('\n')
}
buf.WriteRune('>')
buf.WriteRune(' ')
buf.WriteString(row)
}
if child.IsBlock() {
buf.WriteRune('\n')
newlined = true
}
}
return strings.TrimSpace(buf.String())
}
func (be *BlockquoteEntity) String() string {
return fmt.Sprintf("&html.BlockquoteEntity{%s},\n", be.BaseEntity)
}

View File

@ -26,3 +26,15 @@ func NewBreakEntity() *BreakEntity {
Block: true,
}}
}
func (be *BreakEntity) Clone() Entity {
return NewBreakEntity()
}
func (be *BreakEntity) PlainText() string {
return "\n"
}
func (be *BreakEntity) String() string {
return "&html.BreakEntity{},\n"
}

View File

@ -37,6 +37,13 @@ func NewCodeBlockEntity(children []Entity, background tcell.Style) *CodeBlockEnt
}
}
func (ce *CodeBlockEntity) Clone() Entity {
return &CodeBlockEntity{
BaseEntity: ce.BaseEntity.Clone().(*BaseEntity),
Background: ce.Background,
}
}
func (ce *CodeBlockEntity) Draw(screen mauview.Screen) {
screen.Fill(' ', ce.Background)
ce.BaseEntity.Draw(screen)

View File

@ -165,17 +165,20 @@ func (he *BaseEntity) PlainText() string {
buf.WriteString(he.Text)
newlined := false
for _, child := range he.Children {
if child.IsBlock() && !newlined {
text := child.PlainText()
if !strings.HasPrefix(text, "\n") && child.IsBlock() && !newlined {
buf.WriteRune('\n')
}
newlined = false
buf.WriteString(child.PlainText())
buf.WriteString(text)
if child.IsBlock() {
buf.WriteRune('\n')
if !strings.HasSuffix(text, "\n") {
buf.WriteRune('\n')
}
newlined = true
}
}
return buf.String()
return strings.TrimSpace(buf.String())
}
// Draw draws this entity onto the given mauview Screen.

View File

@ -0,0 +1,56 @@
// gomuks - A terminal Matrix client written in Go.
// Copyright (C) 2019 Tulir Asokan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package html
import (
"strings"
"maunium.net/go/mauview"
)
type HorizontalLineEntity struct {
*BaseEntity
}
const HorizontalLineChar = '━'
func NewHorizontalLineEntity() *HorizontalLineEntity {
return &HorizontalLineEntity{&BaseEntity{
Tag: "hr",
Block: true,
DefaultHeight: 1,
}}
}
func (he *HorizontalLineEntity) Clone() Entity {
return NewHorizontalLineEntity()
}
func (he *HorizontalLineEntity) Draw(screen mauview.Screen) {
width, _ := screen.Size()
for x := 0; x < width; x++ {
screen.SetContent(x, 0, HorizontalLineChar, nil, he.Style)
}
}
func (he *HorizontalLineEntity) PlainText() string {
return strings.Repeat(string(HorizontalLineChar), 5)
}
func (he *HorizontalLineEntity) String() string {
return "&html.HorizontalLineEntity{},\n"
}

View File

@ -56,6 +56,14 @@ func NewListEntity(ordered bool, start int, children []Entity) *ListEntity {
return entity
}
func (le *ListEntity) Clone() Entity {
return &ListEntity{
BaseEntity: le.BaseEntity.Clone().(*BaseEntity),
Ordered: le.Ordered,
Start: le.Start,
}
}
func (le *ListEntity) Draw(screen mauview.Screen) {
width, _ := screen.Size()
@ -75,6 +83,31 @@ func (le *ListEntity) Draw(screen mauview.Screen) {
}
}
func (le *ListEntity) PlainText() string {
if len(le.Children) == 0 {
return ""
}
var buf strings.Builder
for i, child := range le.Children {
indent := strings.Repeat(" ", le.Indent)
if le.Ordered {
number := le.Start + i
_, _ = fmt.Fprintf(&buf, "%d. %s", number, strings.Repeat(" ", le.Indent-2-digits(number)))
} else {
buf.WriteString("● ")
}
for j, row := range strings.Split(child.PlainText(), "\n") {
if j != 0 {
buf.WriteRune('\n')
buf.WriteString(indent)
}
buf.WriteString(row)
}
buf.WriteRune('\n')
}
return strings.TrimSpace(buf.String())
}
func (le *ListEntity) String() string {
return fmt.Sprintf("&html.ListEntity{Ordered=%t, Start=%d, Base=%s},\n", le.Ordered, le.Start, le.BaseEntity)
}

View File

@ -111,7 +111,7 @@ func (parser *htmlParser) basicFormatToEntity(node *html.Node) Entity {
entity.AdjustStyle(AdjustStyleBold)
case "i", "em":
entity.AdjustStyle(AdjustStyleItalic)
case "s", "del":
case "s", "del", "strike":
entity.AdjustStyle(AdjustStyleStrikethrough)
case "u", "ins":
entity.AdjustStyle(AdjustStyleUnderline)
@ -237,7 +237,7 @@ func (parser *htmlParser) syntaxHighlight(text, language string) Entity {
children := make([]Entity, len(tokens))
for i, token := range tokens {
if token.Value == "\n" {
children[i] = &BaseEntity{Block: true, Tag: "br"}
children[i] = NewBreakEntity()
} else {
children[i] = &BaseEntity{
Tag: token.Type.String(),
@ -282,7 +282,7 @@ func (parser *htmlParser) tagNodeToEntity(node *html.Node) Entity {
return parser.headerToEntity(node)
case "br":
return NewBreakEntity()
case "b", "strong", "i", "em", "s", "del", "u", "ins", "font":
case "b", "strong", "i", "em", "s", "strike", "del", "u", "ins", "font":
return parser.basicFormatToEntity(node)
case "a":
return parser.linkToEntity(node)
@ -290,6 +290,10 @@ func (parser *htmlParser) tagNodeToEntity(node *html.Node) Entity {
return parser.imageToEntity(node)
case "pre":
return parser.codeblockToEntity(node)
case "hr":
return NewHorizontalLineEntity()
case "mx-reply":
return nil
default:
return &BaseEntity{
Tag: node.Data,