summaryrefslogtreecommitdiff
path: root/actions.go
diff options
context:
space:
mode:
Diffstat (limited to 'actions.go')
-rw-r--r--actions.go122
1 files changed, 118 insertions, 4 deletions
diff --git a/actions.go b/actions.go
index 065b673..6e5c7dd 100644
--- a/actions.go
+++ b/actions.go
@@ -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)