[gjs: 2/3] console: Exit if Ctrl+C pressed twice




commit 99e73f20d6ddbec0e4c0087cd1c61f040b9dfeee
Author: Philip Chimento <philip chimento gmail com>
Date:   Sat Feb 20 13:44:06 2021 -0800

    console: Exit if Ctrl+C pressed twice
    
    Node.js does this: if Ctrl+C is pressed at the interactive prompt and
    nothing has been typed in so far, then print a message telling how to exit
    the interpreter (and set a flag so that if you press Ctrl+C again
    immediately, it will exit as well.)
    
    (This is not really possible to test other than manually, so no tests.)
    
    See: #98

 modules/console.cpp | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)
---
diff --git a/modules/console.cpp b/modules/console.cpp
index 944dec26..6a48b5a9 100644
--- a/modules/console.cpp
+++ b/modules/console.cpp
@@ -107,6 +107,12 @@ class AutoCatchCtrlC {
         if (m_prev_handler != SIG_ERR)
             signal(SIGINT, m_prev_handler);
     }
+
+    void raise_default() {
+        if (m_prev_handler != SIG_ERR)
+            signal(SIGINT, m_prev_handler);
+        raise(SIGINT);
+    }
 };
 sigjmp_buf AutoCatchCtrlC::jump_buffer;
 
@@ -175,19 +181,23 @@ gjs_console_interact(JSContext *context,
                      JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp(argc, vp);
-    bool eof;
+    bool eof, exit_warning;
     JS::RootedObject global(context, gjs_get_import_global(context));
     char* temp_buf;
     int lineno;
     int startline;
 
+#ifndef HAVE_READLINE_READLINE_H
+    int rl_end = 0;  // nonzero if using readline and any text is typed in
+#endif
+
     JS::SetWarningReporter(context, gjs_console_warning_reporter);
 
     AutoCatchCtrlC ctrl_c;
 
     // Separate initialization from declaration because of possible overwriting
     // when siglongjmp() jumps into this function
-    eof = false;
+    eof = exit_warning = false;
     temp_buf = nullptr;
     lineno = 1;
     do {
@@ -207,6 +217,17 @@ gjs_console_interact(JSContext *context,
             // buffer.
             while (sigsetjmp(AutoCatchCtrlC::jump_buffer, 1) != 0) {
                 g_fprintf(stdout, "\n");
+                if (buffer.empty() && rl_end == 0) {
+                    if (!exit_warning) {
+                        g_fprintf(stdout,
+                                  "(To exit, press Ctrl+C again or Ctrl+D)\n");
+                        exit_warning = true;
+                    } else {
+                        ctrl_c.raise_default();
+                    }
+                } else {
+                    exit_warning = false;
+                }
                 buffer.clear();
                 startline = lineno = 1;
             }
@@ -229,6 +250,7 @@ gjs_console_interact(JSContext *context,
             AutoReportException are(context);
             ok = gjs_console_eval_and_print(context, buffer, startline);
         }
+        exit_warning = false;
 
         GjsContextPrivate* gjs = GjsContextPrivate::from_cx(context);
         ok = gjs->run_jobs_fallible() && ok;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]