1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-21 17:17:58 +01:00

Add real mappings for most HINT mode keys. Lazily expand leader, and keep in sync with 'mapleader'.

--HG--
branch : bootstrapped
This commit is contained in:
Kris Maglione
2010-12-28 14:33:57 -05:00
parent 83aa5e4857
commit 9655d741b8
8 changed files with 166 additions and 132 deletions

View File

@@ -1021,11 +1021,10 @@ var Buffer = Module("buffer", {
this.callback(file);
else {
this.file = io.createTempFile();
var webBrowserPersist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
.createInstance(Ci.nsIWebBrowserPersist);
webBrowserPersist.persistFlags = webBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
webBrowserPersist.progressListener = this;
webBrowserPersist.saveURI(uri, null, null, null, null, this.file);
var persist = services.Persist();
persist.persistFlags = persist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
persist.progressListener = this;
persist.saveURI(uri, null, null, null, null, this.file);
}
return null;
},

View File

@@ -757,9 +757,6 @@ var CommandLine = Module("commandline", {
* the MOW.
*/
echo: function echo(str, highlightGroup, flags) {
if (String(str) == "undefined")
util.dumpStack();
// dactyl.echo uses different order of flags as it omits the highlight group, change commandline.echo argument order? --mst
if (this._silent)
return;

View File

@@ -2131,12 +2131,12 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
dactyl.log("All modules loaded", 3);
AddonManager.getAddonByID(services["dactyl:"].addonID, function (addon) {
AddonManager.getAddonByID(services["dactyl:"].addonID, this.wrapCallback(function (addon) {
// @DATE@ token replaced by the Makefile
// TODO: Find it automatically
prefs.set("extensions.dactyl.version", addon.version);
dactyl.version = addon.version + " (created: @DATE@)";
});
}));
if (!services.commandLineHandler)
services.add("commandLineHandler", "@mozilla.org/commandlinehandler/general-startup;1?type=" + config.name);

View File

@@ -47,19 +47,29 @@ var Events = Module("events", {
this._keyTable = {
add: ["Plus", "Add"],
back_space: ["BS"],
count: ["count"],
delete: ["Del"],
escape: ["Esc", "Escape"],
insert: ["Insert", "Ins"],
leader: ["Leader"],
left_shift: ["LT", "<"],
nop: ["Nop"],
return: ["Return", "CR", "Enter"],
right_shift: [">"],
space: ["Space", " "],
subtract: ["Minus", "Subtract"]
};
this._pseudoKeys = set(["count", "leader", "nop"]);
this._key_key = {};
this._code_key = {};
this._key_code = {};
for (let list in values(this._keyTable))
for (let v in values(list))
this._key_key[v.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())
@@ -67,8 +77,10 @@ var Events = Module("events", {
if (k in this._keyTable)
names = this._keyTable[k];
this._code_key[v] = names[0];
for (let [, name] in Iterator(names))
for (let [, name] in Iterator(names)) {
this._key_key[name.toLowerCase()] = name;
this._key_code[name.toLowerCase()] = v;
}
}
// HACK: as Gecko does not include an event for <, we must add this in manually.
@@ -436,7 +448,7 @@ var Events = Module("events", {
keyname = String.fromCharCode(parseInt(keyname.substr(1), 16));
if (keyname && (unknownOk || keyname.length == 1 || /mouse$/.test(keyname) ||
this._key_code[keyname] || keyname == "nop")) {
this._key_code[keyname] || set.has(this._pseudoKeys, keyname))) {
evt_obj.ctrlKey = /C-/.test(modifier);
evt_obj.altKey = /A-/.test(modifier);
evt_obj.shiftKey = /S-/.test(modifier);
@@ -451,8 +463,8 @@ var Events = Module("events", {
evt_obj.charCode = keyname.charCodeAt(0);
}
else if (keyname == "nop") {
evt_obj.dactylString = "<Nop>";
else if (set.has(this._pseudoKeys)) {
evt_obj.dactylString = "<" + this._key_key[keyname] + ">";
}
else if (/mouse$/.test(keyname)) { // mouse events
evt_obj.type = (/2-/.test(modifier) ? "dblclick" : "click");
@@ -576,7 +588,7 @@ var Events = Module("events", {
}
}
if (key == null)
key = event.dactylKeyname;
key = this._key_key[event.dactylKeyname] || event.dactylKeyname;
if (key == null)
return null;
}
@@ -1070,9 +1082,9 @@ var Events = Module("events", {
const self = this;
let key = events.toString(event);
let [, countStr, candidateCommand] = /^((?:[1-9][0-9]*)?)(.*)/.exec(this.buffer + key);
let [, countStr, command] = /^((?:[1-9][0-9]*)?)(.*)/.exec(this.buffer + key);
let map = mappings[event.noremap ? "getDefault" : "get"](this.main, candidateCommand);
let map = mappings[event.noremap ? "getDefault" : "get"](this.main, command);
function execute(map) {
if (self.preExecute)
@@ -1083,7 +1095,7 @@ var Events = Module("events", {
return res;
}
let candidates = mappings.getCandidates(this.main, candidateCommand);
let candidates = mappings.getCandidates(this.main, command);
if (candidates.length == 0 && !map) {
map = this.pendingMap;
this.pendingMap = null;
@@ -1092,7 +1104,7 @@ var Events = Module("events", {
}
// counts must be at the start of a complete mapping (10j -> go 10 lines down)
if (countStr && !candidateCommand) {
if (countStr && !command) {
// no count for insert mode mappings
if (!this.main.count)
return this.append(event);
@@ -1102,9 +1114,9 @@ var Events = Module("events", {
this.append(event);
}
else if (this.pendingArgMap) {
let map = this.pendingArgMap;
let [map, command] = this.pendingArgMap;
if (!Events.isEscape(key))
execute(map, null, this.count, key);
execute(map, null, this.count, key, command);
return true;
}
else if (map && !event.skipmap && candidates.length == 0) {
@@ -1118,27 +1130,28 @@ var Events = Module("events", {
if (map.arg) {
this.append(event);
this.pendingArgMap = map;
this.pendingArgMap = [map, command];
}
else if (this.pendingMotionMap) {
let [map, command] = this.pendingMotionMap;
if (!Events.isEscape(key))
execute(this.pendingMotionMap, candidateCommand, this.motionCount || this.count, null);
execute(map, command, this.motionCount || this.count, null, command);
return true;
}
else if (map.motion) {
this.buffer = "";
this.pendingMotionMap = map;
this.pendingMotionMap = [map, command];
}
else {
if (modes.replaying && !this.waitForPageLoad())
return true;
return !execute(map, null, this.count) || !map.route
return !execute(map, null, this.count, null, command) || !map.route
}
}
else if (mappings.getCandidates(this.main, candidateCommand).length > 0 && !event.skipmap) {
else if (mappings.getCandidates(this.main, command).length > 0 && !event.skipmap) {
this.append(event);
this.pendingMap = map;
this.pendingMap = [map, command];
}
else {
this.append(event);

View File

@@ -74,6 +74,15 @@ var Hints = Module("hints", {
Buffer.isScrollable(elem, 0, true) || Buffer.isScrollable(elem, 0, false);
},
/**
* Clear any timeout which might be active after pressing a number
*/
clearTimeout: function () {
if (this._activeTimeout)
this._activeTimeout.cancel();
this._activeTimeout = null;
},
/**
* Reset hints, so that they can be cleanly used again.
*/
@@ -92,10 +101,7 @@ var Hints = Module("hints", {
this._pageHints = [];
this._validHints = [];
this._docs = [];
if (this._activeTimeout)
this._activeTimeout.cancel();
this._activeTimeout = null;
this.clearTimeout();
},
__reset: function __reset() {
if (!this._usedTabKey)
@@ -582,11 +588,7 @@ var Hints = Module("hints", {
_onInput: function _onInput(event) {
this.prevInput = "text";
// clear any timeout which might be active after pressing a number
if (this._activeTimeout) {
this._activeTimeout.cancel();
this._activeTimeout = null;
}
this.clearTimeout();
this._hintNumber = 0;
this._hintString = commandline.command;
@@ -896,104 +898,38 @@ var Hints = Module("hints", {
*/
onEvent: function onEvent(event) {
let key = events.toString(event);
let followFirst = false;
// clear any timeout which might be active after pressing a number
if (this._activeTimeout) {
this._activeTimeout.cancel();
this._activeTimeout = null;
}
this.clearTimeout();
switch (key) {
case "<Return>":
followFirst = true;
break;
if (!this.escNumbers && this.isHintKey(key)) {
this.prevInput = "number";
case "<Tab>":
case "<S-Tab>":
this._usedTabKey = true;
if (this._hintNumber == 0)
this._hintNumber = 1;
let oldId = this._hintNumber;
if (key == "<Tab>") {
if (++this._hintNumber > this._validHints.length)
this._hintNumber = 1;
}
else {
if (--this._hintNumber < 1)
this._hintNumber = this._validHints.length;
}
this._showActiveHint(this._hintNumber, oldId);
this._updateStatusline();
return false;
case "<BS>":
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)
this.prevInput = "text";
}
else {
this._usedTabKey = false;
let oldHintNumber = this._hintNumber;
if (this._usedTabKey) {
this._hintNumber = 0;
dactyl.beep();
this._usedTabKey = false;
}
this._hintNumber = this._hintNumber * this.hintKeys.length +
this.hintKeys.indexOf(key);
this._updateStatusline();
if (!this._canUpdate)
return;
}
break;
case options["mapleader"]:
hints.escNumbers = !hints.escNumbers;
if (hints.escNumbers && this._usedTabKey)
this._hintNumber = 0;
this._updateStatusline();
return false;
default:
if (!this.escNumbers && this.isHintKey(key)) {
this.prevInput = "number";
let oldHintNumber = this._hintNumber;
if (this._usedTabKey) {
this._hintNumber = 0;
this._usedTabKey = false;
}
this._hintNumber = this._hintNumber * this.hintKeys.length +
this.hintKeys.indexOf(key);
this._updateStatusline();
if (!this._canUpdate)
return;
if (this._docs.length == 0) {
this._generate();
this._showHints();
}
this._showActiveHint(this._hintNumber, oldHintNumber || 1);
dactyl.assert(this._hintNumber != 0);
this._checkUnique();
return false;
}
return true;
}
this._updateStatusline();
if (this._canUpdate) {
if (this._docs.length == 0 && this._hintString.length > 0)
if (this._docs.length == 0) {
this._generate();
this._showHints();
}
this._showActiveHint(this._hintNumber, oldHintNumber || 1);
this._showHints();
this._processHints(followFirst);
dactyl.assert(this._hintNumber != 0);
this._checkUnique();
return false;
}
return false;
return !Events.isEscape(key);
}
//}}}
}, {
@@ -1118,6 +1054,84 @@ var Hints = Module("hints", {
"Start an extended hint mode and stay there until <Esc> is pressed",
function (count) { hints.open("g;", { continue: true, count: count }); },
{ count: true });
function update(followFirst) {
hints.clearTimeout();
hints._updateStatusline();
if (hints._canUpdate) {
if (hints._docs.length == 0 && hints._hintString.length > 0)
hints._generate();
hints._showHints();
hints._processHints(followFirst);
}
}
mappings.add(modes.HINTS, ["<Return>"],
"Follow the selected hint",
function () { update(true) });
function tab(previous) {
hints.clearTimeout();
this._usedTabKey = true;
if (this._hintNumber == 0)
this._hintNumber = 1;
let oldId = this._hintNumber;
if (!previous) {
if (++this._hintNumber > this._validHints.length)
this._hintNumber = 1;
}
else {
if (--this._hintNumber < 1)
this._hintNumber = this._validHints.length;
}
this._showActiveHint(this._hintNumber, oldId);
this._updateStatusline();
}
mappings.add(modes.HINTS, ["<Tab>"],
"Focus the next matching hint",
function () { tab.call(hints, false) });
mappings.add(modes.HINTS, ["<S-Tab>"],
"Focus the previous matching hint",
function () { tab.call(hints, true) });
mappings.add(modes.HINTS, ["<BS>", "<C-h>"],
"Delete the previous character",
function () {
hints.clearTimeout();
if (hints.prevInput !== "number")
return true;
if (hints._hintNumber > 0 && !hints._usedTabKey) {
hints._hintNumber = Math.floor(hints._hintNumber / hints.hintKeys.length);
if (hints._hintNumber == 0)
hints.prevInput = "text";
update(false);
}
else {
hints._usedTabKey = false;
hints._hintNumber = 0;
dactyl.beep();
}
return false;
},
{ route: true });
mappings.add(modes.HINTS, ["<Leader>"],
"Toggle hint filtering",
function () {
hints.clearTimeout();
hints.escNumbers = !hints.escNumbers;
if (hints.escNumbers && hints._usedTabKey)
hints._hintNumber = 0;
hints._updateStatusline();
});
},
options: function () {
const DEFAULT_HINTTAGS =

View File

@@ -90,7 +90,9 @@ var Map = Class("Map", {
* @param {string} name The name to query.
* @returns {boolean}
*/
hasName: function (name) this.names.indexOf(name) >= 0,
hasName: function (name) this.keys.indexOf(name) >= 0,
keys: Class.memoize(function () this.names.map(mappings._expandLeader)),
/**
* Execute the action for this mapping.
@@ -102,7 +104,7 @@ var Map = Class("Map", {
* @param {string} argument The normal argument if accepted by this
* mapping. E.g. "a" for "ma"
*/
execute: function (motion, count, argument) {
execute: function (motion, count, argument, command) {
let args = [];
if (this.motion)
@@ -111,6 +113,7 @@ var Map = Class("Map", {
args.push(count);
if (this.arg)
args.push(argument);
args.push(command);
let self = this;
function repeat() self.action.apply(self, args);
@@ -153,10 +156,9 @@ var Mappings = Module("mappings", {
_getMap: function (mode, cmd, stack) {
let maps = stack[mode] || [];
for (let [, map] in Iterator(maps)) {
for (let [, map] in Iterator(maps))
if (map.hasName(cmd))
return map;
}
return null;
},
@@ -233,7 +235,6 @@ var Mappings = Module("mappings", {
* @optional
*/
addUserMap: function (modes, keys, description, action, extra) {
keys = keys.map(this._expandLeader);
extra = extra || {};
extra.user = true;
let map = Map(modes, keys, description, action, extra);
@@ -631,7 +632,16 @@ var Mappings = Module("mappings", {
options: function () {
options.add(["mapleader", "ml"],
"Define the replacement keys for the <Leader> pseudo-key",
"string", "\\");
"string", "\\", {
setter: function (value) {
if (this.hasChanged)
for (let hive in values([mappings._user, mappings._main]))
for (let mode in values(hive))
for (let map in values(mode))
delete map.keys;
return value;
}
});
}
});

View File

@@ -66,6 +66,7 @@ var Services = Module("Services", {
this.addClass("Find", "@mozilla.org/embedcomp/rangefind;1", Ci.nsIFind);
this.addClass("HtmlConverter","@mozilla.org/widget/htmlformatconverter;1", Ci.nsIFormatConverter);
this.addClass("HtmlEncoder", "@mozilla.org/layout/htmlCopyEncoder;1", Ci.nsIDocumentEncoder);
this.addClass("Persist", "@mozilla.org/embedding/browser/nsWebBrowserPersist;1", Ci.nsIWebBrowserPersist);
this.addClass("Process", "@mozilla.org/process/util;1", Ci.nsIProcess, "init");
this.addClass("String", "@mozilla.org/supports-string;1", Ci.nsISupportsString);
this.addClass("Timer", "@mozilla.org/timer;1", Ci.nsITimer, "initWithCallback");

View File

@@ -486,7 +486,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
*/
dumpStack: function dumpStack(msg, frames) {
let stack = util.stackLines(Error().stack);
stack = stack.slice(2, 2 + (frames || stack.length)).join("\n").replace(/^/gm, " ");
stack = stack.slice(1, 1 + (frames || stack.length)).join("\n").replace(/^/gm, " ");
util.dump((arguments.length == 0 ? "Stack" : msg) + "\n" + stack + "\n");
},