summaryrefslogtreecommitdiff
path: root/actions.go
diff options
context:
space:
mode:
authortjp <tjp@ctrl-c.club>2024-01-03 12:17:37 -0700
committertjp <tjp@ctrl-c.club>2024-01-03 12:17:37 -0700
commit859f74231f2b48d2dcf6a29682e7651b504fda12 (patch)
treee03126c48c8385d98ba81525e7b628d5ca2257ca /actions.go
parent6c9558c0d2201d933b1d396febeb6e70ceaad058 (diff)
tours
Diffstat (limited to 'actions.go')
-rw-r--r--actions.go103
1 files changed, 101 insertions, 2 deletions
diff --git a/actions.go b/actions.go
index 8ea7ce8..d9a5d06 100644
--- a/actions.go
+++ b/actions.go
@@ -7,9 +7,11 @@ import (
"io"
"net/url"
"os"
+ "os/exec"
"path/filepath"
"strconv"
"strings"
+ "sync"
"syscall"
"tildegit.org/tjp/sliderule"
@@ -32,7 +34,8 @@ var (
ErrInvalidNumericLink = errors.New("no link with that number")
ErrInvalidLink = errors.New("that doesn't look like a valid URL")
ErrSaveNeedsFilename = errors.New("save requires a filename argument")
- ErrUnrecognizedMark = errors.New("mark what?")
+ ErrInvalidMarkArgs = errors.New("mark what?")
+ ErrInvalidTourArgs = errors.New("tour what?")
)
func Navigate(state *BrowserState, target *url.URL, navIndex int, conf *Config) error {
@@ -215,6 +218,9 @@ func Go(state *BrowserState, dest string, conf *Config) error {
func parseURL(str string, state *BrowserState, defaultScheme string) (*url.URL, int, error) {
if str == "." {
+ if state.Url == nil {
+ return nil, -1, ErrMustBeOnAPage
+ }
return state.Url, -1, nil
}
@@ -224,6 +230,34 @@ func parseURL(str string, state *BrowserState, defaultScheme string) (*url.URL,
return nil, -1, err
}
str = target
+ } else if strings.HasPrefix(str, "t:") {
+ i, err := strconv.Atoi(str[2:])
+ if err != nil {
+ return nil, -1, ErrInvalidLink
+ }
+
+ if i < 0 || i >= len(state.CurrentTour.Links) {
+ return nil, -1, ErrInvalidTourPos
+ }
+ return state.CurrentTour.Links[i], -1, nil
+ } else if strings.HasPrefix(str, "t[") {
+ idx := strings.IndexByte(str, ']')
+ if idx < 0 || idx >= len(str)-2 || str[idx+1] != ':' {
+ return nil, -1, ErrInvalidLink
+ }
+ if i, err := strconv.Atoi(str[idx+2:]); err != nil {
+ return nil, -1, ErrInvalidLink
+ } else {
+ tour, err := findTour(state, str[2:idx])
+ if err != nil {
+ return nil, -1, err
+ }
+
+ if i < 0 || i >= len(tour.Links) {
+ return nil, -1, ErrInvalidTourPos
+ }
+ return tour.Links[i], -1, nil
+ }
}
var u *url.URL
@@ -246,6 +280,11 @@ func parseURL(str string, state *BrowserState, defaultScheme string) (*url.URL,
if state.Url != nil {
u = state.Url.ResolveReference(u)
}
+
+ if u.Hostname() == "" {
+ return nil, -1, ErrInvalidLink
+ }
+
return u, i, nil
}
@@ -338,5 +377,65 @@ func Mark(state *BrowserState, args []string, conf *Config) error {
return MarkList(state)
}
- return ErrUnrecognizedMark
+ return ErrInvalidMarkArgs
+}
+
+func TourCmd(state *BrowserState, args []string, conf *Config) error {
+ switch args[0] {
+ case "add":
+ if args[1] == "next" {
+ return TourAddNext(state, conf, args[2:])
+ }
+ return TourAdd(state, conf, args[1:])
+ case "show":
+ return TourShow(state)
+ case "set":
+ return TourSet(state, args[1])
+ case "next":
+ return TourNext(state, conf)
+ case "previous":
+ return TourPrevious(state, conf)
+ case "clear":
+ return TourClear(state)
+ case "list":
+ return TourList(state)
+ case "go":
+ return TourGo(state, conf, args[1])
+ }
+
+ return ErrInvalidTourArgs
+}
+
+func Pipe(state *BrowserState, cmdStr string) error {
+ if state.Body == nil {
+ return ErrMustBeOnAPage
+ }
+
+ sh, err := exec.LookPath("sh")
+ if err != nil {
+ return err
+ }
+
+ cmd := exec.Command(sh, "-c", cmdStr)
+ cmd.Stdin = bytes.NewBuffer(state.Body)
+
+ r, w := io.Pipe()
+ cmd.Stdout = w
+ cmd.Stderr = w
+
+ cmd.Start()
+
+ wg := &sync.WaitGroup{}
+ wg.Add(1)
+ var copyErr error
+ go func() {
+ defer wg.Done()
+ _, copyErr = io.Copy(os.Stdout, r)
+ }()
+
+ waitErr := cmd.Wait()
+ _ = w.Close()
+ wg.Wait()
+
+ return errors.Join(waitErr, copyErr)
}