This commit is contained in:
tjp 2024-01-14 19:54:15 -07:00
parent b173ca9cb2
commit dfebc9013b
8 changed files with 88 additions and 34 deletions

View File

@ -2,6 +2,7 @@ package main
import (
"bytes"
"context"
"crypto/tls"
"errors"
"fmt"
@ -14,6 +15,7 @@ import (
"strconv"
"strings"
"syscall"
"time"
"tildegit.org/tjp/sliderule"
"tildegit.org/tjp/sliderule/gemini"
@ -72,22 +74,25 @@ It was written by TJP and released to the public domain.
}
func Navigate(state *BrowserState, target *url.URL, navIndex int, conf *Config) error {
hist := state.History
if hist.Url == nil || target.String() != hist.Url.String() {
state.History = &History{
Url: target,
Depth: hist.Depth + 1,
Back: hist,
NavIndex: navIndex,
}
hist.Forward = state.History
if state.Url == nil || target.String() != state.Url.String() {
pushHistory(state, target, navIndex)
}
state.Modal = nil
return Reload(state, conf)
}
func pushHistory(state *BrowserState, target *url.URL, navIndex int) {
hist := state.History
state.History = &History{
Url: target,
Depth: hist.Depth + 1,
Back: hist,
NavIndex: navIndex,
}
hist.Forward = state.History
}
func gopherURL(u *url.URL) (string, sliderule.Status) {
if u.Scheme != "gopher" || len(u.Path) < 2 || !strings.HasPrefix(u.Path, "/") {
return u.String(), 0
@ -173,6 +178,8 @@ outer:
default:
return fmt.Errorf("gemini response %s: %s", gemini.StatusName(response.Status), response.Meta.(string))
}
} else {
break
}
}
@ -190,10 +197,22 @@ outer:
return HandleResource(state, conf)
}
func requestCtx(timeout time.Duration) (context.Context, context.CancelFunc) {
ctx := context.Background()
if timeout > 0 {
return context.WithTimeout(ctx, timeout)
}
return ctx, func() {}
}
func fetch(state *BrowserState, u string, tlsConf *tls.Config) (*sliderule.Response, error) {
ctx, cancel := requestCtx(state.Timeout)
defer cancel()
tlsConf.ClientSessionCache = nil
response, err := sliderule.NewClient(tlsConf).Fetch(u)
response, err := sliderule.NewClient(tlsConf).Fetch(ctx, u)
var tofuErr *TOFUViolation
if errors.As(err, &tofuErr) {
writeError(err.Error())
state.Readline.SetPrompt("Trust new certificate instead (y/n)? [n] ")
@ -210,7 +229,9 @@ func fetch(state *BrowserState, u string, tlsConf *tls.Config) (*sliderule.Respo
return nil, err
}
return sliderule.NewClient(tlsConf).Fetch(u)
ctx, cancel = requestCtx(state.Timeout)
defer cancel()
return sliderule.NewClient(tlsConf).Fetch(ctx, u)
} else if err != nil {
return nil, err
}
@ -218,8 +239,11 @@ func fetch(state *BrowserState, u string, tlsConf *tls.Config) (*sliderule.Respo
}
func upload(state *BrowserState, u string, body io.Reader, tlsConf *tls.Config) (*sliderule.Response, error) {
ctx, cancel := requestCtx(state.Timeout)
defer cancel()
tlsConf.ClientSessionCache = nil
response, err := sliderule.NewClient(tlsConf).Upload(u, body)
response, err := sliderule.NewClient(tlsConf).Upload(ctx, u, body)
var tofuErr *TOFUViolation
if errors.As(err, &tofuErr) {
writeError(err.Error())
@ -237,7 +261,9 @@ func upload(state *BrowserState, u string, body io.Reader, tlsConf *tls.Config)
return nil, err
}
return sliderule.NewClient(tlsConf).Upload(u, body)
ctx, cancel = requestCtx(state.Timeout)
defer cancel()
return sliderule.NewClient(tlsConf).Upload(ctx, u, body)
} else if err != nil {
return nil, err
}
@ -306,16 +332,16 @@ func back(state *BrowserState) error {
return nil
}
func Back(state *BrowserState, num int) error {
func Back(state *BrowserState, conf *Config, num int) error {
for i := 0; i < num; i += 1 {
if err := back(state); err != nil {
return err
}
}
return print(state)
return HandleResource(state, conf)
}
func Forward(state *BrowserState, num int) error {
func Forward(state *BrowserState, conf *Config, num int) error {
for i := 0; i < num; i += 1 {
if state.Forward == nil {
return ErrNoNextHistory
@ -324,7 +350,7 @@ func Forward(state *BrowserState, num int) error {
}
state.Modal = nil
return print(state)
return HandleResource(state, conf)
}
func Next(state *BrowserState, conf *Config) error {

View File

@ -383,13 +383,13 @@ func RunCommand(conf *Config, cmd *Command, state *BrowserState) error {
if len(cmd.Args) == 1 {
num, _ = strconv.Atoi(cmd.Args[0])
}
return Back(state, num)
return Back(state, conf, num)
case "forward":
num := 1
if len(cmd.Args) == 1 {
num, _ = strconv.Atoi(cmd.Args[0])
}
return Forward(state, num)
return Forward(state, conf, num)
case "next":
return Next(state, conf)
case "previous":

View File

@ -11,17 +11,19 @@ import (
"path/filepath"
"strings"
"syscall"
"time"
"github.com/BurntSushi/toml"
)
type ConfigMain struct {
DefaultScheme string `toml:"default_scheme"`
SoftWrap int `toml:"soft_wrap"`
DownloadFolder string `toml:"download_folder"`
VimKeys bool `toml:"vim_keys"`
Quiet bool `toml:"quiet"`
Pager string `toml:"pager"`
DefaultScheme string `toml:"default_scheme"`
SoftWrap int `toml:"soft_wrap"`
DownloadFolder string `toml:"download_folder"`
VimKeys bool `toml:"vim_keys"`
Quiet bool `toml:"quiet"`
Pager string `toml:"pager"`
Timeout duration `toml:"duration"`
}
type Config struct {
@ -30,6 +32,14 @@ type Config struct {
Handlers map[string]string `toml:"handlers"`
}
type duration struct{ time.Duration }
func (d *duration) UnmarshalText(text []byte) error {
var err error
d.Duration, err = time.ParseDuration(string(text))
return err
}
func getConfig() (*Config, error) {
home := os.Getenv("HOME")
path := os.Getenv("XDG_CONFIG_HOME")
@ -50,6 +60,9 @@ func getConfig() (*Config, error) {
DownloadFolder: home,
Quiet: false,
Pager: "auto",
Timeout: duration{
time.Duration(10 * time.Second),
},
},
Handlers: map[string]string{},
}

2
go.mod
View File

@ -5,7 +5,7 @@ go 1.21.0
require (
github.com/BurntSushi/toml v1.3.2
github.com/chzyer/readline v1.5.1
tildegit.org/tjp/sliderule v1.6.2-0.20240110181009-de1490808fa6
tildegit.org/tjp/sliderule v1.6.2-0.20240115025310-751f423f11bf
)
require (

4
go.sum
View File

@ -20,5 +20,5 @@ golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40W
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
tildegit.org/tjp/sliderule v1.6.2-0.20240110181009-de1490808fa6 h1:nVGF/L3NI+dqmlEdagFFjZZabPMPOocr1zVW1qBfGVg=
tildegit.org/tjp/sliderule v1.6.2-0.20240110181009-de1490808fa6/go.mod h1:opdo8E25iS9X9pNismM8U7pCH8XO0PdRIIhdADn8Uik=
tildegit.org/tjp/sliderule v1.6.2-0.20240115025310-751f423f11bf h1:p0MqM4m/LcgLjRH24OOV+oNOu/8+alABAdI6kLantvE=
tildegit.org/tjp/sliderule v1.6.2-0.20240115025310-751f423f11bf/go.mod h1:opdo8E25iS9X9pNismM8U7pCH8XO0PdRIIhdADn8Uik=

View File

@ -64,7 +64,8 @@ Consult "help COMMAND" for more information on any single command.
`[1:],
"cli": `
x-1 [-c COMMANDS] [URL]
x-1 -h
x-1 [-q] [-c COMMANDS] [URL]
-----------------------
With no arguments or flags, x-1 will just display the prompt and begin
executing your commands. Use the "help" command to begin exploring this
@ -75,6 +76,9 @@ provided by separating them with a semi-colon ';') and then exit. In
this mode it also forces quiet mode, in which it doesn't automatically
print loaded pages.
The -q flag will force quiet mode, overriding "quiet" in the
configuration file.
With a URL argument, it will begin an interactive prompt session by
loading the requested url.
`[1:],
@ -122,6 +126,9 @@ The section "[main]" contains general configuration options:
will pipe every page printed through less(1), "never" will not, and
"auto" will pipe it through "less -F", which skips the pager when
the output fits on a single screen anyway.
* timeout (string): Maximum time to wait trying to make a connection
to the host. Should be in the form with a unit suffix, like "15s" or
"500ms". The default is "10s".
`[1:],

View File

@ -13,6 +13,7 @@ import (
var cmdMode = flag.String("c", "", "")
var helpMode = flag.Bool("h", false, "")
var quietMode = flag.Bool("q", false, "")
func main() {
conf, err := getConfig()
@ -62,6 +63,10 @@ func main() {
return
}
if *quietMode {
state.Quiet = true
}
rl, err := readline.New(Prompt)
if err != nil {
log.Fatal(err)

View File

@ -2,6 +2,7 @@ package main
import (
"net/url"
"time"
"github.com/chzyer/readline"
)
@ -19,8 +20,9 @@ type BrowserState struct {
DefaultTour Tour
CurrentTour *Tour
Quiet bool
Pager string
Quiet bool
Pager string
Timeout time.Duration
Readline *readline.Instance
}
@ -58,8 +60,9 @@ func NewBrowserState(conf *Config) *BrowserState {
NavIndex: -1,
},
Quiet: conf.Quiet,
Pager: conf.Pager,
Quiet: conf.Quiet,
Pager: conf.Pager,
Timeout: conf.Timeout.Duration,
}
state.CurrentTour = &state.DefaultTour
return state