Updated notes, added auto-download for binary files, and added comments

This commit is contained in:
sloumdrone 2019-03-20 22:29:09 -07:00
parent 44f6c461d5
commit 26f80dafbc
8 changed files with 85 additions and 40 deletions

View File

@ -45,12 +45,26 @@ func save_file(address, name string) error {
return err
}
err = ioutil.WriteFile(userinfo.HomeDir + "/" + name, data, 0644)
err = ioutil.WriteFile(options["savelocation"] + name, data, 0644)
if err != nil {
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 {
@ -138,7 +152,7 @@ func go_to_url(u string) error {
}
} else if v.Address.IsBinary {
// TO DO: run this into the write to file method
return fmt.Errorf("Not built yet")
return save_file_from_data(v)
} else {
history.Add(v)
}
@ -165,7 +179,7 @@ func go_to_link(l string) error {
return err
}
} else if v.Address.IsBinary {
// TO DO: run this into the write to file method
return save_file_from_data(v)
} else {
history.Add(v)
}
@ -322,7 +336,7 @@ func display_error(err error, redraw *bool) {
func initClient() {
history.Position = -1
screen = cui.NewScreen()
screen.SetCharMode()
cui.SetCharMode()
screen.AddWindow(2, 1, screen.Height - 2, screen.Width, false, false, true)
screen.AddMsgBar(1, " ((( Bombadillo ))) ", " A fun gopher client!", true)
bookmarksWidth := 40

View File

@ -1,10 +1,7 @@
package cui
import (
)
// MsgBar is a struct to represent a single row horizontal
// bar on the screen.
type MsgBar struct {
row int
title string
@ -12,19 +9,24 @@ type MsgBar struct {
showTitle bool
}
// SetTitle sets the title for the MsgBar in question
func (m *MsgBar) SetTitle(s string) {
m.title = s
}
// SetMessage sets the message for the MsgBar in question
func (m *MsgBar) SetMessage(s string) {
m.message = s
}
// ClearAll clears all text from the message bar (title and message)
func (m MsgBar) ClearAll() {
MoveCursorTo(m.row, 1)
Clear("line")
}
// ClearMessage clears all message text while leaving the title in place
func (m *MsgBar) ClearMessage() {
MoveCursorTo(m.row, len(m.title) + 1)
Clear("right")

View File

@ -8,9 +8,14 @@ import (
"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
// 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 {
Height 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) {
w := Window{box{r1, c1, r2, c2}, scroll, 0, []string{}, border, false, show}
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) {
b := MsgBar{row, title, msg, showTitle}
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() {
s.Clear()
for _, w := range s.Windows {
@ -40,6 +49,7 @@ func (s Screen) DrawAllWindows() {
MoveCursorTo(s.Height - 1, 1)
}
// Clear removes all content from the interior of the screen
func (s Screen) Clear() {
fill := strings.Repeat(" ", s.Width)
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
// Then redraws the screen. Takes a bool to decide whether
// ReflashScreen checks for a screen resize and resizes windows if
// needed then redraws the screen. It takes a bool to decide whether
// to redraw the full screen or just the content. On a resize
// event, the full screen will always be redrawn.
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() {
for _, bar := range s.Bars {
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() {
cmd := exec.Command("stty", "size")
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 {
if screenInit {
fmt.Println("Fatal error: Cannot create multiple screens")

View File

@ -5,11 +5,30 @@ import (
"strings"
)
//------------------------------------------------\\
// + + + T Y P E S + + + \\
//--------------------------------------------------\\
//Bookmarks is a holder for titles and links that
//can be retrieved by index
type Bookmarks struct {
Titles []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 {
if len(v) < 2 {
return fmt.Errorf("Received %d arguments, expected 2 or more", len(v))

View File

@ -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
// text based resources.
// text based resources, the url represents a parsed url.
package gopher
import (
@ -16,7 +16,7 @@ import (
// + + + 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
var types = map[string]string{
"0": "TXT",
@ -80,10 +80,10 @@ func Retrieve(u Url) ([]byte, error) {
}
// The "Visit" function is a high level combination of a few
// different 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).
// Visit is a high level combination of a few different
// 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) {
u, err := MakeUrl(addr)
if err != nil {

View File

@ -72,10 +72,11 @@ func MakeUrl(u string) (Url, error) {
out.Gophertype = "1"
}
if out.Gophertype == "1" || out.Gophertype == "0" {
out.IsBinary = false
} else {
out.IsBinary = true
switch out.Gophertype {
case "1", "0", "h", "7":
out.IsBinary = false
default:
out.IsBinary = true
}
if out.Scheme == "gopher" && out.Gophertype == "" {

View File

@ -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
// as string slices, and the Url struct representing the page.
type View struct {
@ -27,8 +27,8 @@ type View struct {
//--------------------------------------------------\\
// The "ParseMap" receiver is called by a view struct. It
// checks if the view is for a gophermap. If not,it does
// ParseMap is called by a view struct to parse a gophermap.
// It checks if the view is for a gophermap. If not,it does
// nothing. If so, it parses the gophermap into comment lines
// and link lines. For link lines it adds a link to the links
// 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.
// It prints the content, line by line, of the View.
// Display is called on a view struct to print the contents of the view.
// This receiver does not return anything.
func (v View) Display() {
fmt.Println()
@ -76,10 +75,10 @@ func (v View) Display() {
//--------------------------------------------------\\
// Constructor function for View struct.
// This is used to initialize a View with
// a Url struct, links, and content. It takes
// a Url struct and a content []string and returns
// MakeView creates and returns a new View struct from
// a Url and a string splice of content. This is used to
// initialize a View with a Url struct, links, and content.
// It takes a Url struct and a content []string and returns
// a View (NOT a pointer to a View).
func MakeView(url Url, content []string) View {
v := View{content, make([]string, 0), url}

View File

@ -2,7 +2,6 @@ TODO
- Add built in help system: SIMPLE :help, DO :help action
- Add styles/color support
- Add comments/documentation for all items
- Finish out binary download support
- Make sure html links using the URL convention work correctly
- Add "Search" command. ":search thing1 thing2" that uses search as set in config
- Verify that all gophertypes work correctly