mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-20 18:17:58 +01:00
Register and selection magic.
This commit is contained in:
@@ -26,22 +26,6 @@ var Editor = Module("editor", XPCOM(Ci.nsIEditActionListener, ModuleBase), {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
signals: {
|
|
||||||
"mappings.willExecute": function mappings_willExecute(map) {
|
|
||||||
if (this.currentRegister && !(this._currentMap && this._wait == util.yielders)) {
|
|
||||||
this._currentMap = map;
|
|
||||||
this._wait = util.yielders;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mappings.executed": function mappings_executed(map) {
|
|
||||||
if (this._currentMap == map) {
|
|
||||||
this.currentRegister = null;
|
|
||||||
this._wait = util.yielders;
|
|
||||||
this._currentMap = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
get registers() storage.newMap("registers", { privateData: true, store: true }),
|
get registers() storage.newMap("registers", { privateData: true, store: true }),
|
||||||
get registerRing() storage.newArray("register-ring", { privateData: true, store: true }),
|
get registerRing() storage.newArray("register-ring", { privateData: true, store: true }),
|
||||||
|
|
||||||
@@ -50,6 +34,18 @@ var Editor = Module("editor", XPCOM(Ci.nsIEditActionListener, ModuleBase), {
|
|||||||
// Fixme: Move off this object.
|
// Fixme: Move off this object.
|
||||||
currentRegister: null,
|
currentRegister: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporarily set the default register for the span of the next
|
||||||
|
* mapping.
|
||||||
|
*/
|
||||||
|
pushRegister: function pushRegister(arg) {
|
||||||
|
let restore = this.currentRegister;
|
||||||
|
this.currentRegister = arg;
|
||||||
|
mappings.afterCommands(2, function () {
|
||||||
|
this.currentRegister = restore;
|
||||||
|
}, this);
|
||||||
|
},
|
||||||
|
|
||||||
defaultRegister: "*",
|
defaultRegister: "*",
|
||||||
|
|
||||||
selectionRegisters: {
|
selectionRegisters: {
|
||||||
@@ -97,7 +93,7 @@ var Editor = Module("editor", XPCOM(Ci.nsIEditActionListener, ModuleBase), {
|
|||||||
* @param {string|Range|Selection|Node} value The value to save to
|
* @param {string|Range|Selection|Node} value The value to save to
|
||||||
* the register.
|
* the register.
|
||||||
*/
|
*/
|
||||||
setRegister: function setRegister(name, value) {
|
setRegister: function setRegister(name, value, verbose) {
|
||||||
if (name == null)
|
if (name == null)
|
||||||
name = editor.currentRegister || editor.defaultRegister;
|
name = editor.currentRegister || editor.defaultRegister;
|
||||||
|
|
||||||
@@ -110,7 +106,7 @@ var Editor = Module("editor", XPCOM(Ci.nsIEditActionListener, ModuleBase), {
|
|||||||
if (name == "_")
|
if (name == "_")
|
||||||
;
|
;
|
||||||
else if (Set.has(this.selectionRegisters, name))
|
else if (Set.has(this.selectionRegisters, name))
|
||||||
dactyl.clipboardWrite(value.text, false, this.selectionRegisters[name]);
|
dactyl.clipboardWrite(value.text, verbose, this.selectionRegisters[name]);
|
||||||
else if (!/^[0-9]$/.test(name))
|
else if (!/^[0-9]$/.test(name))
|
||||||
this.registers.set(name, value);
|
this.registers.set(name, value);
|
||||||
else {
|
else {
|
||||||
@@ -608,21 +604,21 @@ var Editor = Module("editor", XPCOM(Ci.nsIEditActionListener, ModuleBase), {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
extendRange: function extendRange(range, forward, re, sameWord, root) {
|
extendRange: function extendRange(range, forward, re, sameWord, root, end) {
|
||||||
function advance(positive) {
|
function advance(positive) {
|
||||||
while (true) {
|
while (true) {
|
||||||
while (idx == text.length && (node = iterator.getNext())) {
|
while (idx == text.length && (node = iterator.getNext())) {
|
||||||
if (node == iterator.start)
|
if (node == iterator.start)
|
||||||
idx = range.endOffset;
|
idx = range[offset];
|
||||||
|
|
||||||
offset = text.length;
|
start = text.length;
|
||||||
text += node.textContent;
|
text += node.textContent;
|
||||||
range.setEnd(node, idx - offset);
|
range[set](node, idx - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx >= text.length || re.test(text[idx]) != positive)
|
if (idx >= text.length || re.test(text[idx]) != positive)
|
||||||
break;
|
break;
|
||||||
range.setEnd(range.endContainer, ++idx - offset);
|
range[set](range[container], ++idx - start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function retreat(positive) {
|
function retreat(positive) {
|
||||||
@@ -630,21 +626,26 @@ var Editor = Module("editor", XPCOM(Ci.nsIEditActionListener, ModuleBase), {
|
|||||||
while (idx == 0 && (node = iterator.getPrev())) {
|
while (idx == 0 && (node = iterator.getPrev())) {
|
||||||
let str = node.textContent;
|
let str = node.textContent;
|
||||||
if (node == iterator.start)
|
if (node == iterator.start)
|
||||||
idx = range.startOffset;
|
idx = range[offset];
|
||||||
else
|
else
|
||||||
idx = str.length;
|
idx = str.length;
|
||||||
|
|
||||||
text = str + text;
|
text = str + text;
|
||||||
range.setStart(node, idx);
|
range[set](node, idx);
|
||||||
}
|
}
|
||||||
if (idx == 0 || re.test(text[idx - 1]) != positive)
|
if (idx == 0 || re.test(text[idx - 1]) != positive)
|
||||||
break;
|
break;
|
||||||
range.setStart(range.startContainer, --idx);
|
range[set](range[container], --idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (end == null)
|
||||||
|
end = forward ? "end" : "start";
|
||||||
|
let [container, offset, set] = [end + "Container", end + "Offset",
|
||||||
|
"set" + util.capitalize(end)];
|
||||||
|
|
||||||
if (!root)
|
if (!root)
|
||||||
for (root = range.startContainer;
|
for (root = range[container];
|
||||||
root.parentNode instanceof Element && !DOM(root).isEditable;
|
root.parentNode instanceof Element && !DOM(root).isEditable;
|
||||||
root = root.parentNode)
|
root = root.parentNode)
|
||||||
;
|
;
|
||||||
@@ -653,13 +654,13 @@ var Editor = Module("editor", XPCOM(Ci.nsIEditActionListener, ModuleBase), {
|
|||||||
if (root instanceof Ci.nsIEditor)
|
if (root instanceof Ci.nsIEditor)
|
||||||
root = root.rootElement;
|
root = root.rootElement;
|
||||||
|
|
||||||
let node = range[forward ? "endContainer" : "startContainer"];
|
let node = range[container];
|
||||||
let iterator = Editor.TextsIterator(RangeFind.nodeContents(root),
|
let iterator = Editor.TextsIterator(RangeFind.nodeContents(root),
|
||||||
node, !forward);
|
node, !forward);
|
||||||
|
|
||||||
let text = "";
|
let text = "";
|
||||||
let idx = 0;
|
let idx = 0;
|
||||||
let offset = 0;
|
let start = 0;
|
||||||
|
|
||||||
if (forward) {
|
if (forward) {
|
||||||
advance(true);
|
advance(true);
|
||||||
@@ -886,11 +887,17 @@ var Editor = Module("editor", XPCOM(Ci.nsIEditActionListener, ModuleBase), {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateRange(editor, forward, re, modify, sameWord) {
|
function updateRange(editor, forward, re, modify, sameWord) {
|
||||||
let range = Editor.extendRange(editor.selection.getRangeAt(0),
|
let sel = editor.selection;
|
||||||
forward, re, sameWord, editor.rootElement);
|
let range = sel.getRangeAt(0);
|
||||||
|
|
||||||
|
let end = range.endContainer == sel.focusNode && range.endOffset == sel.focusOffset;
|
||||||
|
if (range.collapsed)
|
||||||
|
end = forward;
|
||||||
|
|
||||||
|
Editor.extendRange(range, forward, re, sameWord,
|
||||||
|
editor.rootElement, end ? "end" : "start");
|
||||||
modify(range);
|
modify(range);
|
||||||
editor.selection.removeAllRanges();
|
editor.selectionController.repaintSelection(editor.selectionController.SELECTION_NORMAL);
|
||||||
editor.selection.addRange(range);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function clear(forward, re)
|
function clear(forward, re)
|
||||||
@@ -979,29 +986,35 @@ var Editor = Module("editor", XPCOM(Ci.nsIEditActionListener, ModuleBase), {
|
|||||||
function ({ command, count, motion }) {
|
function ({ command, count, motion }) {
|
||||||
let start = editor.selectedRange.cloneRange();
|
let start = editor.selectedRange.cloneRange();
|
||||||
|
|
||||||
editor._currentMap = null;
|
mappings.pushCommand();
|
||||||
modes.push(modes.OPERATOR, null, {
|
modes.push(modes.OPERATOR, null, {
|
||||||
forCommand: command,
|
forCommand: command,
|
||||||
|
|
||||||
count: count,
|
count: count,
|
||||||
|
|
||||||
leave: function leave(stack) {
|
leave: function leave(stack) {
|
||||||
if (stack.push || stack.fromEscape)
|
try {
|
||||||
return;
|
if (stack.push || stack.fromEscape)
|
||||||
|
return;
|
||||||
|
|
||||||
editor.withSavedValues(["inEditMap"], function () {
|
editor.withSavedValues(["inEditMap"], function () {
|
||||||
this.inEditMap = true;
|
this.inEditMap = true;
|
||||||
|
|
||||||
let range = RangeFind.union(start, editor.selectedRange);
|
let range = RangeFind.union(start, editor.selectedRange);
|
||||||
editor.selectedRange = select ? range : start;
|
editor.selectedRange = select ? range : start;
|
||||||
doTxn(range, editor);
|
doTxn(range, editor);
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.currentRegister = null;
|
editor.currentRegister = null;
|
||||||
modes.delay(function () {
|
modes.delay(function () {
|
||||||
if (mode)
|
if (mode)
|
||||||
modes.push(mode);
|
modes.push(mode);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (!stack.push)
|
||||||
|
mappings.popCommand();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -1011,7 +1024,7 @@ var Editor = Module("editor", XPCOM(Ci.nsIEditActionListener, ModuleBase), {
|
|||||||
desc,
|
desc,
|
||||||
function ({ count, motion }) {
|
function ({ count, motion }) {
|
||||||
dactyl.assert(caretOk || editor.isTextEdit);
|
dactyl.assert(caretOk || editor.isTextEdit);
|
||||||
if (modes.isTextEdit)
|
if (editor.isTextEdit)
|
||||||
doTxn(editor.selectedRange, editor);
|
doTxn(editor.selectedRange, editor);
|
||||||
else
|
else
|
||||||
cmd(editor, buffer.selection.getRangeAt(0));
|
cmd(editor, buffer.selection.getRangeAt(0));
|
||||||
@@ -1232,14 +1245,14 @@ var Editor = Module("editor", XPCOM(Ci.nsIEditActionListener, ModuleBase), {
|
|||||||
mappings.add([modes.COMMAND],
|
mappings.add([modes.COMMAND],
|
||||||
['"'], "Bind a register to the next command",
|
['"'], "Bind a register to the next command",
|
||||||
function ({ arg }) {
|
function ({ arg }) {
|
||||||
editor.currentRegister = arg;
|
editor.pushRegister(arg);
|
||||||
},
|
},
|
||||||
{ arg: true });
|
{ arg: true });
|
||||||
|
|
||||||
mappings.add([modes.INPUT],
|
mappings.add([modes.INPUT],
|
||||||
["<C-'>", '<C-">'], "Bind a register to the next command",
|
["<C-'>", '<C-">'], "Bind a register to the next command",
|
||||||
function ({ arg }) {
|
function ({ arg }) {
|
||||||
editor.currentRegister = arg;
|
editor.pushRegister(arg);
|
||||||
},
|
},
|
||||||
{ arg: true });
|
{ arg: true });
|
||||||
|
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ var Map = Class("Map", {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
dactyl.triggerObserver("mappings.willExecute", this, args);
|
dactyl.triggerObserver("mappings.willExecute", this, args);
|
||||||
|
mappings.pushCommand();
|
||||||
this.preExecute(args);
|
this.preExecute(args);
|
||||||
this.executing = true;
|
this.executing = true;
|
||||||
var res = repeat();
|
var res = repeat();
|
||||||
@@ -145,6 +146,7 @@ var Map = Class("Map", {
|
|||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
this.executing = false;
|
this.executing = false;
|
||||||
|
mappings.popCommand();
|
||||||
this.postExecute(args);
|
this.postExecute(args);
|
||||||
dactyl.triggerObserver("mappings.executed", this, args);
|
dactyl.triggerObserver("mappings.executed", this, args);
|
||||||
}
|
}
|
||||||
@@ -320,6 +322,31 @@ var MapHive = Class("MapHive", Contexts.Hive, {
|
|||||||
*/
|
*/
|
||||||
var Mappings = Module("mappings", {
|
var Mappings = Module("mappings", {
|
||||||
init: function () {
|
init: function () {
|
||||||
|
this.watches = [];
|
||||||
|
this._watchStack = 0;
|
||||||
|
this._yielders = 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
afterCommands: function afterCommands(count, cmd, self) {
|
||||||
|
this.watches.push([cmd, self, Math.max(this._watchStack - 1, 0), count || 1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
pushCommand: function pushCommand(cmd) {
|
||||||
|
this._watchStack++;
|
||||||
|
this._yielders = util.yielders;
|
||||||
|
},
|
||||||
|
popCommand: function popCommand(cmd) {
|
||||||
|
this._watchStack = Math.max(this._watchStack - 1, 0);
|
||||||
|
if (util.yielders > this._yielders)
|
||||||
|
this._watchStack = 0;
|
||||||
|
|
||||||
|
this.watches = this.watches.filter(function (elem) {
|
||||||
|
if (elem[2] <= this._watchStack)
|
||||||
|
elem[3]--;
|
||||||
|
if (elem[3] <= 0)
|
||||||
|
elem[0].call(elem[1] || null);
|
||||||
|
return elem[3] > 0;
|
||||||
|
}, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
repeat: Modes.boundProperty(),
|
repeat: Modes.boundProperty(),
|
||||||
|
|||||||
@@ -54,16 +54,9 @@ var Tabs = Module("tabs", {
|
|||||||
enter: function enter() {
|
enter: function enter() {
|
||||||
if (window.TabsInTitlebar)
|
if (window.TabsInTitlebar)
|
||||||
window.TabsInTitlebar.allowedBy("dactyl", true);
|
window.TabsInTitlebar.allowedBy("dactyl", true);
|
||||||
},
|
}
|
||||||
|
|
||||||
"mappings.executed": function mappings_executed() {
|
|
||||||
if (this._mappingCount && !--this._mappingCount)
|
|
||||||
dactyl.forceTarget = null;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_mappingCount: 0,
|
|
||||||
|
|
||||||
_alternates: Class.Memoize(function () [config.tabbrowser.mCurrentTab, null]),
|
_alternates: Class.Memoize(function () [config.tabbrowser.mCurrentTab, null]),
|
||||||
|
|
||||||
cleanup: function cleanup() {
|
cleanup: function cleanup() {
|
||||||
@@ -1116,8 +1109,10 @@ var Tabs = Module("tabs", {
|
|||||||
mappings.add([modes.COMMAND], ["<C-t>", "<new-tab-next>"],
|
mappings.add([modes.COMMAND], ["<C-t>", "<new-tab-next>"],
|
||||||
"Execute the next mapping in a new tab",
|
"Execute the next mapping in a new tab",
|
||||||
function ({ count }) {
|
function ({ count }) {
|
||||||
tabs._mappingCount = (count || 1) + 1;
|
|
||||||
dactyl.forceTarget = dactyl.NEW_TAB;
|
dactyl.forceTarget = dactyl.NEW_TAB;
|
||||||
|
mappings.afterCommands((count || 1) + 1, function () {
|
||||||
|
dactyl.forceTarget = null;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
{ count: true });
|
{ count: true });
|
||||||
|
|
||||||
|
|||||||
@@ -1247,7 +1247,7 @@ var Buffer = Module("Buffer", {
|
|||||||
return "";
|
return "";
|
||||||
|
|
||||||
let range = selection.getRangeAt(0).cloneRange();
|
let range = selection.getRangeAt(0).cloneRange();
|
||||||
if (range.collapsed && range.startContainer instanceof Ci.nsIDOMText) {
|
if (range.collapsed) {
|
||||||
let re = options.get("iskeyword").regexp;
|
let re = options.get("iskeyword").regexp;
|
||||||
Editor.extendRange(range, true, re, true);
|
Editor.extendRange(range, true, re, true);
|
||||||
Editor.extendRange(range, false, re, true);
|
Editor.extendRange(range, false, re, true);
|
||||||
@@ -1824,7 +1824,7 @@ var Buffer = Module("Buffer", {
|
|||||||
events.listen(config.browser, "scroll", buffer.closure._updateBufferPosition, false);
|
events.listen(config.browser, "scroll", buffer.closure._updateBufferPosition, false);
|
||||||
},
|
},
|
||||||
mappings: function initMappings(dactyl, modules, window) {
|
mappings: function initMappings(dactyl, modules, window) {
|
||||||
let { Editor, Events, buffer, events, ex, mappings, modes, options, tabs } = modules;
|
let { Editor, Events, buffer, editor, events, ex, mappings, modes, options, tabs } = modules;
|
||||||
|
|
||||||
mappings.add([modes.NORMAL],
|
mappings.add([modes.NORMAL],
|
||||||
["y", "<yank-location>"], "Yank current location to the clipboard",
|
["y", "<yank-location>"], "Yank current location to the clipboard",
|
||||||
@@ -2094,7 +2094,7 @@ var Buffer = Module("Buffer", {
|
|||||||
function () {
|
function () {
|
||||||
let sel = buffer.currentWord;
|
let sel = buffer.currentWord;
|
||||||
dactyl.assert(sel);
|
dactyl.assert(sel);
|
||||||
dactyl.clipboardWrite(sel, true);
|
editor.setRegister(null, sel, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// zooming
|
// zooming
|
||||||
|
|||||||
Reference in New Issue
Block a user