InteractiveConsole::InteractiveConsole(QWidget *parent) : QDialog(parent), m_splitter(new QSplitter(Qt::Vertical, this)), m_editorPart(0), m_editor(0), m_output(0), m_loadAction(KStandardAction::open(this, SLOT(openScriptFile()), this)), m_saveAction(KStandardAction::saveAs(this, SLOT(saveScript()), this)), m_clearAction(KStandardAction::clear(this, SLOT(clearEditor()), this)), m_executeAction(new QAction(QIcon::fromTheme(QStringLiteral("system-run")), i18n("&Execute"), this)), m_plasmaAction(new QAction(QIcon::fromTheme(QStringLiteral("plasma")), i18nc("Toolbar Button to switch to Plasma Scripting Mode", "Plasma"), this)), m_kwinAction(new QAction(QIcon::fromTheme(QStringLiteral("kwin")), i18nc("Toolbar Button to switch to KWin Scripting Mode", "KWin"), this)), m_snippetsMenu(new QMenu(i18n("Templates"), this)), m_fileDialog(0), m_closeWhenCompleted(false), m_mode(PlasmaConsole) { addAction(KStandardAction::close(this, SLOT(close()), this)); addAction(m_saveAction); addAction(m_clearAction); setWindowTitle(i18n("Desktop Shell Scripting Console")); setAttribute(Qt::WA_DeleteOnClose); //setButtons(QDialog::None); QWidget *widget = new QWidget(m_splitter); QVBoxLayout *editorLayout = new QVBoxLayout(widget); QLabel *label = new QLabel(i18n("Editor"), widget); QFont f = label->font(); f.setBold(true); label->setFont(f); editorLayout->addWidget(label); connect(m_snippetsMenu, &QMenu::aboutToShow, this, &InteractiveConsole::populateTemplatesMenu); QToolButton *loadTemplateButton = new QToolButton(this); loadTemplateButton->setPopupMode(QToolButton::InstantPopup); loadTemplateButton->setMenu(m_snippetsMenu); loadTemplateButton->setText(i18n("Load")); connect(loadTemplateButton, &QToolButton::triggered, this, &InteractiveConsole::loadTemplate); QToolButton *useTemplateButton = new QToolButton(this); useTemplateButton->setPopupMode(QToolButton::InstantPopup); useTemplateButton->setMenu(m_snippetsMenu); useTemplateButton->setText(i18n("Use")); connect(useTemplateButton, &QToolButton::triggered, this, &InteractiveConsole::useTemplate); QActionGroup *modeGroup = new QActionGroup(this); modeGroup->addAction(m_plasmaAction); modeGroup->addAction(m_kwinAction); m_plasmaAction->setCheckable(true); m_kwinAction->setCheckable(true); m_plasmaAction->setChecked(true); connect(modeGroup, &QActionGroup::triggered, this, &InteractiveConsole::modeSelectionChanged); KToolBar *toolBar = new KToolBar(this, true, false); toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); toolBar->addAction(m_loadAction); toolBar->addAction(m_saveAction); toolBar->addAction(m_clearAction); toolBar->addAction(m_executeAction); toolBar->addAction(m_plasmaAction); toolBar->addAction(m_kwinAction); toolBar->addWidget(loadTemplateButton); toolBar->addWidget(useTemplateButton); editorLayout->addWidget(toolBar); KService::List offers = KServiceTypeTrader::self()->query(QStringLiteral("KTextEditor/Document")); foreach (const KService::Ptr service, offers) { m_editorPart = service->createInstance<KTextEditor::Document>(widget); if (m_editorPart) { m_editorPart->setHighlightingMode(QStringLiteral("JavaScript/PlasmaDesktop")); KTextEditor::View * view = m_editorPart->createView(widget); view->setContextMenu(view->defaultContextMenu()); KTextEditor::ConfigInterface *config = qobject_cast<KTextEditor::ConfigInterface*>(view); if (config) { config->setConfigValue(QStringLiteral("line-numbers"), true); config->setConfigValue(QStringLiteral("dynamic-word-wrap"), true); } editorLayout->addWidget(view); connect(m_editorPart, &KTextEditor::Document::textChanged, this, &InteractiveConsole::scriptTextChanged); break; } }
PRIntn prmain(PRIntn argc, char **argv) { void *stackBasePtr; gpsee_interpreter_t *jsi; /* Handle describing a GPSEE/JavaScript Interpreter */ gpsee_realm_t *realm; /* Interpreter's primordial realm */ JSContext *cx; /* A context in realm */ const char *scriptCode = NULL; /* String with JavaScript program in it */ const char *scriptFilename = NULL; /* Filename with JavaScript program in it */ char * const *script_argv; /* Becomes arguments array in JS program */ char * const *script_environ = NULL; /* Environment to pass to script */ char *flags = malloc(8); /* Flags found on command line */ int noRunScript = 0; /* !0 = compile but do not run */ int fiArg = 0; int skipSheBang = 0; int exitCode; int verbosity; /* Verbosity to use before flags are processed */ #ifdef GPSEE_DEBUGGER JSDContext *jsdc; #endif #if defined(__SURELYNX__) permanent_pool = apr_initRuntime(); #endif gpsee_setVerbosity(isatty(STDERR_FILENO) ? GSR_PREPROGRAM_TTY_VERBOSITY : GSR_PREPROGRAM_NOTTY_VERBOSITY); gpsee_openlog(gpsee_basename(argv[0])); /* Print usage and exit if no arguments were given */ if (argc < 2) usage(argv[0]); flags[0] = (char)0; fiArg = findFileToInterpret(argc, argv); if (fiArg == 0) /* Not a script file interpreter (shebang) */ { int c; char *flag_p = flags; while ((c = getopt(argc, argv, whenSureLynx("D:r:","") "v:c:hHnf:F:aCRxSUWdeJz")) != -1) { switch(c) { #if defined(__SURELYNX__) case 'D': redirect_output(permanent_pool, optarg); break; case 'r': /* handled by cfg_openfile() */ break; #endif case 'c': scriptCode = optarg; break; case 'h': usage(argv[0]); break; case 'H': moreHelp(argv[0]); break; case 'n': noRunScript = 1; break; case 'F': skipSheBang = 1; case 'f': scriptFilename = optarg; break; case 'a': case 'C': case 'd': case 'e': case 'J': case 'S': case 'R': case 'U': case 'W': case 'x': case 'z': { char *flags_storage = realloc(flags, (flag_p - flags) + 1 + 1); if (flags_storage != flags) { flag_p = (flag_p - flags) + flags_storage; flags = flags_storage; } *flag_p++ = c; *flag_p = '\0'; } break; case '?': { char buf[32]; snprintf(buf, sizeof(buf), "Invalid option: %c\n", optopt); fatal(buf); } case ':': { char buf[32]; snprintf(buf, sizeof(buf), "Missing parameter to option '%c'\n", optopt); fatal(buf); } } } /* getopt wend */ /* Create the script's argument vector with the script name as arguments[0] */ { char **nc_script_argv = malloc(sizeof(argv[0]) * (2 + (argc - optind))); nc_script_argv[0] = (char *)scriptFilename; memcpy(nc_script_argv + 1, argv + optind, sizeof(argv[0]) * ((1 + argc) - optind)); script_argv = nc_script_argv; } *flag_p = (char)0; } else { scriptFilename = argv[fiArg]; if (fiArg == 2) { if (argv[1][0] != '-') fatal("Invalid syntax for file-interpreter flags! (Must begin with '-')"); flags = realloc(flags, strlen(argv[1]) + 1); strcpy(flags, argv[1] + 1); } /* This is a file interpreter; script_argv is correct at offset fiArg. */ script_argv = argv + fiArg; } if (strchr(flags, 'a')) { #if defined(GPSEE_DARWIN_SYSTEM) script_environ = (char * const *)_NSGetEnviron(); #else extern char **environ; script_environ = (char * const *)environ; #endif } loadRuntimeConfig(scriptFilename, flags, argc, argv); if (strchr(flags, 'U') || (cfg_bool_value(cfg, "gpsee_force_no_utf8_c_strings") == cfg_true) || getenv("GPSEE_NO_UTF8_C_STRINGS")) { JS_DestroyRuntime(JS_NewRuntime(1024)); putenv((char *)"GPSEE_NO_UTF8_C_STRINGS=1"); } jsi = gpsee_createInterpreter(); realm = jsi->realm; cx = jsi->cx; #if defined(GPSEE_DEBUGGER) jsdc = gpsee_initDebugger(cx, realm, DEBUGGER_JS); #endif gpsee_setThreadStackLimit(cx, &stackBasePtr, strtol(cfg_default_value(cfg, "gpsee_thread_stack_limit_bytes", "0x80000"), NULL, 0)); processFlags(cx, flags, &verbosity); free(flags); #if defined(__SURELYNX__) sl_set_debugLevel(gpsee_verbosity(0)); /* enableTerminalLogs(permanent_pool, gpsee_verbosity(0) > 0, NULL); */ #else if (verbosity < GSR_MIN_TTY_VERBOSITY && isatty(STDERR_FILENO)) verbosity = GSR_MIN_TTY_VERBOSITY; #endif if (gpsee_verbosity(0) < verbosity) gpsee_setVerbosity(verbosity); /* Run JavaScript specified with -c */ if (scriptCode) { jsval v; if (JS_EvaluateScript(cx, realm->globalObject, scriptCode, strlen(scriptCode), "command_line", 1, &v) == JS_FALSE) { v = JSVAL_NULL; goto out; } v = JSVAL_NULL; } if ((argv[0][0] == '/') #if defined(SYSTEM_GSR) && (strcmp(argv[0], SYSTEM_GSR) != 0) #endif && cfg_bool_value(cfg, "no_gsr_preload_script") != cfg_true) { char preloadScriptFilename[FILENAME_MAX]; char mydir[FILENAME_MAX]; int i; jsi->grt->exitType = et_unknown; i = snprintf(preloadScriptFilename, sizeof(preloadScriptFilename), "%s/.%s_preload", gpsee_dirname(argv[0], mydir, sizeof(mydir)), gpsee_basename(argv[0])); if ((i == 0) || (i == (sizeof(preloadScriptFilename) -1))) gpsee_log(cx, GLOG_EMERG, PRODUCT_SHORTNAME ": Unable to create preload script filename!"); else errno = 0; if (access(preloadScriptFilename, F_OK) == 0) { jsval v; JSScript *script; JSObject *scrobj; if (!gpsee_compileScript(cx, preloadScriptFilename, NULL, NULL, &script, realm->globalObject, &scrobj)) { jsi->grt->exitType = et_compileFailure; gpsee_log(cx, GLOG_EMERG, PRODUCT_SHORTNAME ": Unable to compile preload script '%s'", preloadScriptFilename); goto out; } if (!script || !scrobj) goto out; if (!noRunScript) { JS_AddNamedObjectRoot(cx, &scrobj, "preload_scrobj"); jsi->grt->exitType = et_execFailure; if (JS_ExecuteScript(cx, realm->globalObject, script, &v) == JS_TRUE) jsi->grt->exitType = et_finished; else jsi->grt->exitType = et_exception; JS_RemoveObjectRoot(cx, &scrobj); v = JSVAL_NULL; } } if (jsi->grt->exitType & et_errorMask) goto out; } /* Setup for main-script running -- cancel preprogram verbosity and use our own error reporting system in gsr that does not use error reporter */ gpsee_setVerbosity(verbosity); JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT); if (!scriptFilename) { if (!scriptCode) /* Command-line options did not include code to run */ usage(argv[0]); if (jsi->grt->exitType == et_unknown) jsi->grt->exitType = et_finished; } else { FILE *scriptFile = openScriptFile(cx, scriptFilename, skipSheBang || (fiArg != 0)); if (!scriptFile) { gpsee_log(cx, GLOG_NOTICE, PRODUCT_SHORTNAME ": Unable to open' script '%s'! (%m)", scriptFilename); jsi->grt->exitType = et_compileFailure; goto out; } processInlineFlags(cx, scriptFile, &verbosity); gpsee_setVerbosity(verbosity); /* Just compile and exit? */ if (noRunScript) { JSScript *script; JSObject *scrobj; if (!gpsee_compileScript(cx, scriptFilename, scriptFile, NULL, &script, realm->globalObject, &scrobj)) { jsi->grt->exitType = et_exception; gpsee_reportUncaughtException(cx, JSVAL_NULL, (gpsee_verbosity(0) >= GSR_FORCE_STACK_DUMP_VERBOSITY) || ((gpsee_verbosity(0) >= GPSEE_ERROR_OUTPUT_VERBOSITY) && isatty(STDERR_FILENO))); } else { jsi->grt->exitType = et_finished; } } else /* noRunScript is false; run the program */ { jsi->grt->exitType = et_execFailure; if (gpsee_runProgramModule(cx, scriptFilename, NULL, scriptFile, script_argv, script_environ) == JS_TRUE) { jsi->grt->exitType = et_finished; } else { int code; code = gpsee_getExceptionExitCode(cx); if (code >= 0) /** e.g. throw 6 */ { jsi->grt->exitType = et_requested; jsi->grt->exitCode = code; } else { if (JS_IsExceptionPending(cx)) { jsi->grt->exitType = et_exception; gpsee_reportUncaughtException(cx, JSVAL_NULL, (gpsee_verbosity(0) >= GSR_FORCE_STACK_DUMP_VERBOSITY) || ((gpsee_verbosity(0) >= GPSEE_ERROR_OUTPUT_VERBOSITY) && isatty(STDERR_FILENO))); } } } } fclose(scriptFile); goto out; } out: #ifdef GPSEE_DEBUGGER gpsee_finiDebugger(jsdc); #endif if (jsi->grt->exitType & et_successMask) { exitCode = jsi->grt->exitCode; } else { const char *reason; exitCode = 1; switch(jsi->grt->exitType) { case et_successMask: case et_errorMask: case et_requested: case et_finished: case et_dummy: default: GPSEE_NOT_REACHED("impossible"); reason = NULL; /* quell compiler warning below */ break; case et_execFailure: reason = "execFailure - probable native module error, returning JS_FALSE without setting exception"; break; case et_compileFailure: reason = "script could not be compiled"; break; case et_unknown: reason = "unknown - probable native module error, returning JS_FALSE without setting exception"; break; case et_exception: reason = NULL; break; } if (reason) { gpsee_log(cx, GLOG_NOTICE, "Unexpected interpreter shutdown: %s (%m)", reason); if (gpsee_verbosity(0) == 0) { /* not gpsee_ */ fprintf(stderr, "*** Unexpected interpreter shutdown: %s", reason); if (errno) fprintf(stderr, " (%s)\n", strerror(errno)); else fputs("\n", stderr); } } } gpsee_destroyInterpreter(jsi); JS_ShutDown(); return exitCode; }