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
|
// ==UserScript==
// @name Global Keybindings
// @version 1.0
// @description Setup global keybindings on all windows
// @startup UC.globalKeybindings.init(win);
// @shutdown UC.globalKeybindings.destroy();
// ==/UserScript==
(() => {
// Configure global keybindings
const KEYBINDINGS = () => ({
RELEASE: [
[ctrl(key('j')), nextTab()],
[ctrl(key('k')), prevTab()],
[alt(key('j')), moveSelectedTabBy(+1)],
[alt(key('k')), moveSelectedTabBy(-1)],
[ctrl(shift(key('J'))), moveSelectedTabBy(+1)],
[ctrl(shift(key('K'))), moveSelectedTabBy(-1)],
...(Array.from({ length: 10 }, (_, idx) =>
[ctrl(key(idx === 9 ? 0 : idx + 1)), tabIndex(idx)],
)),
],
PRESS: [
// Prevent the default browser's action
[ctrl(shift(key('J'))), preventDefault()],
[ctrl(shift(key('K'))), preventDefault()],
],
});
const nextTab = () => () => updateTabIndex((n, len) => (n + 1) % len);
const prevTab = () => () => updateTabIndex((n, len) => n === 0 ? len - 1 : n - 1);
const tabIndex = idx => () => updateTabIndex((_n, _len) => idx)
const preventDefault = f => e => { e.preventDefault(); f?.(e); };
const moveSelectedTabBy = incr => () => updateSelectedTabIndex(incr);
const ctrl = b => e => b(e) && e.ctrlKey;
const alt = b => e => b(e) && e.altKey;
const shift = b => e => b(e) && e.shiftKey;
const key = key => e => `${e.key}` === `${key}`;
const updateTabIndex = (f) => {
const newIndex = f(gBrowser.tabContainer.selectedIndex, gBrowser.tabs.length)
if (typeof newIndex !== 'number') return;
if (newIndex >= gBrowser.tabContainer.allTabs.length) return;
if (newIndex < 0) return;
gBrowser.selectTabAtIndex(newIndex);
};
const updateSelectedTabIndex = (incr) => {
if (typeof incr !== 'number') return;
if (incr === +1) return gBrowser.moveTabForward();
if (incr === -1) return gBrowser.moveTabBackward();
const newIndex = gBrowser.tabContainer.selectedIndex + incr;
if (newIndex >= gBrowser.tabContainer.allTabs.length) return;
if (newIndex < 0) return;
gBrowser.moveTabTo(gBrowser.selectedTab, newIndex)
};
const module = {
enabled: true,
evaluateKeybindings: (bindings, e) => {
if (!module.enabled) return;
for (const [isKey, action] of bindings) {
if (isKey(e)) {
const shouldContinue = action(e);
if (!shouldContinue) break;
}
}
},
handleKeyUpEvent: e => module.evaluateKeybindings(KEYBINDINGS().RELEASE, e),
handleKeyDownEvent: e => module.evaluateKeybindings(KEYBINDINGS().PRESS, e),
init(win) {
let observe = () => {
Services.obs.removeObserver(observe, 'browser-window-before-show');
win.addEventListener('keyup', module.handleKeyUpEvent, true);
win.addEventListener('keydown', module.handleKeyDownEvent, true);
}
if (win.__SSi) {
win.addEventListener('keyup', module.handleKeyUpEvent, true);
win.addEventListener('keydown', module.handleKeyDownEvent, true);
} else {
Services.obs.addObserver(observe, 'browser-window-before-show');
}
},
destroy() {
_uc.windows((_doc, win) => {
win.removeEventListener('keyup', module.handleKeyUpEvent, true);
win.removeEventListener('keydown', module.handleKeyDownEvent, true);
});
delete UC.globalKeybindings;
},
};
UC.globalKeybindings = module;
})();
|