reslop 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -1
- package/LICENSE +1 -1
- package/README.md +12 -13
- package/bin/reslop.js +3 -8
- package/lib/ansi.js +32 -19
- package/lib/capabilities.js +8 -12
- package/lib/cli.js +40 -74
- package/lib/clipboard.js +48 -18
- package/lib/dashboard/git.js +128 -0
- package/lib/dashboard/model.js +332 -0
- package/lib/dashboard/npm.js +193 -0
- package/lib/dashboard/tree.js +278 -0
- package/lib/deps-diff.js +196 -404
- package/lib/deps.js +240 -399
- package/lib/detect.js +8 -18
- package/lib/diff/align.js +41 -113
- package/lib/diff/diff.js +12 -43
- package/lib/diff/display.js +25 -36
- package/lib/diff/edit.js +6 -20
- package/lib/diff/inline.js +138 -141
- package/lib/diff/items.js +33 -47
- package/lib/diff/parse.js +28 -56
- package/lib/diff/patch.js +12 -33
- package/lib/diff/unit.js +90 -206
- package/lib/editor.js +98 -55
- package/lib/files.js +86 -103
- package/lib/git-branches.js +254 -416
- package/lib/git-deps.js +182 -344
- package/lib/git-reword-todo.js +5 -13
- package/lib/git-worktree.js +141 -212
- package/lib/git.js +21 -49
- package/lib/github.js +67 -181
- package/lib/gitlab.js +40 -90
- package/lib/highlight/bash.js +55 -177
- package/lib/highlight/core.js +157 -132
- package/lib/highlight/css.js +25 -58
- package/lib/highlight/csv.js +19 -37
- package/lib/highlight/dart.js +72 -213
- package/lib/highlight/dot.js +16 -26
- package/lib/highlight/html.js +42 -63
- package/lib/highlight/js.js +177 -506
- package/lib/highlight/json.js +17 -37
- package/lib/highlight/log.js +22 -35
- package/lib/highlight/txt.js +9 -22
- package/lib/highlight.js +17 -46
- package/lib/keys.js +62 -85
- package/lib/manifest.js +67 -130
- package/lib/npm-commands.js +119 -189
- package/lib/remote.js +141 -197
- package/lib/render/branches.js +66 -73
- package/lib/render/chrome.js +264 -323
- package/lib/render/commits.js +187 -500
- package/lib/render/dash-activity.js +212 -0
- package/lib/render/dash-blocks.js +245 -0
- package/lib/render/dash-table.js +290 -0
- package/lib/render/dashboard.js +62 -0
- package/lib/render/diff.js +123 -228
- package/lib/render/files.js +45 -99
- package/lib/render/frame.js +129 -183
- package/lib/render/notes.js +144 -160
- package/lib/render/npm.js +234 -112
- package/lib/render/present.js +4 -11
- package/lib/render/primitives.js +131 -170
- package/lib/render/render.js +5 -14
- package/lib/render/report.js +43 -0
- package/lib/render/tiles.js +260 -0
- package/lib/render/unit.js +15 -28
- package/lib/report-model.js +110 -33
- package/lib/report-parse.js +56 -38
- package/lib/report-render.js +102 -59
- package/lib/report-run.js +87 -78
- package/lib/report-test.js +256 -141
- package/lib/report-tools.js +96 -161
- package/lib/review-merge.js +114 -152
- package/lib/review.js +115 -189
- package/lib/runs.js +225 -0
- package/lib/select.js +89 -75
- package/lib/session/accessors.js +14 -21
- package/lib/session/actions.js +82 -63
- package/lib/session/branches.js +193 -247
- package/lib/session/change-actions.js +171 -214
- package/lib/session/commit.js +280 -342
- package/lib/session/compose.js +559 -674
- package/lib/session/dashboard.js +385 -0
- package/lib/session/dispatch.js +164 -157
- package/lib/session/edit-click.js +57 -0
- package/lib/session/files-pane.js +85 -53
- package/lib/session/items.js +73 -104
- package/lib/session/lifecycle.js +403 -541
- package/lib/session/load.js +48 -68
- package/lib/session/navigation.js +96 -87
- package/lib/session/npm.js +409 -345
- package/lib/session/ops.js +196 -63
- package/lib/session/pointer.js +23 -15
- package/lib/session/progress.js +33 -21
- package/lib/session/review.js +33 -54
- package/lib/session/tasks.js +333 -0
- package/lib/session/templates.js +51 -59
- package/lib/session/terminal.js +85 -136
- package/lib/session/unit.js +3 -4
- package/lib/session/update.js +76 -97
- package/lib/session/view.js +52 -83
- package/lib/session/watch.js +208 -204
- package/lib/session.js +112 -237
- package/lib/update.js +45 -116
- package/lib/utilities.js +67 -89
- package/lib/wrap.js +33 -44
- package/package.json +1 -1
- package/lib/session/todos.js +0 -293
package/lib/highlight/json.js
CHANGED
|
@@ -1,51 +1,31 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const core = require('./core.js');
|
|
4
|
-
const { emit,
|
|
4
|
+
const { emit, wordStyles, scanWhile, stringEnd } = core;
|
|
5
5
|
|
|
6
|
-
const JSON_LITERAL = {
|
|
7
|
-
true: 'literal',
|
|
8
|
-
false: 'literal',
|
|
9
|
-
null: 'literal',
|
|
10
|
-
};
|
|
6
|
+
const JSON_LITERAL = wordStyles({ literal: ['true', 'false', 'null'] });
|
|
11
7
|
|
|
12
8
|
const highlight = (source) => {
|
|
13
9
|
const out = [];
|
|
14
10
|
let i = 0;
|
|
15
|
-
const
|
|
16
|
-
|
|
11
|
+
const take = (style, end) => {
|
|
12
|
+
emit(out, style, source.slice(i, end));
|
|
13
|
+
i = end;
|
|
14
|
+
};
|
|
15
|
+
while (i < source.length) {
|
|
17
16
|
const ch = source[i];
|
|
18
17
|
if (ch === '"') {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
while (j < n && /[0-9.eE+-]/.test(source[j])) j += 1;
|
|
30
|
-
emit(out, 'number', source.slice(i, j));
|
|
31
|
-
i = j;
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
if (/[a-z]/.test(ch)) {
|
|
35
|
-
let j = i;
|
|
36
|
-
while (j < n && /[a-z]/.test(source[j])) j += 1;
|
|
37
|
-
const word = source.slice(i, j);
|
|
38
|
-
emit(out, JSON_LITERAL[word] ?? 'plain', word);
|
|
39
|
-
i = j;
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
if (/[{}[\],:]/.test(ch)) {
|
|
43
|
-
emit(out, 'punct', ch);
|
|
44
|
-
i += 1;
|
|
45
|
-
continue;
|
|
18
|
+
const end = stringEnd(source, i);
|
|
19
|
+
const after = source[scanWhile(source, end, /\s/)];
|
|
20
|
+
take(after === ':' ? 'property' : 'string', end);
|
|
21
|
+
} else if (/[0-9-]/.test(ch)) {
|
|
22
|
+
take('number', scanWhile(source, i, /[0-9.eE+-]/));
|
|
23
|
+
} else if (/[a-z]/.test(ch)) {
|
|
24
|
+
const end = scanWhile(source, i, /[a-z]/);
|
|
25
|
+
take(JSON_LITERAL[source.slice(i, end)] ?? 'plain', end);
|
|
26
|
+
} else {
|
|
27
|
+
take(/[{}[\],:]/.test(ch) ? 'punct' : 'plain', i + 1);
|
|
46
28
|
}
|
|
47
|
-
emit(out, 'plain', ch);
|
|
48
|
-
i += 1;
|
|
49
29
|
}
|
|
50
30
|
return out;
|
|
51
31
|
};
|
package/lib/highlight/log.js
CHANGED
|
@@ -1,59 +1,46 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const core = require('./core.js');
|
|
4
|
-
const { emit } = core;
|
|
4
|
+
const { emit, highlightLines, wordStyles } = core;
|
|
5
5
|
|
|
6
6
|
const LOG_DATETIME_RE = new RegExp(
|
|
7
7
|
'^(\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}' +
|
|
8
8
|
'(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?)',
|
|
9
9
|
);
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
};
|
|
11
|
+
const LOG_TAG_RE = /^(\s*)(\[[^\]]+\])/;
|
|
12
|
+
|
|
13
|
+
const LOG_TAG_STYLE = wordStyles({
|
|
14
|
+
logError: ['error', 'err'],
|
|
15
|
+
logWarn: ['warn', 'warning'],
|
|
16
|
+
logInfo: ['info'],
|
|
17
|
+
logDebug: ['debug'],
|
|
18
|
+
});
|
|
20
19
|
|
|
21
20
|
const highlightLogLine = (line) => {
|
|
22
|
-
if (!line) return [];
|
|
23
21
|
const out = [];
|
|
24
22
|
let rest = line;
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
emit(out, 'logDate',
|
|
28
|
-
rest = rest.slice(
|
|
23
|
+
const date = LOG_DATETIME_RE.exec(rest);
|
|
24
|
+
if (date) {
|
|
25
|
+
emit(out, 'logDate', date[1]);
|
|
26
|
+
rest = rest.slice(date[1].length);
|
|
29
27
|
}
|
|
30
|
-
const tag =
|
|
28
|
+
const tag = LOG_TAG_RE.exec(rest);
|
|
31
29
|
if (tag) {
|
|
32
30
|
emit(out, 'plain', tag[1]);
|
|
33
|
-
const name = tag[2].
|
|
31
|
+
const name = tag[2].slice(1, -1).toLowerCase();
|
|
34
32
|
emit(out, LOG_TAG_STYLE[name] || 'plain', tag[2]);
|
|
35
33
|
rest = rest.slice(tag[0].length);
|
|
36
34
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
emit(out, `logCol${i}`, parts[i]);
|
|
42
|
-
}
|
|
43
|
-
return out;
|
|
35
|
+
const columns = rest.split('\t');
|
|
36
|
+
for (let i = 0; i < columns.length; i += 1) {
|
|
37
|
+
if (i) emit(out, 'plain', '\t');
|
|
38
|
+
emit(out, `logCol${i}`, columns[i]);
|
|
44
39
|
}
|
|
45
|
-
if (rest) emit(out, 'logCol0', rest);
|
|
46
40
|
return out;
|
|
47
41
|
};
|
|
48
42
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
53
|
-
if (i) emit(out, 'plain', '\n');
|
|
54
|
-
for (const t of highlightLogLine(lines[i])) out.push(t);
|
|
55
|
-
}
|
|
56
|
-
return out;
|
|
43
|
+
module.exports = {
|
|
44
|
+
langs: ['log'],
|
|
45
|
+
highlight: highlightLines(highlightLogLine),
|
|
57
46
|
};
|
|
58
|
-
|
|
59
|
-
module.exports = { langs: ['log'], highlight };
|
package/lib/highlight/txt.js
CHANGED
|
@@ -1,37 +1,24 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const core = require('./core.js');
|
|
4
|
-
const { emit } = core;
|
|
4
|
+
const { emit, highlightLines } = core;
|
|
5
|
+
|
|
6
|
+
const URL_RE = /https?:\/\/[^\s<>"']+|www\.[^\s<>"']+/g;
|
|
5
7
|
|
|
6
8
|
const highlightTxtLine = (line) => {
|
|
7
|
-
if (!line) return [];
|
|
8
9
|
const out = [];
|
|
9
|
-
const re = /(https?:\/\/[^\s<>"']+|www\.[^\s<>"']+)/g;
|
|
10
10
|
let last = 0;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
last = m.index + m[0].length;
|
|
16
|
-
m = re.exec(line);
|
|
17
|
-
}
|
|
18
|
-
if (last < line.length) emit(out, 'plain', line.slice(last));
|
|
19
|
-
if (!out.length) emit(out, 'plain', line);
|
|
20
|
-
return out;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const highlight = (source) => {
|
|
24
|
-
const lines = source.split('\n');
|
|
25
|
-
const out = [];
|
|
26
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
27
|
-
if (i) emit(out, 'plain', '\n');
|
|
28
|
-
for (const t of highlightTxtLine(lines[i])) out.push(t);
|
|
11
|
+
for (const match of line.matchAll(URL_RE)) {
|
|
12
|
+
emit(out, 'plain', line.slice(last, match.index));
|
|
13
|
+
emit(out, 'string', match[0]);
|
|
14
|
+
last = match.index + match[0].length;
|
|
29
15
|
}
|
|
16
|
+
emit(out, 'plain', line.slice(last));
|
|
30
17
|
return out;
|
|
31
18
|
};
|
|
32
19
|
|
|
33
20
|
module.exports = {
|
|
34
21
|
langs: ['txt', 'py', 'md'],
|
|
35
22
|
aliases: { text: 'txt', plain: 'txt', markdown: 'md', python: 'py' },
|
|
36
|
-
highlight,
|
|
23
|
+
highlight: highlightLines(highlightTxtLine),
|
|
37
24
|
};
|
package/lib/highlight.js
CHANGED
|
@@ -1,40 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const fs = require('node:fs');
|
|
4
|
-
const path = require('node:path');
|
|
5
|
-
|
|
6
3
|
const core = require('./highlight/core.js');
|
|
7
|
-
const { tokensText } = core;
|
|
4
|
+
const { tokensText, words } = core;
|
|
8
5
|
|
|
9
|
-
const
|
|
10
|
-
const SKIP = ['core.js'];
|
|
6
|
+
const PLUGIN_NAMES = words('bash css csv dart dot html js json log txt');
|
|
11
7
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
.readdirSync(PLUGIN_DIR)
|
|
15
|
-
.filter((name) => name.endsWith('.js') && !SKIP.includes(name));
|
|
16
|
-
names.sort();
|
|
17
|
-
return names.map((file) => require(path.join(PLUGIN_DIR, file)));
|
|
18
|
-
};
|
|
8
|
+
const HIGHLIGHTERS = Object.create(null);
|
|
9
|
+
const LANG = Object.create(null);
|
|
19
10
|
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
highlighters[id] = plugin.highlight;
|
|
26
|
-
lang[id] = id;
|
|
27
|
-
}
|
|
28
|
-
const aliases = plugin.aliases ?? {};
|
|
29
|
-
for (const name of Object.keys(aliases)) lang[name] = aliases[name];
|
|
11
|
+
for (const name of PLUGIN_NAMES) {
|
|
12
|
+
const plugin = require(`./highlight/${name}.js`);
|
|
13
|
+
for (const id of plugin.langs) {
|
|
14
|
+
HIGHLIGHTERS[id] = plugin.highlight;
|
|
15
|
+
LANG[id] = id;
|
|
30
16
|
}
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const PLUGINS = loadPlugins();
|
|
35
|
-
const registry = indexPlugins(PLUGINS);
|
|
36
|
-
const HIGHLIGHTERS = registry.highlighters;
|
|
37
|
-
const LANG = registry.lang;
|
|
17
|
+
Object.assign(LANG, plugin.aliases);
|
|
18
|
+
}
|
|
38
19
|
|
|
39
20
|
const mapLang = (name) => {
|
|
40
21
|
if (!name) return 'txt';
|
|
@@ -42,10 +23,8 @@ const mapLang = (name) => {
|
|
|
42
23
|
};
|
|
43
24
|
|
|
44
25
|
const tokenize = (lang, source) => {
|
|
45
|
-
const text = source ?? '';
|
|
46
26
|
const key = mapLang(lang);
|
|
47
|
-
|
|
48
|
-
return highlight(text, key);
|
|
27
|
+
return HIGHLIGHTERS[key](source ?? '', key);
|
|
49
28
|
};
|
|
50
29
|
|
|
51
30
|
const overlayTokens = (tokens, spans) => {
|
|
@@ -61,14 +40,12 @@ const overlayTokens = (tokens, spans) => {
|
|
|
61
40
|
const span = diff[spanIndex];
|
|
62
41
|
const tokenText = token.text ?? '';
|
|
63
42
|
const spanText = span.text ?? '';
|
|
64
|
-
const
|
|
65
|
-
const spanLeft = spanText.length - spanOff;
|
|
66
|
-
const n = Math.min(tokenLeft, spanLeft);
|
|
43
|
+
const n = Math.min(tokenText.length - tokenOff, spanText.length - spanOff);
|
|
67
44
|
if (n > 0) {
|
|
68
|
-
const
|
|
45
|
+
const style = typeof token.style === 'string' && token.style;
|
|
69
46
|
pieces.push({
|
|
70
47
|
text: tokenText.slice(tokenOff, tokenOff + n),
|
|
71
|
-
style:
|
|
48
|
+
style: style || 'plain',
|
|
72
49
|
changed: span.changed === true,
|
|
73
50
|
});
|
|
74
51
|
}
|
|
@@ -83,21 +60,15 @@ const overlayTokens = (tokens, spans) => {
|
|
|
83
60
|
spanOff = 0;
|
|
84
61
|
}
|
|
85
62
|
}
|
|
86
|
-
|
|
63
|
+
for (; spanIndex < diff.length; spanIndex++) {
|
|
87
64
|
const span = diff[spanIndex];
|
|
88
65
|
const text = (span.text ?? '').slice(spanOff);
|
|
89
66
|
if (text) {
|
|
90
67
|
pieces.push({ text, style: 'plain', changed: span.changed === true });
|
|
91
68
|
}
|
|
92
|
-
spanIndex += 1;
|
|
93
69
|
spanOff = 0;
|
|
94
70
|
}
|
|
95
71
|
return pieces;
|
|
96
72
|
};
|
|
97
73
|
|
|
98
|
-
module.exports = {
|
|
99
|
-
tokensText,
|
|
100
|
-
tokenize,
|
|
101
|
-
overlayTokens,
|
|
102
|
-
mapLang,
|
|
103
|
-
};
|
|
74
|
+
module.exports = { tokensText, tokenize, overlayTokens, mapLang };
|
package/lib/keys.js
CHANGED
|
@@ -3,15 +3,13 @@
|
|
|
3
3
|
const actions = require('./session/actions.js');
|
|
4
4
|
|
|
5
5
|
const { ACTIONS, ACTION_IDS, BRANCH_ACTIONS, COMMIT_ACTIONS } = actions;
|
|
6
|
-
const {
|
|
7
|
-
const {
|
|
8
|
-
const {
|
|
6
|
+
const { DASH_IDS, DASH_HIDDEN } = actions;
|
|
7
|
+
const { DIFF_DISABLED, FILES_GIT_DISABLED, FILES_HIDDEN } = actions;
|
|
8
|
+
const { TASKS_DISABLED, BRANCHES_DISABLED } = actions;
|
|
9
9
|
const { COMMITS_DISABLED, UNIT_DISABLED, NPM_DISABLED } = actions;
|
|
10
|
-
const {
|
|
11
|
-
const {
|
|
12
|
-
const {
|
|
13
|
-
const { CONFIRM, CONFIRM_MODE, confirmKey, applyConfirm } = actions;
|
|
14
|
-
const { confirmPrefix, promptFromChoices } = actions;
|
|
10
|
+
const { diffGitDisabled, branchGitDisabled, commitGitDisabled } = actions;
|
|
11
|
+
const { actionLetter, buttonWord } = actions;
|
|
12
|
+
const { CONFIRM, confirmPrefix, promptFromChoices } = actions;
|
|
15
13
|
|
|
16
14
|
const CSI_KEYS = {
|
|
17
15
|
A: 'up',
|
|
@@ -48,46 +46,52 @@ const MOUSE_WHEEL = {
|
|
|
48
46
|
65: 'wheelDown',
|
|
49
47
|
};
|
|
50
48
|
|
|
51
|
-
const
|
|
52
|
-
const body = rest.slice(2);
|
|
53
|
-
let i = 0;
|
|
54
|
-
while (i < body.length) {
|
|
55
|
-
const code = body.charCodeAt(i);
|
|
56
|
-
if (code >= 64 && code <= 126) break;
|
|
57
|
-
i += 1;
|
|
58
|
-
}
|
|
59
|
-
if (i >= body.length) {
|
|
60
|
-
if (rest.length > CSI_MAX) {
|
|
61
|
-
return { event: { type: 'key', key: 'escape' }, eat: 1 };
|
|
62
|
-
}
|
|
63
|
-
return { needMore: true };
|
|
64
|
-
}
|
|
65
|
-
return { params: body.slice(0, i), final: body[i], eat: 2 + i + 1 };
|
|
66
|
-
};
|
|
49
|
+
const NEED_MORE = { needMore: true };
|
|
67
50
|
|
|
68
|
-
const
|
|
51
|
+
const keyAt = (key, end) => ({ event: { type: 'key', key }, end });
|
|
52
|
+
|
|
53
|
+
const modifiedKey = (base, modText) => {
|
|
54
|
+
const arrow =
|
|
55
|
+
base === 'left' || base === 'right' || base === 'up' || base === 'down';
|
|
56
|
+
const end = base === 'home' || base === 'end';
|
|
57
|
+
if (!arrow && !end) return base;
|
|
69
58
|
const mod = parseInt(modText, 10);
|
|
70
|
-
|
|
59
|
+
const bits = Number.isFinite(mod) ? mod - 1 : 0;
|
|
60
|
+
const ctrl = (bits & 4) !== 0;
|
|
61
|
+
const shift = (bits & 1) !== 0;
|
|
62
|
+
if (ctrl && shift && arrow) return `ctrl-shift-${base}`;
|
|
63
|
+
if (ctrl && arrow) return `ctrl-${base}`;
|
|
64
|
+
if (shift) return `shift-${base}`;
|
|
65
|
+
return base;
|
|
71
66
|
};
|
|
72
67
|
|
|
73
68
|
const keyFromCsi = (paramsText, final) => {
|
|
74
69
|
const params = paramsText ? paramsText.split(';') : [];
|
|
75
|
-
|
|
76
|
-
const base = CSI_KEYS[final];
|
|
70
|
+
const base = final === '~' ? CSI_TILDE[params[0]] : CSI_KEYS[final];
|
|
77
71
|
if (!base) return null;
|
|
78
72
|
if (params.length < 2) return base;
|
|
79
|
-
|
|
80
|
-
base === 'left' || base === 'right' || base === 'up' || base === 'down';
|
|
81
|
-
if (ctrlHeld(params[1]) && arrow) return `ctrl-${base}`;
|
|
82
|
-
return base;
|
|
73
|
+
return modifiedKey(base, params[1]);
|
|
83
74
|
};
|
|
84
75
|
|
|
85
|
-
const
|
|
76
|
+
const parseCsi = (rest, start) => {
|
|
77
|
+
let i = 2;
|
|
78
|
+
while (i < rest.length) {
|
|
79
|
+
const code = rest.charCodeAt(i);
|
|
80
|
+
if (code >= 64 && code <= 126) break;
|
|
81
|
+
i += 1;
|
|
82
|
+
}
|
|
83
|
+
if (i >= rest.length) {
|
|
84
|
+
return rest.length > CSI_MAX ? keyAt('escape', start + 1) : NEED_MORE;
|
|
85
|
+
}
|
|
86
|
+
const key = keyFromCsi(rest.slice(2, i), rest[i]);
|
|
87
|
+
return key ? keyAt(key, start + i + 1) : keyAt('escape', start + 1);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const mouseKind = (button, press) => {
|
|
86
91
|
const wheel = MOUSE_WHEEL[button];
|
|
87
92
|
if (wheel) return wheel;
|
|
88
93
|
if (!press) return 'release';
|
|
89
|
-
|
|
90
|
-
return 'press';
|
|
94
|
+
return button & 32 ? 'drag' : 'press';
|
|
91
95
|
};
|
|
92
96
|
|
|
93
97
|
const parseMouse = (body, flag) => {
|
|
@@ -100,81 +104,60 @@ const parseMouse = (body, flag) => {
|
|
|
100
104
|
return null;
|
|
101
105
|
}
|
|
102
106
|
const press = flag === 'M';
|
|
103
|
-
const kind =
|
|
107
|
+
const kind = mouseKind(button, press);
|
|
104
108
|
return { type: 'mouse', button, x, y, press, kind, btn: button & 3 };
|
|
105
109
|
};
|
|
106
110
|
|
|
107
111
|
const parseEsc = (text, start) => {
|
|
108
112
|
const rest = text.slice(start);
|
|
109
|
-
if (rest === '\x1b'
|
|
110
|
-
if (rest.startsWith('\x1b[') && rest.length === 2) return { needMore: true };
|
|
113
|
+
if (rest === '\x1b' || rest === '\x1b[') return NEED_MORE;
|
|
111
114
|
if (rest.startsWith('\x1b[<')) {
|
|
112
115
|
const endM = rest.search(/[Mm]/);
|
|
113
|
-
if (endM < 0) return
|
|
114
|
-
const
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
if (!mouse) {
|
|
118
|
-
return { event: { type: 'key', key: 'escape' }, end: start + endM + 1 };
|
|
119
|
-
}
|
|
120
|
-
return { event: mouse, end: start + endM + 1 };
|
|
121
|
-
}
|
|
122
|
-
if (rest.startsWith('\x1b[')) {
|
|
123
|
-
const csi = parseCsiSeq(rest);
|
|
124
|
-
if (csi.needMore) return csi;
|
|
125
|
-
if (csi.event) return { event: csi.event, end: start + csi.eat };
|
|
126
|
-
const key = keyFromCsi(csi.params, csi.final);
|
|
127
|
-
if (key) return { event: { type: 'key', key }, end: start + csi.eat };
|
|
128
|
-
return { event: { type: 'key', key: 'escape' }, end: start + 1 };
|
|
116
|
+
if (endM < 0) return NEED_MORE;
|
|
117
|
+
const mouse = parseMouse(rest.slice(3, endM), rest[endM]);
|
|
118
|
+
const end = start + endM + 1;
|
|
119
|
+
return mouse ? { event: mouse, end } : keyAt('escape', end);
|
|
129
120
|
}
|
|
121
|
+
if (rest.startsWith('\x1b[')) return parseCsi(rest, start);
|
|
130
122
|
if (rest.startsWith('\x1bO')) {
|
|
131
|
-
if (rest.length < 3) return
|
|
123
|
+
if (rest.length < 3) return NEED_MORE;
|
|
132
124
|
const key = CSI_KEYS[rest[2]];
|
|
133
|
-
|
|
134
|
-
return { event: { type: 'key', key: 'escape' }, end: start + 1 };
|
|
125
|
+
return key ? keyAt(key, start + 3) : keyAt('escape', start + 1);
|
|
135
126
|
}
|
|
136
|
-
return
|
|
127
|
+
return keyAt('escape', start + 1);
|
|
137
128
|
};
|
|
138
129
|
|
|
139
130
|
const decodeChunk = (text, carry = '') => {
|
|
140
131
|
const source = carry + text;
|
|
141
|
-
const events =
|
|
142
|
-
let n = 0;
|
|
132
|
+
const events = [];
|
|
143
133
|
let i = 0;
|
|
144
134
|
while (i < source.length) {
|
|
145
135
|
const ch = source[i];
|
|
146
136
|
if (ch === '\x1b') {
|
|
147
137
|
const parsed = parseEsc(source, i);
|
|
148
|
-
if (parsed.needMore) {
|
|
149
|
-
|
|
150
|
-
return { events, carry: source.slice(i) };
|
|
151
|
-
}
|
|
152
|
-
events[n++] = parsed.event;
|
|
138
|
+
if (parsed.needMore) return { events, carry: source.slice(i) };
|
|
139
|
+
events.push(parsed.event);
|
|
153
140
|
i = parsed.end;
|
|
154
141
|
continue;
|
|
155
142
|
}
|
|
156
143
|
const named = LITERAL_KEY[ch];
|
|
144
|
+
const code = source.charCodeAt(i);
|
|
157
145
|
if (named) {
|
|
158
|
-
events
|
|
146
|
+
events.push({ type: 'key', key: named });
|
|
159
147
|
i += 1;
|
|
160
148
|
continue;
|
|
161
149
|
}
|
|
162
|
-
const code = source.charCodeAt(i);
|
|
163
150
|
if (code >= 1 && code <= 26) {
|
|
164
151
|
const letter = String.fromCharCode(96 + code);
|
|
165
|
-
events
|
|
152
|
+
events.push({ type: 'key', key: `ctrl-${letter}` });
|
|
166
153
|
i += 1;
|
|
167
154
|
continue;
|
|
168
155
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
events[n++] = { type: 'key', key: ch };
|
|
175
|
-
i += 1;
|
|
156
|
+
const isPair = code >= 0xd800 && code <= 0xdbff && i + 1 < source.length;
|
|
157
|
+
const size = isPair ? 2 : 1;
|
|
158
|
+
events.push({ type: 'key', key: source.slice(i, i + size) });
|
|
159
|
+
i += size;
|
|
176
160
|
}
|
|
177
|
-
events.length = n;
|
|
178
161
|
return { events, carry: '' };
|
|
179
162
|
};
|
|
180
163
|
|
|
@@ -188,32 +171,26 @@ const hitAction = (hits, x) => {
|
|
|
188
171
|
module.exports = {
|
|
189
172
|
ACTIONS,
|
|
190
173
|
ACTION_IDS,
|
|
174
|
+
DASH_IDS,
|
|
175
|
+
DASH_HIDDEN,
|
|
191
176
|
BRANCH_ACTIONS,
|
|
192
177
|
COMMIT_ACTIONS,
|
|
193
178
|
DIFF_DISABLED,
|
|
194
|
-
FILES_DISABLED,
|
|
195
179
|
FILES_HIDDEN,
|
|
196
180
|
FILES_GIT_DISABLED,
|
|
197
|
-
|
|
198
|
-
TODO_DISABLED,
|
|
181
|
+
TASKS_DISABLED,
|
|
199
182
|
BRANCHES_DISABLED,
|
|
200
183
|
COMMITS_DISABLED,
|
|
201
184
|
NPM_DISABLED,
|
|
202
185
|
UNIT_DISABLED,
|
|
203
|
-
disabledActions,
|
|
204
186
|
diffGitDisabled,
|
|
205
187
|
branchGitDisabled,
|
|
206
188
|
commitGitDisabled,
|
|
207
189
|
decodeChunk,
|
|
208
|
-
actionFromKey,
|
|
209
|
-
actionHot,
|
|
210
190
|
actionLetter,
|
|
211
191
|
buttonWord,
|
|
212
192
|
hitAction,
|
|
213
193
|
CONFIRM,
|
|
214
|
-
CONFIRM_MODE,
|
|
215
|
-
confirmKey,
|
|
216
|
-
applyConfirm,
|
|
217
194
|
confirmPrefix,
|
|
218
195
|
promptFromChoices,
|
|
219
196
|
};
|