From 5e3994ce2cead6851d19a37dc6d76104f4152e7f Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Mon, 11 Jun 2018 19:38:19 +0300 Subject: [PATCH] Add font tag support and /rainbow command --- ui/command-processor.go | 2 ++ ui/commands.go | 53 ++++++++++++++++++++++++++++++++ ui/messages/parser/htmlparser.go | 23 ++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/ui/command-processor.go b/ui/command-processor.go index 2fe47bf..0f38c57 100644 --- a/ui/command-processor.go +++ b/ui/command-processor.go @@ -78,6 +78,7 @@ func NewCommandProcessor(parent *MainView) *CommandProcessor { "part": {"leave"}, "send": {"sendevent"}, "state": {"setstate"}, + "rb": {"rainbow"}, }, commands: map[string]CommandHandler{ "unknown-command": cmdUnknownCommand, @@ -91,6 +92,7 @@ func NewCommandProcessor(parent *MainView) *CommandProcessor { "logout": cmdLogout, "sendevent": cmdSendEvent, "setstate": cmdSetState, + "rainbow": cmdRainbow, }, } } diff --git a/ui/commands.go b/ui/commands.go index 510fc5d..8746305 100644 --- a/ui/commands.go +++ b/ui/commands.go @@ -20,6 +20,9 @@ import ( "encoding/json" "maunium.net/go/gomuks/debug" "strings" + "fmt" + "github.com/lucasb-eyer/go-colorful" + "unicode" ) func cmdMe(cmd *Command) { @@ -29,6 +32,56 @@ func cmdMe(cmd *Command) { cmd.UI.Render() } +// GradientTable from https://github.com/lucasb-eyer/go-colorful/blob/master/doc/gradientgen/gradientgen.go +type GradientTable []struct { + Col colorful.Color + Pos float64 +} + +func (gt GradientTable) GetInterpolatedColorFor(t float64) colorful.Color { + for i := 0; i < len(gt)-1; i++ { + c1 := gt[i] + c2 := gt[i+1] + if c1.Pos <= t && t <= c2.Pos { + t := (t - c1.Pos) / (c2.Pos - c1.Pos) + return c1.Col.BlendHcl(c2.Col, t).Clamped() + } + } + return gt[len(gt)-1].Col +} + +var rainbow = GradientTable{ + {colorful.LinearRgb(1, 0, 0), 0.0}, + {colorful.LinearRgb(1, 0.5, 0), 0.1}, + {colorful.LinearRgb(1, 1, 0), 0.2}, + {colorful.LinearRgb(0.5, 1, 0), 0.3}, + {colorful.LinearRgb(0, 1, 0), 0.4}, + {colorful.LinearRgb(0, 1, 0.5), 0.5}, + {colorful.LinearRgb(0, 1, 1), 0.6}, + {colorful.LinearRgb(0, 0.5, 1), 0.7}, + {colorful.LinearRgb(0.5, 0, 1), 0.8}, + {colorful.LinearRgb(1, 0, 1), 0.9}, + {colorful.LinearRgb(1, 0, 0.5), 1}, +} + +// TODO this command definitely belongs in a plugin once we have a plugin system. +func cmdRainbow(cmd *Command) { + text := strings.Join(cmd.Args, " ") + var html strings.Builder + fmt.Fprint(&html, "**🌈** ") + for i, char := range text { + if unicode.IsSpace(char) { + html.WriteRune(char) + continue + } + color := rainbow.GetInterpolatedColorFor(float64(i)/float64(len(text))).Hex() + fmt.Fprintf(&html, "%c", color, char) + } + tempMessage := cmd.Room.NewTempMessage("m.text", html.String()) + go cmd.MainView.sendTempMessage(cmd.Room, tempMessage, html.String()) + cmd.UI.Render() +} + func cmdQuit(cmd *Command) { cmd.Gomuks.Stop() } diff --git a/ui/messages/parser/htmlparser.go b/ui/messages/parser/htmlparser.go index 98894fd..c8b000e 100644 --- a/ui/messages/parser/htmlparser.go +++ b/ui/messages/parser/htmlparser.go @@ -29,6 +29,7 @@ import ( "maunium.net/go/gomuks/ui/widget" "maunium.net/go/tcell" "strconv" + "github.com/lucasb-eyer/go-colorful" ) var matrixToURL = regexp.MustCompile("^(?:https?://)?(?:www\\.)?matrix\\.to/#/([#@!].*)") @@ -125,6 +126,26 @@ func (parser *htmlParser) basicFormatToTString(node *html.Node, stripLinebreak b return str } +func (parser *htmlParser) fontToTString(node *html.Node, stripLinebreak bool) tstring.TString { + str := parser.nodeToTagAwareTString(node.FirstChild, stripLinebreak) + hex := parser.getAttribute(node, "color") + if len(hex) == 0 { + return str + } + + color, err := colorful.Hex(hex) + if err != nil { + return str + } + + r, g, b := color.RGB255() + tcellColor := tcell.NewRGBColor(int32(r), int32(g), int32(b)) + str.AdjustStyleFull(func(style tcell.Style) tcell.Style { + return style.Foreground(tcellColor) + }) + return str +} + func (parser *htmlParser) headerToTString(node *html.Node, stripLinebreak bool) tstring.TString { children := parser.nodeToTStrings(node.FirstChild, stripLinebreak) length := int(node.Data[1] - '0') @@ -172,6 +193,8 @@ func (parser *htmlParser) tagToTString(node *html.Node, stripLinebreak bool) tst return tstring.NewTString("\n") case "b", "strong", "i", "em", "s", "del", "u", "ins": return parser.basicFormatToTString(node, stripLinebreak) + case "font": + return parser.fontToTString(node, stripLinebreak) case "a": return parser.linkToTString(node, stripLinebreak) case "p":