1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
const Marks = {
previousPositionRegisters: ["`", "'"],
localRegisters: {},
currentRegistryEntry: null,
mode: null,
exit(continuation = null) {
if (this.mode != null) {
this.mode.exit();
}
this.mode = null;
if (continuation) {
return continuation(); // TODO(philc): Is this return necessary?
}
},
// This returns the key which is used for storing mark locations in localStorage.
getLocationKey(keyChar) {
return `vimiumMark|${window.location.href.split("#")[0]}|${keyChar}`;
},
getMarkString() {
return JSON.stringify({
scrollX: window.scrollX,
scrollY: window.scrollY,
hash: window.location.hash,
});
},
setPreviousPosition() {
const markString = this.getMarkString();
for (const reg of this.previousPositionRegisters) {
this.localRegisters[reg] = markString;
}
},
showMessage(message, keyChar) {
HUD.show(`${message} \"${keyChar}\".`, 1000);
},
// If <Shift> is depressed, then it's a global mark, otherwise it's a local mark. This is
// consistent vim's [A-Z] for global marks and [a-z] for local marks. However, it also admits
// other non-Latin characters. The exceptions are "`" and "'", which are always considered local
// marks. The "swap" command option inverts global and local marks.
isGlobalMark(event, keyChar) {
let shiftKey = event.shiftKey;
if (this.currentRegistryEntry.options.swap) {
shiftKey = !shiftKey;
}
return shiftKey && !this.previousPositionRegisters.includes(keyChar);
},
activateCreateMode(_count, { registryEntry }) {
this.currentRegistryEntry = registryEntry;
this.mode = new Mode();
this.mode.init({
name: "create-mark",
indicator: "Create mark...",
exitOnEscape: true,
suppressAllKeyboardEvents: true,
keydown: (event) => {
if (KeyboardUtils.isPrintable(event)) {
const keyChar = KeyboardUtils.getKeyChar(event);
this.exit(() => {
if (this.isGlobalMark(event, keyChar)) {
// We record the current scroll position, but only if this is the top frame within the
// tab. Otherwise, we'll fetch the scroll position of the top frame from the
// background page later.
let scrollX, scrollY;
if (DomUtils.isTopFrame()) {
[scrollX, scrollY] = [window.scrollX, window.scrollY];
}
chrome.runtime.sendMessage({
handler: "createMark",
markName: keyChar,
scrollX,
scrollY,
}, () => this.showMessage("Created global mark", keyChar));
} else {
localStorage[this.getLocationKey(keyChar)] = this.getMarkString();
this.showMessage("Created local mark", keyChar);
}
});
return handlerStack.suppressEvent;
}
},
});
},
activateGotoMode(_count, { registryEntry }) {
this.currentRegistryEntry = registryEntry;
this.mode = new Mode();
this.mode.init({
name: "goto-mark",
indicator: "Go to mark...",
exitOnEscape: true,
suppressAllKeyboardEvents: true,
keydown: (event) => {
if (KeyboardUtils.isPrintable(event)) {
this.exit(() => {
const keyChar = KeyboardUtils.getKeyChar(event);
if (this.isGlobalMark(event, keyChar)) {
// This key must match @getLocationKey() in the back end.
const key = `vimiumGlobalMark|${keyChar}`;
chrome.storage.local.get(key, function (items) {
if (key in items) {
chrome.runtime.sendMessage({ handler: "gotoMark", markName: keyChar });
HUD.show(`Jumped to global mark '${keyChar}'`, 1000);
} else {
HUD.show(`Global mark not set '${keyChar}'`, 1000);
}
});
} else {
const markString = this.localRegisters[keyChar] != null
? this.localRegisters[keyChar]
: localStorage[this.getLocationKey(keyChar)];
if (markString != null) {
this.setPreviousPosition();
const position = JSON.parse(markString);
if (position.hash && (position.scrollX === 0) && (position.scrollY === 0)) {
window.location.hash = position.hash;
} else {
window.scrollTo(position.scrollX, position.scrollY);
}
this.showMessage("Jumped to local mark", keyChar);
} else {
this.showMessage("Local mark not set", keyChar);
}
}
});
return handlerStack.suppressEvent;
}
},
});
},
};
window.Marks = Marks;
|