Updated notes, added auto-download for binary files, and added comments
This commit is contained in:
parent
44f6c461d5
commit
26f80dafbc
|
@ -45,12 +45,26 @@ func save_file(address, name string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ioutil.WriteFile(userinfo.HomeDir + "/" + name, data, 0644)
|
err = ioutil.WriteFile(options["savelocation"] + name, data, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return fmt.Errorf("Saved file to " + options["savelocation"] + name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func save_file_from_data(v gopher.View) error {
|
||||||
|
urlsplit := strings.Split(v.Address.Full, "/")
|
||||||
|
filename := urlsplit[len(urlsplit) - 1]
|
||||||
|
save_msg := fmt.Sprintf("Saved file as %q", options["savelocation"] + filename)
|
||||||
|
quickMessage(save_msg, false)
|
||||||
|
defer quickMessage(save_msg, true)
|
||||||
|
err := ioutil.WriteFile(options["savelocation"] + filename, []byte(strings.Join(v.Content, "")), 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf(save_msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func search(u string) error {
|
func search(u string) error {
|
||||||
|
@ -138,7 +152,7 @@ func go_to_url(u string) error {
|
||||||
}
|
}
|
||||||
} else if v.Address.IsBinary {
|
} else if v.Address.IsBinary {
|
||||||
// TO DO: run this into the write to file method
|
// TO DO: run this into the write to file method
|
||||||
return fmt.Errorf("Not built yet")
|
return save_file_from_data(v)
|
||||||
} else {
|
} else {
|
||||||
history.Add(v)
|
history.Add(v)
|
||||||
}
|
}
|
||||||
|
@ -165,7 +179,7 @@ func go_to_link(l string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if v.Address.IsBinary {
|
} else if v.Address.IsBinary {
|
||||||
// TO DO: run this into the write to file method
|
return save_file_from_data(v)
|
||||||
} else {
|
} else {
|
||||||
history.Add(v)
|
history.Add(v)
|
||||||
}
|
}
|
||||||
|
@ -322,7 +336,7 @@ func display_error(err error, redraw *bool) {
|
||||||
func initClient() {
|
func initClient() {
|
||||||
history.Position = -1
|
history.Position = -1
|
||||||
screen = cui.NewScreen()
|
screen = cui.NewScreen()
|
||||||
screen.SetCharMode()
|
cui.SetCharMode()
|
||||||
screen.AddWindow(2, 1, screen.Height - 2, screen.Width, false, false, true)
|
screen.AddWindow(2, 1, screen.Height - 2, screen.Width, false, false, true)
|
||||||
screen.AddMsgBar(1, " ((( Bombadillo ))) ", " A fun gopher client!", true)
|
screen.AddMsgBar(1, " ((( Bombadillo ))) ", " A fun gopher client!", true)
|
||||||
bookmarksWidth := 40
|
bookmarksWidth := 40
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
package cui
|
package cui
|
||||||
|
|
||||||
import (
|
// MsgBar is a struct to represent a single row horizontal
|
||||||
|
// bar on the screen.
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
type MsgBar struct {
|
type MsgBar struct {
|
||||||
row int
|
row int
|
||||||
title string
|
title string
|
||||||
|
@ -12,19 +9,24 @@ type MsgBar struct {
|
||||||
showTitle bool
|
showTitle bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// SetTitle sets the title for the MsgBar in question
|
||||||
func (m *MsgBar) SetTitle(s string) {
|
func (m *MsgBar) SetTitle(s string) {
|
||||||
m.title = s
|
m.title = s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetMessage sets the message for the MsgBar in question
|
||||||
func (m *MsgBar) SetMessage(s string) {
|
func (m *MsgBar) SetMessage(s string) {
|
||||||
m.message = s
|
m.message = s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClearAll clears all text from the message bar (title and message)
|
||||||
func (m MsgBar) ClearAll() {
|
func (m MsgBar) ClearAll() {
|
||||||
MoveCursorTo(m.row, 1)
|
MoveCursorTo(m.row, 1)
|
||||||
Clear("line")
|
Clear("line")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClearMessage clears all message text while leaving the title in place
|
||||||
func (m *MsgBar) ClearMessage() {
|
func (m *MsgBar) ClearMessage() {
|
||||||
MoveCursorTo(m.row, len(m.title) + 1)
|
MoveCursorTo(m.row, len(m.title) + 1)
|
||||||
Clear("right")
|
Clear("right")
|
||||||
|
|
|
@ -8,9 +8,14 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// screenInit records whether or not the screen has been initialized
|
||||||
|
// this is used to prevent more than one screen from being used
|
||||||
var screenInit bool = false
|
var screenInit bool = false
|
||||||
|
|
||||||
|
// Screen represent the top level abstraction for a cui application.
|
||||||
|
// It takes up the full width and height of the terminal window and
|
||||||
|
// holds the various Windows and MsgBars for the application as well
|
||||||
|
// as a record of which window is active for control purposes.
|
||||||
type Screen struct {
|
type Screen struct {
|
||||||
Height int
|
Height int
|
||||||
Width int
|
Width int
|
||||||
|
@ -20,16 +25,20 @@ type Screen struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// AddWindow adds a new window to the Screen struct in question
|
||||||
func (s *Screen) AddWindow(r1, c1, r2, c2 int, scroll, border, show bool) {
|
func (s *Screen) AddWindow(r1, c1, r2, c2 int, scroll, border, show bool) {
|
||||||
w := Window{box{r1, c1, r2, c2}, scroll, 0, []string{}, border, false, show}
|
w := Window{box{r1, c1, r2, c2}, scroll, 0, []string{}, border, false, show}
|
||||||
s.Windows = append(s.Windows, &w)
|
s.Windows = append(s.Windows, &w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddMsgBar adds a new MsgBar to the Screen struct in question
|
||||||
func (s *Screen) AddMsgBar(row int, title, msg string, showTitle bool) {
|
func (s *Screen) AddMsgBar(row int, title, msg string, showTitle bool) {
|
||||||
b := MsgBar{row, title, msg, showTitle}
|
b := MsgBar{row, title, msg, showTitle}
|
||||||
s.Bars = append(s.Bars, &b)
|
s.Bars = append(s.Bars, &b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DrawAllWindows loops over every window in the Screen struct and
|
||||||
|
// draws it to screen in index order (smallest to largest)
|
||||||
func (s Screen) DrawAllWindows() {
|
func (s Screen) DrawAllWindows() {
|
||||||
s.Clear()
|
s.Clear()
|
||||||
for _, w := range s.Windows {
|
for _, w := range s.Windows {
|
||||||
|
@ -40,6 +49,7 @@ func (s Screen) DrawAllWindows() {
|
||||||
MoveCursorTo(s.Height - 1, 1)
|
MoveCursorTo(s.Height - 1, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear removes all content from the interior of the screen
|
||||||
func (s Screen) Clear() {
|
func (s Screen) Clear() {
|
||||||
fill := strings.Repeat(" ", s.Width)
|
fill := strings.Repeat(" ", s.Width)
|
||||||
for i := 0; i <= s.Height; i++ {
|
for i := 0; i <= s.Height; i++ {
|
||||||
|
@ -48,14 +58,9 @@ func (s Screen) Clear() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Screen) SetCharMode() {
|
|
||||||
exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run()
|
|
||||||
exec.Command("stty", "-F", "/dev/tty", "-echo").Run()
|
|
||||||
fmt.Print("\033[?25l")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks for a screen resize and resizes windows if needed
|
// ReflashScreen checks for a screen resize and resizes windows if
|
||||||
// Then redraws the screen. Takes a bool to decide whether
|
// needed then redraws the screen. It takes a bool to decide whether
|
||||||
// to redraw the full screen or just the content. On a resize
|
// to redraw the full screen or just the content. On a resize
|
||||||
// event, the full screen will always be redrawn.
|
// event, the full screen will always be redrawn.
|
||||||
func (s *Screen) ReflashScreen(clearScreen bool) {
|
func (s *Screen) ReflashScreen(clearScreen bool) {
|
||||||
|
@ -91,6 +96,8 @@ func (s *Screen) ReflashScreen(clearScreen bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DrawMsgBars draws all MsgBars present in the Screen struct.
|
||||||
|
// All MsgBars are looped over and drawn in index order (sm - lg).
|
||||||
func (s *Screen) DrawMsgBars() {
|
func (s *Screen) DrawMsgBars() {
|
||||||
for _, bar := range s.Bars {
|
for _, bar := range s.Bars {
|
||||||
MoveCursorTo(bar.row, 1)
|
MoveCursorTo(bar.row, 1)
|
||||||
|
@ -118,6 +125,9 @@ func (s *Screen) DrawMsgBars() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// GetSize retrieves the terminal size and sets the Screen
|
||||||
|
// width and height to that size
|
||||||
func (s *Screen) GetSize() {
|
func (s *Screen) GetSize() {
|
||||||
cmd := exec.Command("stty", "size")
|
cmd := exec.Command("stty", "size")
|
||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
|
@ -135,7 +145,8 @@ func (s *Screen) GetSize() {
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
// NewScreen is a constructor function that returns a pointer
|
||||||
|
// to a Screen struct
|
||||||
func NewScreen() *Screen {
|
func NewScreen() *Screen {
|
||||||
if screenInit {
|
if screenInit {
|
||||||
fmt.Println("Fatal error: Cannot create multiple screens")
|
fmt.Println("Fatal error: Cannot create multiple screens")
|
||||||
|
|
|
@ -5,11 +5,30 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//------------------------------------------------\\
|
||||||
|
// + + + T Y P E S + + + \\
|
||||||
|
//--------------------------------------------------\\
|
||||||
|
|
||||||
|
|
||||||
|
//Bookmarks is a holder for titles and links that
|
||||||
|
//can be retrieved by index
|
||||||
type Bookmarks struct {
|
type Bookmarks struct {
|
||||||
Titles []string
|
Titles []string
|
||||||
Links []string
|
Links []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------\\
|
||||||
|
// + + + R E C E I V E R S + + + \\
|
||||||
|
//--------------------------------------------------\\
|
||||||
|
|
||||||
|
|
||||||
|
// Add adds a new title and link combination to the bookmarks
|
||||||
|
// struct. It takes as input a string slice in which the first
|
||||||
|
// element represents the link and all following items represent
|
||||||
|
// the title of the bookmark (they will be joined with spaces).
|
||||||
func (b *Bookmarks) Add(v []string) error {
|
func (b *Bookmarks) Add(v []string) error {
|
||||||
if len(v) < 2 {
|
if len(v) < 2 {
|
||||||
return fmt.Errorf("Received %d arguments, expected 2 or more", len(v))
|
return fmt.Errorf("Received %d arguments, expected 2 or more", len(v))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Contains the building blocks of a gopher client: history and view.
|
// Contains the building blocks of a gopher client: history, url, and view.
|
||||||
// History handles the browsing session and view represents individual
|
// History handles the browsing session and view represents individual
|
||||||
// text based resources.
|
// text based resources, the url represents a parsed url.
|
||||||
package gopher
|
package gopher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -16,7 +16,7 @@ import (
|
||||||
// + + + V A R I A B L E S + + + \\
|
// + + + V A R I A B L E S + + + \\
|
||||||
//--------------------------------------------------\\
|
//--------------------------------------------------\\
|
||||||
|
|
||||||
// Types is a map of gophertypes to a string representing their
|
// types is a map of gophertypes to a string representing their
|
||||||
// type, to be used when displaying gophermaps
|
// type, to be used when displaying gophermaps
|
||||||
var types = map[string]string{
|
var types = map[string]string{
|
||||||
"0": "TXT",
|
"0": "TXT",
|
||||||
|
@ -80,10 +80,10 @@ func Retrieve(u Url) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The "Visit" function is a high level combination of a few
|
// Visit is a high level combination of a few different
|
||||||
// different types that makes it easy to create a Url,
|
// types that makes it easy to create a Url, make a request
|
||||||
// make a request to that Url, and add the response and Url
|
// to that Url, and add the response and Url to a View.
|
||||||
// to a View. Returns a copy of the view and an error (or nil).
|
// Returns a copy of the view and an error (or nil).
|
||||||
func Visit(addr string) (View, error) {
|
func Visit(addr string) (View, error) {
|
||||||
u, err := MakeUrl(addr)
|
u, err := MakeUrl(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -72,10 +72,11 @@ func MakeUrl(u string) (Url, error) {
|
||||||
out.Gophertype = "1"
|
out.Gophertype = "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
if out.Gophertype == "1" || out.Gophertype == "0" {
|
switch out.Gophertype {
|
||||||
out.IsBinary = false
|
case "1", "0", "h", "7":
|
||||||
} else {
|
out.IsBinary = false
|
||||||
out.IsBinary = true
|
default:
|
||||||
|
out.IsBinary = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if out.Scheme == "gopher" && out.Gophertype == "" {
|
if out.Scheme == "gopher" && out.Gophertype == "" {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
//--------------------------------------------------\\
|
//--------------------------------------------------\\
|
||||||
|
|
||||||
|
|
||||||
// The view struct represents a gopher page. It contains
|
// View is a struct representing a gopher page. It contains
|
||||||
// the page content as a string slice, a list of link URLs
|
// the page content as a string slice, a list of link URLs
|
||||||
// as string slices, and the Url struct representing the page.
|
// as string slices, and the Url struct representing the page.
|
||||||
type View struct {
|
type View struct {
|
||||||
|
@ -27,8 +27,8 @@ type View struct {
|
||||||
//--------------------------------------------------\\
|
//--------------------------------------------------\\
|
||||||
|
|
||||||
|
|
||||||
// The "ParseMap" receiver is called by a view struct. It
|
// ParseMap is called by a view struct to parse a gophermap.
|
||||||
// checks if the view is for a gophermap. If not,it does
|
// It checks if the view is for a gophermap. If not,it does
|
||||||
// nothing. If so, it parses the gophermap into comment lines
|
// nothing. If so, it parses the gophermap into comment lines
|
||||||
// and link lines. For link lines it adds a link to the links
|
// and link lines. For link lines it adds a link to the links
|
||||||
// slice and changes the content value to just the printable
|
// slice and changes the content value to just the printable
|
||||||
|
@ -60,8 +60,7 @@ func (v *View) ParseMap() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The "Display" receiver is called on a view struct.
|
// Display is called on a view struct to print the contents of the view.
|
||||||
// It prints the content, line by line, of the View.
|
|
||||||
// This receiver does not return anything.
|
// This receiver does not return anything.
|
||||||
func (v View) Display() {
|
func (v View) Display() {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
@ -76,10 +75,10 @@ func (v View) Display() {
|
||||||
//--------------------------------------------------\\
|
//--------------------------------------------------\\
|
||||||
|
|
||||||
|
|
||||||
// Constructor function for View struct.
|
// MakeView creates and returns a new View struct from
|
||||||
// This is used to initialize a View with
|
// a Url and a string splice of content. This is used to
|
||||||
// a Url struct, links, and content. It takes
|
// initialize a View with a Url struct, links, and content.
|
||||||
// a Url struct and a content []string and returns
|
// It takes a Url struct and a content []string and returns
|
||||||
// a View (NOT a pointer to a View).
|
// a View (NOT a pointer to a View).
|
||||||
func MakeView(url Url, content []string) View {
|
func MakeView(url Url, content []string) View {
|
||||||
v := View{content, make([]string, 0), url}
|
v := View{content, make([]string, 0), url}
|
||||||
|
|
1
notes.md
1
notes.md
|
@ -2,7 +2,6 @@ TODO
|
||||||
- Add built in help system: SIMPLE :help, DO :help action
|
- Add built in help system: SIMPLE :help, DO :help action
|
||||||
- Add styles/color support
|
- Add styles/color support
|
||||||
- Add comments/documentation for all items
|
- Add comments/documentation for all items
|
||||||
- Finish out binary download support
|
|
||||||
- Make sure html links using the URL convention work correctly
|
- Make sure html links using the URL convention work correctly
|
||||||
- Add "Search" command. ":search thing1 thing2" that uses search as set in config
|
- Add "Search" command. ":search thing1 thing2" that uses search as set in config
|
||||||
- Verify that all gophertypes work correctly
|
- Verify that all gophertypes work correctly
|
||||||
|
|
Loading…
Reference in New Issue