-
Notifications
You must be signed in to change notification settings - Fork 0
/
vim.js
124 lines (110 loc) · 2.54 KB
/
vim.js
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
// 简易的 Vim 按键模拟。
class __Vim {
constructor() {
this.maps = {}; // 已知的按键绑定映射
this.tree = {}; // TRIE 树,用于搜索
this.stack = []; // 按键栈
this.timer = null; // 定时清理掉无效的按键
this.init();
}
init() {
document.body.addEventListener('keypress', (function (e) {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
if (e.target.tagName != 'BODY') {
this.stack = [];
return;
}
this.stack.push(e.key);
this.trigger();
if (this.stack.length) {
this.timer = setInterval(() => {
if (this.stack.length > 0) {
this.stack = [];
console.log('key stack cleared');
}
}, 1000);
}
}).bind(this));
this.maps = {
gg: function() {
window.scrollTo({left: 0, top: 0, behavior: 'smooth'});
},
G: function() {
window.scrollTo({left: 0, top: document.body.scrollHeight, behavior: 'smooth'});
},
j: function() {
window.scrollBy({left: 0, top: +150, behavior: 'smooth'});
},
k: function() {
window.scrollBy({left: 0, top: -150, behavior: 'smooth'});
},
f: function() {
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
document.documentElement.requestFullscreen();
}
},
r: function() {
location.reload();
},
b: function() {
location.pathname = '/';
},
'?': function() {
console.log('Vim Help');
console.table({
gg: '回到页首',
G: '回到页尾',
j: '向下滚动',
k: '向上滚动',
f: '进入全屏',
r: '刷新',
b: '回到首页',
});
},
};
for (let key in this.maps) {
let node = this.tree;
for (let i in key) {
if (!node[key[i]]) {
node[key[i]] = {};
}
node = node[key[i]];
}
node.__handler = this.maps[key];
}
}
trigger() {
let node = this.tree;
console.log('stack:', this.stack);
// 遍历树以寻找匹配按键序列的按键映射/绑定。
for (let i = 0; i < this.stack.length; i++) {
let child = node[this.stack[i]];
if (!child) {
node = null;
break;
}
node = child;
}
// 说明根本没有这个按键映射,
// 属于无效的按键映射,清空。
if (!node) {
console.log('no such key binding:', this.stack);
this.stack = [];
return;
}
// 按键组合还没有到达最后一个按键。
if (!node.__handler) {
return;
}
// console.log(node);
console.log('triggering:', node);
node.__handler.call(this);
this.stack = [];
}
}
let vim = new __Vim();