diff --git a/bombadillo.1 b/bombadillo.1 index aa0296a..f044def 100644 --- a/bombadillo.1 +++ b/bombadillo.1 @@ -231,7 +231,7 @@ Tells the browser what command to use to start a telnet session. Should be a val .TP .B theme -Can toggle between visual modes. Valid values are \fInormal\fP and \fIinverse\fP. When set to inverse, the terminal color mode is inverted. +Can toggle between visual modes. Valid values are \fInormal\fP, \fIcolor\fP, and \fIinverse\fP. When set to inverse, the normal mode colors mode is inverted. When set to color, Bombadillo will render color codes in documents. .TP .B tlscertificate diff --git a/client.go b/client.go index dcdd8bc..b0270ac 100644 --- a/client.go +++ b/client.go @@ -86,9 +86,12 @@ func (c *client) Draw() { screen.WriteString("\033[0m") screen.WriteString(c.TopBar.Render(c.Width, c.Options["theme"])) screen.WriteString("\n") - pageContent := c.PageState.Render(c.Height, c.Width-1) + pageContent := c.PageState.Render(c.Height, c.Width-1, (c.Options["theme"] == "color")) + var re *regexp.Regexp if c.Options["theme"] == "inverse" { screen.WriteString("\033[7m") + } else if c.Options["theme"] == "color" { + re = regexp.MustCompile(`\033\[(?:\d*;?)+[A-Za-z]`) } if c.BookMarks.IsOpen { bm := c.BookMarks.Render(c.Width, c.Height) @@ -97,7 +100,14 @@ func (c *client) Draw() { if c.Width > bmWidth { contentWidth := c.Width - bmWidth if i < len(pageContent) { - screen.WriteString(fmt.Sprintf("%-*.*s", contentWidth, contentWidth, pageContent[i])) + extra := 0 + if c.Options["theme"] == "color" { + escapes := re.FindAllString(pageContent[i], -1) + for _, esc := range escapes { + extra += len(esc) + } + } + screen.WriteString(fmt.Sprintf("%-*.*s", contentWidth+extra, contentWidth+extra, pageContent[i])) } else { screen.WriteString(fmt.Sprintf("%-*.*s", contentWidth, contentWidth, " ")) } @@ -110,6 +120,9 @@ func (c *client) Draw() { screen.WriteString("\033[2m") } + if c.Options["theme"] == "color" { + screen.WriteString("\033[0m") + } screen.WriteString(bm[i]) if c.Options["theme"] == "inverse" && !c.BookMarks.IsFocused { @@ -123,7 +136,14 @@ func (c *client) Draw() { } else { for i := 0; i < c.Height-3; i++ { if i < len(pageContent) { - screen.WriteString(fmt.Sprintf("%-*.*s", c.Width, c.Width, pageContent[i])) + extra := 0 + if c.Options["theme"] == "color" { + escapes := re.FindAllString(pageContent[i], -1) + for _, esc := range escapes { + extra += len(esc) + } + } + screen.WriteString(fmt.Sprintf("%-*.*s", c.Width+extra, c.Width+extra, pageContent[i])) screen.WriteString("\n") } else { screen.WriteString(fmt.Sprintf("%-*.*s", c.Width, c.Width, " ")) @@ -219,7 +239,7 @@ func (c *client) TakeControlInput() { // Process a command c.ClearMessage() c.ClearMessageLine() - if c.Options["theme"] == "normal" { + if c.Options["theme"] == "normal" || c.Options["theme"] == "color" { fmt.Printf("\033[7m%*.*s\r", c.Width, c.Width, "") } entry, err := cui.GetLine() @@ -620,7 +640,7 @@ func (c *client) search(query, url, question string) { if query == "" { c.ClearMessage() c.ClearMessageLine() - if c.Options["theme"] == "normal" { + if c.Options["theme"] == "normal" || c.Options["theme"] == "color" { fmt.Printf("\033[7m%*.*s\r", c.Width, c.Width, "") } fmt.Print(question) @@ -773,7 +793,7 @@ func (c *client) DrawMessage() { func (c *client) RenderMessage() string { leadIn, leadOut := "", "" - if c.Options["theme"] == "normal" { + if c.Options["theme"] == "normal" || c.Options["theme"] == "color" { leadIn = "\033[7m" leadOut = "\033[0m" } @@ -782,7 +802,7 @@ func (c *client) RenderMessage() string { leadIn = "\033[31;1m" leadOut = "\033[0m" - if c.Options["theme"] == "normal" { + if c.Options["theme"] == "normal" || c.Options["theme"] == "color" { leadIn = "\033[41;1;7m" } } @@ -891,7 +911,7 @@ func (c *client) handleGopher(u Url) { return } pg := MakePage(u, content, links) - pg.WrapContent(c.Width - 1) + pg.WrapContent(c.Width-1, (c.Options["theme"] == "color")) c.PageState.Add(pg) c.SetPercentRead() c.ClearMessage() @@ -914,7 +934,7 @@ func (c *client) handleGemini(u Url) { case 2: if capsule.MimeMaj == "text" { pg := MakePage(u, capsule.Content, capsule.Links) - pg.WrapContent(c.Width - 1) + pg.WrapContent(c.Width-1, (c.Options["theme"] == "color")) c.PageState.Add(pg) c.SetPercentRead() c.ClearMessage() @@ -962,7 +982,7 @@ func (c *client) handleLocal(u Url) { return } pg := MakePage(u, content, links) - pg.WrapContent(c.Width - 1) + pg.WrapContent(c.Width-1, (c.Options["theme"] == "color")) c.PageState.Add(pg) c.SetPercentRead() c.ClearMessage() @@ -978,7 +998,7 @@ func (c *client) handleFinger(u Url) { return } pg := MakePage(u, content, []string{}) - pg.WrapContent(c.Width - 1) + pg.WrapContent(c.Width-1, (c.Options["theme"] == "color")) c.PageState.Add(pg) c.SetPercentRead() c.ClearMessage() @@ -998,7 +1018,7 @@ func (c *client) handleWeb(u Url) { return } pg := MakePage(u, page.Content, page.Links) - pg.WrapContent(c.Width - 1) + pg.WrapContent(c.Width-1, (c.Options["theme"] == "color")) c.PageState.Add(pg) c.SetPercentRead() c.ClearMessage() diff --git a/defaults.go b/defaults.go index 022435f..1c0a230 100644 --- a/defaults.go +++ b/defaults.go @@ -51,7 +51,7 @@ var defaultOptions = map[string]string{ "telnetcommand": "telnet", "configlocation": xdgConfigPath(), "defaultscheme": "gopher", // "gopher", "gemini", "http", "https" - "theme": "normal", // "normal", "inverted" + "theme": "normal", // "normal", "inverted", "color" "tlscertificate": "", "tlskey": "", "webmode": "none", // "none", "gui", "lynx", "w3m", "elinks" diff --git a/main.go b/main.go index 5fb0596..998624f 100644 --- a/main.go +++ b/main.go @@ -47,10 +47,10 @@ func saveConfig() error { opts.WriteString("\n[SETTINGS]\n") for k, v := range bombadillo.Options { - if k == "theme" && v != "normal" && v != "inverse" { - v = "normal" - bombadillo.Options["theme"] = "normal" - } + // if k == "theme" && v != "normal" && v != "inverse" { + // v = "normal" + // bombadillo.Options["theme"] = "normal" + // } opts.WriteString(k) opts.WriteRune('=') opts.WriteString(v) @@ -67,7 +67,7 @@ func saveConfig() error { func validateOpt(opt, val string) bool { var validOpts = map[string][]string{ "webmode": []string{"none", "gui", "lynx", "w3m", "elinks"}, - "theme": []string{"normal", "inverse"}, + "theme": []string{"normal", "inverse", "color"}, "defaultscheme": []string{"gopher", "gemini", "http", "https"}, } @@ -117,11 +117,7 @@ func loadConfig() { for _, v := range settings.Settings { lowerkey := strings.ToLower(v.Key) if lowerkey == "configlocation" { - // The config defaults to the home folder. - // Users cannot really edit this value. But - // a compile time override is available. - // It is still stored in the ini and as a part - // of the options map. + // Read only continue } diff --git a/page.go b/page.go index 4c8c0d8..fe65387 100644 --- a/page.go +++ b/page.go @@ -47,7 +47,7 @@ func (p *Page) ScrollPositionRange(termHeight int) (int, int) { // width and updates the WrappedContent // of the Page struct width a string slice // of the wrapped data -func (p *Page) WrapContent(width int) { +func (p *Page) WrapContent(width int, color bool) { counter := 0 var content strings.Builder escape := false @@ -57,6 +57,9 @@ func (p *Page) WrapContent(width int) { if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') { escape = false } + if color { + content.WriteRune(ch) + } continue } if ch == '\n' { @@ -75,6 +78,9 @@ func (p *Page) WrapContent(width int) { continue } else if ch == 27 { escape = true + if color { + content.WriteRune(ch) + } continue } else { if counter < width { diff --git a/pages.go b/pages.go index 3a1db87..46d962b 100644 --- a/pages.go +++ b/pages.go @@ -60,13 +60,13 @@ func (p *Pages) Add(pg Page) { // Render wraps the content for the current page and returns // the page content as a string slice -func (p *Pages) Render(termHeight, termWidth int) []string { +func (p *Pages) Render(termHeight, termWidth int, color bool) []string { if p.Length < 1 { return make([]string, 0) } pos := p.History[p.Position].ScrollPosition prev := len(p.History[p.Position].WrappedContent) - p.History[p.Position].WrapContent(termWidth) + p.History[p.Position].WrapContent(termWidth, color) now := len(p.History[p.Position].WrappedContent) if prev > now { diff := prev - now