diff options
Diffstat (limited to 'actions.go')
| -rw-r--r-- | actions.go | 122 |
1 files changed, 118 insertions, 4 deletions
@@ -14,6 +14,8 @@ import ( "syscall" "tildegit.org/tjp/sliderule" + "tildegit.org/tjp/sliderule/gemini" + "tildegit.org/tjp/sliderule/gopher" ) var client sliderule.Client @@ -103,10 +105,66 @@ func Reload(state *BrowserState, conf *Config) error { return ErrMustBeOnAPage } - urlStr, _ := gopherURL(state.Url) - response, err := client.Fetch(urlStr) - if err != nil { - return err + urlStr, itemType := gopherURL(state.Url) + if itemType == gopher.SearchType && state.Url.RawQuery == "" { + state.Readline.SetPrompt("query: ") + line, err := state.Readline.Readline() + if err != nil { + return err + } + + state.Url.RawQuery = url.QueryEscape(strings.TrimRight(line, "\n")) + urlStr, _ = gopherURL(state.Url) + } + + var response *sliderule.Response + var err error + if state.Url.Scheme == "spartan" && state.Url.Fragment == "prompt" { + input, err := externalMessage() + if err != nil { + return err + } + body := io.LimitReader(bytes.NewBuffer(input), int64(len(input))) + + state.Url.Fragment = "" + response, err = client.Upload(state.Url.String(), body) + state.Url.Fragment = "prompt" + if err != nil { + return err + } + } else { + response, err = client.Fetch(urlStr) + if err != nil { + return err + } + } + + if state.Url.Scheme == "gemini" { + switch response.Status { + case gemini.StatusInput: + state.Readline.SetPrompt("input: ") + line, err := state.Readline.Readline() + if err != nil { + return err + } + + state.Url.RawQuery = url.QueryEscape(strings.TrimRight(line, "\n")) + response, err = client.Fetch(state.Url.String()) + if err != nil { + return err + } + case gemini.StatusSensitiveInput: + line, err := state.Readline.ReadPassword("password: ") + if err != nil { + return err + } + + state.Url.RawQuery = url.QueryEscape(strings.TrimRight(string(line), "\n")) + response, err = client.Fetch(state.Url.String()) + if err != nil { + return err + } + } } state.DocType = docType(state.Url, response) @@ -123,6 +181,59 @@ func Reload(state *BrowserState, conf *Config) error { return print(state) } +func externalMessage() ([]byte, error) { + tmpf, err := os.CreateTemp("", "*") + if err != nil { + return nil, err + } + defer func() { _ = os.Remove(tmpf.Name()) }() + + prompt := []byte("# enter input below (this line will be ignored)\n") + + err = (func() error { + defer func() { _ = tmpf.Close() }() + + if _, err := tmpf.Write(prompt); err != nil { + return err + } + + return nil + }()) + if err != nil { + return nil, err + } + + editor := os.Getenv("EDITOR") + if editor == "" { + editor = "vi" + } + editor, err = exec.LookPath(editor) + if err != nil { + return nil, err + } + + cmd := exec.Command(editor, tmpf.Name()) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + return nil, err + } + + tmpf, err = os.Open(tmpf.Name()) + if err != nil { + return nil, err + } + defer func() { _ = tmpf.Close() }() + + buf, err := io.ReadAll(tmpf) + if err != nil { + return nil, err + } + + return bytes.TrimPrefix(buf, prompt), nil +} + func back(state *BrowserState) error { if state.Back == nil { return ErrNoPreviousHistory @@ -287,6 +398,9 @@ func parseURL(str string, state *BrowserState, defaultScheme string) (*url.URL, return nil, -1, ErrInvalidNumericLink } u = state.Links[i].Target + if state.Links[i].Prompt { + u.Fragment = "prompt" + } } else { i = -1 u, err = url.Parse(str) |
