From 41335adaae3cbcef469ac48d46c9ed28e4963e68 Mon Sep 17 00:00:00 2001
From: Kris Maglione
Date: Wed, 6 Oct 2010 10:34:28 -0400
Subject: [PATCH 01/16] Fix some major mode changing bugs. Closes issue #55.
--HG--
branch : mode-refactoring
---
common/content/buffer.js | 6 +-
common/content/commandline.js | 16 +--
common/content/dactyl.js | 4 +-
common/content/editor.js | 121 +++++++++++-----------
common/content/events.js | 187 +++++++++++++---------------------
common/content/modes.js | 149 +++++++++++++++++++--------
common/content/options.js | 30 ++++--
common/modules/util.jsm | 3 +-
8 files changed, 274 insertions(+), 242 deletions(-)
diff --git a/common/content/buffer.js b/common/content/buffer.js
index 7903bc2c..ef322e21 100644
--- a/common/content/buffer.js
+++ b/common/content/buffer.js
@@ -1532,11 +1532,7 @@ const Buffer = Module("buffer", {
mappings.add(myModes, ["i", ""],
"Start caret mode",
- function () {
- // setting this option notifies an observer which takes care of the
- // mode setting
- options.setPref("accessibility.browsewithcaret", true);
- });
+ function () { modes.push(modes.CARET); });
mappings.add(myModes, [""],
"Stop loading the current web page",
diff --git a/common/content/commandline.js b/common/content/commandline.js
index 95388bac..c2ddf9bd 100644
--- a/common/content/commandline.js
+++ b/common/content/commandline.js
@@ -441,7 +441,10 @@ const CommandLine = Module("commandline", {
*/
open: function open(prompt, cmd, extendedMode) {
modes.push(modes.COMMAND_LINE, this.currentExtendedMode, {
- leave: commandline.closure.leave
+ leave: function (params) {
+ if (params.pop)
+ commandline.leave();
+ }
});
this.currentExtendedMode = extendedMode || null;
@@ -689,13 +692,12 @@ const CommandLine = Module("commandline", {
};
modes.push(modes.COMMAND_LINE, modes.PROMPT | extra.extended, {
- leave: function (newMode) {
- commandline.leave(newMode);
+ enter: function (stack) { extra.enter && extra.enter(stack); },
+ leave: function (stack) {
+ commandline.leave(stack);
if (extra.leave)
- extra.leave(newMode);
- },
- restore: function (newMode) { extra.restore && extra.restore(newMode) },
- save: function (newMode) { extra.save && extra.save(newMode) }
+ extra.leave(stack);
+ }
});
this.currentExtendedMode = modes.PROMPT;
diff --git a/common/content/dactyl.js b/common/content/dactyl.js
index 73853241..1ea54a8d 100644
--- a/common/content/dactyl.js
+++ b/common/content/dactyl.js
@@ -162,7 +162,7 @@ const Dactyl = Module("dactyl", {
*
* @returns {string}
*/
- clipboardRead: function clipboardRead() {
+ clipboardRead: function clipboardRead(getClipboard) {
let str = null;
try {
@@ -171,7 +171,7 @@ const Dactyl = Module("dactyl", {
transferable.addDataFlavor("text/unicode");
- if (clipboard.supportsSelectionClipboard())
+ if (!getClipboard && clipboard.supportsSelectionClipboard())
clipboard.getData(transferable, clipboard.kSelectionClipboard);
else
clipboard.getData(transferable, clipboard.kGlobalClipboard);
diff --git a/common/content/editor.js b/common/content/editor.js
index ecaa2a58..02140809 100644
--- a/common/content/editor.js
+++ b/common/content/editor.js
@@ -16,30 +16,11 @@ const Editor = Module("editor", {
//
this._lastFindChar = null;
this._lastFindCharFunc = null;
-
- // Hack?
- dactyl.registerObserver("modeChange", function (oldMode, newMode, stack) {
- switch (oldMode[0]) {
- case modes.TEXTAREA:
- case modes.INSERT:
- editor.unselectText();
- break;
-
- case modes.VISUAL:
- if (newMode[0] == modes.CARET) {
- try { // clear any selection made; a simple if (selection) does not work
- let selection = window.content.getSelection();
- selection.collapseToStart();
- }
- catch (e) {}
- }
- else
- editor.unselectText();
- break;
- }
- });
},
+ get isCaret() modes.getStack(1).main === modes.CARET,
+ get isTextArea() modes.getStack(1).main === modes.TEXTAREA,
+
line: function () {
let line = 1;
let text = Editor.getEditor().value;
@@ -60,12 +41,15 @@ const Editor = Module("editor", {
return col;
},
- unselectText: function () {
+ unselectText: function (toEnd) {
let elem = dactyl.focus;
// A error occurs if the element has been removed when "elem.selectionStart" is executed.
try {
if (elem && elem.selectionEnd)
- elem.selectionEnd = elem.selectionStart;
+ if (toEnd)
+ elem.selectionStart = elem.selectionEnd;
+ else
+ elem.selectionEnd = elem.selectionStart;
}
catch (e) {}
},
@@ -75,7 +59,7 @@ const Editor = Module("editor", {
return text.substring(Editor.getEditor().selectionStart, Editor.getEditor().selectionEnd);
},
- pasteClipboard: function () {
+ pasteClipboard: function (clipboard, toStart) {
if (dactyl.has("WINNT")) {
this.executeCommand("cmd_paste");
return;
@@ -85,7 +69,7 @@ const Editor = Module("editor", {
let elem = dactyl.focus;
if (elem.setSelectionRange) {
- let text = dactyl.clipboardRead();
+ let text = dactyl.clipboardRead(clipboard);
if (!text)
return;
@@ -101,7 +85,7 @@ const Editor = Module("editor", {
let tempStr2 = text;
let tempStr3 = elem.value.substring(rangeEnd);
elem.value = tempStr1 + tempStr2 + tempStr3;
- elem.selectionStart = rangeStart + tempStr2.length;
+ elem.selectionStart = rangeStart + (toStart ? 0 : tempStr2.length);
elem.selectionEnd = elem.selectionStart;
elem.scrollTop = curTop;
@@ -153,7 +137,8 @@ const Editor = Module("editor", {
count--;
}
- modes.set(modes.VISUAL, modes.TEXTAREA);
+ if (modes.main != modes.VISUAL)
+ modes.push(modes.VISUAL);
switch (motion) {
case "j":
@@ -204,16 +189,16 @@ const Editor = Module("editor", {
switch (cmd) {
case "d":
this.executeCommand("cmd_delete", 1);
- // need to reset the mode as the visual selection changes it
- modes.main = modes.TEXTAREA;
+ modes.pop(modes.TEXTAREA);
break;
case "c":
this.executeCommand("cmd_delete", 1);
- modes.set(modes.INSERT, modes.TEXTAREA);
+ modes.pop(modes.TEXTAREA);
+ modes.push(modes.INSERT);
break;
case "y":
this.executeCommand("cmd_copy", 1);
- this.unselectText();
+ modes.pop(modes.TEXTAREA);
break;
default:
@@ -457,19 +442,37 @@ const Editor = Module("editor", {
if (hasCount)
extraInfo.count = true;
+ function caretExecute(arg, again) {
+ function fixSelection() {
+ sel.removeAllRanges();
+ sel.addRange(RangeFind.endpoint(
+ RangeFind.nodeRange(buffer.focusedFrame.document.documentElement),
+ true));
+ }
+
+ let controller = buffer.selectionController;
+ let sel = controller.getSelection(controller.SELECTION_NORMAL);
+ if (!sel.rangeCount) // Hack.
+ fixSelection();
+
+ try {
+ controller[caretModeMethod](caretModeArg, arg);
+ }
+ catch (e) {
+ dactyl.assert(again && e.result === Cr.NS_ERROR_FAILURE);
+ fixSelection();
+ caretExecute(arg, false);
+ }
+ return false;
+ }
+
mappings.add([modes.CARET], keys, "",
function (count) {
if (typeof count != "number" || count < 1)
count = 1;
- let controller = buffer.selectionController;
- let sel = controller.getSelection(controller.SELECTION_NORMAL);
- if (!sel.rangeCount) // Hack.
- sel.addRange(RangeFind.endpoint(
- RangeFind.nodeRange(buffer.focusedFrame.document.documentElement),
- true));
while (count--)
- controller[caretModeMethod](caretModeArg, false);
+ caretExecute(false, true);
},
extraInfo);
@@ -479,15 +482,15 @@ const Editor = Module("editor", {
count = 1;
let controller = buffer.selectionController;
- while (count--) {
- if (modes.extended & modes.TEXTAREA) {
+ while (count-- && modes.main == modes.VISUAL) {
+ if (editor.isTextArea) {
if (typeof visualTextareaCommand == "function")
visualTextareaCommand();
else
editor.executeCommand(visualTextareaCommand);
}
else
- controller[caretModeMethod](caretModeArg, true);
+ caretExecute(true, true);
}
},
extraInfo);
@@ -508,7 +511,7 @@ const Editor = Module("editor", {
function (count) {
commands.forEach(function (cmd)
editor.executeCommand(cmd, 1));
- modes.set(modes.INSERT, modes.TEXTAREA);
+ modes.push(modes.INSERT);
});
}
@@ -608,7 +611,7 @@ const Editor = Module("editor", {
mappings.add([modes.INSERT],
[""], "Edit text field in Vi mode",
- function () { dactyl.mode = modes.TEXTAREA; });
+ function () { modes.push(modes.TEXTAREA); });
mappings.add([modes.INSERT],
["", ""], "Expand insert mode abbreviation",
@@ -628,7 +631,7 @@ const Editor = Module("editor", {
["u"], "Undo",
function (count) {
editor.executeCommand("cmd_undo", count);
- dactyl.mode = modes.TEXTAREA;
+ editor.unselectText();
},
{ count: true });
@@ -636,7 +639,7 @@ const Editor = Module("editor", {
[""], "Redo",
function (count) {
editor.executeCommand("cmd_redo", count);
- dactyl.mode = modes.TEXTAREA;
+ editor.unselectText();
},
{ count: true });
@@ -648,7 +651,7 @@ const Editor = Module("editor", {
["o"], "Open line below current",
function (count) {
editor.executeCommand("cmd_endLine", 1);
- modes.set(modes.INSERT, modes.TEXTAREA);
+ modes.push(modes.INSERT);
events.feedkeys("");
});
@@ -656,7 +659,7 @@ const Editor = Module("editor", {
["O"], "Open line above current",
function (count) {
editor.executeCommand("cmd_beginLine", 1);
- modes.set(modes.INSERT, modes.TEXTAREA);
+ modes.push(modes.INSERT);
events.feedkeys("");
editor.executeCommand("cmd_linePrevious", 1);
});
@@ -674,7 +677,7 @@ const Editor = Module("editor", {
// visual mode
mappings.add([modes.CARET, modes.TEXTAREA],
["v"], "Start visual mode",
- function (count) { modes.set(modes.VISUAL, dactyl.mode); });
+ function (count) { modes.push(modes.VISUAL); });
mappings.add([modes.VISUAL],
["v"], "End visual mode",
@@ -683,7 +686,7 @@ const Editor = Module("editor", {
mappings.add([modes.TEXTAREA],
["V"], "Start visual line mode",
function (count) {
- modes.set(modes.VISUAL, modes.TEXTAREA | modes.LINE);
+ modes.push(modes.VISUAL, modes.LINE);
editor.executeCommand("cmd_beginLine", 1);
editor.executeCommand("cmd_selectLineNext", 1);
});
@@ -691,17 +694,17 @@ const Editor = Module("editor", {
mappings.add([modes.VISUAL],
["c", "s"], "Change selected text",
function (count) {
- dactyl.assert(modes.extended & modes.TEXTAREA);
+ dactyl.assert(editor.isTextArea);
editor.executeCommand("cmd_cut");
- modes.set(modes.INSERT, modes.TEXTAREA);
+ modes.replace(modes.VISUAL);
});
mappings.add([modes.VISUAL],
["d"], "Delete selected text",
function (count) {
- if (modes.extended & modes.TEXTAREA) {
+ if (editor.isTextArea) {
editor.executeCommand("cmd_cut");
- modes.set(modes.TEXTAREA);
+ modes.pop();
}
else
dactyl.beep();
@@ -710,9 +713,9 @@ const Editor = Module("editor", {
mappings.add([modes.VISUAL],
["y"], "Yank selected text",
function (count) {
- if (modes.extended & modes.TEXTAREA) {
+ if (editor.isTextArea) {
editor.executeCommand("cmd_copy");
- modes.set(modes.TEXTAREA);
+ modes.pop();
}
else
dactyl.clipboardWrite(buffer.getCurrentWord(), true);
@@ -721,12 +724,12 @@ const Editor = Module("editor", {
mappings.add([modes.VISUAL, modes.TEXTAREA],
["p"], "Paste clipboard contents",
function (count) {
- dactyl.assert(!(modes.extended & modes.CARET));
+ dactyl.assert(!editor.isCaret);
if (!count)
count = 1;
while (count--)
editor.executeCommand("cmd_paste");
- dactyl.mode = modes.TEXTAREA;
+ modes.pop(modes.TEXTAREA);
});
// finding characters
@@ -786,7 +789,7 @@ const Editor = Module("editor", {
text.substring(pos + 1);
editor.moveToPosition(pos + 1, true, false);
}
- modes.set(modes.TEXTAREA);
+ modes.pop(modes.TEXTAREA);
},
{ count: true });
},
diff --git a/common/content/events.js b/common/content/events.js
index 26607990..05cdd7bf 100644
--- a/common/content/events.js
+++ b/common/content/events.js
@@ -76,11 +76,11 @@ const Events = Module("events", {
this._activeMenubar = false;
this.addSessionListener(window, "DOMMenuBarActive", this.closure.onDOMMenuBarActive, true);
this.addSessionListener(window, "DOMMenuBarInactive", this.closure.onDOMMenuBarInactive, true);
- this.addSessionListener(window, "focus", this.wrapListener(this.closure.onFocus), true);
- this.addSessionListener(window, "keydown", this.wrapListener(this.closure.onKeyUpOrDown), true);
- this.addSessionListener(window, "keypress", this.wrapListener(this.closure.onKeyPress), true);
- this.addSessionListener(window, "keyup", this.wrapListener(this.closure.onKeyUpOrDown), true);
- this.addSessionListener(window, "mousedown", this.wrapListener(this.closure.onMouseDown), true);
+ this.addSessionListener(window, "focus", this.wrapListener(this.onFocus), true);
+ this.addSessionListener(window, "keydown", this.wrapListener(this.onKeyUpOrDown), true);
+ this.addSessionListener(window, "keypress", this.wrapListener(this.onKeyPress), true);
+ this.addSessionListener(window, "keyup", this.wrapListener(this.onKeyUpOrDown), true);
+ this.addSessionListener(window, "mousedown", this.wrapListener(this.onMouseDown), true);
this.addSessionListener(window, "popuphidden", this.closure.onPopupHidden, true);
this.addSessionListener(window, "popupshown", this.closure.onPopupShown, true);
this.addSessionListener(window, "resize", this.closure.onResize, true);
@@ -90,7 +90,8 @@ const Events = Module("events", {
destroy: function () {
util.dump("Removing all event listeners");
for (let args in values(this.sessionListeners))
- args[0].removeEventListener.apply(args[0], args.slice(1));
+ if (args[0].get())
+ args[0].get().removeEventListener.apply(args[0].get(), args.slice(1));
},
/**
@@ -105,7 +106,8 @@ const Events = Module("events", {
*/
addSessionListener: function (target, event, callback, capture) {
let args = Array.slice(arguments, 0);
- target.addEventListener.apply(args[0], args.slice(1));
+ args[0].addEventListener.apply(args[0], args.slice(1));
+ args[0] = Cu.getWeakReference(args[0]);
this.sessionListeners.push(args);
},
@@ -113,6 +115,7 @@ const Events = Module("events", {
* Wraps an event listener to ensure that errors are reported.
*/
wrapListener: function wrapListener(method, self) {
+ self = self || this;
return function (event) {
try {
method.apply(self, arguments);
@@ -625,69 +628,17 @@ const Events = Module("events", {
* The global escape key handler. This is called in ALL modes.
*/
onEscape: function () {
- if (modes.passNextKey)
- return;
-
- if (modes.passAllKeys) {
- modes.passAllKeys = false;
- return;
- }
-
switch (dactyl.mode) {
- case modes.NORMAL:
- // clear any selection made
- let selection = window.content.getSelection();
- try { // a simple if (selection) does not seem to work
- selection.collapseToStart();
- }
- catch (e) {}
-
- modes.reset();
- break;
-
- case modes.VISUAL:
- if (modes.extended & modes.TEXTAREA)
- dactyl.mode = modes.TEXTAREA;
- else if (modes.extended & modes.CARET)
- dactyl.mode = modes.CARET;
- break;
-
- case modes.CARET:
- // setting this option will trigger an observer which will
- // take care of all other details like setting the NORMAL
- // mode
- options.setPref("accessibility.browsewithcaret", false);
- break;
-
- case modes.TEXTAREA:
- // TODO: different behaviour for text areas and other input
- // fields seems unnecessarily complicated. If the user
- // likes Vi-mode then they probably like it for all input
- // fields, if not they can enter it explicitly for only
- // text areas. The mode name TEXTAREA is confusing and
- // would be better replaced with something indicating that
- // it's a Vi editing mode. Extended modes really need to be
- // displayed too. --djk
- function isInputField() {
- let elem = dactyl.focus;
- return elem instanceof HTMLInputElement && set.has(Events.editableInputs, elem.type)
- || elem instanceof HTMLIsIndexElement;
- }
-
- if (options["insertmode"] || isInputField())
- dactyl.mode = modes.INSERT;
- else
- modes.reset();
- break;
-
+ case modes.COMMAND_LINE:
case modes.INSERT:
- if ((modes.extended & modes.TEXTAREA))
- dactyl.mode = modes.TEXTAREA;
- else
- modes.reset();
+ case modes.PASS_THROUGH:
+ case modes.QUOTE:
+ case modes.TEXTAREA:
+ case modes.VISUAL:
+ modes.pop();
break;
- default: // HINTS, CUSTOM or COMMAND_LINE
+ default:
modes.reset();
break;
}
@@ -752,12 +703,15 @@ const Events = Module("events", {
}
if (elem instanceof HTMLTextAreaElement || (elem && util.computedStyle(elem).MozUserModify == "read-write")) {
+ if (modes.main === modes.VISUAL && elem.selectionEnd == elem.selectionStart)
+ modes.pop();
if (options["insertmode"])
modes.set(modes.INSERT);
- else if (elem.selectionEnd - elem.selectionStart > 0)
- modes.set(modes.VISUAL, modes.TEXTAREA);
- else
- modes.main = modes.TEXTAREA;
+ else {
+ modes.set(modes.TEXTAREA);
+ if (elem.selectionEnd - elem.selectionStart > 0)
+ modes.push(modes.VISUAL);
+ }
if (hasHTMLDocument(win))
buffer.lastInputField = elem;
return;
@@ -772,7 +726,7 @@ const Events = Module("events", {
if (elem == null && urlbar && urlbar.inputField == this._lastFocus)
util.threadYield(true);
- if (dactyl.mode & (modes.EMBED | modes.INSERT | modes.TEXTAREA | modes.VISUAL))
+ if (modes.getMode(modes.main).ownsFocus)
modes.reset();
}
finally {
@@ -784,7 +738,7 @@ const Events = Module("events", {
// the commandline has focus
// TODO: ...help me...please...
onKeyPress: function (event) {
- function isEscapeKey(key) key == "" || key == "";
+ function isEscape(key) key == "" || key == "";
function killEvent() {
event.preventDefault();
@@ -802,7 +756,7 @@ const Events = Module("events", {
dactyl.echomsg("Recorded macro '" + this._currentMacro + "'");
return killEvent();
}
- else if (!mappings.hasMap(dactyl.mode, this._input.buffer + key))
+ else if (!mappings.hasMap(mode, this._input.buffer + key))
this._macros.set(this._currentMacro, {
keys: this._macros.get(this._currentMacro, {}).keys + key,
timeRecorded: Date.now()
@@ -832,6 +786,7 @@ const Events = Module("events", {
try {
let stop = false;
+ let mode = modes.main;
let win = document.commandDispatcher.focusedWindow;
if (win && win.document && "designMode" in win.document && win.document.designMode == "on" && !config.isComposeWindow)
@@ -839,20 +794,19 @@ const Events = Module("events", {
// menus have their own command handlers
if (modes.extended & modes.MENU)
stop = true;
+ else if (modes.main == modes.PASS_THROUGH)
+ // let flow continue to handle these keys to cancel escape-all-keys mode
+ stop = !isEscape(key) && key != ""
// handle Escape-one-key mode (Ctrl-v)
- else if (modes.passNextKey && !modes.passAllKeys) {
- modes.passNextKey = false;
- stop = true;
+ else if (modes.main == modes.QUOTE) {
+ stop = modes.getStack(1).main !== modes.PASS_THROUGH || isEscape(key);
+ // We need to preserve QUOTE mode until the escape
+ // handler to escape the key
+ if (!stop || !isEscape(key))
+ modes.pop();
+ mode = modes.getStack(1).main;
}
// handle Escape-all-keys mode (Ctrl-q)
- else if (modes.passAllKeys) {
- if (modes.passNextKey)
- modes.passNextKey = false; // and then let flow continue
- else if (isEscapeKey(key) || key == "")
- ; // let flow continue to handle these keys to cancel escape-all-keys mode
- else
- stop = true;
- }
if (stop) {
this._input.buffer = "";
@@ -862,7 +816,7 @@ const Events = Module("events", {
stop = true; // set to false if we should NOT consume this event but let the host app handle it
// just forward event without checking any mappings when the MOW is open
- if (dactyl.mode == modes.COMMAND_LINE && (modes.extended & modes.OUTPUT_MULTILINE)) {
+ if (mode == modes.COMMAND_LINE && (modes.extended & modes.OUTPUT_MULTILINE)) {
commandline.onMultilineOutputEvent(event);
return killEvent();
}
@@ -871,16 +825,16 @@ const Events = Module("events", {
// they are without beeping also fixes key navigation in combo
// boxes, submitting forms, etc.
// FIXME: breaks iabbr for now --mst
- if (key in config.ignoreKeys && (config.ignoreKeys[key] & dactyl.mode)) {
+ if (key in config.ignoreKeys && (config.ignoreKeys[key] & mode)) {
this._input.buffer = "";
return null;
}
// TODO: handle middle click in content area
- if (!isEscapeKey(key)) {
+ if (!isEscape(key)) {
// custom mode...
- if (dactyl.mode == modes.CUSTOM) {
+ if (mode == modes.CUSTOM) {
plugins.onEvent(event);
return killEvent();
}
@@ -910,15 +864,17 @@ const Events = Module("events", {
// whatever reason). if that happens to be correct, well..
// XXX: why not just do that as well for HINTS mode actually?
- if (dactyl.mode == modes.CUSTOM)
+ if (mode == modes.CUSTOM)
return null;
+ let mainMode = modes.getMode(mode);
+
let inputStr = this._input.buffer + key;
let countStr = inputStr.match(/^[1-9][0-9]*|/)[0];
let candidateCommand = inputStr.substr(countStr.length);
- let map = mappings[event.noremap ? "getDefault" : "get"](dactyl.mode, candidateCommand);
+ let map = mappings[event.noremap ? "getDefault" : "get"](mode, candidateCommand);
- let candidates = mappings.getCandidates(dactyl.mode, candidateCommand);
+ let candidates = mappings.getCandidates(mode, candidateCommand);
if (candidates.length == 0 && !map) {
map = this._input.pendingMap;
this._input.pendingMap = null;
@@ -929,7 +885,7 @@ const Events = Module("events", {
// counts must be at the start of a complete mapping (10j -> go 10 lines down)
if (countStr && !candidateCommand) {
// no count for insert mode mappings
- if (!modes.mainMode.count || modes.mainMode.input)
+ if (!mainMode.count || mainMode.input)
stop = false;
else
this._input.buffer = inputStr;
@@ -938,7 +894,7 @@ const Events = Module("events", {
this._input.buffer = "";
let map = this._input.pendingArgMap;
this._input.pendingArgMap = null;
- if (!isEscapeKey(key)) {
+ if (!isEscape(key)) {
if (modes.isReplaying && !this.waitForPageLoad())
return null;
map.execute(null, this._input.count, key);
@@ -957,7 +913,7 @@ const Events = Module("events", {
this._input.pendingArgMap = map;
}
else if (this._input.pendingMotionMap) {
- if (!isEscapeKey(key))
+ if (!isEscape(key))
this._input.pendingMotionMap.execute(candidateCommand, this._input.count, null);
this._input.pendingMotionMap = null;
}
@@ -974,14 +930,14 @@ const Events = Module("events", {
stop = false;
}
}
- else if (mappings.getCandidates(dactyl.mode, candidateCommand).length > 0 && !event.skipmap) {
+ else if (mappings.getCandidates(mode, candidateCommand).length > 0 && !event.skipmap) {
this._input.pendingMap = map;
this._input.buffer += key;
}
else { // if the key is neither a mapping nor the start of one
// the mode checking is necessary so that things like g do not beep
if (this._input.buffer != "" && !event.skipmap &&
- (dactyl.mode & (modes.INSERT | modes.COMMAND_LINE | modes.TEXTAREA)))
+ (mode & (modes.INSERT | modes.COMMAND_LINE | modes.TEXTAREA)))
events.feedkeys(this._input.buffer, { noremap: true, skipmap: true });
this._input.buffer = "";
@@ -989,17 +945,17 @@ const Events = Module("events", {
this._input.pendingMotionMap = null;
this._input.pendingMap = null;
- if (!isEscapeKey(key)) {
+ if (!isEscape(key)) {
// allow key to be passed to the host app if we can't handle it
- stop = (dactyl.mode == modes.TEXTAREA);
+ stop = (mode == modes.TEXTAREA);
- if (dactyl.mode == modes.COMMAND_LINE) {
+ if (mode == modes.COMMAND_LINE) {
if (!(modes.extended & modes.INPUT_MULTILINE))
dactyl.trapErrors(function () {
commandline.onEvent(event); // reroute event in command line mode
});
}
- else if (!modes.mainMode.input)
+ else if (!mainMode.input)
dactyl.beep();
}
}
@@ -1019,9 +975,8 @@ const Events = Module("events", {
// this is need for sites like msn.com which focus the input field on keydown
onKeyUpOrDown: function (event) {
- if (modes.passNextKey ^ modes.passAllKeys || Events.isInputElemFocused())
- return;
- event.stopPropagation();
+ if (!Events.isInputElemFocused() && !modes.passThrough)
+ event.stopPropagation();
},
onMouseDown: function (event) {
@@ -1052,20 +1007,18 @@ const Events = Module("events", {
},
onSelectionChange: function (event) {
- let couldCopy = false;
let controller = document.commandDispatcher.getControllerForCommand("cmd_copy");
- if (controller && controller.isCommandEnabled("cmd_copy"))
- couldCopy = true;
+ let couldCopy = controller && controller.isCommandEnabled("cmd_copy");
- if (dactyl.mode != modes.VISUAL) {
- if (couldCopy) {
- if ((dactyl.mode == modes.TEXTAREA ||
- (modes.extended & modes.TEXTAREA))
- && !options["insertmode"])
- modes.set(modes.VISUAL, modes.TEXTAREA);
- else if (dactyl.mode == modes.CARET)
- modes.set(modes.VISUAL, modes.CARET);
- }
+ if (dactyl.mode === modes.VISUAL) {
+ if (!couldCopy)
+ modes.pop(); // Really not ideal.
+ }
+ else if (couldCopy) {
+ if (modes.main == modes.TEXTAREA && !options["insertmode"])
+ modes.push(modes.VISUAL);
+ else if (dactyl.mode == modes.CARET)
+ modes.push(modes.VISUAL);
}
// XXX: disabled, as i think automatically starting visual caret mode does more harm than help
// else
@@ -1144,11 +1097,11 @@ const Events = Module("events", {
mappings.add(modes.all,
[""], "Temporarily ignore all " + config.appName + " key bindings",
- function () { modes.passAllKeys = true; });
+ function () { modes.push(modes.PASS_THROUGH); });
mappings.add(modes.all,
[""], "Pass through next key",
- function () { modes.passNextKey = true; });
+ function () { modes.push(modes.QUOTE); });
mappings.add(modes.all,
[""], "Do nothing",
diff --git a/common/content/modes.js b/common/content/modes.js
index 5b963da4..53b4e8b6 100644
--- a/common/content/modes.js
+++ b/common/content/modes.js
@@ -30,14 +30,42 @@ const Modes = Module("modes", {
this.boundProperties = {};
// main modes, only one should ever be active
- this.addMode("NORMAL", { char: "n", display: null });
- this.addMode("INSERT", { char: "i", input: true });
- this.addMode("VISUAL", { char: "v", display: function () "VISUAL" + (this._extended & modes.LINE ? " LINE" : "") });
+ this.addMode("NORMAL", { char: "n", display: function () null });
+ this.addMode("INSERT", { char: "i", input: true, ownsFocus: true });
+ this.addMode("VISUAL", { char: "v", ownsFocus: true, display: function () "VISUAL" + (this._extended & modes.LINE ? " LINE" : "") }, {
+ leave: function (stack, newMode) {
+ if (newMode.main == modes.CARET) {
+ let selection = window.content.getSelection();
+ if (selection && !selection.isCollapsed)
+ selection.collapseToStart();
+ }
+ else
+ editor.unselectText();
+ }
+ });
this.addMode("COMMAND_LINE", { char: "c", input: true });
- this.addMode("CARET"); // text cursor is visible
- this.addMode("TEXTAREA", { char: "i" });
- this.addMode("EMBED", { input: true });
- this.addMode("CUSTOM", { display: function () plugins.mode });
+ this.addMode("CARET", {}, {
+ get pref() options.getPref("accessibility.browsewithcaret"),
+ set pref(val) options.setPref("accessibility.browsewithcaret", val),
+ enter: function (stack) {
+ if (stack.pop && !this.pref)
+ modes.pop();
+ else if (!stack.pop && !this.pref)
+ this.pref = true;
+ },
+ leave: function (stack) {
+ if (!stack.push && this.pref)
+ this.pref = false;
+ }
+ });
+ this.addMode("TEXTAREA", { char: "i", ownsFocus: true });
+ this.addMode("EMBED", { input: true, ownsFocus: true });
+ this.addMode("PASS_THROUGH");
+ this.addMode("QUOTE", {
+ display: function () modes.getStack(1).main == modes.PASS_THROUGH
+ ? (modes.getStack(2).mainMode.display() || modes.getStack(2).mainMode.name) + " (next)"
+ : "PASS THROUGH (next)"
+ });
// this._extended modes, can include multiple modes, and even main modes
this.addMode("EX", true);
this.addMode("HINTS", true);
@@ -45,30 +73,31 @@ const Modes = Module("modes", {
this.addMode("OUTPUT_MULTILINE", true);
this.addMode("SEARCH_FORWARD", true);
this.addMode("SEARCH_BACKWARD", true);
- this.addMode("SEARCH_VIEW_FORWARD", true);
- this.addMode("SEARCH_VIEW_BACKWARD", true);
this.addMode("MENU", true); // a popupmenu is active
this.addMode("LINE", true); // linewise visual mode
this.addMode("PROMPT", true);
this.push(this.NORMAL, 0, {
- restore: function (prev) {
- // disable caret mode when we want to switch to normal mode
+ enter: function (stack, prev) {
if (options.getPref("accessibility.browsewithcaret"))
options.setPref("accessibility.browsewithcaret", false);
statusline.updateUrl();
- dactyl.focusContent(true);
+ if (prev.mainMode.input || prev.mainMode.ownsFocus)
+ dactyl.focusContent(true);
+ if (prev.main === modes.NORMAL) {
+ dactyl.focusContent(true);
+ // clear any selection made
+ let selection = window.content.getSelection();
+ if (selection && !selection.isCollapsed)
+ selection.collapseToStart();
+ }
+
}
});
},
_getModeMessage: function () {
- if (this._passNextKey && !this._passAllKeys)
- return "-- PASS THROUGH (next) --";
- else if (this._passAllKeys && !this._passNextKey)
- return "-- PASS THROUGH --";
-
// when recording a macro
let macromode = "";
if (modes.isRecording)
@@ -81,7 +110,8 @@ const Modes = Module("modes", {
ext += " (menu)";
ext += " --" + macromode;
- if (this._main in this._modeMap && typeof this._modeMap[this._main].display == "function")
+ let val = this._modeMap[this._main].display();
+ if (val)
return "-- " + this._modeMap[this._main].display() + ext;
return macromode;
},
@@ -98,27 +128,31 @@ const Modes = Module("modes", {
get topOfStack() this._modeStack[this._modeStack.length - 1],
- addMode: function (name, extended, options) {
+ addMode: function (name, extended, options, params) {
let disp = name.replace("_", " ", "g");
this[name] = 1 << this._lastMode++;
+
if (typeof extended == "object") {
+ params = options;
options = extended;
extended = false;
}
+
let mode = util.extend({
- extended: extended,
count: true,
+ disp: disp,
+ extended: extended,
input: false,
mask: this[name],
name: name,
- disp: disp
+ params: params || {}
}, options);
if (mode.char) {
this.modeChars[mode.char] = this.modeChars[mode.char] || [];
this.modeChars[mode.char].push(mode);
}
- if (mode.display !== null)
+ if (mode.display == null)
mode.display = function () disp;
this._modeMap[name] = mode;
this._modeMap[this[name]] = mode;
@@ -129,6 +163,8 @@ const Modes = Module("modes", {
getMode: function (name) this._modeMap[name],
+ getStack: function (idx) this._modeStack[this._modeStack.length - idx - 1] || this._modeStack[0],
+
getCharModes: function (chr) [m for (m in values(this._modeMap)) if (m.char == chr)],
matchModes: function (obj)
@@ -158,7 +194,7 @@ const Modes = Module("modes", {
// helper function to set both modes in one go
// if silent == true, you also need to take care of the mode handling changes yourself
set: function (mainMode, extendedMode, params, stack) {
- params = params || {};
+ params = params || this.getMode(mainMode || this.main).params;
if (!stack && mainMode != null && this._modeStack.length > 1)
this.reset();
@@ -166,9 +202,8 @@ const Modes = Module("modes", {
let push = mainMode != null && !(stack && stack.pop) &&
Modes.StackElem(mainMode, extendedMode || this.NONE, params, {});
if (push && this.topOfStack) {
- if (this.topOfStack.params.save)
- this.topOfStack.params.save(push);
-
+ if (this.topOfStack.params.leave)
+ this.topOfStack.params.leave({ push: push }, push);
for (let [id, { obj, prop }] in Iterator(this.boundProperties)) {
if (!obj.get())
delete this.boundProperties(id);
@@ -189,8 +224,12 @@ const Modes = Module("modes", {
this._extended = this.NONE;
}
+ let prev = stack && stack.pop || this.topOfStack;
if (push)
this._modeStack.push(push);
+ if (this.topOfStack.params.enter && prev)
+ this.topOfStack.params.enter(push ? { push: push } : stack || {},
+ prev);
dactyl.triggerObserver("modeChange", [oldMain, oldExtended], [this._main, this._extended], stack);
@@ -202,22 +241,31 @@ const Modes = Module("modes", {
this.set(mainMode, extendedMode, params, { push: this.topOfStack });
},
- pop: function () {
- let a = this._modeStack.pop();
- if (a.params.leave)
- a.params.leave(this.topOfStack);
+ pop: function (mode) {
+ while (this._modeStack.length > 1 && this.main != mode) {
+ let a = this._modeStack.pop();
+ if (a.params.leave)
+ a.params.leave({ pop: a }, this.topOfStack);
- this.set(this.topOfStack.main, this.topOfStack.extended, this.topOfStack.params, { pop: a });
- if (this.topOfStack.params.restore)
- this.topOfStack.params.restore(a);
+ this.set(this.topOfStack.main, this.topOfStack.extended, this.topOfStack.params, { pop: a });
- for (let [k, { obj, prop, value }] in Iterator(this.topOfStack.saved))
- obj[prop] = value;
+ for (let [k, { obj, prop, value }] in Iterator(this.topOfStack.saved))
+ obj[prop] = value;
+
+ if (mode == null)
+ return;
+ }
+ },
+
+ replace: function (mode, oldMode) {
+ // TODO: This should really be done in one step.
+ this.pop(oldMode);
+ this.push(mode);
},
reset: function () {
- if (this._modeStack.length == 1 && this.topOfStack.params.restore)
- this.topOfStack.params.restore(this.topOfStack);
+ if (this._modeStack.length == 1 && this.topOfStack.params.enter)
+ this.topOfStack.params.enter({}, this.topOfStack);
while (this._modeStack.length > 1)
this.pop();
},
@@ -229,12 +277,6 @@ const Modes = Module("modes", {
}
},
- get passNextKey() this._passNextKey,
- set passNextKey(value) { this._passNextKey = value; this.show(); },
-
- get passAllKeys() this._passAllKeys,
- set passAllKeys(value) { this._passAllKeys = value; this.show(); },
-
get isRecording() this._isRecording,
set isRecording(value) { this._isRecording = value; this.show(); },
@@ -247,7 +289,17 @@ const Modes = Module("modes", {
get extended() this._extended,
set extended(value) { this.set(null, value); }
}, {
- StackElem: Struct("main", "extended", "params", "saved"),
+ StackElem: (function () {
+ let struct = Struct("main", "extended", "params", "saved");
+ struct.prototype.__defineGetter__("mainMode", function () modes.getMode(this.main));
+ struct.prototype.toString = function () !loaded.modes ? this.main : "[mode " +
+ modes.getMode(this.main).name +
+ (!this.extended ? "" :
+ "(" +
+ [modes.getMode(1<
Date: Wed, 6 Oct 2010 23:28:42 -0400
Subject: [PATCH 02/16] Use JSON.parse rather than eval to parse strings.
--HG--
branch : mode-refactoring
---
common/content/commands.js | 2 +-
common/content/javascript.js | 4 +---
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/common/content/commands.js b/common/content/commands.js
index ecb8751d..014fa7fd 100644
--- a/common/content/commands.js
+++ b/common/content/commands.js
@@ -917,7 +917,7 @@ const Commands = Module("commands", {
if ((res = re2.exec(str)))
arg += keepQuotes ? res[0] : res[2].replace(/\\(.)/g, "$1");
else if ((res = /^(")((?:[^\\"]|\\.)*)("?)/.exec(str)))
- arg += keepQuotes ? res[0] : window.eval(res[0] + (res[3] ? "" : '"'));
+ arg += keepQuotes ? res[0] : JSON.parse(res[0] + (res[3] ? "" : '"'));
else if ((res = /^(')((?:[^']|'')*)('?)/.exec(str)))
arg += keepQuotes ? res[0] : res[2].replace("''", "'", "g");
else
diff --git a/common/content/javascript.js b/common/content/javascript.js
index 8c6c492f..c5c6cd19 100644
--- a/common/content/javascript.js
+++ b/common/content/javascript.js
@@ -478,9 +478,7 @@ const JavaScript = Module("javascript", {
// The top of the stack is the sting we're completing.
// Wrap it in its delimiters and eval it to process escape sequences.
let string = this._str.substring(this._get(-1).offset + 1, this._lastIdx);
- // This is definitely a properly quoted string.
- // Just eval it normally.
- string = window.eval(this._last + string + this._last);
+ string = JSON.parse(this._last + string + this._last);
// Is this an object accessor?
if (this._get(-2).char == "[") { // Are we inside of []?
From 248c906e9cd36ddc030e5f0ce71f1e10ccb5f098 Mon Sep 17 00:00:00 2001
From: Kris Maglione
Date: Thu, 7 Oct 2010 23:18:09 -0400
Subject: [PATCH 03/16] Some minor fixes, and add ctypes support to iter().
--HG--
branch : mode-refactoring
---
common/content/dactyl.js | 8 ++++----
common/content/io.js | 16 +++++++++-------
common/content/javascript.js | 23 ++++++++++++-----------
common/modules/base.jsm | 21 ++++++++++++++++++++-
4 files changed, 45 insertions(+), 23 deletions(-)
diff --git a/common/content/dactyl.js b/common/content/dactyl.js
index 1ea54a8d..fe375905 100644
--- a/common/content/dactyl.js
+++ b/common/content/dactyl.js
@@ -25,16 +25,16 @@ const FailedAssertion = Class("FailedAssertion", Error, {
}
});
-deprecated.seen = { "chrome://dactyl/content/javascript.js": true };
-function deprecated(reason, fn)
+function deprecated(reason, fn) update(
function deprecatedMethod() {
let frame = Components.stack.caller;
- if (!set.add(deprecated.seen, frame.filename))
+ if (!set.add(deprecatedMethod.seen, frame.filename))
dactyl.echoerr(frame.filename + ":" + frame.lineNumber + ": " +
(this.className || this.constructor.className) + "." + fn.name +
" is deprecated: " + reason);
return fn.apply(this, arguments);
- }
+ },
+ { seen: { "chrome://dactyl/content/javascript.js": true } });
const Dactyl = Module("dactyl", {
init: function () {
diff --git a/common/content/io.js b/common/content/io.js
index 6660ecac..efab3aa7 100644
--- a/common/content/io.js
+++ b/common/content/io.js
@@ -345,13 +345,15 @@ lookup:
dactyl.helpInitialized = false;
}
catch (e) {
- if (isString(e))
- e = { message: e };
- let err = new Error();
- for (let [k, v] in Iterator(e))
- err[k] = v;
- err.echoerr = <>{file.path}:{e.lineNumber}: {e}>;
- throw err;
+ if (e.fileName)
+ try {
+ e.fileName = e.fileName.replace(/^(chrome|resource):.*? -> /, "");
+ if (e.fileName == uri.spec)
+ e.fileName = filename;
+ e.echoerr = <>{e.fileName}:{e.lineNumber}: {e}>
+ }
+ catch (e) {}
+ throw e;
}
}
else if (/\.css$/.test(filename))
diff --git a/common/content/javascript.js b/common/content/javascript.js
index c5c6cd19..c0d30380 100644
--- a/common/content/javascript.js
+++ b/common/content/javascript.js
@@ -358,8 +358,6 @@ const JavaScript = Module("javascript", {
}
let args = {
- completer: compl,
- anchored: true,
filter: last == null ? key : string,
last: last,
prefix: last != null ? key : ""
@@ -369,39 +367,42 @@ const JavaScript = Module("javascript", {
// TODO: Make this a generic completion helper function.
for (let [, obj] in Iterator(objects))
this.context.fork(obj[1], this._top.offset, this, this._fill,
- update({}, args, {
+ update({
obj: obj[0],
- name: obj[1]
- }));
+ name: obj[1],
+ anchored: true,
+ completer: compl
+ }, args));
if (orig)
return;
for (let [, obj] in Iterator(objects))
this.context.fork(obj[1] + "/prototypes", this._top.offset, this, this._fill,
- update({}, args, {
+ update({
obj: obj[0],
name: obj[1] + " (prototypes)",
+ anchored: true,
completer: function (a, b) compl(a, b, true)
- }));
+ }, args));
for (let [, obj] in Iterator(objects))
this.context.fork(obj[1] + "/substrings", this._top.offset, this, this._fill,
- update({}, args, {
+ update({
obj: obj[0],
name: obj[1] + " (substrings)",
anchored: false,
completer: compl
- }));
+ }, args));
for (let [, obj] in Iterator(objects))
this.context.fork(obj[1] + "/prototypes/substrings", this._top.offset, this, this._fill,
- update({}, args, {
+ update({
obj: obj[0],
name: obj[1] + " (prototype substrings)",
anchored: false,
completer: function (a, b) compl(a, b, true)
- }));
+ }, args));
},
_getKey: function () {
diff --git a/common/modules/base.jsm b/common/modules/base.jsm
index 33635641..9b360ba8 100644
--- a/common/modules/base.jsm
+++ b/common/modules/base.jsm
@@ -10,6 +10,11 @@ const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+try {
+ var ctypes;
+ Components.utils.import("resource://gre/modules/ctypes.jsm");
+}
+catch (e) {}
let objproto = Object.prototype;
let hasOwnProperty = objproto.hasOwnProperty;
@@ -149,7 +154,7 @@ defineModule("base", {
exports: [
"Cc", "Ci", "Class", "Cr", "Cu", "Module", "Object", "Runnable",
"Struct", "StructBase", "Timer", "UTF8", "XPCOM", "XPCOMUtils", "array",
- "call", "callable", "curry", "debuggerProperties", "defineModule",
+ "call", "callable", "ctypes", "curry", "debuggerProperties", "defineModule",
"endModule", "forEach", "isArray", "isGenerator", "isinstance",
"isObject", "isString", "isSubclass", "iter", "iterAll", "keys",
"memoize", "properties", "requiresMainThread", "set", "update", "values"
@@ -356,6 +361,20 @@ set.remove = function (set, key) {
* @returns {Generator}
*/
function iter(obj) {
+ if (ctypes && obj instanceof ctypes.CData) {
+ while (obj.constructor instanceof ctypes.PointerType)
+ obj = obj.contents;
+ if (obj.constructor instanceof ctypes.ArrayType)
+ return array.iterItems(obj);
+ if (obj.constructor instanceof ctypes.StructType)
+ return (function () {
+ for (let prop in values(obj.constructor.fields))
+ let ([name, type] = Iterator(prop).next()) {
+ yield [name, obj[name]];
+ }
+ })();
+ obj = {};
+ }
if (isinstance(obj, [Ci.nsIDOMHTMLCollection, Ci.nsIDOMNodeList]))
return array.iterItems(obj);
if (obj instanceof Ci.nsIDOMNamedNodeMap)
From 301a8e53779f08274ee46355316982a499d85fe8 Mon Sep 17 00:00:00 2001
From: Kris Maglione
Date: Thu, 7 Oct 2010 23:35:53 -0400
Subject: [PATCH 04/16] Just use with (window) in userEval. Adding it to the
prototype chain causes too much trouble.
--HG--
branch : mode-refactoring
---
common/content/dactyl-overlay.js | 3 ++-
common/content/dactyl.js | 3 +--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/common/content/dactyl-overlay.js b/common/content/dactyl-overlay.js
index 93b054b1..676a403d 100644
--- a/common/content/dactyl-overlay.js
+++ b/common/content/dactyl-overlay.js
@@ -18,7 +18,8 @@
__proto__: jsmodules,
get content() window.content,
jsmodules: jsmodules,
- newContext: newContext
+ newContext: newContext,
+ window: window
};
modules.modules = modules;
diff --git a/common/content/dactyl.js b/common/content/dactyl.js
index fe375905..d089724d 100644
--- a/common/content/dactyl.js
+++ b/common/content/dactyl.js
@@ -294,7 +294,7 @@ const Dactyl = Module("dactyl", {
if (!context)
context = userContext;
- return Cu.evalInSandbox(str, context, "1.8", fileName, lineNumber);
+ return Cu.evalInSandbox("with (window) {" + str + "}", context, "1.8", fileName, lineNumber);
},
/**
@@ -1876,7 +1876,6 @@ const Dactyl = Module("dactyl", {
};
},
load: function () {
- jsmodules.__proto__ = window;
dactyl.triggerObserver("load");
dactyl.log("All modules loaded", 3);
From ce10a9af13ec6951dfe643df2c49cc22bce874e1 Mon Sep 17 00:00:00 2001
From: Doug Kearns
Date: Sat, 9 Oct 2010 02:05:00 +1100
Subject: [PATCH 05/16] Fix 'c' and 's' VISUAL mode mappings.
--HG--
branch : mode-refactoring
---
common/content/editor.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/content/editor.js b/common/content/editor.js
index 02140809..0244d5f9 100644
--- a/common/content/editor.js
+++ b/common/content/editor.js
@@ -696,7 +696,7 @@ const Editor = Module("editor", {
function (count) {
dactyl.assert(editor.isTextArea);
editor.executeCommand("cmd_cut");
- modes.replace(modes.VISUAL);
+ modes.replace(modes.INSERT, modes.TEXTAREA);
});
mappings.add([modes.VISUAL],
From c3f977cf74c8d510613cb671fee25e230d741b14 Mon Sep 17 00:00:00 2001
From: Doug Kearns
Date: Sat, 9 Oct 2010 04:18:59 +1100
Subject: [PATCH 06/16] Prevent endless TEXTAREA->INSERT->TEXTAREA mode
stacking.
--HG--
branch : mode-refactoring
---
common/content/editor.js | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/common/content/editor.js b/common/content/editor.js
index 0244d5f9..32052505 100644
--- a/common/content/editor.js
+++ b/common/content/editor.js
@@ -611,7 +611,12 @@ const Editor = Module("editor", {
mappings.add([modes.INSERT],
[""], "Edit text field in Vi mode",
- function () { modes.push(modes.TEXTAREA); });
+ function () {
+ if (!editor.isTextArea)
+ modes.push(modes.TEXTAREA);
+ else
+ dactyl.beep();
+ });
mappings.add([modes.INSERT],
["", ""], "Expand insert mode abbreviation",
From 0856343b4078cfd1f368e286f3099b38410e27cb Mon Sep 17 00:00:00 2001
From: Kris Maglione
Date: Fri, 8 Oct 2010 13:42:16 -0400
Subject: [PATCH 07/16] Rename TEXTAREA mode to TEXT EDIT mode, and move it
from :imap to :tmap.
--HG--
branch : mode-refactoring
---
common/content/editor.js | 82 ++++++++++++++++-----------------
common/content/events.js | 12 ++---
common/content/finder.js | 4 +-
common/content/modes.js | 2 +-
common/locale/en-US/index.xml | 2 +-
common/locale/en-US/insert.xml | 6 +--
common/locale/en-US/map.xml | 13 ++++++
common/locale/en-US/options.xml | 2 +-
common/modules/util.jsm | 2 +-
9 files changed, 69 insertions(+), 56 deletions(-)
diff --git a/common/content/editor.js b/common/content/editor.js
index 32052505..94347886 100644
--- a/common/content/editor.js
+++ b/common/content/editor.js
@@ -19,7 +19,7 @@ const Editor = Module("editor", {
},
get isCaret() modes.getStack(1).main === modes.CARET,
- get isTextArea() modes.getStack(1).main === modes.TEXTAREA,
+ get isTextEdit() modes.getStack(1).main === modes.TEXT_EDIT,
line: function () {
let line = 1;
@@ -189,16 +189,16 @@ const Editor = Module("editor", {
switch (cmd) {
case "d":
this.executeCommand("cmd_delete", 1);
- modes.pop(modes.TEXTAREA);
+ modes.pop(modes.TEXT_EDIT);
break;
case "c":
this.executeCommand("cmd_delete", 1);
- modes.pop(modes.TEXTAREA);
+ modes.pop(modes.TEXT_EDIT);
modes.push(modes.INSERT);
break;
case "y":
this.executeCommand("cmd_copy", 1);
- modes.pop(modes.TEXTAREA);
+ modes.pop(modes.TEXT_EDIT);
break;
default:
@@ -436,8 +436,8 @@ const Editor = Module("editor", {
mappings: function () {
var myModes = [modes.INSERT, modes.COMMAND_LINE];
- // add mappings for commands like h,j,k,l,etc. in CARET, VISUAL and TEXTAREA mode
- function addMovementMap(keys, hasCount, caretModeMethod, caretModeArg, textareaCommand, visualTextareaCommand) {
+ // add mappings for commands like h,j,k,l,etc. in CARET, VISUAL and TEXT_EDIT mode
+ function addMovementMap(keys, hasCount, caretModeMethod, caretModeArg, textEditCommand, visualTextEditCommand) {
let extraInfo = {};
if (hasCount)
extraInfo.count = true;
@@ -483,11 +483,11 @@ const Editor = Module("editor", {
let controller = buffer.selectionController;
while (count-- && modes.main == modes.VISUAL) {
- if (editor.isTextArea) {
- if (typeof visualTextareaCommand == "function")
- visualTextareaCommand();
+ if (editor.isTextEdit) {
+ if (typeof visualTextEditCommand == "function")
+ visualTextEditCommand();
else
- editor.executeCommand(visualTextareaCommand);
+ editor.executeCommand(visualTextEditCommand);
}
else
caretExecute(true, true);
@@ -495,19 +495,19 @@ const Editor = Module("editor", {
},
extraInfo);
- mappings.add([modes.TEXTAREA], keys, "",
+ mappings.add([modes.TEXT_EDIT], keys, "",
function (count) {
if (typeof count != "number" || count < 1)
count = 1;
- editor.executeCommand(textareaCommand, count);
+ editor.executeCommand(textEditCommand, count);
},
extraInfo);
}
- // add mappings for commands like i,a,s,c,etc. in TEXTAREA mode
+ // add mappings for commands like i,a,s,c,etc. in TEXT_EDIT mode
function addBeginInsertModeMap(keys, commands) {
- mappings.add([modes.TEXTAREA], keys, "",
+ mappings.add([modes.TEXT_EDIT], keys, "",
function (count) {
commands.forEach(function (cmd)
editor.executeCommand(cmd, 1));
@@ -516,7 +516,7 @@ const Editor = Module("editor", {
}
function addMotionMap(key) {
- mappings.add([modes.TEXTAREA], [key],
+ mappings.add([modes.TEXT_EDIT], [key],
"Motion command",
function (motion, count) { editor.executeCommandWithMotion(key, motion, count); },
{ count: true, motion: true });
@@ -532,7 +532,7 @@ const Editor = Module("editor", {
editor.executeCommand("cmd_selectLineNext");
}
- // KEYS COUNT CARET TEXTAREA VISUAL_TEXTAREA
+ // KEYS COUNT CARET TEXT_EDIT VISUAL_TEXT_EDIT
addMovementMap(["k", ""], true, "lineMove", false, "cmd_linePrevious", selectPreviousLine);
addMovementMap(["j", "", ""], true, "lineMove", true, "cmd_lineNext", selectNextLine);
addMovementMap(["h", "", ""], true, "characterMove", false, "cmd_charPrevious", "cmd_selectCharPrevious");
@@ -612,8 +612,8 @@ const Editor = Module("editor", {
mappings.add([modes.INSERT],
[""], "Edit text field in Vi mode",
function () {
- if (!editor.isTextArea)
- modes.push(modes.TEXTAREA);
+ if (!editor.isTextEdit)
+ modes.push(modes.TEXT_EDIT);
else
dactyl.beep();
});
@@ -631,8 +631,8 @@ const Editor = Module("editor", {
["", ""], "Expand insert mode abbreviation",
function () { editor.expandAbbreviation(modes.INSERT); });
- // textarea mode
- mappings.add([modes.TEXTAREA],
+ // text edit mode
+ mappings.add([modes.TEXT_EDIT],
["u"], "Undo",
function (count) {
editor.executeCommand("cmd_undo", count);
@@ -640,7 +640,7 @@ const Editor = Module("editor", {
},
{ count: true });
- mappings.add([modes.TEXTAREA],
+ mappings.add([modes.TEXT_EDIT],
[""], "Redo",
function (count) {
editor.executeCommand("cmd_redo", count);
@@ -648,11 +648,11 @@ const Editor = Module("editor", {
},
{ count: true });
- mappings.add([modes.TEXTAREA],
+ mappings.add([modes.TEXT_EDIT],
["D"], "Delete the characters under the cursor until the end of the line",
function () { editor.executeCommand("cmd_deleteToEndOfLine"); });
- mappings.add([modes.TEXTAREA],
+ mappings.add([modes.TEXT_EDIT],
["o"], "Open line below current",
function (count) {
editor.executeCommand("cmd_endLine", 1);
@@ -660,7 +660,7 @@ const Editor = Module("editor", {
events.feedkeys("");
});
- mappings.add([modes.TEXTAREA],
+ mappings.add([modes.TEXT_EDIT],
["O"], "Open line above current",
function (count) {
editor.executeCommand("cmd_beginLine", 1);
@@ -669,18 +669,18 @@ const Editor = Module("editor", {
editor.executeCommand("cmd_linePrevious", 1);
});
- mappings.add([modes.TEXTAREA],
+ mappings.add([modes.TEXT_EDIT],
["X"], "Delete character to the left",
function (count) { editor.executeCommand("cmd_deleteCharBackward", count); },
{ count: true });
- mappings.add([modes.TEXTAREA],
+ mappings.add([modes.TEXT_EDIT],
["x"], "Delete character to the right",
function (count) { editor.executeCommand("cmd_deleteCharForward", count); },
{ count: true });
// visual mode
- mappings.add([modes.CARET, modes.TEXTAREA],
+ mappings.add([modes.CARET, modes.TEXT_EDIT],
["v"], "Start visual mode",
function (count) { modes.push(modes.VISUAL); });
@@ -688,7 +688,7 @@ const Editor = Module("editor", {
["v"], "End visual mode",
function (count) { events.onEscape(); });
- mappings.add([modes.TEXTAREA],
+ mappings.add([modes.TEXT_EDIT],
["V"], "Start visual line mode",
function (count) {
modes.push(modes.VISUAL, modes.LINE);
@@ -699,15 +699,15 @@ const Editor = Module("editor", {
mappings.add([modes.VISUAL],
["c", "s"], "Change selected text",
function (count) {
- dactyl.assert(editor.isTextArea);
+ dactyl.assert(editor.isTextEdit);
editor.executeCommand("cmd_cut");
- modes.replace(modes.INSERT, modes.TEXTAREA);
+ modes.replace(modes.INSERT, modes.TEXT_EDIT);
});
mappings.add([modes.VISUAL],
["d"], "Delete selected text",
function (count) {
- if (editor.isTextArea) {
+ if (editor.isTextEdit) {
editor.executeCommand("cmd_cut");
modes.pop();
}
@@ -718,7 +718,7 @@ const Editor = Module("editor", {
mappings.add([modes.VISUAL],
["y"], "Yank selected text",
function (count) {
- if (editor.isTextArea) {
+ if (editor.isTextEdit) {
editor.executeCommand("cmd_copy");
modes.pop();
}
@@ -726,7 +726,7 @@ const Editor = Module("editor", {
dactyl.clipboardWrite(buffer.getCurrentWord(), true);
});
- mappings.add([modes.VISUAL, modes.TEXTAREA],
+ mappings.add([modes.VISUAL, modes.TEXT_EDIT],
["p"], "Paste clipboard contents",
function (count) {
dactyl.assert(!editor.isCaret);
@@ -734,11 +734,11 @@ const Editor = Module("editor", {
count = 1;
while (count--)
editor.executeCommand("cmd_paste");
- modes.pop(modes.TEXTAREA);
+ modes.pop(modes.TEXT_EDIT);
});
// finding characters
- mappings.add([modes.TEXTAREA, modes.VISUAL],
+ mappings.add([modes.TEXT_EDIT, modes.VISUAL],
["f"], "Move to a character on the current line after the cursor",
function (count, arg) {
let pos = editor.findCharForward(arg, count);
@@ -747,7 +747,7 @@ const Editor = Module("editor", {
},
{ arg: true, count: true });
- mappings.add([modes.TEXTAREA, modes.VISUAL],
+ mappings.add([modes.TEXT_EDIT, modes.VISUAL],
["F"], "Move to a charater on the current line before the cursor",
function (count, arg) {
let pos = editor.findCharBackward(arg, count);
@@ -756,7 +756,7 @@ const Editor = Module("editor", {
},
{ arg: true, count: true });
- mappings.add([modes.TEXTAREA, modes.VISUAL],
+ mappings.add([modes.TEXT_EDIT, modes.VISUAL],
["t"], "Move before a character on the current line",
function (count, arg) {
let pos = editor.findCharForward(arg, count);
@@ -765,7 +765,7 @@ const Editor = Module("editor", {
},
{ arg: true, count: true });
- mappings.add([modes.TEXTAREA, modes.VISUAL],
+ mappings.add([modes.TEXT_EDIT, modes.VISUAL],
["T"], "Move before a character on the current line, backwards",
function (count, arg) {
let pos = editor.findCharBackward(arg, count);
@@ -774,8 +774,8 @@ const Editor = Module("editor", {
},
{ arg: true, count: true });
- // textarea and visual mode
- mappings.add([modes.TEXTAREA, modes.VISUAL],
+ // text edit and visual mode
+ mappings.add([modes.TEXT_EDIT, modes.VISUAL],
["~"], "Switch case of the character under the cursor and move the cursor to the right",
function (count) {
if (modes.main == modes.VISUAL)
@@ -794,7 +794,7 @@ const Editor = Module("editor", {
text.substring(pos + 1);
editor.moveToPosition(pos + 1, true, false);
}
- modes.pop(modes.TEXTAREA);
+ modes.pop(modes.TEXT_EDIT);
},
{ count: true });
},
diff --git a/common/content/events.js b/common/content/events.js
index 05cdd7bf..c69723d8 100644
--- a/common/content/events.js
+++ b/common/content/events.js
@@ -633,7 +633,7 @@ const Events = Module("events", {
case modes.INSERT:
case modes.PASS_THROUGH:
case modes.QUOTE:
- case modes.TEXTAREA:
+ case modes.TEXT_EDIT:
case modes.VISUAL:
modes.pop();
break;
@@ -708,7 +708,7 @@ const Events = Module("events", {
if (options["insertmode"])
modes.set(modes.INSERT);
else {
- modes.set(modes.TEXTAREA);
+ modes.set(modes.TEXT_EDIT);
if (elem.selectionEnd - elem.selectionStart > 0)
modes.push(modes.VISUAL);
}
@@ -937,7 +937,7 @@ const Events = Module("events", {
else { // if the key is neither a mapping nor the start of one
// the mode checking is necessary so that things like g do not beep
if (this._input.buffer != "" && !event.skipmap &&
- (mode & (modes.INSERT | modes.COMMAND_LINE | modes.TEXTAREA)))
+ (mode & (modes.INSERT | modes.COMMAND_LINE | modes.TEXT_EDIT)))
events.feedkeys(this._input.buffer, { noremap: true, skipmap: true });
this._input.buffer = "";
@@ -947,7 +947,7 @@ const Events = Module("events", {
if (!isEscape(key)) {
// allow key to be passed to the host app if we can't handle it
- stop = (mode == modes.TEXTAREA);
+ stop = (mode == modes.TEXT_EDIT);
if (mode == modes.COMMAND_LINE) {
if (!(modes.extended & modes.INPUT_MULTILINE))
@@ -1015,7 +1015,7 @@ const Events = Module("events", {
modes.pop(); // Really not ideal.
}
else if (couldCopy) {
- if (modes.main == modes.TEXTAREA && !options["insertmode"])
+ if (modes.main == modes.TEXT_EDIT && !options["insertmode"])
modes.push(modes.VISUAL);
else if (dactyl.mode == modes.CARET)
modes.push(modes.VISUAL);
@@ -1091,7 +1091,7 @@ const Events = Module("events", {
[""], "Advance keyboard focus",
function () { document.commandDispatcher.advanceFocus(); });
- mappings.add([modes.NORMAL, modes.PLAYER, modes.VISUAL, modes.CARET, modes.INSERT, modes.TEXTAREA],
+ mappings.add([modes.NORMAL, modes.PLAYER, modes.VISUAL, modes.CARET, modes.INSERT, modes.TEXT_EDIT],
[""], "Rewind keyboard focus",
function () { document.commandDispatcher.rewindFocus(); });
diff --git a/common/content/finder.js b/common/content/finder.js
index d3182b7e..c92ac86d 100644
--- a/common/content/finder.js
+++ b/common/content/finder.js
@@ -189,14 +189,14 @@ const RangeFinder = Module("rangefinder", {
["N"], "Find previous",
function () { rangefinder.findAgain(true); });
- mappings.add(myModes.concat([modes.CARET, modes.TEXTAREA]), ["*"],
+ mappings.add(myModes.concat([modes.CARET, modes.TEXT_EDIT]), ["*"],
"Find word under cursor",
function () {
rangefinder.find(buffer.getCurrentWord(), false);
rangefinder.findAgain();
});
- mappings.add(myModes.concat([modes.CARET, modes.TEXTAREA]), ["#"],
+ mappings.add(myModes.concat([modes.CARET, modes.TEXT_EDIT]), ["#"],
"Find word under cursor backwards",
function () {
rangefinder.find(buffer.getCurrentWord(), true);
diff --git a/common/content/modes.js b/common/content/modes.js
index 53b4e8b6..32521510 100644
--- a/common/content/modes.js
+++ b/common/content/modes.js
@@ -58,7 +58,7 @@ const Modes = Module("modes", {
this.pref = false;
}
});
- this.addMode("TEXTAREA", { char: "i", ownsFocus: true });
+ this.addMode("TEXT_EDIT", { char: "t", ownsFocus: true });
this.addMode("EMBED", { input: true, ownsFocus: true });
this.addMode("PASS_THROUGH");
this.addMode("QUOTE", {
diff --git a/common/locale/en-US/index.xml b/common/locale/en-US/index.xml
index c533535f..965fd886 100644
--- a/common/locale/en-US/index.xml
+++ b/common/locale/en-US/index.xml
@@ -18,7 +18,7 @@ This file contains a list of all available commands, mappings and options.
- i
- Start Insert mode in text areas when insertmode is not set
- Launch the external editor
- - Enter Textarea mode
+ - Enter TextEdit mode
- Expand an Insert-mode abbreviation
diff --git a/common/locale/en-US/insert.xml b/common/locale/en-US/insert.xml
index 7a7e1d7a..3ec7d65a 100644
--- a/common/locale/en-US/insert.xml
+++ b/common/locale/en-US/insert.xml
@@ -20,8 +20,8 @@
-
- i_i
- i_i
+ t_i
+ t_i
Starts Insert mode in text areas when insertmode is not set.
@@ -42,7 +42,7 @@
<C-t>
- Enter Textarea mode. This is useful for quick editing of text fields
+ Enter TextEdit mode. This is useful for quick editing of text fields
with basic Vim-keys support. See also insertmode.
diff --git a/common/locale/en-US/map.xml b/common/locale/en-US/map.xml
index a1c8a1b9..3382fbec 100644
--- a/common/locale/en-US/map.xml
+++ b/common/locale/en-US/map.xml
@@ -52,6 +52,7 @@
n Normal mode: When browsing normally
v Visual mode: When selecting text with the cursor keys
i Insert mode: When interacting with text fields on a website
+ t TextEdit mode: When editing text fields in Vim-like NORMAL mode
c Command-line mode: When typing into the &dactyl.appName; command line
@@ -82,6 +83,8 @@
:vmap lhs rhs
:im :imap
:imap lhs rhs
+ :tm :tmap
+ :tmap lhs rhs
:cm :cmap
:cmap lhs rhs
@@ -126,6 +129,8 @@
:vnoremap lhs rhs
:ino :inoremap
:inoremap lhs rhs
+ :tno :tnoremap
+ :tnoremap lhs rhs
:cno :cnoremap
:cnoremap lhs rhs
@@ -150,6 +155,8 @@
:vunmap lhs rhs
:iu :iunmap
:iunmap lhs rhs
+ :tu :tunmap
+ :tunmap lhs rhs
:cu :cunmap
:cunmap lhs rhs
@@ -166,6 +173,8 @@
:vmapclear
:imapc :imapclear
:imapclear
+ :tmapc :tmapclear
+ :tmapclear
:cmapc :cmapclear
:cmapclear
@@ -180,6 +189,7 @@
:nmap
:vmap
:imap
+ :tmap
:cmap
List all mappings for the applicable mode(s).
@@ -195,6 +205,8 @@
:vmap lhs
:imap_l
:imap lhs
+ :tmap_l
+ :tmap lhs
:cmap_l
:cmap lhs
@@ -224,6 +236,7 @@
:nmap :nnoremap :nunmap :nmapclear – Normal mode
:vmap :vnoremap :vunmap :vmapclear – Visual mode
:imap :inoremap :iunmap :imapclear – Insert mode
+:tmap :tnoremap :tunmap :tmapclear – TextArea mode
:cmap :cnoremap :cunmap :cmapclear – Command-line mode
diff --git a/common/locale/en-US/options.xml b/common/locale/en-US/options.xml
index e1f6a0f5..5cddc7c7 100644
--- a/common/locale/en-US/options.xml
+++ b/common/locale/en-US/options.xml
@@ -833,7 +833,7 @@
- Textarea mode can be entered with from Insert mode.
+ TextEdit mode can be entered with from Insert mode.
diff --git a/common/modules/util.jsm b/common/modules/util.jsm
index 14a43a59..3e8e7ffc 100644
--- a/common/modules/util.jsm
+++ b/common/modules/util.jsm
@@ -74,7 +74,7 @@ const Util = Module("Util", {
if (services.get("threadManager").isMainThread)
callback.call(self);
else
- mainThread.dispatch(Runnable(self, callback), mainThread.DISPATCH_NORMAL);
+ mainThread.dispatch(Runnable(self, callback, Array.slice(arguments, 2)), mainThread.DISPATCH_NORMAL);
},
/**
From 16f67b0d7dd9cae7f5b7ffd1cf25695ae51dafa0 Mon Sep 17 00:00:00 2001
From: Doug Kearns
Date: Sat, 9 Oct 2010 05:49:10 +1100
Subject: [PATCH 08/16] Fix some outdated TEXTAREA mode references.
--HG--
branch : mode-refactoring
---
common/locale/en-US/map.xml | 2 +-
teledactyl/content/config.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/common/locale/en-US/map.xml b/common/locale/en-US/map.xml
index 3382fbec..de3a9952 100644
--- a/common/locale/en-US/map.xml
+++ b/common/locale/en-US/map.xml
@@ -236,7 +236,7 @@
:nmap :nnoremap :nunmap :nmapclear – Normal mode
:vmap :vnoremap :vunmap :vmapclear – Visual mode
:imap :inoremap :iunmap :imapclear – Insert mode
-:tmap :tnoremap :tunmap :tmapclear – TextArea mode
+:tmap :tnoremap :tunmap :tmapclear – Text Edit mode
:cmap :cnoremap :cunmap :cmapclear – Command-line mode
diff --git a/teledactyl/content/config.js b/teledactyl/content/config.js
index d2183827..1711774c 100644
--- a/teledactyl/content/config.js
+++ b/teledactyl/content/config.js
@@ -62,7 +62,7 @@ const Config = Module("config", ConfigBase, {
// we switch to -- MESSAGE -- mode for Teledactyl when the main HTML widget gets focus
if (win && win.document instanceof HTMLDocument || dactyl.focus instanceof HTMLAnchorElement) {
if (config.isComposeWindow)
- modes.set(modes.INSERT, modes.TEXTAREA);
+ modes.set(modes.INSERT, modes.TEXT_EDIT);
else if (dactyl.mode != modes.MESSAGE)
dactyl.mode = modes.MESSAGE;
}
From 9295b36aad1aee730b766d83da9fd1bc9c5cff1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20N=C4=9Bmec?=
Date: Fri, 8 Oct 2010 21:34:01 +0200
Subject: [PATCH 09/16] Fix the help index to match docs updated during the
recent TextEdit frenzy.
--HG--
branch : mode-refactoring
---
common/locale/en-US/index.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/locale/en-US/index.xml b/common/locale/en-US/index.xml
index 965fd886..fb267897 100644
--- a/common/locale/en-US/index.xml
+++ b/common/locale/en-US/index.xml
@@ -16,7 +16,7 @@ This file contains a list of all available commands, mappings and options.
Insert mode
- - i
- Start Insert mode in text areas when insertmode is not set
+ - i
- Start Insert mode in text areas when insertmode is not set
- Launch the external editor
- Enter TextEdit mode
- Expand an Insert-mode abbreviation
From c05ad658954dfeec4da3e37a7cd0f8a768125490 Mon Sep 17 00:00:00 2001
From: Kris Maglione
Date: Fri, 8 Oct 2010 15:37:30 -0400
Subject: [PATCH 10/16] Remove spurious modes.reset() in RangeFinder#onSubmit.
Fixes focusing links on submit.
--HG--
branch : mode-refactoring
extra : rebase_source : 494ba7809803499905f135c4410f5e87af4417d6
---
common/content/dactyl-overlay.js | 2 +-
common/content/finder.js | 2 --
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/common/content/dactyl-overlay.js b/common/content/dactyl-overlay.js
index f764ef9d..676a403d 100644
--- a/common/content/dactyl-overlay.js
+++ b/common/content/dactyl-overlay.js
@@ -13,7 +13,7 @@
sandbox.__proto__ = proto || modules;
return sandbox;
}
- const jsmodules = { dump: function dump_(arg) window.dump("dactyl: " + arg + "\n") };
+ const jsmodules = {};
const modules = {
__proto__: jsmodules,
get content() window.content,
diff --git a/common/content/finder.js b/common/content/finder.js
index c92ac86d..0ef0dea0 100644
--- a/common/content/finder.js
+++ b/common/content/finder.js
@@ -114,8 +114,6 @@ const RangeFinder = Module("rangefinder", {
if (options["hlsearch"])
this.highlight();
this.rangeFind.focus();
-
- modes.reset();
},
// Called when the search is canceled - for example if someone presses
From 42d79460e2ce970f693b1b6824e185c8fb43a2fb Mon Sep 17 00:00:00 2001
From: Kris Maglione
Date: Fri, 8 Oct 2010 20:49:54 -0400
Subject: [PATCH 11/16] Change the timing of mode-change callbacks slightly.
Fix some message display bugs.
--HG--
branch : mode-refactoring
---
common/content/commandline.js | 3 +++
common/content/events.js | 6 ------
common/content/modes.js | 39 ++++++++++++++++-------------------
3 files changed, 21 insertions(+), 27 deletions(-)
diff --git a/common/content/commandline.js b/common/content/commandline.js
index c2ddf9bd..fb4a8cd7 100644
--- a/common/content/commandline.js
+++ b/common/content/commandline.js
@@ -440,6 +440,8 @@ const CommandLine = Module("commandline", {
* @param {number} extendedMode
*/
open: function open(prompt, cmd, extendedMode) {
+ this.widgets.message = null;
+
modes.push(modes.COMMAND_LINE, this.currentExtendedMode, {
leave: function (params) {
if (params.pop)
@@ -556,6 +558,7 @@ const CommandLine = Module("commandline", {
let doc = this.widgets.multilineOutput.contentDocument;
let win = this.widgets.multilineOutput.contentWindow;
+ this.widgets.message = null;
if (!this.commandVisible)
this.hide();
diff --git a/common/content/events.js b/common/content/events.js
index c69723d8..eca59980 100644
--- a/common/content/events.js
+++ b/common/content/events.js
@@ -1020,12 +1020,6 @@ const Events = Module("events", {
else if (dactyl.mode == modes.CARET)
modes.push(modes.VISUAL);
}
- // XXX: disabled, as i think automatically starting visual caret mode does more harm than help
- // else
- // {
- // if (!couldCopy && modes.extended & modes.CARET)
- // dactyl.mode = modes.CARET;
- // }
}
}, {
editableInputs: set(["date", "datetime", "datetime-local", "email", "file",
diff --git a/common/content/modes.js b/common/content/modes.js
index 32521510..ec78fca5 100644
--- a/common/content/modes.js
+++ b/common/content/modes.js
@@ -175,7 +175,8 @@ const Modes = Module("modes", {
let msg = null;
if (options["showmode"])
msg = this._getModeMessage();
- commandline.widgets.mode = msg || null;
+ if (loaded.commandline)
+ commandline.widgets.mode = msg || null;
},
// add/remove always work on the this._extended mode only
@@ -199,8 +200,21 @@ const Modes = Module("modes", {
if (!stack && mainMode != null && this._modeStack.length > 1)
this.reset();
+ let oldMain = this._main, oldExtended = this._extended;
+
+ if (typeof extendedMode === "number")
+ this._extended = extendedMode;
+ if (typeof mainMode === "number") {
+ this._main = mainMode;
+ if (!extendedMode)
+ this._extended = this.NONE;
+ }
+
+ if (stack && stack.pop && stack.pop.params.leave)
+ stack.pop.params.leave(stack, this.topOfStack);
+
let push = mainMode != null && !(stack && stack.pop) &&
- Modes.StackElem(mainMode, extendedMode || this.NONE, params, {});
+ Modes.StackElem(this._main, this._extended, params, {});
if (push && this.topOfStack) {
if (this.topOfStack.params.leave)
this.topOfStack.params.leave({ push: push }, push);
@@ -212,18 +226,6 @@ const Modes = Module("modes", {
}
}
- let silent = this._main === mainMode && this._extended === extendedMode;
- // if a this._main mode is set, the this._extended is always cleared
- let oldMain = this._main, oldExtended = this._extended;
-
- if (typeof extendedMode === "number")
- this._extended = extendedMode;
- if (typeof mainMode === "number") {
- this._main = mainMode;
- if (!extendedMode)
- this._extended = this.NONE;
- }
-
let prev = stack && stack.pop || this.topOfStack;
if (push)
this._modeStack.push(push);
@@ -232,9 +234,7 @@ const Modes = Module("modes", {
prev);
dactyl.triggerObserver("modeChange", [oldMain, oldExtended], [this._main, this._extended], stack);
-
- if (!silent)
- this.show();
+ this.show();
},
push: function (mainMode, extendedMode, params) {
@@ -244,9 +244,6 @@ const Modes = Module("modes", {
pop: function (mode) {
while (this._modeStack.length > 1 && this.main != mode) {
let a = this._modeStack.pop();
- if (a.params.leave)
- a.params.leave({ pop: a }, this.topOfStack);
-
this.set(this.topOfStack.main, this.topOfStack.extended, this.topOfStack.params, { pop: a });
for (let [k, { obj, prop, value }] in Iterator(this.topOfStack.saved))
@@ -325,7 +322,7 @@ const Modes = Module("modes", {
}, {
options: function () {
options.observePref("accessibility.browsewithcaret", function (value) {
- if (!value && modes.topOfStack.main === modes.CARET)
+ if (!value && modes.main === modes.CARET)
modes.pop();
if (value && modes.main === modes.NORMAL)
modes.push(modes.CARET);
From a682373e27f5ff366a1dd59f261f88c22b605cfd Mon Sep 17 00:00:00 2001
From: Kris Maglione
Date: Sat, 9 Oct 2010 02:26:12 -0400
Subject: [PATCH 12/16] Replace spurious modes.replace call that Doug, er,
warned be about before I committed it.
--HG--
branch : mode-refactoring
---
common/content/editor.js | 2 +-
common/content/modes.js | 6 ++++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/common/content/editor.js b/common/content/editor.js
index 94347886..b737a93a 100644
--- a/common/content/editor.js
+++ b/common/content/editor.js
@@ -701,7 +701,7 @@ const Editor = Module("editor", {
function (count) {
dactyl.assert(editor.isTextEdit);
editor.executeCommand("cmd_cut");
- modes.replace(modes.INSERT, modes.TEXT_EDIT);
+ modes.push(modes.INSERT);
});
mappings.add([modes.VISUAL],
diff --git a/common/content/modes.js b/common/content/modes.js
index 141c6afa..39e4f836 100644
--- a/common/content/modes.js
+++ b/common/content/modes.js
@@ -265,8 +265,10 @@ const Modes = Module("modes", {
},
replace: function (mode, oldMode) {
- // TODO: This should really be done in one step.
- this.pop(oldMode);
+ while (oldMode && this._modeStack.length > 1 && this.main != oldMode)
+ this.pop();
+
+ this.set(mode, null, null, { push: this.topOfStack, pop: this._modeStack.pop() });
this.push(mode);
},
From 29448adaa6f9271a6f3ae85ce9d2ada4917528fd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20N=C4=9Bmec?=
Date: Sat, 9 Oct 2010 12:24:43 +0200
Subject: [PATCH 13/16] Fix a typo.
--HG--
branch : mode-refactoring
---
common/content/dactyl.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/content/dactyl.js b/common/content/dactyl.js
index 14a6d9e1..d79f9089 100644
--- a/common/content/dactyl.js
+++ b/common/content/dactyl.js
@@ -1519,7 +1519,7 @@ const Dactyl = Module("dactyl", {
perm: "disable"
},
{
- name: "extu[update]",
+ name: "extu[pdate]",
description: "Update an extension",
actions: updateAddons,
filter: function ({ item }) !item.userDisabled,
From 08ed30f07a6a0a0511b49b3417c388875107a59f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20N=C4=9Bmec?=
Date: Sat, 9 Oct 2010 12:26:20 +0200
Subject: [PATCH 14/16] Fix :extupdate documentation markup.
--HG--
branch : mode-refactoring
---
common/locale/en-US/gui.xml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/common/locale/en-US/gui.xml b/common/locale/en-US/gui.xml
index 81d32a5a..6b638a01 100644
--- a/common/locale/en-US/gui.xml
+++ b/common/locale/en-US/gui.xml
@@ -154,7 +154,8 @@
-
:extu :extupdate
- :extupdate! extension
+ :extupdate extension
+ :extupdate!
Update an extension. When ! is given, update all
From 0d3c9bd613f2789ce041ff5195c5beb7bd5ad2eb Mon Sep 17 00:00:00 2001
From: Kris Maglione
Date: Sat, 9 Oct 2010 12:56:05 -0400
Subject: [PATCH 15/16] Fix now spurious :autocmd examples.
--HG--
branch : mode-refactoring
---
common/content/buffer.js | 4 +++-
common/locale/en-US/autocommands.xml | 10 ++++------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/common/content/buffer.js b/common/content/buffer.js
index ef322e21..747c33b8 100644
--- a/common/content/buffer.js
+++ b/common/content/buffer.js
@@ -271,7 +271,9 @@ const Buffer = Module("buffer", {
statusline.updateUrl();
statusline.updateProgress();
- autocommands.trigger("LocationChange", { url: buffer.URL });
+ util.timeout(function () {
+ autocommands.trigger("LocationChange", { url: buffer.URL });
+ });
// if this is not delayed we get the position of the old buffer
util.timeout(function () {
diff --git a/common/locale/en-US/autocommands.xml b/common/locale/en-US/autocommands.xml
index e2a06c3b..3ba97b52 100644
--- a/common/locale/en-US/autocommands.xml
+++ b/common/locale/en-US/autocommands.xml
@@ -90,18 +90,16 @@
Enable passthrough mode on all Google sites:
-:autocmd LocationChange .* js modes.passAllKeys = /google\.com/.test(buffer.URL)
+:autocmd LocationChange google\.com -js modes.push(modes.PASS_THROUGH)
Enable passthrough mode on some Google sites:
-:autocmd LocationChange .* js modes.passAllKeys = /(www|mail)\.google\.com/.test(buffer.URL)
+:autocmd LocationChange (www|mail)\.google\.com -js modes.push(modes.PASS_THROUGH)
Set the filetype to mail when editing email at Gmail:
-
-:autocmd LocationChange !'mail\.google\.com' :set editor=gvim -f
-:autocmd LocationChange 'mail\.google\.com' :set editor=gvim -f -c 'set ft=mail'
-
+:autocmd LocationChange !mail\.google\.com :set editor=gvim -f
+:autocmd LocationChange mail\.google\.com :set editor=gvim -f -c 'set ft=mail'
From d7ff35c565742460cb0b40cfe1f02a7019fd3c05 Mon Sep 17 00:00:00 2001
From: Kris Maglione
Date: Sun, 10 Oct 2010 15:19:27 -0400
Subject: [PATCH 16/16] Get rid of a lot of special casing in the event loops.
Merge default.
--HG--
branch : mode-refactoring
---
common/content/commandline.js | 36 +++++-------
common/content/events.js | 100 +++++++++++---------------------
common/content/help.xsl | 4 +-
common/content/hints.js | 70 +++++++++++-----------
common/locale/en-US/cmdline.xml | 6 +-
common/locale/en-US/map.xml | 6 +-
common/locale/en-US/marks.xml | 6 +-
common/locale/en-US/options.xml | 26 ++++-----
common/locale/en-US/pattern.xml | 4 +-
common/locale/en-US/styling.xml | 9 ++-
common/locale/en-US/tabs.xml | 2 +-
common/locale/en-US/various.xml | 9 ++-
pentadactyl/NEWS | 10 +++-
13 files changed, 129 insertions(+), 159 deletions(-)
diff --git a/common/content/commandline.js b/common/content/commandline.js
index d277cf73..87f5ba1f 100644
--- a/common/content/commandline.js
+++ b/common/content/commandline.js
@@ -567,7 +567,9 @@ const CommandLine = Module("commandline", {
this._startHints = false;
if (!(modes.extended & modes.OUTPUT_MULTILINE))
- modes.push(modes.COMMAND_LINE, modes.OUTPUT_MULTILINE);
+ modes.push(modes.COMMAND_LINE, modes.OUTPUT_MULTILINE, {
+ onEvent: this.closure.onMultilineOutputEvent
+ });
// If it's already XML, assume it knows what it's doing.
// Otherwise, white space is significant.
@@ -695,14 +697,13 @@ const CommandLine = Module("commandline", {
cancel: extra.onCancel
};
- modes.push(modes.COMMAND_LINE, modes.PROMPT | extra.extended, {
- enter: function (stack) { extra.enter && extra.enter(stack); },
- leave: function (stack) {
- commandline.leave(stack);
- if (extra.leave)
- extra.leave(stack);
- }
- });
+ modes.push(modes.COMMAND_LINE, modes.PROMPT | extra.extended,
+ update(Object.create(extra), {
+ leave: function leave(stack) {
+ commandline.leave(stack);
+ leave.supercall(this, stack);
+ }
+ }));
this.currentExtendedMode = modes.PROMPT;
this.widgets.prompt = !prompt ? null : [extra.promptHighlight || "Question", prompt];
@@ -934,14 +935,7 @@ const CommandLine = Module("commandline", {
}
if (event instanceof MouseEvent)
- return;
-
- if (this._startHints) {
- statusline.updateInputBuffer("");
- this._startHints = false;
- hints.show(key, { window: win });
- return;
- }
+ return false;
function isScrollable() !win.scrollMaxY == 0;
function atEnd() win.scrollY / win.scrollMaxY >= 1;
@@ -953,7 +947,7 @@ const CommandLine = Module("commandline", {
case ":":
commandline.open(":", "", modes.EX);
- return;
+ return false;
// down a line
case "j":
@@ -1065,9 +1059,8 @@ const CommandLine = Module("commandline", {
break;
case ";":
- statusline.updateInputBuffer(";");
- this._startHints = true;
- break;
+ hints.open(";", { window: win });
+ return false;
// unmapped key
default:
@@ -1085,6 +1078,7 @@ const CommandLine = Module("commandline", {
}
else
commandline.updateMorePrompt(showMorePrompt, showMoreHelpPrompt);
+ return false;
},
getSpaceNeeded: function getSpaceNeeded() {
diff --git a/common/content/events.js b/common/content/events.js
index dd10e32d..a3d0a450 100644
--- a/common/content/events.js
+++ b/common/content/events.js
@@ -47,17 +47,16 @@ const Events = Module("events", {
this._code_key = {};
this._key_code = {};
- for (let [k, v] in Iterator(KeyEvent))
- if (/^DOM_VK_(?![A-Z0-9]$)/.test(k)) {
- k = k.substr(7).toLowerCase();
- let names = [k.replace(/(^|_)(.)/g, function (m, n1, n2) n2.toUpperCase())
- .replace(/^NUMPAD/, "k")];
- if (k in this._keyTable)
- names = this._keyTable[k];
- this._code_key[v] = names[0];
- for (let [, name] in Iterator(names))
- this._key_code[name.toLowerCase()] = v;
- }
+ for (let [k, v] in Iterator(KeyEvent)) {
+ k = k.substr(7).toLowerCase();
+ let names = [k.replace(/(^|_)(.)/g, function (m, n1, n2) n2.toUpperCase())
+ .replace(/^NUMPAD/, "k")];
+ if (k in this._keyTable)
+ names = this._keyTable[k];
+ this._code_key[v] = names[0];
+ for (let [, name] in Iterator(names))
+ this._key_code[name.toLowerCase()] = v;
+ }
// HACK: as Gecko does not include an event for <, we must add this in manually.
if (!("<" in this._key_code)) {
@@ -374,7 +373,7 @@ const Events = Module("events", {
* @param {string} keys The string to parse.
* @returns {Array[Object]}
*/
- fromString: function (input) {
+ fromString: function (input, unknownOk) {
let out = [];
let re = RegExp("<.*?>?>|[^<]|<(?!.*>)", "g");
@@ -388,9 +387,10 @@ const Events = Module("events", {
let [match, modifier, keyname] = evt_str.match(/^<((?:[CSMA]-)*)(.+?)>$/i) || [false, '', ''];
modifier = modifier.toUpperCase();
keyname = keyname.toLowerCase();
+ evt_obj.dactylKeyname = keyname;
if (keyname && !(keyname.length == 1 && modifier.length == 0 || // disallow <> and
- !(keyname.length == 1 || this._key_code[keyname] || keyname == "nop" || /mouse$/.test(keyname)))) { // disallow
+ !(unknownOk || keyname.length == 1 || this._key_code[keyname] || keyname == "nop" || /mouse$/.test(keyname)))) { // disallow
evt_obj.ctrlKey = /C-/.test(modifier);
evt_obj.altKey = /A-/.test(modifier);
evt_obj.shiftKey = /S-/.test(modifier);
@@ -504,7 +504,7 @@ const Events = Module("events", {
else if (charCode > 0) {
key = String.fromCharCode(charCode);
- if (key in this._key_code) {
+ if (!/^[a-z0-9]$/i.test(key) && key in this._key_code) {
// a named charcode key ( and ) space can be shifted, must be forced
if ((key.match(/^\s$/) && event.shiftKey) || event.dactylShift)
modifier += "S-";
@@ -786,7 +786,7 @@ const Events = Module("events", {
try {
let stop = false;
- let mode = modes.main;
+ let mode = modes.getStack(0);
let win = document.commandDispatcher.focusedWindow;
if (win && win.document && "designMode" in win.document && win.document.designMode == "on" && !config.isComposeWindow)
@@ -804,7 +804,7 @@ const Events = Module("events", {
// handler to escape the key
if (!stop || !isEscape(key))
modes.pop();
- mode = modes.getStack(1).main;
+ mode = modes.getStack(1);
}
// handle Escape-all-keys mode (Ctrl-q)
@@ -815,66 +815,32 @@ const Events = Module("events", {
stop = true; // set to false if we should NOT consume this event but let the host app handle it
- // just forward event without checking any mappings when the MOW is open
- if (mode == modes.COMMAND_LINE && (modes.extended & modes.OUTPUT_MULTILINE)) {
- commandline.onMultilineOutputEvent(event);
- return killEvent();
- }
-
// XXX: ugly hack for now pass certain keys to the host app as
// they are without beeping also fixes key navigation in combo
// boxes, submitting forms, etc.
// FIXME: breaks iabbr for now --mst
- if (key in config.ignoreKeys && (config.ignoreKeys[key] & mode)) {
+ if (key in config.ignoreKeys && (config.ignoreKeys[key] & mode.main)) {
this._input.buffer = "";
return null;
}
- // TODO: handle middle click in content area
+ if (mode.params.onEvent) {
+ this._input.buffer = "";
+ // Bloody hell.
+ if (key === "")
+ key = event.dactylString = "";
- if (!isEscape(key)) {
- // custom mode...
- if (mode == modes.CUSTOM) {
- plugins.onEvent(event);
- return killEvent();
- }
-
- // All of these special cases for hint mode are driving
- // me insane! -Kris
- if (modes.extended & modes.HINTS) {
- // under HINT mode, certain keys are redirected to hints.onEvent
- if (key == "" || key == "" || key == ""
- || key == options["mapleader"]
- || (key == "" && hints.prevInput == "number")
- || (hints.isHintKey(key) && !hints.escNumbers)) {
- hints.onEvent(event);
- this._input.buffer = "";
- return killEvent();
- }
-
- // others are left to generate the 'input' event or handled by the host app
- return null;
- }
- }
-
- // FIXME (maybe): (is an ESC or C-] here): on HINTS mode, it enters
- // into 'if (map && !skipMap) below. With that (or however) it
- // triggers the onEscape part, where it resets mode. Here I just
- // return true, with the effect that it also gets to there (for
- // whatever reason). if that happens to be correct, well..
- // XXX: why not just do that as well for HINTS mode actually?
-
- if (mode == modes.CUSTOM)
+ if (mode.params.onEvent(event) === false)
+ killEvent();
return null;
-
- let mainMode = modes.getMode(mode);
+ }
let inputStr = this._input.buffer + key;
let countStr = inputStr.match(/^[1-9][0-9]*|/)[0];
let candidateCommand = inputStr.substr(countStr.length);
- let map = mappings[event.noremap ? "getDefault" : "get"](mode, candidateCommand);
+ let map = mappings[event.noremap ? "getDefault" : "get"](mode.main, candidateCommand);
- let candidates = mappings.getCandidates(mode, candidateCommand);
+ let candidates = mappings.getCandidates(mode.main, candidateCommand);
if (candidates.length == 0 && !map) {
map = this._input.pendingMap;
this._input.pendingMap = null;
@@ -885,7 +851,7 @@ const Events = Module("events", {
// counts must be at the start of a complete mapping (10j -> go 10 lines down)
if (countStr && !candidateCommand) {
// no count for insert mode mappings
- if (!mainMode.count || mainMode.input)
+ if (!mode.mainMode.count || mode.mainMode.input)
stop = false;
else
this._input.buffer = inputStr;
@@ -930,14 +896,14 @@ const Events = Module("events", {
stop = false;
}
}
- else if (mappings.getCandidates(mode, candidateCommand).length > 0 && !event.skipmap) {
+ else if (mappings.getCandidates(mode.main, candidateCommand).length > 0 && !event.skipmap) {
this._input.pendingMap = map;
this._input.buffer += key;
}
else { // if the key is neither a mapping nor the start of one
// the mode checking is necessary so that things like g do not beep
if (this._input.buffer != "" && !event.skipmap &&
- (mode & (modes.INSERT | modes.COMMAND_LINE | modes.TEXT_EDIT)))
+ (mode.main & (modes.INSERT | modes.COMMAND_LINE | modes.TEXT_EDIT)))
events.feedkeys(this._input.buffer, { noremap: true, skipmap: true });
this._input.buffer = "";
@@ -947,15 +913,15 @@ const Events = Module("events", {
if (!isEscape(key)) {
// allow key to be passed to the host app if we can't handle it
- stop = (mode == modes.TEXT_EDIT);
+ stop = (mode.main === modes.TEXT_EDIT);
- if (mode == modes.COMMAND_LINE) {
+ if (mode.main === modes.COMMAND_LINE) {
if (!(modes.extended & modes.INPUT_MULTILINE))
dactyl.trapErrors(function () {
commandline.onEvent(event); // reroute event in command line mode
});
}
- else if (!mainMode.input)
+ else if (!mode.mainMode.input)
dactyl.beep();
}
}
diff --git a/common/content/help.xsl b/common/content/help.xsl
index 727e21ed..908ae3ec 100644
--- a/common/content/help.xsl
+++ b/common/content/help.xsl
@@ -352,8 +352,8 @@
-
-
+
+
diff --git a/common/content/hints.js b/common/content/hints.js
index 4e672459..6721398b 100644
--- a/common/content/hints.js
+++ b/common/content/hints.js
@@ -83,7 +83,7 @@ const Hints = Module("hints", {
this._hintNumber = 0;
this._hintString = "";
statusline.updateInputBuffer("");
- commandline.command = "";
+ commandline.widgets.command = "";
}
this._pageHints = [];
this._validHints = [];
@@ -97,9 +97,9 @@ const Hints = Module("hints", {
if (!this._usedTabKey) {
this._hintNumber = 0;
}
- if (this.__continue && this._validHints.length <= 1) {
+ if (this._continue && this._validHints.length <= 1) {
this._hintString = "";
- commandline.command = this._hintString;
+ commandline.widgets.command = this._hintString;
this._showHints();
}
this._updateStatusline();
@@ -347,8 +347,10 @@ const Hints = Module("hints", {
let prefix = (elem.getAttributeNS(NS, "class") || "") + " ";
if (active)
elem.setAttributeNS(NS, "highlight", prefix + "HintActive");
- else
+ else if (active != null)
elem.setAttributeNS(NS, "highlight", prefix + "HintElem");
+ else
+ elem.removeAttributeNS(NS, "highlight");
},
/**
@@ -429,7 +431,6 @@ const Hints = Module("hints", {
*/
_removeHints: function (timeout, slight) {
for (let [,{ doc: doc, start: start, end: end }] in Iterator(this._docs)) {
- util.dump(String(doc), start, end);
for (let elem in util.evaluateXPath("//*[@dactyl:highlight='hints']", doc))
elem.parentNode.removeChild(elem);
for (let i in util.range(start, end + 1))
@@ -489,12 +490,10 @@ const Hints = Module("hints", {
let n = 5;
(function next() {
- this._setClass(elem, n % 2);
- util.dump(n, String(this._top));
+ let hinted = n || this._validHints.some(function (e) e === elem);
+ this._setClass(elem, n ? n % 2 : !hinted ? null : this._validHints[Math.max(0, this._hintNumber-1)] === elem);
if (n--)
this.timeout(next, 50);
- else if (!this._validHints.some(function (h) h.elem == elem))
- elem.removeAttributeNS(NS, "highlight");
}).call(this);
this.timeout(function () {
@@ -765,6 +764,20 @@ const Hints = Module("hints", {
*/
isHintKey: function (key) this.hintKeys.indexOf(key) >= 0,
+ open: function (mode, opts) {
+ this._extendedhintCount = opts.count;
+ commandline.input(";", null, {
+ promptHighlight: "Normal",
+ completer: function (context) {
+ context.compare = function () 0;
+ context.completions = [[k, v.prompt] for ([k, v] in Iterator(hints._hintModes))];
+ },
+ onAccept: function (arg) { arg && util.timeout(function () hints.show(arg, opts), 0); },
+ get onCancel() this.onAccept,
+ onChange: function () { modes.pop(); }
+ });
+ },
+
/**
* Updates the display of hints.
*
@@ -782,7 +795,8 @@ const Hints = Module("hints", {
if (!stack.push)
hints.hide();
},
- onChange: this.closure._onInput
+ onChange: this.closure._onInput,
+ onEvent: this.closure.onEvent
});
modes.extended = modes.HINTS;
@@ -864,9 +878,12 @@ const Hints = Module("hints", {
}
this._showActiveHint(this._hintNumber, oldId);
this._updateStatusline();
- return;
+ return false;
case "":
+ if (this.prevInput !== "number")
+ return true;
+
if (this._hintNumber > 0 && !this._usedTabKey) {
this._hintNumber = Math.floor(this._hintNumber / this.hintKeys.length);
if (this._hintNumber == 0)
@@ -886,10 +903,10 @@ const Hints = Module("hints", {
this._hintNumber = 0;
this._updateStatusline();
- return;
+ return false;
default:
- if (this.isHintKey(key)) {
+ if (!this.escNumbers && this.isHintKey(key)) {
this.prevInput = "number";
let oldHintNumber = this._hintNumber;
@@ -914,8 +931,9 @@ const Hints = Module("hints", {
dactyl.assert(this._hintNumber != 0);
this._checkUnique();
- return;
+ return false;
}
+ return true;
}
this._updateStatusline();
@@ -927,6 +945,7 @@ const Hints = Module("hints", {
this._showHints();
this._processHints(followFirst);
}
+ return false;
}
//}}}
}, {
@@ -1052,30 +1071,15 @@ const Hints = Module("hints", {
"Start QuickHint mode, but open link in a new tab",
function () { hints.show(options.get("activate").has("links") ? "t" : "b"); });
- function inputOpts(opts) ({
- promptHighlight: "Normal",
- completer: function (context) {
- context.compare = function () 0;
- context.completions = [[k, v.prompt] for ([k, v] in Iterator(hints._hintModes))];
- },
- onAccept: function (arg) { arg && util.timeout(function () hints.show(arg, opts), 0); },
- onChange: function () { modes.pop(); },
- onCancel: function (arg) { arg && util.timeout(function () hints.show(arg, opts), 0); }
- });
-
mappings.add(myModes, [";"],
"Start an extended hint mode",
- function (count) {
- this._extendedhintCount = count;
- commandline.input(";", null, inputOpts());
- }, { count: true });
+ function (count) { hints.open(";", { count: count }); },
+ { count: true });
mappings.add(myModes, ["g;"],
"Start an extended hint mode and stay there until is pressed",
- function (count) {
- this._extendedhintCount = count;
- commandline.input("g;", null, inputOpts({ continue: true }));
- }, { count: true });
+ function (count) { hints.open("g;", { continue: true, count: count }); },
+ { count: true });
},
options: function () {
const DEFAULT_HINTTAGS =
diff --git a/common/locale/en-US/cmdline.xml b/common/locale/en-US/cmdline.xml
index 825f56b1..4e40f784 100644
--- a/common/locale/en-US/cmdline.xml
+++ b/common/locale/en-US/cmdline.xml
@@ -164,7 +164,7 @@
given in a single command line and will be executed consecutively.
| can be included as an argument to a command by escaping
it with a backslash. E.g.
- :map \| :echo "bar"
+ :map \| :echo bar
Several commands process the entire command line string literally.
These commands will include any | as part of their
@@ -239,7 +239,7 @@
optional quoting characters are available:
-
+
- \
-
This is the most basic quoting character. When it is encountered
@@ -261,7 +261,7 @@
included by preceding it with a backslash. Any other occurrence of a
backslash starts an escape sequence as in JavaScript strings. Among
the available escape sequences are:
-
+
- \n
- A newline character.
- \t
- A tab character.
- \0nn
- Where each n is a digit between 0 and 7, represents an octal character code.
diff --git a/common/locale/en-US/map.xml b/common/locale/en-US/map.xml
index de3a9952..4b125a2e 100644
--- a/common/locale/en-US/map.xml
+++ b/common/locale/en-US/map.xml
@@ -48,7 +48,7 @@
common modes,
-
+
- n
- Normal mode: When browsing normally
- v
- Visual mode: When selecting text with the cursor keys
- i
- Insert mode: When interacting with text fields on a website
@@ -108,7 +108,7 @@
Any of the map commands may be given the following options:
-
+
- -builtin
- Execute this mapping as if there were no user-defined mappings (short name -b)
@@ -303,7 +303,7 @@
sequences are interpreted as described,
-
+
- xc
- Type the ‘X’ key followed by the ‘C’ key
diff --git a/common/locale/en-US/marks.xml b/common/locale/en-US/marks.xml
index bf457cf3..04958499 100644
--- a/common/locale/en-US/marks.xml
+++ b/common/locale/en-US/marks.xml
@@ -45,7 +45,7 @@
The following options are available,
-
+
- -keyword
-
A keyword which may be used to open the bookmark via
@@ -124,7 +124,7 @@
The bookmarks may also be filtered via the following options,
-
+
- -keyword
-
The bookmark's keyword (short name -k).
@@ -273,7 +273,7 @@
The pages may also be filtered via the following options,
-
+
- -max
-
The maximum number of items to list or open
diff --git a/common/locale/en-US/options.xml b/common/locale/en-US/options.xml
index b963df15..db8b69fc 100644
--- a/common/locale/en-US/options.xml
+++ b/common/locale/en-US/options.xml
@@ -25,8 +25,8 @@
achieve special effects. These options come in 8 forms:
-
- - boolean
- Can only be on or off
+
+ - boolean
- Can only be on or off
- number
- A numeric value
- string
- A string value
@@ -44,7 +44,7 @@
- stringmap
- - A comma-separated list of key-value pairs, e.g., key:val,foo:bar
+ - A comma-separated list of key-value pairs, e.g., key:val,foo:bar
- regexlist
@@ -430,7 +430,7 @@
Items which are completed at the :open prompts. Available items:
-
+
- s
- Search engines and keyword URLs
- f
- Local files
- l
- &dactyl.host; location bar entries (bookmarks and history sorted in an intelligent way)
@@ -598,7 +598,7 @@
Possible values:
-
+
- 0
- Follow the first hint as soon as typed text uniquely identifies it.
- 1
- Follow the selected hint on .
- 2
- Follow the selected hint on only if it's been -selected.
@@ -630,7 +630,7 @@
Supported characters:
-
+
- B
- Bookmark bar
- C
- Always show the command-line outside of the status line
- M
- Always show messages outside of the status line
@@ -676,7 +676,7 @@
given, and the first successful value is used.
-
+
- value
- The hint is the value displayed in a text input, or the selected option for a drop-down.
- label
- The value of an explicit label for the input; this will not match most manually added labels that are found on sites.
- name
- The name of the input will be used; although the name is not designed for user consumption, it is frequently very similar to the label.
@@ -869,7 +869,7 @@
Possible values:
-
+
- 0
- Never
- 1
- Only if there are multiple windows
- 2
- Always
@@ -1045,7 +1045,7 @@
Items available by default:
-
+
- g
- General info
- f
- Feeds
- m
- Meta tags
@@ -1073,7 +1073,7 @@
Possible values are:
-
+
- tab
- Open pop-ups in a new tab
- window
- Open pop-ups in a new window
- resized
- Open resized pop-ups in a new window
@@ -1185,7 +1185,7 @@
deleted. The value must be of the one of:
-
+
- all
- Everything
- session
- The current session
- nm
- Past n Minutes
@@ -1258,7 +1258,7 @@
Possible values are:
-
+
- 0
- Don't show link destination
- 1
- Show the link's destination in the status-line
- 2
- Show the link's destination in the command-line
@@ -1276,7 +1276,7 @@
Possible values are:
-
+
- 0
- Never show tab line
- 1
- Show tab line only if more than one tab is open
- 2
- Always show tab line
diff --git a/common/locale/en-US/pattern.xml b/common/locale/en-US/pattern.xml
index f4448ecb..5d5cb129 100644
--- a/common/locale/en-US/pattern.xml
+++ b/common/locale/en-US/pattern.xml
@@ -55,7 +55,7 @@
appear is the one that takes effect.
-
+
- \c
- Perform case insensitive search (default if ignorecase is set).
- \C
- Perform case sensitive search
- \l
- Search only in links, as defined by hinttags. (default if linksearch is set).
@@ -66,7 +66,7 @@
Additionally, if the /Find Bar/ extension is installed, the
following flags may be used,
-
+
- \r
- Process the entire pattern as a regular expression.
- \R
- Process the entire pattern as an ordinary string.
diff --git a/common/locale/en-US/styling.xml b/common/locale/en-US/styling.xml
index 3c3d98f0..f5320164 100644
--- a/common/locale/en-US/styling.xml
+++ b/common/locale/en-US/styling.xml
@@ -197,27 +197,30 @@
-
:styleenable :stylee
:styenable :stye
+
:styledisable -name=name -index=index filter css
-
Enable any matching styles. Arguments are the same as for :delstyle.
+ Enable any matching styles. Arguments are the same as for :delstyle
-
:styledisable :styled
:stydisable :styd
+
:styleenable -name=name -index=index filter css
-
Disable any matching styles. Arguments are the same as for :delstyle.
+ Disable any matching styles. Arguments are the same as for :delstyle
-
:styletoggle :stylet
:stytoggle :styt
+
:styletoggle -name=name -index=index filter css
-
Toggle any matching styles. Arguments are the same as for :delstyle.
+ Toggle any matching styles. Arguments are the same as for :delstyle
diff --git a/common/locale/en-US/tabs.xml b/common/locale/en-US/tabs.xml
index 99760426..9beab050 100644
--- a/common/locale/en-US/tabs.xml
+++ b/common/locale/en-US/tabs.xml
@@ -40,7 +40,7 @@
A buffer may be marked with one of the following indicators:
-
+
- %
- The current buffer
- #
- The alternate buffer for :e # and
diff --git a/common/locale/en-US/various.xml b/common/locale/en-US/various.xml
index 31aceb41..bdcc3af2 100644
--- a/common/locale/en-US/various.xml
+++ b/common/locale/en-US/various.xml
@@ -122,16 +122,15 @@
-
&dactyl.appName; fully supports &dactyl.host;'s private browsing mode.
When in private browsing mode, no data other than Bookmarks and QuickMarks
- are written to disk. Further, upon exiting private mode, all new data,
- including command-line history, local and URL marks, and macros,
- are purged. For more information, see private.
+ are written to disk. Further, upon exiting private mode, all newly
+ accumulated data, including command-line history, local and URL
+ marks, and macros, are purged from memory. For more information, see
+ private.
-
In addition to private mode, &dactyl.appName; provides a comprehensive
facility for clearing any potentially sensitive data generated by either
&dactyl.appName; or &dactyl.host;. It directly integrates with
diff --git a/pentadactyl/NEWS b/pentadactyl/NEWS
index 20987801..df7b5ff8 100644
--- a/pentadactyl/NEWS
+++ b/pentadactyl/NEWS
@@ -21,6 +21,13 @@
* Multiple Ex commands may now be separated by |
* Command-line is now hidden by default. Added C and M to
'guioptions'.
+ * Hint mode improvements, including:
+ - Added g; continued extended hint mode, which allows
+ selecting multiple hints. Removed ;F
+ - Hints are now updated after scrolling and window resizing.
+ - Added ;S mode for creating search keywords.
+ - Added 'hintkeys' option.
+ - Added "transliterated" option to 'hintmatching'.
* JavaScript completion improvements, including:
- The prototype of the function whose arguments are currently
being typed is displayed during completion.
@@ -48,7 +55,6 @@
* IMPORTANT: 'guioptions' default value has changed.
* IMPORTANT: 'mapleader' is now an option rather than a :let
variable.
- * Added g; continued extended hint mode and removed ;F
* Added "bookmarks", "diverted", and "links" to 'activate'
option
* Added 'altwildmode' and command-line key binding.
@@ -59,8 +65,6 @@
* Added -keyword, -tags, -title to :delbmarks.
* Added "passwords" and "venkman" dialogs to :dialog.
* Added :extupdate command
- * Added 'hintkeys' option.
- * Added "transliterated" option to 'hintmatching'.
* Replaced 'focuscontent' with 'strictfocus'.
* Changed 'urlseparator' default value to '|'
* Added 'wildanchor' option.