reslop 0.2.7 → 0.3.0
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 +17 -1
- package/README.md +16 -14
- package/bin/reslop.js +8 -5
- package/lib/agents/agents.js +504 -0
- package/lib/agents/allow.js +71 -0
- package/lib/agents/allow.json +16 -0
- package/lib/agents/models.js +460 -0
- package/lib/api.js +15 -12
- package/lib/cli.js +43 -68
- package/lib/{files.js → common/files.js} +48 -55
- package/lib/{find.js → common/find.js} +1 -1
- package/lib/common/format.js +101 -0
- package/lib/{utilities.js → common/process.js} +7 -95
- package/lib/common/tasks.json +27 -0
- package/lib/common/utilities.js +112 -0
- package/lib/dashboard/git.js +9 -16
- package/lib/dashboard/model.js +90 -49
- package/lib/dashboard/npm.js +17 -13
- package/lib/dashboard/tree.js +27 -30
- package/lib/{session → dashboard}/watch.js +36 -31
- package/lib/{workspace.js → dashboard/workspace.js} +23 -38
- package/lib/{deps.js → deps/deps.js} +31 -45
- package/lib/{deps-diff.js → deps/diff.js} +35 -25
- package/lib/{manifest.js → deps/manifest.js} +47 -30
- package/lib/diff/align.js +1 -2
- package/lib/diff/diff.js +2 -2
- package/lib/diff/display.js +29 -5
- package/lib/diff/inline.js +10 -14
- package/lib/diff/items.js +6 -4
- package/lib/diff/patch.js +39 -3
- package/lib/diff/unit.js +45 -16
- package/lib/{git-branches.js → git/branches.js} +53 -48
- package/lib/{git-deps.js → git/deps.js} +123 -96
- package/lib/git/git.js +71 -0
- package/lib/git/worktree.js +475 -0
- package/lib/highlight/bash.js +1 -2
- package/lib/highlight/csv.js +1 -2
- package/lib/highlight/dot.js +1 -2
- package/lib/{highlight.js → highlight/highlight.js} +42 -11
- package/lib/highlight/html.js +20 -18
- package/lib/highlight/json.js +1 -2
- package/lib/highlight/log.js +1 -2
- package/lib/highlight/txt.js +1 -2
- package/lib/{session → input}/actions.js +111 -48
- package/lib/{editor.js → input/editor.js} +7 -8
- package/lib/{keys.js → input/keys.js} +15 -43
- package/lib/input/line-edit.js +77 -0
- package/lib/input/menu-pick.js +70 -0
- package/lib/render/agents.js +640 -0
- package/lib/render/branches.js +4 -5
- package/lib/render/commits.js +54 -64
- package/lib/render/{dash-activity.js → dashboard/activity.js} +25 -40
- package/lib/render/{dash-blocks.js → dashboard/blocks.js} +131 -137
- package/lib/render/{dashboard.js → dashboard/dashboard.js} +25 -22
- package/lib/render/diff.js +166 -45
- package/lib/render/field.js +131 -0
- package/lib/render/files.js +9 -14
- package/lib/render/footer.js +383 -0
- package/lib/render/frame.js +123 -25
- package/lib/render/header.js +176 -0
- package/lib/render/log.js +319 -0
- package/lib/render/menu.js +60 -0
- package/lib/render/notes.js +16 -11
- package/lib/render/npm.js +322 -196
- package/lib/render/packages.js +9 -13
- package/lib/render/primitives.js +101 -15
- package/lib/render/render.js +7 -11
- package/lib/render/repos.js +13 -25
- package/lib/render/status.js +370 -0
- package/lib/render/status.json +85 -0
- package/lib/render/{dash-table.js → table.js} +13 -60
- package/lib/render/tiles.js +109 -48
- package/lib/render/unit.js +32 -13
- package/lib/{report-model.js → report/model.js} +4 -6
- package/lib/{report-parse.js → report/parse.js} +9 -14
- package/lib/{report-render.js → report/render.js} +46 -14
- package/lib/{report-run.js → report/run.js} +42 -30
- package/lib/{report-test.js → report/test.js} +56 -55
- package/lib/{report-tools.js → report/tools.js} +24 -33
- package/lib/review/agent-instructions.md +9 -0
- package/lib/review/format.js +426 -0
- package/lib/{review-merge.js → review/merge.js} +9 -8
- package/lib/review/review.js +190 -0
- package/lib/review/store.js +281 -0
- package/lib/review/templates.js +83 -0
- package/lib/runs/commands.js +14 -0
- package/lib/runs/logs.js +299 -0
- package/lib/runs/output.js +174 -0
- package/lib/runs/process.js +113 -0
- package/lib/{runs.js → runs/runs.js} +84 -36
- package/lib/runs/scripts.js +150 -0
- package/lib/session/agents/agents.js +958 -0
- package/lib/session/agents/job.js +320 -0
- package/lib/session/agents/jobs.js +355 -0
- package/lib/session/agents/options.js +153 -0
- package/lib/session/agents/plans.js +83 -0
- package/lib/session/branches.js +33 -39
- package/lib/session/change-actions.js +34 -100
- package/lib/session/commit.js +91 -52
- package/lib/session/compose.js +181 -145
- package/lib/session/dashboard.js +23 -22
- package/lib/session/dispatch.js +85 -21
- package/lib/session/files-pane.js +47 -26
- package/lib/session/find.js +16 -29
- package/lib/session/import.js +82 -0
- package/lib/session/items.js +8 -17
- package/lib/session/lifecycle.js +75 -72
- package/lib/session/load.js +2 -4
- package/lib/session/navigation.js +6 -3
- package/lib/session/npm/history.js +249 -0
- package/lib/session/npm/npm.js +815 -0
- package/lib/session/{packages.js → npm/packages.js} +21 -14
- package/lib/session/ops.js +125 -34
- package/lib/session/pointer.js +202 -10
- package/lib/session/prefs.js +112 -0
- package/lib/session/reads.js +109 -0
- package/lib/session/review.js +28 -10
- package/lib/session/run-panel.js +40 -0
- package/lib/{session.js → session/session.js} +156 -63
- package/lib/session/tasks.js +320 -65
- package/lib/session/templates.js +1 -1
- package/lib/session/terminal.js +94 -12
- package/lib/session/unit.js +35 -30
- package/lib/session/update.js +194 -6
- package/lib/session/view.js +65 -65
- package/lib/session/workspace.js +39 -78
- package/lib/{capabilities.js → source/capabilities.js} +3 -12
- package/lib/{github.js → source/github.js} +102 -32
- package/lib/{gitlab.js → source/gitlab.js} +87 -10
- package/lib/{remote.js → source/remote.js} +144 -40
- package/lib/source/review-threads.graphql +20 -0
- package/lib/source/source.js +74 -0
- package/lib/term/ansi.js +396 -0
- package/lib/{clipboard.js → term/clipboard.js} +3 -6
- package/lib/{select.js → term/select.js} +2 -2
- package/lib/term/themes/dark.json +122 -0
- package/lib/term/themes/light.json +122 -0
- package/lib/term/wide.txt +21 -0
- package/lib/{wrap.js → term/wrap.js} +4 -4
- package/package.json +2 -2
- package/lib/ansi.js +0 -545
- package/lib/detect.js +0 -34
- package/lib/diff/edit.js +0 -33
- package/lib/git-worktree.js +0 -455
- package/lib/git.js +0 -79
- package/lib/npm-commands.js +0 -522
- package/lib/render/chrome.js +0 -806
- package/lib/render/present.js +0 -19
- package/lib/render/report.js +0 -43
- package/lib/render/search.js +0 -25
- package/lib/review.js +0 -745
- package/lib/session/accessors.js +0 -26
- package/lib/session/edit-click.js +0 -57
- package/lib/session/npm.js +0 -452
- package/lib/session/progress.js +0 -41
- package/lib/source.js +0 -36
- package/lib/update.js +0 -192
- /package/lib/{git-reword-todo.js → git/reword-todo.js} +0 -0
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const LIST_PANES = [
|
|
3
|
+
const LIST_PANES = [
|
|
4
|
+
'files',
|
|
5
|
+
'branches',
|
|
6
|
+
'commits',
|
|
7
|
+
'npm',
|
|
8
|
+
'packages',
|
|
9
|
+
'agents',
|
|
10
|
+
];
|
|
4
11
|
|
|
5
12
|
const ACTIONS = {
|
|
6
13
|
add: ['a'],
|
|
@@ -51,37 +58,63 @@ const NPM_ACTIONS = {
|
|
|
51
58
|
npmNew: ['insert'],
|
|
52
59
|
npmDrop: ['delete'],
|
|
53
60
|
npmLogs: ['l'],
|
|
54
|
-
npmStop: ['
|
|
61
|
+
npmStop: ['s'],
|
|
55
62
|
npmVerbose: ['v'],
|
|
56
63
|
npmRerun: ['r'],
|
|
57
64
|
};
|
|
58
65
|
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
const AGENT_ACTIONS = {
|
|
67
|
+
agentModel: ['m'],
|
|
68
|
+
agentEffort: ['e'],
|
|
69
|
+
agentFast: ['a'],
|
|
70
|
+
agentContext: ['t'],
|
|
71
|
+
agentReview: ['p'],
|
|
72
|
+
agentStop: ['s'],
|
|
73
|
+
agentRerun: ['r'],
|
|
67
74
|
};
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
dashRun: 'run',
|
|
76
|
-
dashTasks: 'tasks',
|
|
75
|
+
|
|
76
|
+
const AGENT_LIST_ACTIONS = {
|
|
77
|
+
agentModel: AGENT_ACTIONS.agentModel,
|
|
78
|
+
agentEffort: AGENT_ACTIONS.agentEffort,
|
|
79
|
+
agentFast: AGENT_ACTIONS.agentFast,
|
|
80
|
+
agentContext: AGENT_ACTIONS.agentContext,
|
|
81
|
+
agentReview: AGENT_ACTIONS.agentReview,
|
|
77
82
|
};
|
|
78
|
-
|
|
83
|
+
|
|
84
|
+
const DASH_TILES = [
|
|
85
|
+
{ id: 'files', key: 'f', action: 'dashFiles', footer: true },
|
|
86
|
+
{ id: 'diffs', key: 'd', action: 'dashDiffs', footer: true },
|
|
87
|
+
{ id: 'tasks', key: 't', action: 'dashTasks', footer: true },
|
|
88
|
+
{ id: 'branches', key: 'b', action: 'dashBranches', footer: true },
|
|
89
|
+
{ id: 'commits', key: 'c', action: 'dashCommits', footer: true },
|
|
90
|
+
{ id: 'run', key: 'r', action: 'dashRun', footer: true },
|
|
91
|
+
{ id: 'npm', key: 'n', action: 'dashNpm', footer: true },
|
|
92
|
+
{ id: 'agents', key: 'a', action: 'dashAgents', footer: false },
|
|
93
|
+
];
|
|
94
|
+
const DASH_ACTIONS = {};
|
|
95
|
+
const DASH_BLOCKS = {};
|
|
96
|
+
const DASH_KEYS = {};
|
|
97
|
+
for (const tile of DASH_TILES) {
|
|
98
|
+
if (tile.footer) DASH_ACTIONS[tile.action] = [tile.key];
|
|
99
|
+
DASH_BLOCKS[tile.action] = tile.id;
|
|
100
|
+
DASH_KEYS[tile.key] = tile.action;
|
|
101
|
+
}
|
|
102
|
+
const DASH_IDS = Object.keys(DASH_ACTIONS);
|
|
103
|
+
const DASH_ALLOWED = [
|
|
104
|
+
...Object.keys(DASH_BLOCKS),
|
|
105
|
+
'back',
|
|
106
|
+
'pull',
|
|
107
|
+
'push',
|
|
108
|
+
'quit',
|
|
109
|
+
'theme',
|
|
110
|
+
];
|
|
79
111
|
const REPOS_ALLOWED = [
|
|
80
112
|
'repoLeft',
|
|
81
113
|
'repoRight',
|
|
82
114
|
'repoUp',
|
|
83
115
|
'repoDown',
|
|
84
116
|
'open',
|
|
117
|
+
'back',
|
|
85
118
|
'quit',
|
|
86
119
|
'theme',
|
|
87
120
|
];
|
|
@@ -95,10 +128,16 @@ const ACTION_HOT = {
|
|
|
95
128
|
newCommit: 'ins',
|
|
96
129
|
feedback: 'q',
|
|
97
130
|
check: 'space',
|
|
131
|
+
taskUp: 'ctrl+up',
|
|
132
|
+
taskDown: 'ctrl+down',
|
|
133
|
+
taskNudge: 'up/dn',
|
|
134
|
+
plan: 'p',
|
|
135
|
+
import: 'i',
|
|
98
136
|
theme: 'l',
|
|
137
|
+
lines: '+l',
|
|
99
138
|
npmNew: 'ins',
|
|
100
139
|
npmDrop: 'del',
|
|
101
|
-
npmStop: '
|
|
140
|
+
npmStop: 's',
|
|
102
141
|
packageNew: 'ins',
|
|
103
142
|
packageDrop: 'del',
|
|
104
143
|
};
|
|
@@ -107,7 +146,13 @@ const ACTION_LABEL = {
|
|
|
107
146
|
...DASH_BLOCKS,
|
|
108
147
|
revert: 'drop',
|
|
109
148
|
check: 'space',
|
|
149
|
+
taskUp: 'ctrl+up',
|
|
150
|
+
taskDown: 'ctrl+down',
|
|
151
|
+
taskNudge: 'ctrl+up/dn',
|
|
152
|
+
plan: 'plan',
|
|
153
|
+
import: 'import',
|
|
110
154
|
theme: 'light',
|
|
155
|
+
lines: 'ctrl+l',
|
|
111
156
|
layout: 'mode',
|
|
112
157
|
tasks: 'tasks',
|
|
113
158
|
view: 'view',
|
|
@@ -125,9 +170,16 @@ const ACTION_LABEL = {
|
|
|
125
170
|
packageDrop: 'delete',
|
|
126
171
|
packageWanted: 'wanted',
|
|
127
172
|
packageLatest: 'latest',
|
|
128
|
-
npmStop: '
|
|
173
|
+
npmStop: 'stop',
|
|
129
174
|
npmVerbose: 'verbose',
|
|
130
175
|
npmRerun: 're-run',
|
|
176
|
+
agentModel: 'model',
|
|
177
|
+
agentEffort: 'effort',
|
|
178
|
+
agentFast: 'fast',
|
|
179
|
+
agentContext: 'context',
|
|
180
|
+
agentReview: 'plan',
|
|
181
|
+
agentStop: 'stop',
|
|
182
|
+
agentRerun: 're-run',
|
|
131
183
|
quit: 'q',
|
|
132
184
|
prev: '←',
|
|
133
185
|
next: '→',
|
|
@@ -193,8 +245,12 @@ const BRANCHES_DISABLED = [
|
|
|
193
245
|
const COMMITS_DISABLED = BRANCHES_DISABLED.filter((id) => id !== 'commit');
|
|
194
246
|
const NPM_DISABLED = [...BRANCHES_DISABLED, 'pull', 'push'];
|
|
195
247
|
|
|
196
|
-
const isTasksTarget = (item) =>
|
|
197
|
-
|
|
248
|
+
const isTasksTarget = (item) => {
|
|
249
|
+
if (!item) return false;
|
|
250
|
+
const tasks = item.kind === 'tasks';
|
|
251
|
+
const task = item.origin === 'task';
|
|
252
|
+
return tasks || task;
|
|
253
|
+
};
|
|
198
254
|
|
|
199
255
|
const DIFF_MOVE_IDS = ['add', 'unstage', 'revert'];
|
|
200
256
|
|
|
@@ -214,8 +270,10 @@ const entryHasDiff = (entry) => {
|
|
|
214
270
|
return total > 0;
|
|
215
271
|
};
|
|
216
272
|
|
|
217
|
-
const lineHasDiff = (line) =>
|
|
218
|
-
|
|
273
|
+
const lineHasDiff = (line) => {
|
|
274
|
+
if (!line) return false;
|
|
275
|
+
return line.type === 'add' || line.type === 'del';
|
|
276
|
+
};
|
|
219
277
|
|
|
220
278
|
const withoutMoves = (off, hasDiff) => {
|
|
221
279
|
if (hasDiff) return off;
|
|
@@ -286,7 +344,9 @@ const disabledActions = (pane, item) => {
|
|
|
286
344
|
if (pane === 'commits') {
|
|
287
345
|
return [...COMMITS_DISABLED, ...commitWriteDisabled(item)];
|
|
288
346
|
}
|
|
289
|
-
if (pane === 'npm' || pane === 'packages')
|
|
347
|
+
if (pane === 'npm' || pane === 'packages' || pane === 'agents') {
|
|
348
|
+
return NPM_DISABLED;
|
|
349
|
+
}
|
|
290
350
|
if (pane === 'tasks' || onTodos) return TASKS_DISABLED;
|
|
291
351
|
return [...DIFF_DISABLED, ...diffGitDisabled(item)];
|
|
292
352
|
};
|
|
@@ -323,7 +383,7 @@ const keysForActions = (actions) => {
|
|
|
323
383
|
|
|
324
384
|
const PANE_ONLY = ['branch', 'file', 'diff'];
|
|
325
385
|
const REVIEW_DROP = { d: 'revert' };
|
|
326
|
-
const DIFF_KEYS = { ...REVIEW_DROP, q: 'feedback' };
|
|
386
|
+
const DIFF_KEYS = { ...REVIEW_DROP, q: 'feedback', 'ctrl-l': 'lines' };
|
|
327
387
|
const BRANCH_KEYS = keysForActions(BRANCH_ACTIONS);
|
|
328
388
|
const COMMIT_KEYS = { ...keysForActions(COMMIT_ACTIONS), s: 'push' };
|
|
329
389
|
const NPM_KEYS = {
|
|
@@ -332,8 +392,7 @@ const NPM_KEYS = {
|
|
|
332
392
|
delete: 'npmDrop',
|
|
333
393
|
l: 'npmLogs',
|
|
334
394
|
};
|
|
335
|
-
const
|
|
336
|
-
const SCREEN_KEYS = DASH_KEYS;
|
|
395
|
+
const SCREEN_KEYS = keysForActions(DASH_ACTIONS);
|
|
337
396
|
const PANE_KEYS = {
|
|
338
397
|
dashboard: { ...DASH_KEYS, p: 'pull', s: 'push' },
|
|
339
398
|
files: REVIEW_DROP,
|
|
@@ -343,7 +402,8 @@ const PANE_KEYS = {
|
|
|
343
402
|
commits: COMMIT_KEYS,
|
|
344
403
|
npm: NPM_KEYS,
|
|
345
404
|
packages: keysForActions(PACKAGE_ACTIONS),
|
|
346
|
-
|
|
405
|
+
agents: keysForActions(AGENT_LIST_ACTIONS),
|
|
406
|
+
tasks: { delete: 'drop', p: 'plan', i: 'import' },
|
|
347
407
|
repos: {
|
|
348
408
|
left: 'repoLeft',
|
|
349
409
|
right: 'repoRight',
|
|
@@ -376,14 +436,17 @@ const actionFromKey = (key, pane) => {
|
|
|
376
436
|
return KEY_TO_ACTION[key] ?? null;
|
|
377
437
|
};
|
|
378
438
|
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
NPM_ACTIONS
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
439
|
+
const ACTION_KEYS = {
|
|
440
|
+
...DASH_ACTIONS,
|
|
441
|
+
...AGENT_ACTIONS,
|
|
442
|
+
...PACKAGE_ACTIONS,
|
|
443
|
+
...NPM_ACTIONS,
|
|
444
|
+
...COMMIT_ACTIONS,
|
|
445
|
+
...BRANCH_ACTIONS,
|
|
446
|
+
...ACTIONS,
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
const actionKeys = (id) => ACTION_KEYS[id] ?? [];
|
|
387
450
|
|
|
388
451
|
const actionLetter = (id) => ACTION_HOT[id] ?? actionKeys(id)[0];
|
|
389
452
|
|
|
@@ -401,15 +464,13 @@ const YES_NO = [
|
|
|
401
464
|
|
|
402
465
|
const CONFIRM = {
|
|
403
466
|
confirmQuit: {
|
|
404
|
-
choices:
|
|
405
|
-
|
|
406
|
-
{ letter: 'c', label: 'continue next time', lead: ' ' },
|
|
407
|
-
],
|
|
467
|
+
choices: YES_NO,
|
|
468
|
+
prefix: (view) => view.quitWarning || ' exit will terminate subprocesses',
|
|
408
469
|
keys: {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
'ctrl-c': 'ready',
|
|
470
|
+
y: 'confirm',
|
|
471
|
+
n: 'cancel',
|
|
412
472
|
escape: 'cancel',
|
|
473
|
+
'ctrl-c': 'cancel',
|
|
413
474
|
},
|
|
414
475
|
},
|
|
415
476
|
confirmUpdate: {
|
|
@@ -445,6 +506,7 @@ const CONFIRM = {
|
|
|
445
506
|
confirmCommit: {
|
|
446
507
|
choices: [
|
|
447
508
|
{ letter: 'esc', label: 'esc cancel', lead: ' ' },
|
|
509
|
+
{ letter: 'u', label: 'update', lead: ' ' },
|
|
448
510
|
{ letter: 'c', label: 'commit', lead: ' ' },
|
|
449
511
|
{ letter: 'a', label: 'amend', lead: ' ' },
|
|
450
512
|
{ letter: 'f', label: 'fixup', lead: ' ' },
|
|
@@ -453,6 +515,8 @@ const CONFIRM = {
|
|
|
453
515
|
keys: {
|
|
454
516
|
esc: 'cancel',
|
|
455
517
|
escape: 'cancel',
|
|
518
|
+
enter: 'update',
|
|
519
|
+
u: 'update',
|
|
456
520
|
c: 'commit',
|
|
457
521
|
a: 'amend',
|
|
458
522
|
f: 'fixup',
|
|
@@ -479,6 +543,7 @@ const promptFromChoices = (choices) =>
|
|
|
479
543
|
|
|
480
544
|
module.exports = {
|
|
481
545
|
LIST_PANES,
|
|
546
|
+
DASH_TILES,
|
|
482
547
|
DASH_IDS,
|
|
483
548
|
DASH_BLOCKS,
|
|
484
549
|
DASH_ALLOWED,
|
|
@@ -486,8 +551,6 @@ module.exports = {
|
|
|
486
551
|
REPOS_ALLOWED,
|
|
487
552
|
ACTIONS,
|
|
488
553
|
ACTION_IDS,
|
|
489
|
-
BRANCH_ACTIONS,
|
|
490
|
-
COMMIT_ACTIONS,
|
|
491
554
|
DIFF_DISABLED,
|
|
492
555
|
UNIT_DISABLED,
|
|
493
556
|
FILES_DISABLED,
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const { graphemes, visibleWidth } = ansi;
|
|
5
|
-
const
|
|
6
|
-
const { wrapMove } = wrap;
|
|
3
|
+
const { clamp } = require('../common/utilities.js');
|
|
4
|
+
const { graphemes, visibleWidth } = require('../term/ansi.js');
|
|
5
|
+
const { wrapMove } = require('../term/wrap.js');
|
|
7
6
|
|
|
8
7
|
const UNDO_CAP = 100;
|
|
9
8
|
const WORD_RE = /[\p{L}\p{N}_]/u;
|
|
@@ -127,7 +126,7 @@ class Editor {
|
|
|
127
126
|
place(offset) {
|
|
128
127
|
this.wantCol = null;
|
|
129
128
|
this.anchor = null;
|
|
130
|
-
this.cursor =
|
|
129
|
+
this.cursor = clamp(offset, 0, this.text.length);
|
|
131
130
|
}
|
|
132
131
|
|
|
133
132
|
backspace() {
|
|
@@ -145,8 +144,8 @@ class Editor {
|
|
|
145
144
|
if (this.removeSpan()) return;
|
|
146
145
|
const { parts, i, pos } = graphemeIndex(this.text, this.cursor);
|
|
147
146
|
if (i >= parts.length) return;
|
|
148
|
-
const
|
|
149
|
-
|
|
147
|
+
const size = parts[i].length;
|
|
148
|
+
const next = this.text.slice(0, pos) + this.text.slice(pos + size);
|
|
150
149
|
this.edit(next, this.cursor);
|
|
151
150
|
}
|
|
152
151
|
|
|
@@ -206,7 +205,7 @@ class Editor {
|
|
|
206
205
|
}
|
|
207
206
|
const rows = this.text.split('\n');
|
|
208
207
|
const { line, col } = this.linePos();
|
|
209
|
-
const next =
|
|
208
|
+
const next = clamp(line + delta, 0, rows.length - 1);
|
|
210
209
|
if (next === line) return;
|
|
211
210
|
let cursor = 0;
|
|
212
211
|
for (let i = 0; i < next; i++) cursor += rows[i].length + 1;
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const actions = require('./
|
|
4
|
-
|
|
5
|
-
const { ACTIONS
|
|
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
|
-
const { COMMITS_DISABLED, UNIT_DISABLED, NPM_DISABLED } = actions;
|
|
10
|
-
const { diffGitDisabled, branchGitDisabled, commitGitDisabled } = actions;
|
|
11
|
-
const { entryHasDiff, lineHasDiff, withoutMoves } = actions;
|
|
12
|
-
const { actionLetter, buttonWord } = actions;
|
|
13
|
-
const { CONFIRM, confirmPrefix, promptFromChoices } = actions;
|
|
3
|
+
const actions = require('./actions.js');
|
|
4
|
+
|
|
5
|
+
const { ACTIONS } = actions;
|
|
14
6
|
|
|
15
7
|
const CSI_KEYS = {
|
|
16
8
|
A: 'up',
|
|
@@ -19,6 +11,7 @@ const CSI_KEYS = {
|
|
|
19
11
|
D: 'left',
|
|
20
12
|
H: 'home',
|
|
21
13
|
F: 'end',
|
|
14
|
+
Z: 'shift-tab',
|
|
22
15
|
};
|
|
23
16
|
|
|
24
17
|
const SS3_KEYS = {
|
|
@@ -68,14 +61,16 @@ const MOUSE_WHEEL = {
|
|
|
68
61
|
65: 'wheelDown',
|
|
69
62
|
};
|
|
70
63
|
|
|
64
|
+
const ARROW_KEYS = ['left', 'right', 'up', 'down'];
|
|
65
|
+
const EDGE_KEYS = ['home', 'end'];
|
|
66
|
+
|
|
71
67
|
const NEED_MORE = { needMore: true };
|
|
72
68
|
|
|
73
69
|
const keyAt = (key, end) => ({ event: { type: 'key', key }, end });
|
|
74
70
|
|
|
75
71
|
const modifiedKey = (base, modText) => {
|
|
76
|
-
const arrow =
|
|
77
|
-
|
|
78
|
-
const end = base === 'home' || base === 'end';
|
|
72
|
+
const arrow = ARROW_KEYS.includes(base);
|
|
73
|
+
const end = EDGE_KEYS.includes(base);
|
|
79
74
|
if (!arrow && !end) return base;
|
|
80
75
|
const mod = parseInt(modText, 10);
|
|
81
76
|
const bits = Number.isFinite(mod) ? mod - 1 : 0;
|
|
@@ -183,6 +178,11 @@ const decodeChunk = (text, carry = '') => {
|
|
|
183
178
|
return { events, carry: '' };
|
|
184
179
|
};
|
|
185
180
|
|
|
181
|
+
const isTextKey = (key) => {
|
|
182
|
+
if (!key || key.length !== 1) return false;
|
|
183
|
+
return key.charCodeAt(0) >= 32;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
186
|
const hitAction = (hits, x) => {
|
|
187
187
|
for (const hit of hits) {
|
|
188
188
|
if (x >= hit.x0 && x < hit.x1) return hit.id;
|
|
@@ -190,32 +190,4 @@ const hitAction = (hits, x) => {
|
|
|
190
190
|
return null;
|
|
191
191
|
};
|
|
192
192
|
|
|
193
|
-
module.exports = {
|
|
194
|
-
ACTIONS,
|
|
195
|
-
ACTION_IDS,
|
|
196
|
-
DASH_IDS,
|
|
197
|
-
DASH_HIDDEN,
|
|
198
|
-
BRANCH_ACTIONS,
|
|
199
|
-
COMMIT_ACTIONS,
|
|
200
|
-
DIFF_DISABLED,
|
|
201
|
-
FILES_HIDDEN,
|
|
202
|
-
FILES_GIT_DISABLED,
|
|
203
|
-
TASKS_DISABLED,
|
|
204
|
-
BRANCHES_DISABLED,
|
|
205
|
-
COMMITS_DISABLED,
|
|
206
|
-
NPM_DISABLED,
|
|
207
|
-
UNIT_DISABLED,
|
|
208
|
-
diffGitDisabled,
|
|
209
|
-
entryHasDiff,
|
|
210
|
-
lineHasDiff,
|
|
211
|
-
withoutMoves,
|
|
212
|
-
branchGitDisabled,
|
|
213
|
-
commitGitDisabled,
|
|
214
|
-
decodeChunk,
|
|
215
|
-
actionLetter,
|
|
216
|
-
buttonWord,
|
|
217
|
-
hitAction,
|
|
218
|
-
CONFIRM,
|
|
219
|
-
confirmPrefix,
|
|
220
|
-
promptFromChoices,
|
|
221
|
-
};
|
|
193
|
+
module.exports = { ACTIONS, decodeChunk, hitAction, isTextKey };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { Editor } = require('./editor.js');
|
|
4
|
+
const { isTextKey } = require('./keys.js');
|
|
5
|
+
const clipboard = require('../term/clipboard.js');
|
|
6
|
+
|
|
7
|
+
const copyLine = (editor, ui) => {
|
|
8
|
+
const text = editor.selectedText();
|
|
9
|
+
if (!text) return;
|
|
10
|
+
const ok = clipboard.copyText(text, ui.stdout);
|
|
11
|
+
ui.status = ok ? 'copied' : 'copy failed';
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const cutLine = (editor, ui) => {
|
|
15
|
+
if (!editor.hasSelect()) return;
|
|
16
|
+
copyLine(editor, ui);
|
|
17
|
+
editor.removeSpan();
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const pasteLine = (editor) => {
|
|
21
|
+
const raw = clipboard.pasteText() ?? '';
|
|
22
|
+
const text = `${raw}`.replaceAll('\r', '').replaceAll('\n', '');
|
|
23
|
+
if (text) editor.insert(text);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const EDIT_OP = {
|
|
27
|
+
left: (editor) => editor.move(-1),
|
|
28
|
+
right: (editor) => editor.move(1),
|
|
29
|
+
'shift-left': (editor) => editor.move(-1, true),
|
|
30
|
+
'shift-right': (editor) => editor.move(1, true),
|
|
31
|
+
'ctrl-left': (editor) => editor.moveWord(-1),
|
|
32
|
+
'ctrl-right': (editor) => editor.moveWord(1),
|
|
33
|
+
'ctrl-shift-left': (editor) => editor.moveWord(-1, true),
|
|
34
|
+
'ctrl-shift-right': (editor) => editor.moveWord(1, true),
|
|
35
|
+
backspace: (editor) => editor.backspace(),
|
|
36
|
+
delete: (editor) => editor.delete(),
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const LINE_OP = {
|
|
40
|
+
...EDIT_OP,
|
|
41
|
+
'ctrl-x': cutLine,
|
|
42
|
+
'ctrl-v': (editor) => pasteLine(editor),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const END_OP = {
|
|
46
|
+
home: (editor) => editor.home(),
|
|
47
|
+
end: (editor) => editor.end(),
|
|
48
|
+
'shift-home': (editor) => editor.home(true),
|
|
49
|
+
'shift-end': (editor) => editor.end(true),
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const LINE_ENDS = { ...LINE_OP, ...END_OP };
|
|
53
|
+
|
|
54
|
+
const lineKey = (editor, key, ui, ends) => {
|
|
55
|
+
if (key === 'ctrl-c') {
|
|
56
|
+
copyLine(editor, ui);
|
|
57
|
+
return 'caret';
|
|
58
|
+
}
|
|
59
|
+
const op = (ends ? LINE_ENDS : LINE_OP)[key];
|
|
60
|
+
if (!op && !isTextKey(key)) return null;
|
|
61
|
+
const before = editor.text;
|
|
62
|
+
if (op) op(editor, ui);
|
|
63
|
+
else editor.insert(key);
|
|
64
|
+
return editor.text === before ? 'caret' : 'text';
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const lineField = (name) => {
|
|
68
|
+
const editor = new Editor('');
|
|
69
|
+
return {
|
|
70
|
+
editor,
|
|
71
|
+
get [name]() {
|
|
72
|
+
return editor.text;
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
module.exports = { EDIT_OP, copyLine, cutLine, lineKey, lineField };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { clamp } = require('../common/utilities.js');
|
|
4
|
+
const { Editor } = require('./editor.js');
|
|
5
|
+
|
|
6
|
+
const MENU_ROWS = 8;
|
|
7
|
+
|
|
8
|
+
const menuRows = (bodyH, fraction = 1) => {
|
|
9
|
+
const height = Math.min(bodyH > 0 ? bodyH : MENU_ROWS, MENU_ROWS);
|
|
10
|
+
return Math.max(1, Math.floor(height * fraction));
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const pickDelta = (key, page, half) => {
|
|
14
|
+
const steps = {
|
|
15
|
+
up: -1,
|
|
16
|
+
down: 1,
|
|
17
|
+
pageUp: -page,
|
|
18
|
+
pageDown: page,
|
|
19
|
+
'ctrl-b': -page,
|
|
20
|
+
'ctrl-f': page,
|
|
21
|
+
'ctrl-u': -half,
|
|
22
|
+
'ctrl-d': half,
|
|
23
|
+
home: -Infinity,
|
|
24
|
+
end: Infinity,
|
|
25
|
+
};
|
|
26
|
+
return Object.hasOwn(steps, key) ? steps[key] : 0;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
class MenuPick {
|
|
30
|
+
constructor(field, cursor) {
|
|
31
|
+
this.field = field;
|
|
32
|
+
this.cursor = cursor;
|
|
33
|
+
this.scroll = 0;
|
|
34
|
+
this.editor = new Editor('');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get query() {
|
|
38
|
+
return this.editor.text;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
filter(items) {
|
|
42
|
+
const query = this.query.trim().toLowerCase();
|
|
43
|
+
if (!query) return items;
|
|
44
|
+
return items.filter((name) => name.toLowerCase().includes(query));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
touch() {
|
|
48
|
+
this.cursor = 0;
|
|
49
|
+
this.scroll = 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
move(delta, items, isOff) {
|
|
53
|
+
const last = items.length - 1;
|
|
54
|
+
const step = delta < 0 ? -1 : 1;
|
|
55
|
+
const goal = clamp(this.cursor + delta, 0, last);
|
|
56
|
+
let cursor = this.cursor;
|
|
57
|
+
for (let next = cursor; next !== goal;) {
|
|
58
|
+
next += step;
|
|
59
|
+
if (!isOff(items[next])) cursor = next;
|
|
60
|
+
}
|
|
61
|
+
if (isOff(items[cursor])) {
|
|
62
|
+
let scan = goal;
|
|
63
|
+
while (scan >= 0 && scan <= last && isOff(items[scan])) scan += step;
|
|
64
|
+
if (scan >= 0 && scan <= last) cursor = scan;
|
|
65
|
+
}
|
|
66
|
+
this.cursor = cursor;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = { menuRows, pickDelta, MenuPick };
|