// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
if (modes.have(modes.OUTPUT_MULTILINE)) {
this.resize(true);
- if (options["more"] && this.isScrollable(1)) {
+ if (options["more"] && this.canScroll(1))
// start the last executed command's output at the top of the screen
- let elements = this.document.getElementsByClassName("ex-command-output");
- elements[elements.length - 1].scrollIntoView(true);
- }
+ DOM(this.document.body.lastElementChild).scrollIntoView(true);
else
this.body.scrollTop = this.body.scrollHeight;
events.listen(window, this, "windowEvents");
modules.mow = this;
- let fontSize = util.computedStyle(document.documentElement).fontSize;
+ let fontSize = DOM(document.documentElement).style.fontSize;
styles.system.add("font-size", "dactyl://content/buffer.xhtml",
"body { font-size: " + fontSize + "; } \
html|html > xul|scrollbar { visibility: collapse !important; }",
true);
- XML.ignoreWhitespace = true;
- util.overlayWindow(window, {
+ overlay.overlayWindow(window, {
objects: {
eventTarget: this
},
- append: <e4x xmlns={XUL} xmlns:dactyl={NS}>
- <window id={document.documentElement.id}>
- <popupset>
- <menupopup id="dactyl-contextmenu" highlight="Events" events="contextEvents">
- <menuitem id="dactyl-context-copylink"
- label="Copy Link Location" dactyl:group="link"
- oncommand="goDoCommand('cmd_copyLink');"/>
- <menuitem id="dactyl-context-copypath"
- label="Copy File Path" dactyl:group="link path"
- oncommand="dactyl.clipboardWrite(document.popupNode.getAttribute('path'));"/>
- <menuitem id="dactyl-context-copy"
- label="Copy" dactyl:group="selection"
- command="cmd_copy"/>
- <menuitem id="dactyl-context-selectall"
- label="Select All"
- command="cmd_selectAll"/>
- </menupopup>
- </popupset>
- </window>
- <vbox id={config.commandContainer}>
- <vbox class="dactyl-container" id="dactyl-multiline-output-container" hidden="false" collapsed="true">
- <iframe id="dactyl-multiline-output" src="dactyl://content/buffer.xhtml"
- flex="1" hidden="false" collapsed="false" contextmenu="dactyl-contextmenu"
- highlight="Events" />
- </vbox>
- </vbox>
- </e4x>
+ append: [
+ ["window", { id: document.documentElement.id, xmlns: "xul" },
+ ["popupset", {},
+ ["menupopup", { id: "dactyl-contextmenu", highlight: "Events", events: "contextEvents" },
+ ["menuitem", { id: "dactyl-context-copylink", label: _("mow.contextMenu.copyLink"),
+ "dactyl:group": "link", oncommand: "goDoCommand('cmd_copyLink');" }],
+ ["menuitem", { id: "dactyl-context-copypath", label: _("mow.contextMenu.copyPath"),
+ "dactyl:group": "link path", oncommand: "dactyl.clipboardWrite(document.popupNode.getAttribute('path'));" }],
+ ["menuitem", { id: "dactyl-context-copy", label: _("mow.contextMenu.copy"),
+ "dactyl:group": "selection", command: "cmd_copy" }],
+ ["menuitem", { id: "dactyl-context-selectall", label: _("mow.contextMenu.selectAll"),
+ command: "cmd_selectAll" }]]]],
+
+ ["vbox", { id: config.ids.commandContainer, xmlns: "xul" },
+ ["vbox", { class: "dactyl-container", id: "dactyl-multiline-output-container", hidden: "false", collapsed: "true" },
+ ["iframe", { id: "dactyl-multiline-output", src: "dactyl://content/buffer.xhtml",
+ flex: "1", hidden: "false", collapsed: "false",
+ contextmenu: "dactyl-contextmenu", highlight: "Events" }]]]]
});
},
__noSuchMethod__: function (meth, args) Buffer[meth].apply(Buffer, [this.body].concat(args)),
get widget() this.widgets.multilineOutput,
- widgets: Class.memoize(function widgets() commandline.widgets),
+ widgets: Class.Memoize(function widgets() commandline.widgets),
- body: Class.memoize(function body() this.widget.contentDocument.documentElement),
+ body: Class.Memoize(function body() this.widget.contentDocument.documentElement),
get document() this.widget.contentDocument,
get window() this.widget.contentWindow,
* @param {string} highlightGroup
*/
echo: function echo(data, highlightGroup, silent) {
- let body = this.document.body;
+ let body = DOM(this.document.body);
this.widgets.message = null;
if (!commandline.commandVisible)
if (modes.main != modes.OUTPUT_MULTILINE) {
modes.push(modes.OUTPUT_MULTILINE, null, {
onKeyPress: this.closure.onKeyPress,
+
leave: this.closure(function leave(stack) {
if (stack.pop)
for (let message in values(this.messages))
if (message.leave)
message.leave(stack);
- })
+ }),
+
+ window: this.window
});
this.messages = [];
}
- // If it's already XML, assume it knows what it's doing.
- // Otherwise, white space is significant.
- // The problem elsewhere is that E4X tends to insert new lines
- // after interpolated data.
- XML.ignoreWhitespace = XML.prettyPrinting = false;
+ highlightGroup = "CommandOutput " + (highlightGroup || "");
- if (isObject(data) && !isinstance(data, _)) {
+ if (isObject(data) && !isinstance(data, _) && !DOM.isJSONXML(data)) {
this.lastOutput = null;
- var output = util.xmlToDom(<div class="ex-command-output" style="white-space: nowrap" highlight={highlightGroup}/>,
- this.document);
+ var output = DOM(["div", { style: "white-space: nowrap", highlight: highlightGroup }],
+ this.document);
data.document = this.document;
try {
- output.appendChild(data.message);
+ output.append(data.message);
}
catch (e) {
util.reportError(e);
util.dump(data);
- this.messages.push(data);
}
+ this.messages.push(data);
}
else {
- let style = isString(data) ? "pre" : "nowrap";
- this.lastOutput = <div class="ex-command-output" style={"white-space: " + style} highlight={highlightGroup}>{data}</div>;
+ let style = isString(data) ? "pre-wrap" : "nowrap";
+ this.lastOutput = ["div", { style: "white-space: " + style, highlight: highlightGroup },
+ data];
- var output = util.xmlToDom(this.lastOutput, this.document);
+ var output = DOM(this.lastOutput, this.document);
}
// FIXME: need to make sure an open MOW is closed when commands
// that don't generate output are executed
if (!this.visible) {
this.body.scrollTop = 0;
- body.textContent = "";
+ body.empty();
}
- body.appendChild(output);
+ body.append(output);
let str = typeof data !== "xml" && data.message || data;
if (!silent)
- dactyl.triggerObserver("echoMultiline", data, highlightGroup, output);
+ dactyl.triggerObserver("echoMultiline", data, highlightGroup, output[0]);
this._timer.tell();
if (!this.visible)
dactyl.open(event.target.href, where);
};
- if (event.target instanceof HTMLAnchorElement)
- switch (events.toString(event)) {
+ if (event.target instanceof Ci.nsIDOMHTMLAnchorElement)
+ switch (DOM.Event.stringify(event)) {
case "<LeftMouse>":
openLink(dactyl.CURRENT_TAB);
break;
popupshowing: function onPopupShowing(event) {
let menu = commandline.widgets.contextMenu;
let enabled = {
- link: window.document.popupNode instanceof HTMLAnchorElement,
+ link: window.document.popupNode instanceof Ci.nsIDOMHTMLAnchorElement,
path: window.document.popupNode.hasAttribute("path"),
selection: !window.document.commandDispatcher.focusedWindow.getSelection().isCollapsed
};
onKeyPress: function onKeyPress(eventList) {
const KILL = false, PASS = true;
- if (options["more"] && mow.isScrollable(1))
+ if (options["more"] && mow.canScroll(1))
this.updateMorePrompt(false, true);
else {
modes.pop();
let doc = this.widget.contentDocument;
- let availableHeight = config.outputHeight;
+ let trim = this.spaceNeeded;
+ let availableHeight = config.outputHeight - trim;
if (this.visible)
availableHeight += parseFloat(this.widgets.mowContainer.height || 0);
availableHeight -= extra || 0;
doc.body.style.minWidth = this.widgets.commandbar.commandline.scrollWidth + "px";
- this.widgets.mowContainer.height = Math.min(doc.body.clientHeight, availableHeight) + "px";
- this.timeout(function ()
- this.widgets.mowContainer.height = Math.min(doc.body.clientHeight, availableHeight) + "px",
- 0);
+
+ function adjust() {
+ let wantedHeight = doc.body.clientHeight;
+ this.widgets.mowContainer.height = Math.min(wantedHeight, availableHeight) + "px",
+ this.wantedHeight = Math.max(0, wantedHeight - availableHeight);
+ }
+ adjust.call(this);
+ this.timeout(adjust);
doc.body.style.minWidth = "";
},
get spaceNeeded() {
- let rect = this.widgets.commandbar.commandline.getBoundingClientRect();
- let offset = rect.bottom - window.innerHeight;
- return Math.max(0, offset);
+ if (DOM("#dactyl-bell", document).isVisible)
+ return 0;
+ return Math.max(0, DOM("#" + config.ids.commandContainer, document).rect.bottom
+ - window.innerHeight);
},
/**
let elem = this.widget.contentDocument.documentElement;
if (showHelp)
- this.widgets.message = ["MoreMsg", "-- More -- SPACE/<C-f>/j: screen/page/line down, <C-b>/<C-u>/k: up, q: quit"];
- else if (force || (options["more"] && Buffer.isScrollable(elem, 1)))
- this.widgets.message = ["MoreMsg", "-- More --"];
+ this.widgets.message = ["MoreMsg", _("mow.moreHelp")];
+ else if (force || (options["more"] && Buffer.canScroll(elem, 1)))
+ this.widgets.message = ["MoreMsg", _("mow.more")];
else
- this.widgets.message = ["Question", "Press ENTER or type command to continue"];
+ this.widgets.message = ["Question", _("mow.continue")];
},
visible: Modes.boundProperty({
if (!value && elem && elem.contentWindow == document.commandDispatcher.focusedWindow) {
let focused = content.document.activeElement;
- if (Events.isInputElement(focused))
+ if (focused && Events.isInputElement(focused))
focused.blur();
document.commandDispatcher.focusedWindow = content;
})
}, {
}, {
+ modes: function initModes() {
+ modes.addMode("OUTPUT_MULTILINE", {
+ description: "Active when the multi-line output buffer is open",
+ bases: [modes.NORMAL]
+ });
+ },
mappings: function initMappings() {
const PASS = true;
const DROP = false;
mappings.add([modes.COMMAND],
["g<lt>"], "Redisplay the last command output",
function () {
- dactyl.assert(commandline.lastOutput, _("mow.noPreviousOutput"));
+ dactyl.assert(mow.lastOutput, _("mow.noPreviousOutput"));
mow.echo(mow.lastOutput, "Normal");
});
+ mappings.add([modes.OUTPUT_MULTILINE],
+ ["<Esc>", "<C-[>"],
+ "Return to the previous mode",
+ function () { modes.pop(null, { fromEscape: true }); });
+
let bind = function bind(keys, description, action, test, default_) {
mappings.add([modes.OUTPUT_MULTILINE],
keys, description,
bind(["j", "<C-e>", "<Down>"], "Scroll down one line",
function ({ count }) { mow.scrollVertical("lines", 1 * (count || 1)); },
- function () mow.isScrollable(1), BEEP);
+ function () mow.canScroll(1), BEEP);
bind(["k", "<C-y>", "<Up>"], "Scroll up one line",
function ({ count }) { mow.scrollVertical("lines", -1 * (count || 1)); },
- function () mow.isScrollable(-1), BEEP);
+ function () mow.canScroll(-1), BEEP);
bind(["<C-j>", "<C-m>", "<Return>"], "Scroll down one line, exit on last line",
function ({ count }) { mow.scrollVertical("lines", 1 * (count || 1)); },
- function () mow.isScrollable(1), DROP);
+ function () mow.canScroll(1), DROP);
// half page down
bind(["<C-d>"], "Scroll down half a page",
function ({ count }) { mow.scrollVertical("pages", .5 * (count || 1)); },
- function () mow.isScrollable(1), BEEP);
+ function () mow.canScroll(1), BEEP);
bind(["<C-f>", "<PageDown>"], "Scroll down one page",
function ({ count }) { mow.scrollVertical("pages", 1 * (count || 1)); },
- function () mow.isScrollable(1), BEEP);
+ function () mow.canScroll(1), BEEP);
bind(["<Space>"], "Scroll down one page",
function ({ count }) { mow.scrollVertical("pages", 1 * (count || 1)); },
- function () mow.isScrollable(1), DROP);
+ function () mow.canScroll(1), DROP);
bind(["<C-u>"], "Scroll up half a page",
function ({ count }) { mow.scrollVertical("pages", -.5 * (count || 1)); },
- function () mow.isScrollable(-1), BEEP);
+ function () mow.canScroll(-1), BEEP);
bind(["<C-b>", "<PageUp>"], "Scroll up half a page",
function ({ count }) { mow.scrollVertical("pages", -1 * (count || 1)); },
- function () mow.isScrollable(-1), BEEP);
+ function () mow.canScroll(-1), BEEP);
bind(["gg"], "Scroll to the beginning of output",
function () { mow.scrollToPercent(null, 0); });
// copy text to clipboard
bind(["<C-y>"], "Yank selection to clipboard",
- function () { dactyl.clipboardWrite(buffer.getCurrentWord(mow.window)); });
+ function () { dactyl.clipboardWrite(Buffer.currentWord(mow.window)); });
// close the window
bind(["q"], "Close the output window",
"boolean", true);
}
});
+
+// vim: set fdm=marker sw=4 sts=4 ts=8 et: