From 36f94158f615e55fd0b554d07ea7a8ea598f9445 Mon Sep 17 00:00:00 2001 From: sloumdrone Date: Thu, 28 Mar 2019 08:24:49 -0700 Subject: [PATCH] Opening html files in browser now works as expected with url resources --- bombadillo.go | 25 ++++++++++++++++--------- cmdparse/lexer.go | 2 +- gopher/gopher.go | 43 ++++++++++++++++++++++++++++++++++++++++++- gopher/history.go | 17 ++++++++++------- gopher/url.go | 2 +- 5 files changed, 70 insertions(+), 19 deletions(-) diff --git a/bombadillo.go b/bombadillo.go index d46b39c..83721a1 100644 --- a/bombadillo.go +++ b/bombadillo.go @@ -14,6 +14,7 @@ import ( "strconv" ) +var helplocation string ="gopher://colorfield.space:70/1/bombadillo-info" var history gopher.History = gopher.MakeHistory() var screen *cui.Screen var userinfo, _ = user.Current() @@ -75,7 +76,7 @@ func search(u string) error { entry := cui.GetLine() quickMessage("Searching...", false) searchurl := fmt.Sprintf("%s\t%s", u, entry) - sv, err := gopher.Visit(searchurl) + sv, err := gopher.Visit(searchurl, options["openhttp"]) if err != nil { quickMessage("Searching...", true) return err @@ -135,6 +136,8 @@ func simple_command(a string) error { toggle_bookmarks() case "SEARCH": return search(options["searchengine"]) + case "HELP": + return go_to_url(helplocation) default: return fmt.Errorf("Unknown action %q", a) @@ -144,7 +147,7 @@ func simple_command(a string) error { func go_to_url(u string) error { quickMessage("Loading...", false) - v, err := gopher.Visit(u) + v, err := gopher.Visit(u, options["openhttp"]) if err != nil { quickMessage("Loading...", true) return err @@ -172,7 +175,7 @@ func go_to_link(l string) error { if item <= linkcount { linkurl := history.Collection[history.Position].Links[item - 1] quickMessage("Loading...", false) - v, err := gopher.Visit(linkurl) + v, err := gopher.Visit(linkurl, options["openhttp"]) if err != nil { quickMessage("Loading...", true) return err @@ -386,15 +389,19 @@ func main() { case 'q', 'Q': cui.Exit() case 'b': - history.GoBack() - mainWindow.Scrollposition = 0 - redrawScreen = true + success := history.GoBack() + if success { + mainWindow.Scrollposition = 0 + redrawScreen = true + } case 'B': toggle_bookmarks() case 'f', 'F': - history.GoForward() - mainWindow.Scrollposition = 0 - redrawScreen = true + success := history.GoForward() + if success { + mainWindow.Scrollposition = 0 + redrawScreen = true + } case ':': redrawScreen = true cui.MoveCursorTo(screen.Height - 1, 0) diff --git a/cmdparse/lexer.go b/cmdparse/lexer.go index 98705a6..2553cc1 100644 --- a/cmdparse/lexer.go +++ b/cmdparse/lexer.go @@ -75,7 +75,7 @@ func (s *scanner) scanText() Token { capInput := strings.ToUpper(buf.String()) switch capInput { case "DELETE", "ADD", "WRITE", "SET", "RECALL", "R", "SEARCH", - "W", "A", "D", "S", "Q", "QUIT", "B", "BOOKMARKS", "H", "HOME": + "W", "A", "D", "S", "Q", "QUIT", "B", "BOOKMARKS", "H", "HOME", "HELP": return Token{Action, capInput} } diff --git a/gopher/gopher.go b/gopher/gopher.go index e644130..4d3e185 100644 --- a/gopher/gopher.go +++ b/gopher/gopher.go @@ -9,6 +9,9 @@ import ( "net" "io/ioutil" "time" + "os/exec" + "runtime" + "fmt" ) @@ -84,12 +87,22 @@ func Retrieve(u Url) ([]byte, error) { // types that makes it easy to create a Url, make a request // to that Url, and add the response and Url to a View. // Returns a copy of the view and an error (or nil). -func Visit(addr string) (View, error) { +func Visit(addr, openhttp string) (View, error) { u, err := MakeUrl(addr) if err != nil { return View{}, err } + if u.Gophertype == "h" { + if res, tf := isWebLink(u.Resource); tf && strings.ToUpper(openhttp) == "TRUE" { + err := openbrowser(res) + if err != nil { + return View{}, err + } + return View{}, fmt.Errorf("") + } + } + text, err := Retrieve(u) if err != nil { return View{}, err @@ -113,3 +126,31 @@ func GetType(t string) string { } +func isWebLink(resource string) (string, bool) { + split := strings.SplitN(resource, ":", 2) + if first := strings.ToUpper(split[0]); first == "URL" && len(split) > 1 { + return split[1], true + } + return "", false +} + +func openbrowser(url string) error { + // gist.github.com/hyg/9c4afcd91fe24316cbf0 + var err error + + switch runtime.GOOS { + case "linux": + err = exec.Command("xdg-open", url).Start() + case "windows": + err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start() + case "darwin": + err = exec.Command("open", url).Start() + default: + err = fmt.Errorf("Unsupported os for browser detection") + } + if err != nil { + return err + } + + return nil +} diff --git a/gopher/history.go b/gopher/history.go index 2c9e30f..2f34d21 100644 --- a/gopher/history.go +++ b/gopher/history.go @@ -66,12 +66,14 @@ func (h History) Get() (*View, error) { // When called it decrements the current position and // displays the content for the View in that position. // If history is at position 0, no action is taken. -func (h *History) GoBack() { +func (h *History) GoBack() bool { if h.Position > 0 { h.Position-- - } else { - fmt.Print("\a") + return true } + + fmt.Print("\a") + return false } @@ -79,13 +81,14 @@ func (h *History) GoBack() { // When called it increments the current position and // displays the content for the View in that position. // If history is at position len - 1, no action is taken. -func (h *History) GoForward() { +func (h *History) GoForward() bool { if h.Position + 1 < h.Length { h.Position++ - h.DisplayCurrentView() - } else { - fmt.Print("\a") + return true } + + fmt.Print("\a") + return false } // The "DisplayCurrentView" receiver is called by a history diff --git a/gopher/url.go b/gopher/url.go index fa13e08..993ab46 100644 --- a/gopher/url.go +++ b/gopher/url.go @@ -32,7 +32,7 @@ type Url struct { // an error (or nil). func MakeUrl(u string) (Url, error) { var out Url - re := regexp.MustCompile(`^((?Pgopher|http|https|ftp|telnet):\/\/)?(?P[\w\-\.\d]+)(?::(?P\d+)?)?(?:/(?P[01345679gIhisp])?)?(?P(?:\/.*)?)?$`) + re := regexp.MustCompile(`^((?Pgopher|http|https|ftp|telnet):\/\/)?(?P[\w\-\.\d]+)(?::(?P\d+)?)?(?:/(?P[01345679gIhisp])?)?(?P(?:[\/|Uu].*)?)?$`) match := re.FindStringSubmatch(u) if valid := re.MatchString(u); valid != true {