reslop 0.2.5 → 0.2.7

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.
Files changed (114) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/LICENSE +1 -1
  3. package/README.md +11 -11
  4. package/bin/reslop.js +3 -8
  5. package/lib/ansi.js +72 -19
  6. package/lib/api.js +1 -1
  7. package/lib/capabilities.js +8 -8
  8. package/lib/cli.js +61 -75
  9. package/lib/clipboard.js +39 -47
  10. package/lib/dashboard/git.js +128 -0
  11. package/lib/dashboard/model.js +357 -0
  12. package/lib/dashboard/npm.js +290 -0
  13. package/lib/dashboard/tree.js +278 -0
  14. package/lib/deps-diff.js +197 -402
  15. package/lib/deps.js +113 -240
  16. package/lib/detect.js +8 -18
  17. package/lib/diff/align.js +41 -113
  18. package/lib/diff/diff.js +12 -43
  19. package/lib/diff/display.js +25 -36
  20. package/lib/diff/edit.js +6 -20
  21. package/lib/diff/inline.js +76 -144
  22. package/lib/diff/items.js +33 -47
  23. package/lib/diff/parse.js +28 -56
  24. package/lib/diff/patch.js +12 -33
  25. package/lib/diff/unit.js +79 -178
  26. package/lib/editor.js +52 -69
  27. package/lib/files.js +79 -91
  28. package/lib/find.js +61 -0
  29. package/lib/git-branches.js +254 -416
  30. package/lib/git-deps.js +148 -272
  31. package/lib/git-reword-todo.js +5 -13
  32. package/lib/git-worktree.js +161 -214
  33. package/lib/git.js +21 -49
  34. package/lib/github.js +67 -181
  35. package/lib/gitlab.js +40 -90
  36. package/lib/highlight/bash.js +55 -177
  37. package/lib/highlight/core.js +155 -141
  38. package/lib/highlight/css.js +25 -58
  39. package/lib/highlight/csv.js +19 -37
  40. package/lib/highlight/dart.js +72 -213
  41. package/lib/highlight/dot.js +14 -14
  42. package/lib/highlight/html.js +42 -63
  43. package/lib/highlight/js.js +177 -506
  44. package/lib/highlight/json.js +17 -37
  45. package/lib/highlight/log.js +19 -25
  46. package/lib/highlight/txt.js +7 -10
  47. package/lib/highlight.js +17 -46
  48. package/lib/keys.js +75 -83
  49. package/lib/manifest.js +67 -126
  50. package/lib/npm-commands.js +120 -169
  51. package/lib/remote.js +140 -190
  52. package/lib/render/branches.js +63 -61
  53. package/lib/render/chrome.js +412 -347
  54. package/lib/render/commits.js +160 -361
  55. package/lib/render/dash-activity.js +212 -0
  56. package/lib/render/dash-blocks.js +496 -0
  57. package/lib/render/dash-table.js +295 -0
  58. package/lib/render/dashboard.js +62 -0
  59. package/lib/render/diff.js +123 -258
  60. package/lib/render/files.js +60 -86
  61. package/lib/render/frame.js +82 -117
  62. package/lib/render/notes.js +150 -210
  63. package/lib/render/npm.js +213 -177
  64. package/lib/render/packages.js +93 -0
  65. package/lib/render/present.js +4 -11
  66. package/lib/render/primitives.js +77 -172
  67. package/lib/render/render.js +5 -14
  68. package/lib/render/report.js +43 -0
  69. package/lib/render/repos.js +226 -0
  70. package/lib/render/search.js +25 -0
  71. package/lib/render/tiles.js +355 -0
  72. package/lib/render/unit.js +15 -31
  73. package/lib/report-model.js +110 -33
  74. package/lib/report-parse.js +56 -37
  75. package/lib/report-render.js +102 -59
  76. package/lib/report-run.js +87 -77
  77. package/lib/report-test.js +221 -99
  78. package/lib/report-tools.js +96 -154
  79. package/lib/review-merge.js +33 -41
  80. package/lib/review.js +69 -129
  81. package/lib/runs.js +225 -0
  82. package/lib/select.js +53 -91
  83. package/lib/session/accessors.js +14 -21
  84. package/lib/session/actions.js +189 -65
  85. package/lib/session/branches.js +164 -222
  86. package/lib/session/change-actions.js +49 -119
  87. package/lib/session/commit.js +298 -352
  88. package/lib/session/compose.js +572 -715
  89. package/lib/session/dashboard.js +530 -0
  90. package/lib/session/dispatch.js +197 -171
  91. package/lib/session/files-pane.js +92 -45
  92. package/lib/session/find.js +94 -0
  93. package/lib/session/items.js +6 -17
  94. package/lib/session/lifecycle.js +420 -466
  95. package/lib/session/load.js +1 -14
  96. package/lib/session/navigation.js +4 -2
  97. package/lib/session/npm.js +403 -420
  98. package/lib/session/ops.js +5 -13
  99. package/lib/session/packages.js +143 -0
  100. package/lib/session/pointer.js +30 -14
  101. package/lib/session/progress.js +39 -30
  102. package/lib/session/review.js +1 -3
  103. package/lib/session/tasks.js +277 -236
  104. package/lib/session/templates.js +51 -59
  105. package/lib/session/terminal.js +85 -132
  106. package/lib/session/view.js +59 -80
  107. package/lib/session/watch.js +201 -212
  108. package/lib/session/workspace.js +455 -0
  109. package/lib/session.js +95 -161
  110. package/lib/update.js +44 -111
  111. package/lib/utilities.js +46 -88
  112. package/lib/workspace.js +166 -0
  113. package/lib/wrap.js +29 -55
  114. package/package.json +1 -1
