mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-22 10:27:58 +01:00
Preliminary REPL mode.
This commit is contained in:
@@ -303,24 +303,29 @@ var CommandMode = Class("CommandMode", {
|
||||
this.keepCommand = userContext.hidden_option_command_afterimage;
|
||||
},
|
||||
|
||||
open: function (command) {
|
||||
this.command = command;
|
||||
get command() this.widgets.command[1],
|
||||
set command(val) this.widgets.command = val,
|
||||
|
||||
get prompt() this.widgets.prompt,
|
||||
set prompt(val) this.widgets.prompt = val,
|
||||
|
||||
open: function (command) {
|
||||
dactyl.assert(isinstance(this.mode, modes.COMMAND_LINE),
|
||||
"Not opening command line in non-command-line mode.");
|
||||
|
||||
commandline.clearMessage();
|
||||
modes.push(this.mode, null, this.closure);
|
||||
modes.push(this.mode, this.extendedMode, this.closure);
|
||||
|
||||
this.widgets.active.commandline.collapsed = false;
|
||||
this.widgets.prompt = this.prompt;
|
||||
this.widgets.command = command || "";
|
||||
|
||||
this.input = this.widgets.active.command.inputField;
|
||||
if (this.historyKey)
|
||||
this.history = CommandLine.History(commandline.widgets.active.command.inputField, this.historyKey, this);
|
||||
this.history = CommandLine.History(this.input, this.historyKey, this);
|
||||
|
||||
if (this.complete)
|
||||
this.completions = CommandLine.Completions(commandline.widgets.active.command.inputField, this);
|
||||
this.completions = CommandLine.Completions(this.input, this);
|
||||
|
||||
if (this.completions && command && commandline.commandSession === this)
|
||||
this.completions.autocompleteTimer.flush(true);
|
||||
@@ -346,6 +351,7 @@ var CommandMode = Class("CommandMode", {
|
||||
leave: function (stack) {
|
||||
if (!stack.push) {
|
||||
commandline.commandSession = null;
|
||||
this.input.dactylKeyPress = undefined;
|
||||
|
||||
if (this.completions)
|
||||
this.completions.cleanup();
|
||||
@@ -1010,6 +1016,7 @@ var CommandLine = Module("commandline", {
|
||||
this.tabTimer.reset();
|
||||
this.autocompleteTimer.reset();
|
||||
this.itemList.visible = false;
|
||||
this.input.dactylKeyPress = undefined;
|
||||
},
|
||||
|
||||
ignoredCount: 0,
|
||||
|
||||
@@ -401,7 +401,14 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
|
||||
if (fileName == null)
|
||||
if (info && info.file[0] !== "[")
|
||||
({ file: fileName, line: lineNumber, context: ctxt }) = info;
|
||||
else try {
|
||||
|
||||
if (!context)
|
||||
context = _userContext || ctxt;
|
||||
|
||||
if (isinstance(context, ["Sandbox"]))
|
||||
return Cu.evalInSandbox(str, context, "1.8", fileName, lineNumber);
|
||||
else
|
||||
try {
|
||||
if (!context)
|
||||
context = userContext || ctxt;
|
||||
|
||||
@@ -424,10 +431,6 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
|
||||
delete context[EVAL_RESULT];
|
||||
delete context[EVAL_STRING];
|
||||
}
|
||||
|
||||
if (!context)
|
||||
context = _userContext || ctxt;
|
||||
return Cu.evalInSandbox(str, context, "1.8", fileName, lineNumber);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1749,21 +1752,6 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
|
||||
});
|
||||
});
|
||||
|
||||
commands.add(["javas[cript]", "js"],
|
||||
"Evaluate a JavaScript string",
|
||||
function (args) {
|
||||
if (args.bang) // open JavaScript console
|
||||
dactyl.open("chrome://global/content/console.xul",
|
||||
{ from: "javascript" });
|
||||
else
|
||||
dactyl.userEval(args[0]);
|
||||
}, {
|
||||
bang: true,
|
||||
completer: function (context) completion.javascript(context),
|
||||
hereDoc: true,
|
||||
literal: 0
|
||||
});
|
||||
|
||||
commands.add(["loadplugins", "lpl"],
|
||||
"Load all plugins immediately",
|
||||
function (args) {
|
||||
|
||||
@@ -31,6 +31,8 @@ var Editor = Module("editor", {
|
||||
}
|
||||
|
||||
let elem = dactyl.focusedElement;
|
||||
if (elem.inputField)
|
||||
elem = elem.inputField;
|
||||
|
||||
if (elem.setSelectionRange) {
|
||||
let text = dactyl.clipboardRead(clipboard);
|
||||
@@ -49,7 +51,8 @@ var Editor = Module("editor", {
|
||||
let value = elem.value.substring(0, start) + text + elem.value.substring(end);
|
||||
elem.value = value;
|
||||
|
||||
Editor.getEditor(elem).rootElement.firstChild.textContent = value;
|
||||
if (/^(search|text)$/.test(elem.type))
|
||||
Editor.getEditor(elem).rootElement.firstChild.textContent = value;
|
||||
|
||||
elem.selectionStart = Math.min(start + (toStart ? 0 : text.length), elem.value.length);
|
||||
elem.selectionEnd = elem.selectionStart;
|
||||
|
||||
@@ -217,7 +217,12 @@ var KeyProcessor = Class("KeyProcessor", {
|
||||
else if (map.motion)
|
||||
return KeyArgProcessor(this, map, true, "motion");
|
||||
|
||||
return this.execute(map, { count: this.count, command: this.command, events: this.events, allEvents: this.allEvents });
|
||||
return this.execute(map, {
|
||||
allEvents: this.allEvents,
|
||||
command: this.command,
|
||||
count: this.count,
|
||||
events: this.events
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.waiting)
|
||||
@@ -347,7 +352,6 @@ var Events = Module("events", {
|
||||
|
||||
this._fullscreen = window.fullScreen;
|
||||
this._lastFocus = null;
|
||||
this._currentMacro = "";
|
||||
this._macroKeys = [];
|
||||
this._lastMacro = "";
|
||||
|
||||
@@ -426,8 +430,8 @@ var Events = Module("events", {
|
||||
* @param {boolean} capture When true, listen during the capture
|
||||
* phase, otherwise during the bubbling phase.
|
||||
*/
|
||||
get addSessionListener() this.builtin.closure.listen,
|
||||
get listen() this.builtin.closure.listen,
|
||||
addSessionListener: deprecated("events.listen", { get: function addSessionListener() this.listen }),
|
||||
|
||||
/**
|
||||
* Wraps an event listener to ensure that errors are reported.
|
||||
@@ -462,34 +466,33 @@ var Events = Module("events", {
|
||||
*
|
||||
* @param {string} macro The name for the macro.
|
||||
*/
|
||||
startRecording: function (macro) {
|
||||
// TODO: ignore this like Vim?
|
||||
dactyl.assert(/[a-zA-Z0-9]/.test(macro),
|
||||
_recording: null,
|
||||
get recording() this._recording,
|
||||
|
||||
set recording(macro) {
|
||||
dactyl.assert(macro == null || /[a-zA-Z0-9]/.test(macro),
|
||||
"E354: Invalid register name: '" + macro + "'");
|
||||
|
||||
modes.recording = true;
|
||||
modes.recording = !!macro;
|
||||
|
||||
if (/[A-Z]/.test(macro)) { // uppercase (append)
|
||||
this._currentMacro = macro.toLowerCase();
|
||||
this._macroKeys = events.fromString((this._macros.get(this._currentMacro) || { keys: "" }).keys, true)
|
||||
macro = macro.toLowerCase();
|
||||
this._macroKeys = events.fromString((this._macros.get(macro) || { keys: "" }).keys, true)
|
||||
.map(events.closure.toString);
|
||||
}
|
||||
else {
|
||||
this._currentMacro = macro;
|
||||
else if (macro) {
|
||||
this._macroKeys = [];
|
||||
}
|
||||
},
|
||||
else {
|
||||
this._macros.set(this.recording, {
|
||||
keys: this._macroKeys.join(""),
|
||||
timeRecorded: Date.now()
|
||||
});
|
||||
|
||||
/** Terminates the recording of the current key event macro. */
|
||||
finishRecording: function () {
|
||||
modes.recording = false;
|
||||
this._macros.set(this._currentMacro, {
|
||||
keys: this._macroKeys.join(""),
|
||||
timeRecorded: Date.now()
|
||||
});
|
||||
|
||||
dactyl.log("Recorded " + this._currentMacro + ": " + this._macroKeys.join(""), 9);
|
||||
dactyl.echomsg("Recorded macro '" + this._currentMacro + "'");
|
||||
dactyl.log("Recorded " + this.recording + ": " + this._macroKeys.join(""), 9);
|
||||
dactyl.echomsg("Recorded macro '" + this.recording + "'");
|
||||
}
|
||||
this._recording = macro || null;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1457,7 +1460,7 @@ var Events = Module("events", {
|
||||
["q", "<record-macro>"], "Record a key sequence into a macro",
|
||||
function ({ arg }) {
|
||||
events._macroKeys.pop();
|
||||
events[modes.recording ? "finishRecording" : "startRecording"](arg);
|
||||
events.recording = arg;
|
||||
},
|
||||
{ get arg() !modes.recording });
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
/** @instance hints */
|
||||
|
||||
var HintSession = Class("HintSession", CommandMode, {
|
||||
get extendedMode() modes.HINTS,
|
||||
|
||||
init: function init(mode, opts) {
|
||||
init.supercall(this);
|
||||
|
||||
@@ -465,7 +467,7 @@ var HintSession = Class("HintSession", CommandMode, {
|
||||
}
|
||||
|
||||
this.timeout(function () {
|
||||
if (isinstance(modes.main, modes.HINTS) && !this.continue)
|
||||
if ((modes.extended & modes.HINTS) && !this.continue)
|
||||
modes.pop();
|
||||
commandline.lastEcho = null; // Hack.
|
||||
dactyl.trapErrors("action", this.hintMode,
|
||||
|
||||
@@ -447,6 +447,11 @@ var ConfigBase = Class("ConfigBase", {
|
||||
EditorBlink1;;* background: yellow !important;
|
||||
EditorBlink2;;*
|
||||
|
||||
REPL overflow: auto; max-height: 40em;
|
||||
REPL-R;;;Question
|
||||
REPL-E white-space: pre-wrap;
|
||||
REPL-P white-space: pre-wrap; margin-bottom: 1em;
|
||||
|
||||
Indicator color: blue; width: 1.5em; text-align: center;
|
||||
Filter font-weight: bold;
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ var Highlights = Module("Highlight", {
|
||||
*/
|
||||
selector: function (class_)
|
||||
let (self = this)
|
||||
class_.replace(/(^|[>\s])([A-Z]\w+)\b/g,
|
||||
class_.replace(/(^|[>\s])([A-Z][\w-]+)\b/g,
|
||||
function (m, n1, hl) n1 +
|
||||
(self.highlight[hl] && self.highlight[hl].class != class_
|
||||
? self.highlight[hl].selector : "[dactyl|highlight~=" + hl + "]")),
|
||||
|
||||
@@ -108,6 +108,7 @@ var JavaScript = Module("javascript", {
|
||||
return cache[key];
|
||||
}
|
||||
catch (e) {
|
||||
util.reportError(e);
|
||||
this.context.message = "Error: " + e;
|
||||
return null;
|
||||
}
|
||||
@@ -306,6 +307,7 @@ var JavaScript = Module("javascript", {
|
||||
|
||||
this._cacheKey = null;
|
||||
let obj = [[this.cache.evalContext, "Local Variables"],
|
||||
[this.replContext, "REPL Variables"],
|
||||
[this.modules.userContext, "Global Variables"],
|
||||
[this.modules, "modules"],
|
||||
[this.window, "window"]]; // Default objects;
|
||||
@@ -673,6 +675,7 @@ var JavaScript = Module("javascript", {
|
||||
}, {
|
||||
init: function init(dactyl, modules, window) {
|
||||
init.superapply(this, arguments);
|
||||
modules.JavaScript = Class("JavaScript", JavaScript, { modules: modules, window: window });
|
||||
},
|
||||
completion: function (dactyl, modules, window) {
|
||||
const { completion } = modules;
|
||||
@@ -681,6 +684,142 @@ var JavaScript = Module("javascript", {
|
||||
javascriptCompleter: JavaScript // Backwards compatibility
|
||||
});
|
||||
},
|
||||
modes: function initModes(dactyl, modules, window) {
|
||||
const { modes } = modules;
|
||||
|
||||
modes.addMode("REPL", {
|
||||
description: "JavaScript Read Eval Print Loop",
|
||||
bases: [modes.COMMAND_LINE]
|
||||
});
|
||||
},
|
||||
commandline: function initCommandLine(dactyl, modules, window) {
|
||||
const { modes } = modules;
|
||||
|
||||
var REPL = Class("REPL", {
|
||||
init: function init(context) {
|
||||
this.context = context;
|
||||
this.results = [];
|
||||
},
|
||||
|
||||
addOutput: function addOutput(js) {
|
||||
default xml namespace = XHTML;
|
||||
this.count++;
|
||||
|
||||
try {
|
||||
var result = dactyl.userEval(js, this.context);
|
||||
var xml = util.objectToString(result, true);
|
||||
}
|
||||
catch (e) {
|
||||
util.reportError(e);
|
||||
result = e;
|
||||
|
||||
if (e.fileName)
|
||||
e = util.fixURI(e.fileName) + ":" + e.lineNumber + ": " + e;
|
||||
xml = <span highlight="ErrorMsg">{e}</span>;
|
||||
}
|
||||
|
||||
let prompt = "js" + this.count;
|
||||
Class.replaceProperty(this.context, prompt, result);
|
||||
|
||||
XML.ignoreWhitespace = XML.prettyPrinting = false;
|
||||
let nodes = {};
|
||||
this.rootNode.appendChild(
|
||||
util.xmlToDom(<e4x>
|
||||
<div highlight="REPL-E" key="e"><span highlight="REPL-R">{prompt}></span> {js}</div>
|
||||
<div highlight="REPL-P" key="p">{xml}</div>
|
||||
</e4x>.elements(), this.document, nodes));
|
||||
|
||||
this.rootNode.scrollTop = nodes.e.getBoundingClientRect().top
|
||||
- this.rootNode.getBoundingClientRect().top;
|
||||
},
|
||||
|
||||
count: 0,
|
||||
|
||||
message: Class.memoize(function () {
|
||||
default xml namespace = XHTML;
|
||||
util.xmlToDom(<div highlight="REPL" key="rootNode"/>,
|
||||
this.document, this);
|
||||
|
||||
return this.rootNode;
|
||||
})
|
||||
});
|
||||
|
||||
modules.CommandREPLMode = Class("CommandREPLMode", modules.CommandMode, {
|
||||
open: function open() {
|
||||
let self = this;
|
||||
|
||||
this.context = modules.newContext(modules.userContext, true);
|
||||
this.js = modules.JavaScript();
|
||||
this.js.replContext = this.context;
|
||||
this.js.newContext = function newContext() modules.newContext(self.context, true);
|
||||
this.repl = REPL(this.context);
|
||||
|
||||
this.updatePrompt();
|
||||
|
||||
modules.mow.echo(this.repl);
|
||||
|
||||
open.superapply(this, arguments);
|
||||
},
|
||||
|
||||
complete: function complete(context) {
|
||||
context.fork("js", 0, this.js, "complete");
|
||||
},
|
||||
|
||||
historyKey: "javascript",
|
||||
|
||||
mode: modes.REPL,
|
||||
|
||||
accept: function accept() {
|
||||
dactyl.trapErrors(function () { this.repl.addOutput(this.command) }, this);
|
||||
|
||||
this.updatePrompt();
|
||||
this.completions.cleanup();
|
||||
this.history.save();
|
||||
|
||||
modules.mow.resize();
|
||||
},
|
||||
|
||||
leave: function leave(params) {
|
||||
leave.superapply(this, arguments);
|
||||
if (!params.push)
|
||||
modes.delay(function () { modes.pop(); });
|
||||
},
|
||||
|
||||
updatePrompt: function updatePrompt() {
|
||||
this.command = "";
|
||||
this.prompt = ["REPL-R", "js" + (this.repl.count + 1) + "> "];
|
||||
}
|
||||
});
|
||||
},
|
||||
commands: function initCommands(dactyl, modules, window) {
|
||||
const { commands } = modules;
|
||||
|
||||
commands.add(["javas[cript]", "js"],
|
||||
"Evaluate a JavaScript string",
|
||||
function (args) {
|
||||
if (args.bang) // open JavaScript console
|
||||
dactyl.open("chrome://global/content/console.xul",
|
||||
{ from: "javascript" });
|
||||
else if (args[0])
|
||||
dactyl.userEval(args[0]);
|
||||
else {
|
||||
modules.commandline;
|
||||
modules.CommandREPLMode().open();
|
||||
}
|
||||
}, {
|
||||
bang: true,
|
||||
completer: function (context) modules.completion.javascript(context),
|
||||
hereDoc: true,
|
||||
literal: 0
|
||||
});
|
||||
},
|
||||
mappings: function initMappings(dactyl, modules, window) {
|
||||
const { mappings, modes } = modules;
|
||||
|
||||
mappings.add([modes.REPL], ["<Return>"],
|
||||
"Accept the current input",
|
||||
function ({ self }) { self.accept(); });
|
||||
},
|
||||
options: function (dactyl, modules, window) {
|
||||
modules.options.add(["jsdebugger", "jsd"],
|
||||
"Enable the JavaScript debugger service for use in JavaScript completion",
|
||||
|
||||
@@ -314,7 +314,7 @@ var Overlay = Module("Overlay", {
|
||||
|
||||
defineModule.loadLog.push("Loaded in " + (Date.now() - start) + "ms");
|
||||
|
||||
modules.events.addSessionListener(window, "unload", function onUnload() {
|
||||
modules.events.listen(window, "unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload.wrapped, false);
|
||||
for (let prop in properties(modules)) {
|
||||
let desc = Object.getOwnPropertyDescriptor(modules, prop);
|
||||
|
||||
@@ -986,7 +986,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
|
||||
obj = Object.prototype.toString.call(obj);
|
||||
}
|
||||
obj = template.highlightFilter(util.clip(obj, 150), "\n", !color ? function () "^J" : function () <span highlight="NonText">^J</span>);
|
||||
let string = <><span highlight="Title Object">{obj}</span>::<br/>
</>;
|
||||
let string = <><span highlight="Title Object">{obj}</span>::
</>;
|
||||
|
||||
let keys = [];
|
||||
|
||||
@@ -1016,7 +1016,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
|
||||
i = parseInt(i);
|
||||
else if (/^[A-Z_]+$/.test(i))
|
||||
i = "";
|
||||
keys.push([i, <>{key}{noVal ? "" : <>: {value}</>}<br/>
</>]);
|
||||
keys.push([i, <>{key}{noVal ? "" : <>: {value}</>}
</>]);
|
||||
}
|
||||
}
|
||||
catch (e) {}
|
||||
@@ -1027,7 +1027,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
|
||||
return String.localeCompare(a[0], b[0]);
|
||||
}
|
||||
string += template.map(keys.sort(compare), function (f) f[1]);
|
||||
return color ? string : [s for each (s in string)].join("");
|
||||
return color ? <div style="white-space: pre-wrap;">{string}</div> : [s for each (s in string)].join("");
|
||||
},
|
||||
|
||||
observers: {
|
||||
|
||||
@@ -336,7 +336,7 @@ var Config = Module("config", ConfigBase, {
|
||||
completion.location);
|
||||
},
|
||||
events: function (dactyl, modules, window) {
|
||||
modules.events.addSessionListener(window, "SidebarFocused", function (event) {
|
||||
modules.events.listen(window, "SidebarFocused", function (event) {
|
||||
modules.config.lastSidebar = window.document.getElementById("sidebar-box")
|
||||
.getAttribute("sidebarcommand");
|
||||
}, false);
|
||||
|
||||
Reference in New Issue
Block a user