diff options
| author | tjp <tjp@ctrl-c.club> | 2024-01-03 12:17:37 -0700 |
|---|---|---|
| committer | tjp <tjp@ctrl-c.club> | 2024-01-03 12:17:37 -0700 |
| commit | 859f74231f2b48d2dcf6a29682e7651b504fda12 (patch) | |
| tree | e03126c48c8385d98ba81525e7b628d5ca2257ca /actions.go | |
| parent | 6c9558c0d2201d933b1d396febeb6e70ceaad058 (diff) | |
tours
Diffstat (limited to 'actions.go')
| -rw-r--r-- | actions.go | 103 |
1 files changed, 101 insertions, 2 deletions
@@ -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) } |
