Fix non-syntax-highlighted code block newline rendering
This commit is contained in:
parent
d0c0af811e
commit
887e2e232a
@ -474,29 +474,25 @@ func (view *MessageView) Draw(screen mauview.Screen) {
|
|||||||
scrollBarHeight, scrollBarPos := view.calculateScrollBar(view.height)
|
scrollBarHeight, scrollBarPos := view.calculateScrollBar(view.height)
|
||||||
|
|
||||||
var prevMeta ifc.MessageMeta
|
var prevMeta ifc.MessageMeta
|
||||||
firstLine := true
|
|
||||||
skippedLines := 0
|
|
||||||
|
|
||||||
for line := 0; line < view.height; line++ {
|
viewStart := 0
|
||||||
index := indexOffset + line
|
if indexOffset < 0 {
|
||||||
if index < 0 {
|
viewStart = -indexOffset
|
||||||
skippedLines++
|
}
|
||||||
continue
|
for line := viewStart; line < view.height; line++ {
|
||||||
} else if index >= view.TotalHeight() {
|
showScrollbar := line-viewStart >= scrollBarPos-scrollBarHeight && line-viewStart < scrollBarPos
|
||||||
break
|
isTop := line == viewStart && view.ScrollOffset+view.height >= view.TotalHeight()
|
||||||
}
|
|
||||||
|
|
||||||
showScrollbar := line-skippedLines >= scrollBarPos-scrollBarHeight && line-skippedLines < scrollBarPos
|
|
||||||
isTop := firstLine && view.ScrollOffset+view.height >= view.TotalHeight()
|
|
||||||
isBottom := line == view.height-1 && view.ScrollOffset == 0
|
isBottom := line == view.height-1 && view.ScrollOffset == 0
|
||||||
|
|
||||||
borderChar, borderStyle := getScrollbarStyle(showScrollbar, isTop, isBottom)
|
borderChar, borderStyle := getScrollbarStyle(showScrollbar, isTop, isBottom)
|
||||||
|
|
||||||
firstLine = false
|
|
||||||
|
|
||||||
if !bareMode {
|
if !bareMode {
|
||||||
screen.SetContent(separatorX, line, borderChar, nil, borderStyle)
|
screen.SetContent(separatorX, line, borderChar, nil, borderStyle)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for line := viewStart; line < view.height && indexOffset+line < view.TotalHeight(); line++ {
|
||||||
|
index := indexOffset + line
|
||||||
|
|
||||||
text, meta := view.textBuffer[index], view.metaBuffer[index]
|
text, meta := view.textBuffer[index], view.metaBuffer[index]
|
||||||
if meta != prevMeta {
|
if meta != prevMeta {
|
||||||
@ -519,11 +515,6 @@ func (view *MessageView) Draw(screen mauview.Screen) {
|
|||||||
line--
|
line--
|
||||||
}
|
}
|
||||||
message.Draw(mauview.NewProxyScreen(screen, messageX, line, view.width-messageX, message.Height()))
|
message.Draw(mauview.NewProxyScreen(screen, messageX, line, view.width-messageX, message.Height()))
|
||||||
if !bareMode {
|
|
||||||
for i := line; i < line+message.Height(); i++ {
|
|
||||||
screen.SetContent(separatorX, i, borderChar, nil, borderStyle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
line += message.Height() - 1
|
line += message.Height() - 1
|
||||||
} else {
|
} else {
|
||||||
text.Draw(screen, messageX, line)
|
text.Draw(screen, messageX, line)
|
||||||
|
@ -36,6 +36,10 @@ type HTMLMessage struct {
|
|||||||
BaseMessage
|
BaseMessage
|
||||||
|
|
||||||
Root HTMLEntity
|
Root HTMLEntity
|
||||||
|
|
||||||
|
FocusedBackground tcell.Color
|
||||||
|
|
||||||
|
focused bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTMLMessage(id, sender, displayname string, msgtype mautrix.MessageType, root HTMLEntity, timestamp time.Time) UIMessage {
|
func NewHTMLMessage(id, sender, displayname string, msgtype mautrix.MessageType, root HTMLEntity, timestamp time.Time) UIMessage {
|
||||||
@ -45,9 +49,21 @@ func NewHTMLMessage(id, sender, displayname string, msgtype mautrix.MessageType,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (hw *HTMLMessage) Draw(screen mauview.Screen) {
|
func (hw *HTMLMessage) Draw(screen mauview.Screen) {
|
||||||
|
if hw.focused {
|
||||||
|
screen.SetStyle(tcell.StyleDefault.Background(hw.FocusedBackground))
|
||||||
|
}
|
||||||
|
screen.Clear()
|
||||||
hw.Root.Draw(screen)
|
hw.Root.Draw(screen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hw *HTMLMessage) Focus() {
|
||||||
|
hw.focused = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hw *HTMLMessage) Blur() {
|
||||||
|
hw.focused = false
|
||||||
|
}
|
||||||
|
|
||||||
func (hw *HTMLMessage) OnKeyEvent(event mauview.KeyEvent) bool {
|
func (hw *HTMLMessage) OnKeyEvent(event mauview.KeyEvent) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -154,7 +170,7 @@ func NewListEntity(ordered bool, start int, children []HTMLEntity) *ListEntity {
|
|||||||
func (le *ListEntity) Draw(screen mauview.Screen) {
|
func (le *ListEntity) Draw(screen mauview.Screen) {
|
||||||
width, _ := screen.Size()
|
width, _ := screen.Size()
|
||||||
|
|
||||||
proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: le.Indent, Width: width - le.Indent}
|
proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: le.Indent, Width: width - le.Indent, Style: le.Style}
|
||||||
for i, entity := range le.Children {
|
for i, entity := range le.Children {
|
||||||
proxyScreen.Height = entity.Height()
|
proxyScreen.Height = entity.Height()
|
||||||
if le.Ordered {
|
if le.Ordered {
|
||||||
@ -165,6 +181,7 @@ func (le *ListEntity) Draw(screen mauview.Screen) {
|
|||||||
screen.SetContent(0, proxyScreen.OffsetY, '●', nil, le.Style)
|
screen.SetContent(0, proxyScreen.OffsetY, '●', nil, le.Style)
|
||||||
}
|
}
|
||||||
entity.Draw(proxyScreen)
|
entity.Draw(proxyScreen)
|
||||||
|
proxyScreen.SetStyle(le.Style)
|
||||||
proxyScreen.OffsetY += entity.Height()
|
proxyScreen.OffsetY += entity.Height()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,6 +190,31 @@ func (le *ListEntity) String() string {
|
|||||||
return fmt.Sprintf("&ListEntity{Ordered=%t, Start=%d, Base=%s},\n", le.Ordered, le.Start, le.BaseHTMLEntity)
|
return fmt.Sprintf("&ListEntity{Ordered=%t, Start=%d, Base=%s},\n", le.Ordered, le.Start, le.BaseHTMLEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CodeBlockEntity struct {
|
||||||
|
*BaseHTMLEntity
|
||||||
|
Background tcell.Style
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCodeBlockEntity(children []HTMLEntity, background tcell.Style) *CodeBlockEntity {
|
||||||
|
return &CodeBlockEntity{
|
||||||
|
BaseHTMLEntity: &BaseHTMLEntity{
|
||||||
|
Tag: "pre",
|
||||||
|
Block: true,
|
||||||
|
Children: children,
|
||||||
|
},
|
||||||
|
Background: background,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ce *CodeBlockEntity) Draw(screen mauview.Screen) {
|
||||||
|
screen.Fill(' ', ce.Background)
|
||||||
|
ce.BaseHTMLEntity.Draw(screen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ce *CodeBlockEntity) AdjustStyle(fn AdjustStyleFunc) HTMLEntity {
|
||||||
|
return ce
|
||||||
|
}
|
||||||
|
|
||||||
type BreakEntity struct {
|
type BreakEntity struct {
|
||||||
*BaseHTMLEntity
|
*BaseHTMLEntity
|
||||||
}
|
}
|
||||||
@ -297,13 +339,14 @@ func (he *BaseHTMLEntity) Draw(screen mauview.Screen) {
|
|||||||
}
|
}
|
||||||
if len(he.Children) > 0 {
|
if len(he.Children) > 0 {
|
||||||
prevBreak := false
|
prevBreak := false
|
||||||
proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: he.Indent, Width: width - he.Indent}
|
proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: he.Indent, Width: width - he.Indent, Style: he.Style}
|
||||||
for i, entity := range he.Children {
|
for i, entity := range he.Children {
|
||||||
if i != 0 && entity.getStartX() == 0 {
|
if i != 0 && entity.getStartX() == 0 {
|
||||||
proxyScreen.OffsetY++
|
proxyScreen.OffsetY++
|
||||||
}
|
}
|
||||||
proxyScreen.Height = entity.Height()
|
proxyScreen.Height = entity.Height()
|
||||||
entity.Draw(proxyScreen)
|
entity.Draw(proxyScreen)
|
||||||
|
proxyScreen.SetStyle(he.Style)
|
||||||
proxyScreen.OffsetY += entity.Height() - 1
|
proxyScreen.OffsetY += entity.Height() - 1
|
||||||
_, isBreak := entity.(*BreakEntity)
|
_, isBreak := entity.(*BreakEntity)
|
||||||
if prevBreak && isBreak {
|
if prevBreak && isBreak {
|
||||||
|
@ -221,7 +221,7 @@ func styleEntryToStyle(se chroma.StyleEntry) tcell.Style {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (parser *htmlParser) syntaxHighlight(text, language string) messages.HTMLEntity {
|
func (parser *htmlParser) syntaxHighlight(text, language string) messages.HTMLEntity {
|
||||||
lexer := lexers.Get(language)
|
lexer := lexers.Get(strings.ToLower(language))
|
||||||
if lexer == nil {
|
if lexer == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -229,7 +229,9 @@ func (parser *htmlParser) syntaxHighlight(text, language string) messages.HTMLEn
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
// TODO allow changing theme
|
||||||
style := styles.SolarizedDark
|
style := styles.SolarizedDark
|
||||||
|
|
||||||
tokens := iter.Tokens()
|
tokens := iter.Tokens()
|
||||||
children := make([]messages.HTMLEntity, len(tokens))
|
children := make([]messages.HTMLEntity, len(tokens))
|
||||||
for i, token := range tokens {
|
for i, token := range tokens {
|
||||||
@ -245,39 +247,26 @@ func (parser *htmlParser) syntaxHighlight(text, language string) messages.HTMLEn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &messages.BaseHTMLEntity{
|
return messages.NewCodeBlockEntity(children, styleEntryToStyle(style.Get(chroma.Background)))
|
||||||
Tag: "pre",
|
|
||||||
Block: true,
|
|
||||||
Children: children,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (parser *htmlParser) codeblockToEntity(node *html.Node) messages.HTMLEntity {
|
func (parser *htmlParser) codeblockToEntity(node *html.Node) messages.HTMLEntity {
|
||||||
entity := &messages.BaseHTMLEntity{
|
lang := "plaintext"
|
||||||
Tag: "pre",
|
|
||||||
Block: true,
|
|
||||||
}
|
|
||||||
// TODO allow disabling syntax highlighting
|
// TODO allow disabling syntax highlighting
|
||||||
if node.FirstChild.Type == html.ElementNode && node.FirstChild.Data == "code" {
|
if node.FirstChild.Type == html.ElementNode && node.FirstChild.Data == "code" {
|
||||||
text := (&messages.BaseHTMLEntity{
|
node = node.FirstChild
|
||||||
Children: parser.nodeToEntities(node.FirstChild.FirstChild, false),
|
attr := parser.getAttribute(node, "class")
|
||||||
}).PlainText()
|
|
||||||
attr := parser.getAttribute(node.FirstChild, "class")
|
|
||||||
var lang string
|
|
||||||
for _, class := range strings.Split(attr, " ") {
|
for _, class := range strings.Split(attr, " ") {
|
||||||
if strings.HasPrefix(class, "language-") {
|
if strings.HasPrefix(class, "language-") {
|
||||||
lang = class[len("language-"):]
|
lang = class[len("language-"):]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(lang) != 0 {
|
|
||||||
if parsed := parser.syntaxHighlight(text, lang); parsed != nil {
|
|
||||||
return parsed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
entity.Children = parser.nodeToEntities(node.FirstChild, false)
|
text := (&messages.BaseHTMLEntity{
|
||||||
return entity
|
Children: parser.nodeToEntities(node.FirstChild, false),
|
||||||
|
}).PlainText()
|
||||||
|
return parser.syntaxHighlight(text, lang)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (parser *htmlParser) tagNodeToEntity(node *html.Node, stripLinebreak bool) messages.HTMLEntity {
|
func (parser *htmlParser) tagNodeToEntity(node *html.Node, stripLinebreak bool) messages.HTMLEntity {
|
||||||
@ -311,7 +300,7 @@ func (parser *htmlParser) singleNodeToEntity(node *html.Node, stripLinebreak boo
|
|||||||
switch node.Type {
|
switch node.Type {
|
||||||
case html.TextNode:
|
case html.TextNode:
|
||||||
if stripLinebreak {
|
if stripLinebreak {
|
||||||
node.Data = strings.Replace(node.Data, "\n", "", -1)
|
node.Data = strings.ReplaceAll(node.Data, "\n", "")
|
||||||
}
|
}
|
||||||
return &messages.BaseHTMLEntity{
|
return &messages.BaseHTMLEntity{
|
||||||
Tag: "text",
|
Tag: "text",
|
||||||
@ -372,7 +361,7 @@ func ParseHTMLMessage(room *rooms.Room, evt *mautrix.Event, senderDisplayname st
|
|||||||
Tag: "emote",
|
Tag: "emote",
|
||||||
Children: []messages.HTMLEntity{
|
Children: []messages.HTMLEntity{
|
||||||
messages.NewHTMLTextEntity("* "),
|
messages.NewHTMLTextEntity("* "),
|
||||||
messages.NewHTMLTextEntity("* ").AdjustStyle(AdjustStyleTextColor(widget.GetHashColor(evt.Sender))),
|
messages.NewHTMLTextEntity(senderDisplayname).AdjustStyle(AdjustStyleTextColor(widget.GetHashColor(evt.Sender))),
|
||||||
messages.NewHTMLTextEntity(" "),
|
messages.NewHTMLTextEntity(" "),
|
||||||
root,
|
root,
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user