Adds support for a new color theme mode

This commit is contained in:
sloumdrone 2019-12-10 21:56:41 -08:00
parent ccc694fb2f
commit 021678d9da
6 changed files with 49 additions and 27 deletions

View File

@ -231,7 +231,7 @@ Tells the browser what command to use to start a telnet session. Should be a val
.TP .TP
.B .B
theme 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 .TP
.B .B
tlscertificate tlscertificate

View File

@ -86,9 +86,12 @@ func (c *client) Draw() {
screen.WriteString("\033[0m") screen.WriteString("\033[0m")
screen.WriteString(c.TopBar.Render(c.Width, c.Options["theme"])) screen.WriteString(c.TopBar.Render(c.Width, c.Options["theme"]))
screen.WriteString("\n") 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" { if c.Options["theme"] == "inverse" {
screen.WriteString("\033[7m") screen.WriteString("\033[7m")
} else if c.Options["theme"] == "color" {
re = regexp.MustCompile(`\033\[(?:\d*;?)+[A-Za-z]`)
} }
if c.BookMarks.IsOpen { if c.BookMarks.IsOpen {
bm := c.BookMarks.Render(c.Width, c.Height) bm := c.BookMarks.Render(c.Width, c.Height)
@ -97,7 +100,14 @@ func (c *client) Draw() {
if c.Width > bmWidth { if c.Width > bmWidth {
contentWidth := c.Width - bmWidth contentWidth := c.Width - bmWidth
if i < len(pageContent) { 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 { } else {
screen.WriteString(fmt.Sprintf("%-*.*s", contentWidth, contentWidth, " ")) screen.WriteString(fmt.Sprintf("%-*.*s", contentWidth, contentWidth, " "))
} }
@ -110,6 +120,9 @@ func (c *client) Draw() {
screen.WriteString("\033[2m") screen.WriteString("\033[2m")
} }
if c.Options["theme"] == "color" {
screen.WriteString("\033[0m")
}
screen.WriteString(bm[i]) screen.WriteString(bm[i])
if c.Options["theme"] == "inverse" && !c.BookMarks.IsFocused { if c.Options["theme"] == "inverse" && !c.BookMarks.IsFocused {
@ -123,7 +136,14 @@ func (c *client) Draw() {
} else { } else {
for i := 0; i < c.Height-3; i++ { for i := 0; i < c.Height-3; i++ {
if i < len(pageContent) { 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") screen.WriteString("\n")
} else { } else {
screen.WriteString(fmt.Sprintf("%-*.*s", c.Width, c.Width, " ")) screen.WriteString(fmt.Sprintf("%-*.*s", c.Width, c.Width, " "))
@ -219,7 +239,7 @@ func (c *client) TakeControlInput() {
// Process a command // Process a command
c.ClearMessage() c.ClearMessage()
c.ClearMessageLine() 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.Printf("\033[7m%*.*s\r", c.Width, c.Width, "")
} }
entry, err := cui.GetLine() entry, err := cui.GetLine()
@ -620,7 +640,7 @@ func (c *client) search(query, url, question string) {
if query == "" { if query == "" {
c.ClearMessage() c.ClearMessage()
c.ClearMessageLine() 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.Printf("\033[7m%*.*s\r", c.Width, c.Width, "")
} }
fmt.Print(question) fmt.Print(question)
@ -773,7 +793,7 @@ func (c *client) DrawMessage() {
func (c *client) RenderMessage() string { func (c *client) RenderMessage() string {
leadIn, leadOut := "", "" leadIn, leadOut := "", ""
if c.Options["theme"] == "normal" { if c.Options["theme"] == "normal" || c.Options["theme"] == "color" {
leadIn = "\033[7m" leadIn = "\033[7m"
leadOut = "\033[0m" leadOut = "\033[0m"
} }
@ -782,7 +802,7 @@ func (c *client) RenderMessage() string {
leadIn = "\033[31;1m" leadIn = "\033[31;1m"
leadOut = "\033[0m" leadOut = "\033[0m"
if c.Options["theme"] == "normal" { if c.Options["theme"] == "normal" || c.Options["theme"] == "color" {
leadIn = "\033[41;1;7m" leadIn = "\033[41;1;7m"
} }
} }
@ -891,7 +911,7 @@ func (c *client) handleGopher(u Url) {
return return
} }
pg := MakePage(u, content, links) pg := MakePage(u, content, links)
pg.WrapContent(c.Width - 1) pg.WrapContent(c.Width-1, (c.Options["theme"] == "color"))
c.PageState.Add(pg) c.PageState.Add(pg)
c.SetPercentRead() c.SetPercentRead()
c.ClearMessage() c.ClearMessage()
@ -914,7 +934,7 @@ func (c *client) handleGemini(u Url) {
case 2: case 2:
if capsule.MimeMaj == "text" { if capsule.MimeMaj == "text" {
pg := MakePage(u, capsule.Content, capsule.Links) 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.PageState.Add(pg)
c.SetPercentRead() c.SetPercentRead()
c.ClearMessage() c.ClearMessage()
@ -962,7 +982,7 @@ func (c *client) handleLocal(u Url) {
return return
} }
pg := MakePage(u, content, links) pg := MakePage(u, content, links)
pg.WrapContent(c.Width - 1) pg.WrapContent(c.Width-1, (c.Options["theme"] == "color"))
c.PageState.Add(pg) c.PageState.Add(pg)
c.SetPercentRead() c.SetPercentRead()
c.ClearMessage() c.ClearMessage()
@ -978,7 +998,7 @@ func (c *client) handleFinger(u Url) {
return return
} }
pg := MakePage(u, content, []string{}) pg := MakePage(u, content, []string{})
pg.WrapContent(c.Width - 1) pg.WrapContent(c.Width-1, (c.Options["theme"] == "color"))
c.PageState.Add(pg) c.PageState.Add(pg)
c.SetPercentRead() c.SetPercentRead()
c.ClearMessage() c.ClearMessage()
@ -998,7 +1018,7 @@ func (c *client) handleWeb(u Url) {
return return
} }
pg := MakePage(u, page.Content, page.Links) 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.PageState.Add(pg)
c.SetPercentRead() c.SetPercentRead()
c.ClearMessage() c.ClearMessage()

View File

@ -51,7 +51,7 @@ var defaultOptions = map[string]string{
"telnetcommand": "telnet", "telnetcommand": "telnet",
"configlocation": xdgConfigPath(), "configlocation": xdgConfigPath(),
"defaultscheme": "gopher", // "gopher", "gemini", "http", "https" "defaultscheme": "gopher", // "gopher", "gemini", "http", "https"
"theme": "normal", // "normal", "inverted" "theme": "normal", // "normal", "inverted", "color"
"tlscertificate": "", "tlscertificate": "",
"tlskey": "", "tlskey": "",
"webmode": "none", // "none", "gui", "lynx", "w3m", "elinks" "webmode": "none", // "none", "gui", "lynx", "w3m", "elinks"

16
main.go
View File

@ -47,10 +47,10 @@ func saveConfig() error {
opts.WriteString("\n[SETTINGS]\n") opts.WriteString("\n[SETTINGS]\n")
for k, v := range bombadillo.Options { for k, v := range bombadillo.Options {
if k == "theme" && v != "normal" && v != "inverse" { // if k == "theme" && v != "normal" && v != "inverse" {
v = "normal" // v = "normal"
bombadillo.Options["theme"] = "normal" // bombadillo.Options["theme"] = "normal"
} // }
opts.WriteString(k) opts.WriteString(k)
opts.WriteRune('=') opts.WriteRune('=')
opts.WriteString(v) opts.WriteString(v)
@ -67,7 +67,7 @@ func saveConfig() error {
func validateOpt(opt, val string) bool { func validateOpt(opt, val string) bool {
var validOpts = map[string][]string{ var validOpts = map[string][]string{
"webmode": []string{"none", "gui", "lynx", "w3m", "elinks"}, "webmode": []string{"none", "gui", "lynx", "w3m", "elinks"},
"theme": []string{"normal", "inverse"}, "theme": []string{"normal", "inverse", "color"},
"defaultscheme": []string{"gopher", "gemini", "http", "https"}, "defaultscheme": []string{"gopher", "gemini", "http", "https"},
} }
@ -117,11 +117,7 @@ func loadConfig() {
for _, v := range settings.Settings { for _, v := range settings.Settings {
lowerkey := strings.ToLower(v.Key) lowerkey := strings.ToLower(v.Key)
if lowerkey == "configlocation" { if lowerkey == "configlocation" {
// The config defaults to the home folder. // Read only
// 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.
continue continue
} }

View File

@ -47,7 +47,7 @@ func (p *Page) ScrollPositionRange(termHeight int) (int, int) {
// width and updates the WrappedContent // width and updates the WrappedContent
// of the Page struct width a string slice // of the Page struct width a string slice
// of the wrapped data // of the wrapped data
func (p *Page) WrapContent(width int) { func (p *Page) WrapContent(width int, color bool) {
counter := 0 counter := 0
var content strings.Builder var content strings.Builder
escape := false escape := false
@ -57,6 +57,9 @@ func (p *Page) WrapContent(width int) {
if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') { if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') {
escape = false escape = false
} }
if color {
content.WriteRune(ch)
}
continue continue
} }
if ch == '\n' { if ch == '\n' {
@ -75,6 +78,9 @@ func (p *Page) WrapContent(width int) {
continue continue
} else if ch == 27 { } else if ch == 27 {
escape = true escape = true
if color {
content.WriteRune(ch)
}
continue continue
} else { } else {
if counter < width { if counter < width {

View File

@ -60,13 +60,13 @@ func (p *Pages) Add(pg Page) {
// Render wraps the content for the current page and returns // Render wraps the content for the current page and returns
// the page content as a string slice // 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 { if p.Length < 1 {
return make([]string, 0) return make([]string, 0)
} }
pos := p.History[p.Position].ScrollPosition pos := p.History[p.Position].ScrollPosition
prev := len(p.History[p.Position].WrappedContent) 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) now := len(p.History[p.Position].WrappedContent)
if prev > now { if prev > now {
diff := prev - now diff := prev - now