@@ -1,51 +1,31 @@
1
1
  'use strict';
2
2
 
3
3
  const core = require('./core.js');
4
- const { emit, readString } = core;
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 n = source.length;
16
- while (i < n) {
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 { text, end } = readString(source, i);
20
- let k = end;
21
- while (k < n && /\s/.test(source[k])) k += 1;
22
- const kind = source[k] === ':' ? 'property' : 'string';
23
- emit(out, kind, text);
24
- i = end;
25
- continue;
26
- }
27
- if (/[0-9-]/.test(ch)) {
28
- let j = i;
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
  };
@@ -1,48 +1,42 @@
1
1
  'use strict';
2
2
 
3
3
  const core = require('./core.js');
4
- const { emit, highlightLines } = 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 LOG_TAG_STYLE = {
12
- error: 'logError',
13
- err: 'logError',
14
- warn: 'logWarn',
15
- warning: 'logWarn',
16
- info: 'logInfo',
17
- debug: 'logDebug',
18
- log: 'plain',
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 dm = rest.match(LOG_DATETIME_RE);
26
- if (dm) {
27
- emit(out, 'logDate', dm[1]);
28
- rest = rest.slice(dm[1].length);
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 = rest.match(/^(\s*)(\[[^\]]+\])/);
28
+ const tag = LOG_TAG_RE.exec(rest);
31
29
  if (tag) {
32
30
  emit(out, 'plain', tag[1]);
33
- const name = tag[2].replace(/^\[|\]$/g, '').toLowerCase();
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
- if (rest.includes('\t')) {
38
- const parts = rest.split('\t');
39
- for (let i = 0; i < parts.length; i += 1) {
40
- if (i) emit(out, 'plain', '\t');
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
 
@@ -3,20 +3,17 @@
3
3
  const core = require('./core.js');
4
4
  const { emit, highlightLines } = core;
5
5
 
6
+ const URL_RE = /https?:\/\/[^\s<>"']+|www\.[^\s<>"']+/g;
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
- let m = re.exec(line);
12
- while (m !== null) {
13
- if (m.index > last) emit(out, 'plain', line.slice(last, m.index));
14
- emit(out, 'string', m[0]);
15
- last = m.index + m[0].length;
16
- m = re.exec(line);
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;
17
15
  }
18
- if (last < line.length) emit(out, 'plain', line.slice(last));
19
- if (!out.length) emit(out, 'plain', line);
16
+ emit(out, 'plain', line.slice(last));
20
17
  return out;
21
18
  };
22
19
 
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 PLUGIN_DIR = path.join(__dirname, 'highlight');
10
- const SKIP = ['core.js'];
6
+ const PLUGIN_NAMES = words('bash css csv dart dot html js json log txt');
11
7
 
12
- const loadPlugins = () => {
13
- const names = fs
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 indexPlugins = (plugins) => {
21
- const highlighters = Object.create(null);
22
- const lang = Object.create(null);
23
- for (const plugin of plugins) {
24
- for (const id of plugin.langs) {
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
- return { highlighters, lang };
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
- const highlight = HIGHLIGHTERS[key] || HIGHLIGHTERS.txt;
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 tokenLeft = tokenText.length - tokenOff;
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 name = typeof token.style === 'string' ? token.style : 'plain';
45
+ const style = typeof token.style === 'string' && token.style;
69
46
  pieces.push({
70
47
  text: tokenText.slice(tokenOff, tokenOff + n),
71
- style: name || 'plain',
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
- while (spanIndex < diff.length) {
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,14 @@
3
3
  const actions = require('./session/actions.js');
4
4
 
5
5
  const { ACTIONS, ACTION_IDS, BRANCH_ACTIONS, COMMIT_ACTIONS } = actions;
6
- const { DIFF_DISABLED, FILES_DISABLED, FILES_GIT_DISABLED } = actions;
7
- const { FILES_HIDDEN, FILES_TASKS_DISABLED } = actions;
6
+ const { DASH_IDS, DASH_HIDDEN } = actions;
7
+ const { DIFF_DISABLED, FILES_GIT_DISABLED, FILES_HIDDEN } = actions;
8
8
  const { TASKS_DISABLED, BRANCHES_DISABLED } = actions;
9
9
  const { COMMITS_DISABLED, UNIT_DISABLED, NPM_DISABLED } = actions;
10
- const { disabledActions, diffGitDisabled, branchGitDisabled } = actions;
11
- const { commitGitDisabled } = actions;
12
- const { actionFromKey, actionHot, actionLetter, buttonWord } = actions;
13
- const { CONFIRM, CONFIRM_MODE, confirmKey, applyConfirm } = actions;
14
- const { confirmPrefix, promptFromChoices } = actions;
10
+ const { diffGitDisabled, branchGitDisabled, commitGitDisabled } = actions;
11
+ const { entryHasDiff, lineHasDiff, withoutMoves } = actions;
12
+ const { actionLetter, buttonWord } = actions;
13
+ const { CONFIRM, confirmPrefix, promptFromChoices } = actions;
15
14
 
16
15
  const CSI_KEYS = {
17
16
  A: 'up',
@@ -22,14 +21,35 @@ const CSI_KEYS = {
22
21
  F: 'end',
23
22
  };
24
23
 
24
+ const SS3_KEYS = {
25
+ ...CSI_KEYS,
26
+ P: 'f1',
27
+ Q: 'f2',
28
+ R: 'f3',
29
+ S: 'f4',
30
+ };
31
+
25
32
  const CSI_TILDE = {
26
33
  1: 'home',
34
+ 2: 'insert',
27
35
  3: 'delete',
28
36
  4: 'end',
29
37
  5: 'pageUp',
30
38
  6: 'pageDown',
31
39
  7: 'home',
32
40
  8: 'end',
41
+ 11: 'f1',
42
+ 12: 'f2',
43
+ 13: 'f3',
44
+ 14: 'f4',
45
+ 15: 'f5',
46
+ 17: 'f6',
47
+ 18: 'f7',
48
+ 19: 'f8',
49
+ 20: 'f9',
50
+ 21: 'f10',
51
+ 23: 'f11',
52
+ 24: 'f12',
33
53
  };
34
54
 
35
55
  const CSI_MAX = 16;
@@ -48,34 +68,17 @@ const MOUSE_WHEEL = {
48
68
  65: 'wheelDown',
49
69
  };
50
70
 
51
- const parseCsiSeq = (rest) => {
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
- };
71
+ const NEED_MORE = { needMore: true };
67
72
 
68
- const modifierBits = (modText) => {
69
- const mod = parseInt(modText, 10);
70
- if (!Number.isFinite(mod)) return 0;
71
- return mod - 1;
72
- };
73
+ const keyAt = (key, end) => ({ event: { type: 'key', key }, end });
73
74
 
74
- const modifiedKey = (base, bits) => {
75
+ const modifiedKey = (base, modText) => {
75
76
  const arrow =
76
77
  base === 'left' || base === 'right' || base === 'up' || base === 'down';
77
78
  const end = base === 'home' || base === 'end';
78
79
  if (!arrow && !end) return base;
80
+ const mod = parseInt(modText, 10);
81
+ const bits = Number.isFinite(mod) ? mod - 1 : 0;
79
82
  const ctrl = (bits & 4) !== 0;
80
83
  const shift = (bits & 1) !== 0;
81
84
  if (ctrl && shift && arrow) return `ctrl-shift-${base}`;
@@ -89,15 +92,28 @@ const keyFromCsi = (paramsText, final) => {
89
92
  const base = final === '~' ? CSI_TILDE[params[0]] : CSI_KEYS[final];
90
93
  if (!base) return null;
91
94
  if (params.length < 2) return base;
92
- return modifiedKey(base, modifierBits(params[1]));
95
+ return modifiedKey(base, params[1]);
93
96
  };
94
97
 
95
- const mouseKindFromButton = (button, press) => {
98
+ const parseCsi = (rest, start) => {
99
+ let i = 2;
100
+ while (i < rest.length) {
101
+ const code = rest.charCodeAt(i);
102
+ if (code >= 64 && code <= 126) break;
103
+ i += 1;
104
+ }
105
+ if (i >= rest.length) {
106
+ return rest.length > CSI_MAX ? keyAt('escape', start + 1) : NEED_MORE;
107
+ }
108
+ const key = keyFromCsi(rest.slice(2, i), rest[i]);
109
+ return key ? keyAt(key, start + i + 1) : keyAt('escape', start + 1);
110
+ };
111
+
112
+ const mouseKind = (button, press) => {
96
113
  const wheel = MOUSE_WHEEL[button];
97
114
  if (wheel) return wheel;
98
115
  if (!press) return 'release';
99
- if (button & 32) return 'drag';
100
- return 'press';
116
+ return button & 32 ? 'drag' : 'press';
101
117
  };
102
118
 
103
119
  const parseMouse = (body, flag) => {
@@ -110,81 +126,60 @@ const parseMouse = (body, flag) => {
110
126
  return null;
111
127
  }
112
128
  const press = flag === 'M';
113
- const kind = mouseKindFromButton(button, press);
129
+ const kind = mouseKind(button, press);
114
130
  return { type: 'mouse', button, x, y, press, kind, btn: button & 3 };
115
131
  };
116
132
 
117
133
  const parseEsc = (text, start) => {
118
134
  const rest = text.slice(start);
119
- if (rest === '\x1b') return { needMore: true };
120
- if (rest.startsWith('\x1b[') && rest.length === 2) return { needMore: true };
135
+ if (rest === '\x1b' || rest === '\x1b[') return NEED_MORE;
121
136
  if (rest.startsWith('\x1b[<')) {
122
137
  const endM = rest.search(/[Mm]/);
123
- if (endM < 0) return { needMore: true };
124
- const kind = rest[endM];
125
- const body = rest.slice(3, endM);
126
- const mouse = parseMouse(body, kind);
127
- if (!mouse) {
128
- return { event: { type: 'key', key: 'escape' }, end: start + endM + 1 };
129
- }
130
- return { event: mouse, end: start + endM + 1 };
131
- }
132
- if (rest.startsWith('\x1b[')) {
133
- const csi = parseCsiSeq(rest);
134
- if (csi.needMore) return csi;
135
- if (csi.event) return { event: csi.event, end: start + csi.eat };
136
- const key = keyFromCsi(csi.params, csi.final);
137
- if (key) return { event: { type: 'key', key }, end: start + csi.eat };
138
- return { event: { type: 'key', key: 'escape' }, end: start + 1 };
138
+ if (endM < 0) return NEED_MORE;
139
+ const mouse = parseMouse(rest.slice(3, endM), rest[endM]);
140
+ const end = start + endM + 1;
141
+ return mouse ? { event: mouse, end } : keyAt('escape', end);
139
142
  }
143
+ if (rest.startsWith('\x1b[')) return parseCsi(rest, start);
140
144
  if (rest.startsWith('\x1bO')) {
141
- if (rest.length < 3) return { needMore: true };
142
- const key = CSI_KEYS[rest[2]];
143
- if (key) return { event: { type: 'key', key }, end: start + 3 };
144
- return { event: { type: 'key', key: 'escape' }, end: start + 1 };
145
+ if (rest.length < 3) return NEED_MORE;
146
+ const key = SS3_KEYS[rest[2]];
147
+ return key ? keyAt(key, start + 3) : keyAt('escape', start + 1);
145
148
  }
146
- return { event: { type: 'key', key: 'escape' }, end: start + 1 };
149
+ return keyAt('escape', start + 1);
147
150
  };
148
151
 
149
152
  const decodeChunk = (text, carry = '') => {
150
153
  const source = carry + text;
151
- const events = new Array(source.length);
152
- let n = 0;
154
+ const events = [];
153
155
  let i = 0;
154
156
  while (i < source.length) {
155
157
  const ch = source[i];
156
158
  if (ch === '\x1b') {
157
159
  const parsed = parseEsc(source, i);
158
- if (parsed.needMore) {
159
- events.length = n;
160
- return { events, carry: source.slice(i) };
161
- }
162
- events[n++] = parsed.event;
160
+ if (parsed.needMore) return { events, carry: source.slice(i) };
161
+ events.push(parsed.event);
163
162
  i = parsed.end;
164
163
  continue;
165
164
  }
166
165
  const named = LITERAL_KEY[ch];
166
+ const code = source.charCodeAt(i);
167
167
  if (named) {
168
- events[n++] = { type: 'key', key: named };
168
+ events.push({ type: 'key', key: named });
169
169
  i += 1;
170
170
  continue;
171
171
  }
172
- const code = source.charCodeAt(i);
173
172
  if (code >= 1 && code <= 26) {
174
173
  const letter = String.fromCharCode(96 + code);
175
- events[n++] = { type: 'key', key: `ctrl-${letter}` };
174
+ events.push({ type: 'key', key: `ctrl-${letter}` });
176
175
  i += 1;
177
176
  continue;
178
177
  }
179
- if (code >= 0xd800 && code <= 0xdbff && i + 1 < source.length) {
180
- events[n++] = { type: 'key', key: source.slice(i, i + 2) };
181
- i += 2;
182
- continue;
183
- }
184
- events[n++] = { type: 'key', key: ch };
185
- i += 1;
178
+ const isPair = code >= 0xd800 && code <= 0xdbff && i + 1 < source.length;
179
+ const size = isPair ? 2 : 1;
180
+ events.push({ type: 'key', key: source.slice(i, i + size) });
181
+ i += size;
186
182
  }
187
- events.length = n;
188
183
  return { events, carry: '' };
189
184
  };
190
185
 
@@ -198,32 +193,29 @@ const hitAction = (hits, x) => {
198
193
  module.exports = {
199
194
  ACTIONS,
200
195
  ACTION_IDS,
196
+ DASH_IDS,
197
+ DASH_HIDDEN,
201
198
  BRANCH_ACTIONS,
202
199
  COMMIT_ACTIONS,
203
200
  DIFF_DISABLED,
204
- FILES_DISABLED,
205
201
  FILES_HIDDEN,
206
202
  FILES_GIT_DISABLED,
207
- FILES_TASKS_DISABLED,
208
203
  TASKS_DISABLED,
209
204
  BRANCHES_DISABLED,
210
205
  COMMITS_DISABLED,
211
206
  NPM_DISABLED,
212
207
  UNIT_DISABLED,
213
- disabledActions,
214
208
  diffGitDisabled,
209
+ entryHasDiff,
210
+ lineHasDiff,
211
+ withoutMoves,
215
212
  branchGitDisabled,
216
213
  commitGitDisabled,
217
214
  decodeChunk,
218
- actionFromKey,
219
- actionHot,
220
215
  actionLetter,
221
216
  buttonWord,
222
217
  hitAction,
223
218
  CONFIRM,
224
- CONFIRM_MODE,
225
- confirmKey,
226
- applyConfirm,
227
219
  confirmPrefix,
228
220
  promptFromChoices,
229
221
  };