package main import ( "bytes" "errors" "fmt" "net/url" "os" "os/exec" "github.com/charmbracelet/lipgloss" "github.com/chzyer/readline" ) type BrowserState struct { *History *Config Modal []byte Marks map[string]string Identities Identities NamedTours map[string]*Tour DefaultTour Tour CurrentTour *Tour Readline *readline.Instance Printer Printer } type History struct { Url *url.URL Depth int DocType string Body []byte Formatted string Links []Link Back *History Forward *History // Non-negative if we browsed here via a page link, else -1. // // The non-negative value is the index in the "back" page's // list of links that got us here. NavIndex int } type Link struct { Text string Target *url.URL Prompt bool } func NewBrowserState(conf *Config) *BrowserState { state := &BrowserState{ History: &History{ Url: nil, Depth: 0, NavIndex: -1, }, Config: conf, } state.CurrentTour = &state.DefaultTour return state } type Printer interface { PrintModal(*BrowserState, []byte) error PrintPage(*BrowserState, string) error PrintError(string) error } type PromptPrinter struct{} func (PromptPrinter) PrintModal(state *BrowserState, contents []byte) error { _, err := os.Stdout.Write(contents) return err } func (PromptPrinter) PrintPage(state *BrowserState, body string) error { if state.Quiet { return nil } lessarg := []string{} switch state.Pager { case "auto": lessarg = []string{"-F"} fallthrough case "always": less, err := exec.LookPath("less") if err != nil { return err } cmd := exec.Command(less, lessarg...) cmd.Stdin = bytes.NewBufferString(body) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd.Run() case "never": _, err := os.Stdout.WriteString(body) return err default: return errors.New("invalid 'pager' value in configuration") } } var promptErrorStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("196")).Bold(true) func (PromptPrinter) PrintError(msg string) error { _, err := fmt.Println(promptErrorStyle.Render(msg)) return err }