about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-03-17 01:23:45 +0100
committerbptato <nincsnevem662@gmail.com>2024-03-17 01:24:23 +0100
commitedeffb73c62adbbffe1fb50cddbc6c494551c07d (patch)
tree2b09b6aab155b1b82c4661cd1c2aacaf1c2e72d6 /src
parentab27cec1f9951b5b6d03cecb8a4a9e65e0258390 (diff)
downloadchawan-edeffb73c62adbbffe1fb50cddbc6c494551c07d.tar.gz
client: fix "Hit any key" bug on load failure
it's an unintended side effect that we do not want
Diffstat (limited to 'src')
-rw-r--r--src/local/client.nim21
-rw-r--r--src/local/container.nim13
-rw-r--r--src/local/pager.nim32
3 files changed, 45 insertions, 21 deletions
diff --git a/src/local/client.nim b/src/local/client.nim
index 8633d051..7947ce15 100644
--- a/src/local/client.nim
+++ b/src/local/client.nim
@@ -646,9 +646,20 @@ proc inputLoop(client: Client) =
       client.handlePagerEvents()
     if client.pager.container == nil and client.pager.lineedit.isNone:
       # No buffer to display.
-      client.pager.term.setCursor(0, client.pager.term.attrs.height - 1)
-      client.pager.term.anyKey("Hit any key to quit Chawan:")
-      quit(1)
+      if not client.pager.hasload:
+        # Failed to load every single URL the user passed us. We quit, and that
+        # will dump all alerts to stderr.
+        quit(1)
+      else:
+        # At least one connection has succeeded, but we have nothing to display.
+        # Normally, this means that the input stream has been redirected to a
+        # file or to an external program. That also means we can't just exit
+        # without potentially interrupting that stream.
+        #TODO: a better UI would be querying the number of ongoing streams in
+        # loader, and then asking for confirmation if there is at least one.
+        client.pager.term.setCursor(0, client.pager.term.attrs.height - 1)
+        client.pager.term.anyKey("Hit any key to quit Chawan:")
+        quit(0)
     client.pager.showAlerts()
     client.pager.draw()
 
@@ -725,7 +736,7 @@ proc addConsole(pager: Pager; interactive: bool; clearFun, showFun, hideFun:
       raise newException(Defect, "Failed to open console pipe.")
     let url = newURL("stream:console").get
     let container = pager.readPipe0("text/plain", CHARSET_UNKNOWN, pipefd[0],
-      url, ConsoleTitle, canreinterpret = false)
+      url, ConsoleTitle, canReinterpret = false, userRequested = false)
     let err = newPosixStream(pipefd[1])
     err.writeLine("Type (M-c) console.hide() to return to buffer mode.")
     let console = newConsole(err, clearFun, showFun, hideFun)
@@ -741,7 +752,7 @@ proc clearConsole(client: Client) =
   let url = newURL("stream:console").get
   let pager = client.pager
   let replacement = pager.readPipe0("text/plain", CHARSET_UNKNOWN, pipefd[0],
-    url, ConsoleTitle, canreinterpret = false)
+    url, ConsoleTitle, canreinterpret = false, userRequested = false)
   replacement.replace = client.consoleWrapper.container
   pager.replace(client.consoleWrapper.container, replacement)
   client.consoleWrapper.container = replacement
diff --git a/src/local/container.nim b/src/local/container.nim
index 62799c56..e722ccfd 100644
--- a/src/local/container.nim
+++ b/src/local/container.nim
@@ -137,7 +137,7 @@ type
     hasstart: bool
     redirectDepth*: int
     select*: Select
-    canreinterpret*: bool
+    canReinterpret*: bool
     cloned: bool
     currentSelection {.jsget.}: Highlight
     tmpJumpMark: PagePos
@@ -148,14 +148,16 @@ type
     bgcolor*: CellColor
     tailOnLoad*: bool
     cacheFile* {.jsget.}: string
