Vast improvements, still squashing bugs like crazy.
This commit is contained in:
parent
98e34576ca
commit
f2f730f3c5
|
@ -107,10 +107,10 @@ func (b Bookmarks) Render(termwidth, termheight int) []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
out := make([]string, 0, 5)
|
out := make([]string, 0, 5)
|
||||||
top := fmt.Sprintf("%s%s%s", tl, strings.Repeat(ceil, width-2), tr)
|
contentWidth := width - 2
|
||||||
|
top := fmt.Sprintf("%s%s%s", tl, strings.Repeat(ceil, contentWidth), tr)
|
||||||
out = append(out, top)
|
out = append(out, top)
|
||||||
marks := b.List()
|
marks := b.List()
|
||||||
contentWidth := width - 2
|
|
||||||
for i := 0; i < termheight - 2; i++ {
|
for i := 0; i < termheight - 2; i++ {
|
||||||
if i + b.Position >= b.Length {
|
if i + b.Position >= b.Length {
|
||||||
out = append(out, fmt.Sprintf("%s%-*.*s%s", wall, contentWidth, contentWidth, "", wall ))
|
out = append(out, fmt.Sprintf("%s%-*.*s%s", wall, contentWidth, contentWidth, "", wall ))
|
||||||
|
@ -119,7 +119,7 @@ func (b Bookmarks) Render(termwidth, termheight int) []string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bottom := fmt.Sprintf("%s%s%s", bl, strings.Repeat(ceil, width-2), br)
|
bottom := fmt.Sprintf("%s%s%s", bl, strings.Repeat(ceil, contentWidth), br)
|
||||||
out = append(out, bottom)
|
out = append(out, bottom)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
128
client.go
128
client.go
|
@ -6,7 +6,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/user"
|
// "os/user"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -41,6 +41,8 @@ type client struct {
|
||||||
//--------------------------------------------------\\
|
//--------------------------------------------------\\
|
||||||
|
|
||||||
func (c *client) GetSize() {
|
func (c *client) GetSize() {
|
||||||
|
c.SetMessage("Initializing...", false)
|
||||||
|
c.DrawMessage()
|
||||||
for {
|
for {
|
||||||
redraw := false
|
redraw := false
|
||||||
cmd := exec.Command("stty", "size")
|
cmd := exec.Command("stty", "size")
|
||||||
|
@ -71,28 +73,33 @@ func (c *client) GetSize() {
|
||||||
func (c *client) Draw() {
|
func (c *client) Draw() {
|
||||||
var screen strings.Builder
|
var screen strings.Builder
|
||||||
screen.Grow(c.Height * c.Width)
|
screen.Grow(c.Height * c.Width)
|
||||||
screen.WriteString(c.TopBar.Render(c.Width))
|
screen.WriteString(c.TopBar.Render(c.Width, c.Options["theme"]))
|
||||||
screen.WriteString("\n")
|
screen.WriteString("\n")
|
||||||
pageContent := c.PageState.Render(c.Height, c.Width)
|
pageContent := c.PageState.Render(c.Height, c.Width)
|
||||||
|
if c.Options["theme"] == "inverse" {
|
||||||
|
screen.WriteString("\033[7m")
|
||||||
|
}
|
||||||
if c.BookMarks.IsOpen {
|
if c.BookMarks.IsOpen {
|
||||||
bm := c.BookMarks.Render(c.Width, c.Height)
|
bm := c.BookMarks.Render(c.Width, c.Height)
|
||||||
bmWidth := 40
|
// TODO remove this hard coded value
|
||||||
|
bmWidth := len([]rune(bm[0]))
|
||||||
for i := 0; i < c.Height - 3; i++ {
|
for i := 0; i < c.Height - 3; i++ {
|
||||||
if c.Width > bmWidth {
|
if c.Width > bmWidth {
|
||||||
contentWidth := c.Width - bmWidth - 1
|
contentWidth := c.Width - bmWidth
|
||||||
if i < len(pageContent) - 1 {
|
if i < len(pageContent) {
|
||||||
screen.WriteString(fmt.Sprintf("%-*.*s", contentWidth, contentWidth, pageContent[i]))
|
screen.WriteString(fmt.Sprintf("%-*.*s", contentWidth, contentWidth, pageContent[i]))
|
||||||
} else {
|
} else {
|
||||||
screen.WriteString(fmt.Sprintf("%-*.*s", contentWidth, contentWidth, " "))
|
screen.WriteString(fmt.Sprintf("%-*.*s", contentWidth, contentWidth, " "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
screen.WriteString(bm[i])
|
screen.WriteString(bm[i])
|
||||||
screen.WriteString("\n")
|
screen.WriteString("\n")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i := 0; i < c.Height - 3; i++ {
|
for i := 0; i < c.Height - 3; i++ {
|
||||||
if i < len(pageContent) - 1 {
|
if i < len(pageContent) - 1 {
|
||||||
screen.WriteString(pageContent[i])
|
screen.WriteString(fmt.Sprintf("%-*.*s", c.Width, c.Width, pageContent[i]))
|
||||||
screen.WriteString("\n")
|
screen.WriteString("\n")
|
||||||
} else {
|
} else {
|
||||||
screen.WriteString(fmt.Sprintf("%*s", c.Width, " "))
|
screen.WriteString(fmt.Sprintf("%*s", c.Width, " "))
|
||||||
|
@ -100,8 +107,9 @@ func (c *client) Draw() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
screen.WriteString("\033[0m")
|
||||||
screen.WriteString("\n") // for the input line
|
screen.WriteString("\n") // for the input line
|
||||||
screen.WriteString(c.FootBar.Render(c.Width))
|
screen.WriteString(c.FootBar.Render(c.Width, c.PageState.Position, c.Options["theme"]))
|
||||||
cui.Clear("screen")
|
cui.Clear("screen")
|
||||||
cui.MoveCursorTo(0,0)
|
cui.MoveCursorTo(0,0)
|
||||||
fmt.Print(screen.String())
|
fmt.Print(screen.String())
|
||||||
|
@ -183,6 +191,9 @@ func (c *client) TakeControlInput() {
|
||||||
// Process a command
|
// Process a command
|
||||||
c.ClearMessage()
|
c.ClearMessage()
|
||||||
c.ClearMessageLine()
|
c.ClearMessageLine()
|
||||||
|
if c.Options["theme"] == "normal" {
|
||||||
|
fmt.Printf("\033[7m%*.*s\r", c.Width, c.Width, "")
|
||||||
|
}
|
||||||
entry, err := cui.GetLine()
|
entry, err := cui.GetLine()
|
||||||
c.ClearMessageLine()
|
c.ClearMessageLine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -190,6 +201,7 @@ func (c *client) TakeControlInput() {
|
||||||
c.DrawMessage()
|
c.DrawMessage()
|
||||||
break
|
break
|
||||||
} else if strings.TrimSpace(entry) == "" {
|
} else if strings.TrimSpace(entry) == "" {
|
||||||
|
c.DrawMessage()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +233,7 @@ func (c *client) routeCommandInput(com *cmdparse.Command) error {
|
||||||
case cmdparse.DO:
|
case cmdparse.DO:
|
||||||
c.doCommand(com.Action, com.Value)
|
c.doCommand(com.Action, com.Value)
|
||||||
case cmdparse.DOLINK:
|
case cmdparse.DOLINK:
|
||||||
// err = doLinkCommand(com.Action, com.Target)
|
c.doLinkCommand(com.Action, com.Target)
|
||||||
case cmdparse.DOAS:
|
case cmdparse.DOAS:
|
||||||
c.doCommandAs(com.Action, com.Value)
|
c.doCommandAs(com.Action, com.Value)
|
||||||
case cmdparse.DOLINKAS:
|
case cmdparse.DOLINKAS:
|
||||||
|
@ -337,7 +349,8 @@ func (c *client) doCommandAs(action string, values []string) {
|
||||||
c.SetMessage("Value set, but error saving config to file", true)
|
c.SetMessage("Value set, but error saving config to file", true)
|
||||||
c.DrawMessage()
|
c.DrawMessage()
|
||||||
} else {
|
} else {
|
||||||
c.SetMessage(fmt.Sprintf("%s is now set to %q", values[0], c.Options[values[0]]), true)
|
c.Draw()
|
||||||
|
c.SetMessage(fmt.Sprintf("%s is now set to %q", values[0], c.Options[values[0]]), false)
|
||||||
c.DrawMessage()
|
c.DrawMessage()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -373,6 +386,47 @@ func (c *client) saveFile(data []byte, name string) (string, error) {
|
||||||
return savePath, nil
|
return savePath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *client) doLinkCommand(action, target string) {
|
||||||
|
num, err := strconv.Atoi(target)
|
||||||
|
if err != nil {
|
||||||
|
c.SetMessage(fmt.Sprintf("Expected number, got %q", target), true)
|
||||||
|
c.DrawMessage()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case "DELETE", "D":
|
||||||
|
msg, err := c.BookMarks.Delete(num)
|
||||||
|
if err != nil {
|
||||||
|
c.SetMessage(err.Error(), true)
|
||||||
|
c.DrawMessage()
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
c.SetMessage(msg, false)
|
||||||
|
c.DrawMessage()
|
||||||
|
}
|
||||||
|
|
||||||
|
err = saveConfig()
|
||||||
|
if err != nil {
|
||||||
|
c.SetMessage("Error saving bookmark deletion to file", true)
|
||||||
|
c.DrawMessage()
|
||||||
|
}
|
||||||
|
if c.BookMarks.IsOpen {
|
||||||
|
c.Draw()
|
||||||
|
}
|
||||||
|
case "BOOKMARKS", "B":
|
||||||
|
if num > len(c.BookMarks.Links)-1 {
|
||||||
|
c.SetMessage(fmt.Sprintf("There is no bookmark with ID %d", num), true)
|
||||||
|
c.DrawMessage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Visit(c.BookMarks.Links[num])
|
||||||
|
default:
|
||||||
|
c.SetMessage(fmt.Sprintf("Action %q does not exist for target %q", action, target), true)
|
||||||
|
c.DrawMessage()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (c *client) search() {
|
func (c *client) search() {
|
||||||
c.ClearMessage()
|
c.ClearMessage()
|
||||||
c.ClearMessageLine()
|
c.ClearMessageLine()
|
||||||
|
@ -408,6 +462,7 @@ func (c *client) search() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) Scroll(amount int) {
|
func (c *client) Scroll(amount int) {
|
||||||
|
var percentRead int
|
||||||
page := c.PageState.History[c.PageState.Position]
|
page := c.PageState.History[c.PageState.Position]
|
||||||
bottom := len(page.WrappedContent) - c.Height + 3 // 3 for the three bars: top, msg, bottom
|
bottom := len(page.WrappedContent) - c.Height + 3 // 3 for the three bars: top, msg, bottom
|
||||||
if amount < 0 && page.ScrollPosition == 0 {
|
if amount < 0 && page.ScrollPosition == 0 {
|
||||||
|
@ -416,6 +471,7 @@ func (c *client) Scroll(amount int) {
|
||||||
fmt.Print("\a")
|
fmt.Print("\a")
|
||||||
return
|
return
|
||||||
} else if (amount > 0 && page.ScrollPosition == bottom) || bottom < 0 {
|
} else if (amount > 0 && page.ScrollPosition == bottom) || bottom < 0 {
|
||||||
|
c.FootBar.SetPercentRead(100)
|
||||||
c.SetMessage("You are already at the bottom", false)
|
c.SetMessage("You are already at the bottom", false)
|
||||||
c.DrawMessage()
|
c.DrawMessage()
|
||||||
fmt.Print("\a")
|
fmt.Print("\a")
|
||||||
|
@ -430,6 +486,14 @@ func (c *client) Scroll(amount int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
c.PageState.History[c.PageState.Position].ScrollPosition = newScrollPosition
|
c.PageState.History[c.PageState.Position].ScrollPosition = newScrollPosition
|
||||||
|
|
||||||
|
if len(page.WrappedContent) < c.Height - 3 {
|
||||||
|
percentRead = 100
|
||||||
|
} else {
|
||||||
|
percentRead = int(float32(newScrollPosition + c.Height - 3) / float32(len(page.WrappedContent)) * 100.0)
|
||||||
|
}
|
||||||
|
c.FootBar.SetPercentRead(percentRead)
|
||||||
|
|
||||||
c.Draw()
|
c.Draw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,21 +510,30 @@ func (c *client) displayConfigValue(setting string) {
|
||||||
func (c *client) SetMessage(msg string, isError bool) {
|
func (c *client) SetMessage(msg string, isError bool) {
|
||||||
leadIn, leadOut := "", ""
|
leadIn, leadOut := "", ""
|
||||||
if isError {
|
if isError {
|
||||||
leadIn = "\033[31m"
|
leadIn = "\033[91m"
|
||||||
|
leadOut = "\033[0m"
|
||||||
|
|
||||||
|
if c.Options["theme"] == "normal" {
|
||||||
|
leadIn = "\033[101;7m"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Options["theme"] == "normal" {
|
||||||
|
leadIn = "\033[7m"
|
||||||
leadOut = "\033[0m"
|
leadOut = "\033[0m"
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Message = fmt.Sprintf("%s%s%s", leadIn, msg, leadOut)
|
c.Message = fmt.Sprintf("%s%-*.*s%s", leadIn, c.Width, c.Width, msg, leadOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) DrawMessage() {
|
func (c *client) DrawMessage() {
|
||||||
c.ClearMessageLine()
|
c.ClearMessageLine()
|
||||||
cui.MoveCursorTo(c.Height-1, 0)
|
cui.MoveCursorTo(c.Height-1, 0)
|
||||||
fmt.Print(c.Message)
|
fmt.Printf("%s", c.Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) ClearMessage() {
|
func (c *client) ClearMessage() {
|
||||||
c.Message = ""
|
c.SetMessage("", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) ClearMessageLine() {
|
func (c *client) ClearMessageLine() {
|
||||||
|
@ -518,12 +591,6 @@ func (c *client) Visit(url string) {
|
||||||
|
|
||||||
switch u.Scheme {
|
switch u.Scheme {
|
||||||
case "gopher":
|
case "gopher":
|
||||||
u, err := MakeUrl(url)
|
|
||||||
if err != nil {
|
|
||||||
c.SetMessage(err.Error(), true)
|
|
||||||
c.DrawMessage()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.SetMessage("Loading...", false)
|
c.SetMessage("Loading...", false)
|
||||||
c.DrawMessage()
|
c.DrawMessage()
|
||||||
content, links, err := gopher.Visit(u.Mime, u.Host, u.Port, u.Resource)
|
content, links, err := gopher.Visit(u.Mime, u.Host, u.Port, u.Resource)
|
||||||
|
@ -535,13 +602,14 @@ func (c *client) Visit(url string) {
|
||||||
pg := MakePage(u, content, links)
|
pg := MakePage(u, content, links)
|
||||||
pg.WrapContent(c.Width)
|
pg.WrapContent(c.Width)
|
||||||
c.PageState.Add(pg)
|
c.PageState.Add(pg)
|
||||||
|
c.Scroll(0) // to update percent read
|
||||||
c.ClearMessage()
|
c.ClearMessage()
|
||||||
c.ClearMessageLine()
|
c.ClearMessageLine()
|
||||||
c.SetHeaderUrl()
|
c.SetHeaderUrl()
|
||||||
c.Draw()
|
c.Draw()
|
||||||
case "gemini":
|
case "gemini":
|
||||||
// TODO send over to gemini request
|
// TODO send over to gemini request
|
||||||
c.SetMessage("Gemini is not currently supported", false)
|
c.SetMessage("Bombadillo has not mastered Gemini yet, check back soon", false)
|
||||||
c.DrawMessage()
|
c.DrawMessage()
|
||||||
case "telnet":
|
case "telnet":
|
||||||
c.SetMessage("Attempting to start telnet session", false)
|
c.SetMessage("Attempting to start telnet session", false)
|
||||||
|
@ -582,16 +650,16 @@ func (c *client) Visit(url string) {
|
||||||
//--------------------------------------------------\\
|
//--------------------------------------------------\\
|
||||||
|
|
||||||
func MakeClient(name string) *client {
|
func MakeClient(name string) *client {
|
||||||
var userinfo, _ = user.Current()
|
// var userinfo, _ = user.Current()
|
||||||
var options = map[string]string{
|
// var options = map[string]string{
|
||||||
"homeurl": "gopher://colorfield.space:70/1/bombadillo-info",
|
// "homeurl": "gopher://colorfield.space:70/1/bombadillo-info",
|
||||||
"savelocation": userinfo.HomeDir,
|
// "savelocation": userinfo.HomeDir,
|
||||||
"searchengine": "gopher://gopher.floodgap.com:70/7/v2/vs",
|
// "searchengine": "gopher://gopher.floodgap.com:70/7/v2/vs",
|
||||||
"openhttp": "false",
|
// "openhttp": "false",
|
||||||
"httpbrowser": "lynx",
|
// "httpbrowser": "lynx",
|
||||||
"configlocation": userinfo.HomeDir,
|
// "configlocation": userinfo.HomeDir,
|
||||||
}
|
// }
|
||||||
c := client{0, 0, options, "", MakePages(), MakeBookmarks(), MakeHeadbar(name), MakeFootbar()}
|
c := client{0, 0, defaultOptions, "", MakePages(), MakeBookmarks(), MakeHeadbar(name), MakeFootbar()}
|
||||||
return &c
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
var userinfo, _ = user.Current()
|
||||||
|
var defaultOptions = map[string]string{
|
||||||
|
//
|
||||||
|
// General configuration options
|
||||||
|
//
|
||||||
|
"homeurl": "gopher://colorfield.space:70/1/bombadillo-info",
|
||||||
|
"savelocation": userinfo.HomeDir,
|
||||||
|
"searchengine": "gopher://gopher.floodgap.com:70/7/v2/vs",
|
||||||
|
"openhttp": "false",
|
||||||
|
"httpbrowser": "lynx",
|
||||||
|
"telnetcommand": "telnet",
|
||||||
|
"configlocation": userinfo.HomeDir,
|
||||||
|
"theme": "normal", // "normal", "inverted"
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO decide whether or not to institute a color theme
|
||||||
|
// system. Preliminary testing implies it should be very
|
||||||
|
// doable.
|
||||||
|
var theme = map[string]string{
|
||||||
|
"topbar_title_bg": "",
|
||||||
|
"topbar_link_fg": "",
|
||||||
|
"body_bg": "237",
|
||||||
|
"body_fg": "",
|
||||||
|
"bookmarks_bg": "",
|
||||||
|
"bookmarks_fg": "",
|
||||||
|
"command_bg": "",
|
||||||
|
"message_fg": "",
|
||||||
|
"error_fg": "",
|
||||||
|
"bottombar_bg": "",
|
||||||
|
"bottombar_fg": "",
|
||||||
|
//
|
||||||
|
// text style options
|
||||||
|
//
|
||||||
|
"topbar_title_style": "bold",
|
||||||
|
"topbar_link_style": "plain",
|
||||||
|
"body_style": "plain",
|
||||||
|
"bookmark_body_style": "plain",
|
||||||
|
"bookmark_border_style": "plain",
|
||||||
|
"message_style": "italic",
|
||||||
|
"error_style": "bold",
|
||||||
|
"command_style": "plain",
|
||||||
|
"bottom_bar_style": "plain",
|
||||||
|
}
|
27
footbar.go
27
footbar.go
|
@ -2,14 +2,16 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------\\
|
//------------------------------------------------\\
|
||||||
// + + + T Y P E S + + + \\
|
// + + + T Y P E S + + + \\
|
||||||
//--------------------------------------------------\\
|
//--------------------------------------------------\\
|
||||||
|
|
||||||
type Footbar struct {
|
type Footbar struct {
|
||||||
PercentRead int
|
PercentRead string
|
||||||
PageType string
|
PageType string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,20 +21,25 @@ type Footbar struct {
|
||||||
//--------------------------------------------------\\
|
//--------------------------------------------------\\
|
||||||
|
|
||||||
func (f *Footbar) SetPercentRead(p int) {
|
func (f *Footbar) SetPercentRead(p int) {
|
||||||
f.PercentRead = p
|
if p > 100 {
|
||||||
|
p = 100
|
||||||
|
} else if p < 0 {
|
||||||
|
p = 0
|
||||||
|
}
|
||||||
|
f.PercentRead = strconv.Itoa(p) + "%"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Footbar) SetPageType(t string) {
|
func (f *Footbar) SetPageType(t string) {
|
||||||
f.PageType = t
|
f.PageType = t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Footbar) Draw() {
|
func (f *Footbar) Render(termWidth, position int, theme string) string {
|
||||||
// TODO this will actually draw the bar
|
pre := fmt.Sprintf("HST: (%2.2d) - - - %4s Read ", position + 1, f.PercentRead)
|
||||||
// without having to redraw everything else
|
out := "\033[0m%*.*s "
|
||||||
}
|
if theme == "inverse" {
|
||||||
|
out = "\033[7m%*.*s \033[0m"
|
||||||
func (f *Footbar) Render(termWidth int) string {
|
}
|
||||||
return fmt.Sprintf("\033[7m%-*.*s\033[0m", termWidth, termWidth, "")
|
return fmt.Sprintf(out, termWidth - 1, termWidth - 1, pre)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,6 +48,6 @@ func (f *Footbar) Render(termWidth int) string {
|
||||||
//--------------------------------------------------\\
|
//--------------------------------------------------\\
|
||||||
|
|
||||||
func MakeFootbar() Footbar {
|
func MakeFootbar() Footbar {
|
||||||
return Footbar{100, "N/A"}
|
return Footbar{"---", "N/A"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
headbar.go
10
headbar.go
|
@ -28,9 +28,13 @@ func (h *Headbar) Draw() {
|
||||||
// without having to redraw everything else
|
// without having to redraw everything else
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Headbar) Render(width int) string {
|
func (h *Headbar) Render(width int, theme string) string {
|
||||||
maxMsgWidth := width - len([]rune(h.title))
|
maxMsgWidth := width - len([]rune(h.title)) - 2
|
||||||
return fmt.Sprintf("\033[7m%s%-*.*s\033[0m", h.title, maxMsgWidth, maxMsgWidth, h.url)
|
if theme == "inverse" {
|
||||||
|
return fmt.Sprintf("\033[7m%s▟\033[27m %-*.*s\033[0m", h.title, maxMsgWidth, maxMsgWidth, h.url)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%s▟\033[7m %-*.*s\033[0m", h.title, maxMsgWidth, maxMsgWidth, h.url)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
99
main.go
99
main.go
|
@ -3,12 +3,10 @@ package main
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
// "strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"tildegit.org/sloum/bombadillo/config"
|
"tildegit.org/sloum/bombadillo/config"
|
||||||
"tildegit.org/sloum/bombadillo/cui"
|
"tildegit.org/sloum/bombadillo/cui"
|
||||||
// "tildegit.org/sloum/bombadillo/gopher"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var bombadillo *client
|
var bombadillo *client
|
||||||
|
@ -32,96 +30,6 @@ var settings config.Config
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// func doLinkCommand(action, target string) error {
|
|
||||||
// num, err := strconv.Atoi(target)
|
|
||||||
// if err != nil {
|
|
||||||
// return fmt.Errorf("Expected number, got %q", target)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// switch action {
|
|
||||||
// case "DELETE", "D":
|
|
||||||
// err := settings.Bookmarks.Del(num)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// screen.Windows[1].Content = settings.Bookmarks.List()
|
|
||||||
// err = saveConfig()
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// screen.ReflashScreen(false)
|
|
||||||
// return nil
|
|
||||||
// case "BOOKMARKS", "B":
|
|
||||||
// if num > len(settings.Bookmarks.Links)-1 {
|
|
||||||
// return fmt.Errorf("There is no bookmark with ID %d", num)
|
|
||||||
// }
|
|
||||||
// err := goToURL(settings.Bookmarks.Links[num])
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return fmt.Errorf("This method has not been built")
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// func doCommand(action string, values []string) error {
|
|
||||||
// if length := len(values); length != 1 {
|
|
||||||
// return fmt.Errorf("Expected 1 argument, received %d", length)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// switch action {
|
|
||||||
// case "CHECK", "C":
|
|
||||||
// err := checkConfigValue(values[0])
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
// return fmt.Errorf("Unknown command structure")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func doLinkCommandAs(action, target string, values []string) error {
|
|
||||||
// num, err := strconv.Atoi(target)
|
|
||||||
// if err != nil {
|
|
||||||
// return fmt.Errorf("Expected number, got %q", target)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// links := history.Collection[history.Position].Links
|
|
||||||
// if num >= len(links) {
|
|
||||||
// return fmt.Errorf("Invalid link id: %s", target)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// switch action {
|
|
||||||
// case "ADD", "A":
|
|
||||||
// newBookmark := append([]string{links[num-1]}, values...)
|
|
||||||
// err := settings.Bookmarks.Add(newBookmark)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// screen.Windows[1].Content = settings.Bookmarks.List()
|
|
||||||
|
|
||||||
// err = saveConfig()
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// screen.ReflashScreen(false)
|
|
||||||
// return nil
|
|
||||||
// case "WRITE", "W":
|
|
||||||
// return saveFile(links[num-1], strings.Join(values, " "))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return fmt.Errorf("This method has not been built")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func updateMainContent() {
|
|
||||||
// screen.Windows[0].Content = history.Collection[history.Position].Content
|
|
||||||
// screen.Bars[0].SetMessage(history.Collection[history.Position].Address.Full)
|
|
||||||
// }
|
|
||||||
|
|
||||||
func saveConfig() error {
|
func saveConfig() error {
|
||||||
bkmrks := bombadillo.BookMarks.IniDump()
|
bkmrks := bombadillo.BookMarks.IniDump()
|
||||||
// TODO opts becomes a string builder rather than concat
|
// TODO opts becomes a string builder rather than concat
|
||||||
|
@ -186,6 +94,9 @@ func main() {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO find out why the loading message
|
||||||
|
// has disappeared on initial load...
|
||||||
|
|
||||||
// Start polling for terminal size changes
|
// Start polling for terminal size changes
|
||||||
go bombadillo.GetSize()
|
go bombadillo.GetSize()
|
||||||
|
|
||||||
|
@ -193,12 +104,12 @@ func main() {
|
||||||
// If a url was passed, move it down the line
|
// If a url was passed, move it down the line
|
||||||
// Goroutine so keypresses can be made during
|
// Goroutine so keypresses can be made during
|
||||||
// page load
|
// page load
|
||||||
bombadillo.Visit(os.Args[1])
|
go bombadillo.Visit(os.Args[1])
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, load the homeurl
|
// Otherwise, load the homeurl
|
||||||
// Goroutine so keypresses can be made during
|
// Goroutine so keypresses can be made during
|
||||||
// page load
|
// page load
|
||||||
bombadillo.Visit(bombadillo.Options["homeurl"])
|
go bombadillo.Visit(bombadillo.Options["homeurl"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop indefinitely on user input
|
// Loop indefinitely on user input
|
||||||
|
|
18
page.go
18
page.go
|
@ -38,9 +38,11 @@ func (p *Page) ScrollPositionRange(termHeight int) (int, int) {
|
||||||
return p.ScrollPosition, end
|
return p.ScrollPosition, end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Performs a hard wrap to the requested
|
||||||
|
// 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) {
|
||||||
// TODO this is a temporary wrapping function
|
|
||||||
// in order to test. Rebuild it.
|
|
||||||
counter := 0
|
counter := 0
|
||||||
var content strings.Builder
|
var content strings.Builder
|
||||||
content.Grow(len(p.RawContent))
|
content.Grow(len(p.RawContent))
|
||||||
|
@ -48,6 +50,18 @@ func (p *Page) WrapContent(width int) {
|
||||||
if ch == '\n' {
|
if ch == '\n' {
|
||||||
content.WriteRune(ch)
|
content.WriteRune(ch)
|
||||||
counter = 0
|
counter = 0
|
||||||
|
} else if ch == '\t' {
|
||||||
|
if counter + 4 < width {
|
||||||
|
content.WriteString(" ")
|
||||||
|
counter += 4
|
||||||
|
} else {
|
||||||
|
content.WriteRune('\n')
|
||||||
|
counter = 0
|
||||||
|
}
|
||||||
|
} else if ch == '\r' {
|
||||||
|
// This handles non-linux line endings...
|
||||||
|
// to some degree...
|
||||||
|
continue
|
||||||
} else {
|
} else {
|
||||||
if counter < width {
|
if counter < width {
|
||||||
content.WriteRune(ch)
|
content.WriteRune(ch)
|
||||||
|
|
2
pages.go
2
pages.go
|
@ -50,7 +50,7 @@ func (p *Pages) Add(pg Page) {
|
||||||
|
|
||||||
func (p *Pages) Render(termHeight, termWidth int) []string {
|
func (p *Pages) Render(termHeight, termWidth int) []string {
|
||||||
if p.Length < 1 {
|
if p.Length < 1 {
|
||||||
return []string{""}
|
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)
|
||||||
|
|
Loading…
Reference in New Issue