[gjs/ewlsh/nova-repl] Support Ctrl+C guard in Repl
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/ewlsh/nova-repl] Support Ctrl+C guard in Repl
- Date: Fri, 3 Sep 2021 20:04:36 +0000 (UTC)
commit d01f1fe85fc6ea37d9b3414bd42fb8bb9ed77ba7
Author: Evan Welsh <contact evanwelsh com>
Date: Fri Sep 3 12:35:57 2021 -0700
Support Ctrl+C guard in Repl
gjs/console.cpp | 2 +-
modules/console.cpp | 28 +++++-----------------------
modules/esm/repl.js | 31 +++++++++++++++++++++++++++++--
tools/run_iwyu.sh | 5 ++---
util/console.cpp | 3 ++-
5 files changed, 39 insertions(+), 30 deletions(-)
---
diff --git a/gjs/console.cpp b/gjs/console.cpp
index 632416f6..d51a98ac 100644
--- a/gjs/console.cpp
+++ b/gjs/console.cpp
@@ -44,7 +44,7 @@ static GOptionEntry entries[] = {
{ "command", 'c', 0, G_OPTION_ARG_STRING, &command, "Program passed in as a string", "COMMAND" },
{ "coverage-prefix", 'C', 0, G_OPTION_ARG_STRING_ARRAY, &coverage_prefixes, "Add the prefix PREFIX to
the list of files to generate coverage info for", "PREFIX" },
{ "coverage-output", 0, 0, G_OPTION_ARG_STRING, &coverage_output_path, "Write coverage output to a
directory DIR. This option is mandatory when using --coverage-prefix", "DIR", },
- { "interactive",'i', 0, G_OPTION_ARG_NONE, &use_interactive_repl,
+ { "interactive", 'i', 0, G_OPTION_ARG_NONE, &use_interactive_repl,
"Start the interactive repl"},
{ "include-path", 'I', 0, G_OPTION_ARG_STRING_ARRAY, &include_path, "Add the directory DIR to the list
of directories to search for js files.", "DIR" },
{ "module", 'm', 0, G_OPTION_ARG_NONE, &exec_as_module, "Execute the file as a module." },
diff --git a/modules/console.cpp b/modules/console.cpp
index ccef2bc3..63d013af 100644
--- a/modules/console.cpp
+++ b/modules/console.cpp
@@ -3,35 +3,25 @@
// SPDX-License-Identifier: MPL-1.1 OR GPL-2.0-or-later OR LGPL-2.1-or-later
// SPDX-FileCopyrightText: 1998 Netscape Communications Corporation
-#include <config.h> // for HAVE_READLINE_READLINE_H
-
-#ifdef HAVE_SIGNAL_H
-# include <setjmp.h>
-# include <signal.h>
-# ifdef _WIN32
-# define sigjmp_buf jmp_buf
-# define siglongjmp(e, v) longjmp (e, v)
-# define sigsetjmp(v, m) setjmp (v)
-# endif
-#endif
+#include <config.h>
#include <string>
#include <glib.h>
-#include <glib/gprintf.h> // for g_fprintf
+#include <stdio.h>
#include <js/CallArgs.h>
#include <js/CompilationAndEvaluation.h>
#include <js/CompileOptions.h>
#include <js/ErrorReport.h>
#include <js/Exception.h>
+#include <js/PropertySpec.h>
#include <js/RootingAPI.h>
#include <js/SourceText.h>
#include <js/TypeDecls.h>
-#include <js/Warnings.h>
+#include <js/Utility.h>
#include <jsapi.h> // for JS_IsExceptionPending, Exce...
-#include "gjs/atoms.h"
#include "gjs/context-private.h"
#include "gjs/jsapi-util-args.h"
#include "gjs/jsapi-util.h"
@@ -42,10 +32,6 @@ namespace mozilla {
union Utf8Unit;
}
-static void gjs_console_warning_reporter(JSContext* cx, JSErrorReport* report) {
- JS::PrintError(cx, stderr, report, /* reportWarnings = */ true);
-}
-
/* Based on js::shell::AutoReportException from SpiderMonkey. */
class AutoReportException {
JSContext *m_cx;
@@ -124,16 +110,13 @@ GJS_JSAPI_RETURN_CONVENTION
static bool gjs_console_interact(JSContext* context, unsigned argc,
JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
- JS::RootedObject global(context, gjs_get_import_global(context));
-
JS::UniqueChars prompt;
if (!gjs_parse_call_args(context, "interact", args, "s", "prompt", &prompt))
return false;
GjsAutoChar buffer;
- if (!gjs_console_readline(buffer.out(), prompt.get())) {
+ if (!gjs_console_readline(buffer.out(), prompt.get()))
return true;
- }
return gjs_string_from_utf8(context, buffer, args.rval());
}
@@ -182,7 +165,6 @@ static bool gjs_console_is_valid_js(JSContext* cx, unsigned argc,
JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::RootedString str(cx);
-
if (!gjs_parse_call_args(cx, "isValid", args, "S", "code", &str))
return false;
diff --git a/modules/esm/repl.js b/modules/esm/repl.js
index 648f0b66..698ec148 100644
--- a/modules/esm/repl.js
+++ b/modules/esm/repl.js
@@ -31,6 +31,8 @@ function toString(value) {
}
const sInputHandler = Symbol('input handler');
+const sExitHandler = Symbol('exit handler');
+const sExitWarning = Symbol('exit warning');
class ReplInput {
/**
* @param {object} _ _
@@ -81,6 +83,8 @@ class ReplInput {
* @param {string} _input the inputted line or lines (separated by \n)
*/
_input => { };
+
+ this[sExitWarning] = false;
}
[Symbol.toStringTag]() {
@@ -149,6 +153,17 @@ class ReplInput {
this.writeSync(Ansi.eraseDown(lines));
}
+ exit() {
+ if (this[sExitWarning]) {
+ this[sExitWarning] = false;
+ this[sExitHandler]?.();
+ } else {
+ this[sExitWarning] = true;
+ this.writeSync('\n(To exit, press Ctrl+C again or Ctrl+D)\n');
+ this.flush();
+ }
+ }
+
historyUp() {
if (this.historyIndex < this.history.length - 1) {
this.historyIndex++;
@@ -201,7 +216,7 @@ class ReplInput {
if (this.cursorColumn < editableValue.length - 1)
editableValue.splice(this.cursorColumn, 1);
else
- this.stop();
+ this.exit();
}
deleteToBeginning() {
@@ -310,6 +325,7 @@ class ReplInput {
if (this.validate(js)) {
// Reset lines before input is triggered
this.pendingInputLines = [];
+ this[sExitWarning] = false;
this[sInputHandler]?.(js);
} else {
// Buffer the input until a compilable unit is found...
@@ -320,6 +336,9 @@ class ReplInput {
handleEvent(key) {
if (key.ctrl && !key.meta && !key.shift) {
switch (key.name) {
+ case 'c':
+ this.exit();
+ return;
case 'h':
this.deleteChar();
return;
@@ -452,7 +471,7 @@ class ReplInput {
}
/**
- * @param {Uint8Array} buffer a string or Uint8Array to write to stdout
+ * @param {Uint8Array | string} buffer a string or Uint8Array to write to stdout
*/
writeSync(buffer) {
if (typeof buffer === 'string')
@@ -515,6 +534,10 @@ class ReplInput {
this._cancelled = false;
this.read();
}
+
+ onExit(exitHandler) {
+ this[sExitHandler] = exitHandler;
+ }
}
class FallbackReplInput extends ReplInput {
@@ -651,6 +674,10 @@ export class Repl {
enableColor: this[sSupportsColor],
});
+ this.input.onExit(() => {
+ this.exit();
+ });
+
this._registerInputHandler();
// Install our default mainloop...
diff --git a/tools/run_iwyu.sh b/tools/run_iwyu.sh
index 458578f0..9a2b2f3a 100755
--- a/tools/run_iwyu.sh
+++ b/tools/run_iwyu.sh
@@ -28,7 +28,6 @@ should_analyze () {
all) return 0 ;;
*$file*) return 0 ;;
*${file%.cpp}.h*) return 0 ;;
- *${file%.cpp}.hxx*) return 0 ;;
*${file%.cpp}-inl.h*) return 0 ;;
*${file%.cpp}-private.h*) return 0 ;;
*${file%.c}.h*) return 0 ;;
@@ -44,7 +43,7 @@ fi
echo "files: $files"
-IWYU="python3 $(which iwyu_tool || which iwyu_tool.py) -p ."
+IWYU="python3 $(which iwyu_tool || which iwyu-tool || which iwyu_tool.py) -p ."
IWYU_RAW="include-what-you-use -xc++ -std=c++17 -Xiwyu --keep=config.h"
IWYU_RAW_INC="-I. -I.. $(pkg-config --cflags gobject-introspection-1.0 mozjs-78)"
PRIVATE_MAPPING="-Xiwyu --mapping_file=$SRCDIR/tools/gjs-private-iwyu.imp -Xiwyu --keep=config.h"
@@ -57,7 +56,7 @@ EXIT=0
for FILE in $SRCDIR/gi/arg-types-inl.h $SRCDIR/gi/js-value-inl.h \
$SRCDIR/gi/utils-inl.h $SRCDIR/gjs/enum-utils.h \
$SRCDIR/gjs/jsapi-util-args.h $SRCDIR/gjs/jsapi-util-root.h \
- $SRCDIR/modules/cairo-module.h
+ $SRCDIR/modules/cairo-module.h $SRCDIR/util/console.hxx
do
if should_analyze $FILE; then
if ! $IWYU_RAW $(realpath --relative-to=. $FILE) $IWYU_RAW_INC 2>&1 \
diff --git a/util/console.cpp b/util/console.cpp
index 4498d165..3c0b7649 100644
--- a/util/console.cpp
+++ b/util/console.cpp
@@ -97,8 +97,9 @@ bool enable_raw_mode() {
// Disable echoing (terminal reprinting input)
// Disable canonical mode (output reflects input)
// Disable "extensions" that allow users to inject
+ // Disable C signal handling
// https://www.gnu.org/software/libc/manual/html_node/Other-Special.html
- raw.c_lflag &= ~(ECHO | ICANON | IEXTEN);
+ raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
// Set 0 characters required for a read
raw.c_cc[VMIN] = 0;
// Set the read timeout to 1 decisecond (0.1 seconds)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]