+    userRequested*: bool
 
 jsDestructor(Highlight)
 jsDestructor(Container)
 
 proc newContainer*(config: BufferConfig; loaderConfig: LoaderClientConfig;
     url: URL; request: Request; attrs: WindowAttributes; title: string;
-    redirectDepth: int; canreinterpret: bool; contentType: Option[string];
-    charsetStack: seq[Charset]; cacheId: int; cacheFile: string): Container =
+    redirectDepth: int; canReinterpret: bool; contentType: Option[string];
+    charsetStack: seq[Charset]; cacheId: int; cacheFile: string;
+    userRequested: bool): Container =
   return Container(
     url: url,
     request: request,
@@ -169,11 +171,12 @@ proc newContainer*(config: BufferConfig; loaderConfig: LoaderClientConfig;
     pos: CursorPosition(
       setx: -1
     ),
-    canreinterpret: canreinterpret,
+    canReinterpret: canReinterpret,
     loadinfo: "Connecting to " & request.url.host & "...",
     cacheId: cacheId,
     cacheFile: cacheFile,
-    process: -1
+    process: -1,
+    userRequested: userRequested
   )
 
 func location(container: Container): URL {.jsfget.} =
diff --git a/src/local/pager.nim b/src/local/pager.nim
index f82a9f93..6448d1a8 100644
--- a/src/local/pager.nim
+++ b/src/local/pager.nim
@@ -114,6 +114,7 @@ type
     devRandom: PosixStream
     display: FixedGrid
     forkserver*: ForkServer
+    hasload*: bool # has a page been successfully loaded since startup?
     inputBuffer*: string # currently uninterpreted characters
     iregex: Result[Regex, string]
     isearchpromise: EmptyPromise
@@ -125,7 +126,7 @@ type
     mailcap: Mailcap
     mimeTypes: MimeTypes
     notnum*: bool # has a non-numeric character been input already?
-    numload*: int
+    numload*: int # number of pages currently being loaded
     omnirules: seq[OmniRule]
     precnum*: int32 # current number prefix (when vi-numeric-prefix is true)
     procmap*: seq[ProcMapItem]
@@ -542,9 +543,9 @@ proc onSetLoadInfo(pager: Pager; container: Container) =
 
 proc newContainer(pager: Pager; bufferConfig: BufferConfig;
     loaderConfig: LoaderClientConfig; request: Request; title = "";
-    redirectDepth = 0; canreinterpret = true; contentType = none(string);
+    redirectDepth = 0; canReinterpret = true; contentType = none(string);
     charsetStack: seq[Charset] = @[]; url = request.url; cacheId = -1;
-    cacheFile = ""): Container =
+    cacheFile = ""; userRequested = true): Container =
   request.suspended = true
   if loaderConfig.cookieJar != nil:
     # loader stores cookie jars per client, but we have no client yet.
@@ -568,11 +569,12 @@ proc newContainer(pager: Pager; bufferConfig: BufferConfig;
     pager.term.attrs,
     title,
     redirectDepth,
-    canreinterpret,
+    canReinterpret,
     contentType,
     charsetStack,
     cacheId,
-    cacheFile
+    cacheFile,
+    userRequested
   )
   pager.connectingContainers.add(ConnectingContainerItem(
     state: ccsBeforeResult,
@@ -834,7 +836,7 @@ template myExec(cmd: string) =
   exitnow(127)
 
 proc toggleSource(pager: Pager) {.jsfunc.} =
-  if not pager.container.canreinterpret:
+  if not pager.container.canReinterpret:
     return
   if pager.container.sourcepair != nil:
     pager.setContainer(pager.container.sourcepair)
@@ -1063,8 +1065,9 @@ proc loadURL*(pager: Pager, url: string, ctype = none(string),
     if pager.container != prevc:
       pager.container.retry = urls
 
-proc readPipe0*(pager: Pager, contentType: string, cs: Charset,
-    fd: FileHandle, url: URL, title: string, canreinterpret: bool): Container =
+proc readPipe0*(pager: Pager; contentType: string; cs: Charset;
+    fd: FileHandle; url: URL, title: string;
+    canReinterpret, userRequested: bool): Container =
   var url = url
   pager.loader.passFd(url.pathname, fd)
   safeClose(fd)
@@ -1075,14 +1078,16 @@ proc readPipe0*(pager: Pager, contentType: string, cs: Charset,
     loaderConfig,
     newRequest(url),
     title = title,
-    canreinterpret = canreinterpret,
-    contentType = some(contentType)
+    canReinterpret = canReinterpret,
+    contentType = some(contentType),
+    userRequested = userRequested
   )
 
 proc readPipe*(pager: Pager, contentType: string, cs: Charset, fd: FileHandle,
     title: string) =
   let url = newURL("stream:-").get
-  let container = pager.readPipe0(contentType, cs, fd, url, title, true)
+  let container = pager.readPipe0(contentType, cs, fd, url, title,
+    canReinterpret = true, userRequested = true)
   inc pager.numload
   pager.addContainer(container)
 
@@ -1604,6 +1609,11 @@ proc connected(pager: Pager; container: Container; response: Response) =
     pager.lineData = LineDataAuth(url: container.url)
     istream.close()
     return
+  # This forces client to ask for confirmation before quitting.
+  # (It checks a flag on container, because console buffers must not affect this
+  # variable.)
+  if container.userRequested:
+    pager.hasload = true
   let realContentType = if "Content-Type" in response.headers:
     response.headers["Content-Type"]
   else: