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
package/lib/session/dispatch.js
CHANGED
|
@@ -1,33 +1,30 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const {
|
|
5
|
-
const
|
|
6
|
-
const { hasStagedChanges, listedCommits } = commit;
|
|
7
|
-
const actions = require('./actions.js');
|
|
3
|
+
const { COMPOSE_LEAVE } = require('./compose.js');
|
|
4
|
+
const { listedCommits } = require('./commit.js');
|
|
5
|
+
const actions = require('../input/actions.js');
|
|
8
6
|
const { LIST_PANES, DASH_BLOCKS, DASH_ALLOWED, CONFIRM_MODE } = actions;
|
|
9
7
|
const { REPOS_ALLOWED } = actions;
|
|
10
8
|
const { disabledActions, actionFromKey, confirmKey, lineHasDiff } = actions;
|
|
11
|
-
const
|
|
12
|
-
const { onCommand } = changeActions;
|
|
9
|
+
const { onCommand } = require('./change-actions.js');
|
|
13
10
|
const filesPane = require('./files-pane.js');
|
|
14
|
-
const
|
|
15
|
-
const {
|
|
16
|
-
const
|
|
17
|
-
const {
|
|
11
|
+
const { handlePointer } = require('./pointer.js');
|
|
12
|
+
const { FIND_PANES, startFind, onFindKey } = require('./find.js');
|
|
13
|
+
const { startImport, stopImport, onImportKey } = require('./import.js');
|
|
14
|
+
const { unitBodyLines } = require('./view.js');
|
|
18
15
|
|
|
19
16
|
const currentTarget = (ui) => {
|
|
20
17
|
if (ui.pane === 'files') return ui.fileCursorEntry();
|
|
21
18
|
if (ui.pane === 'branches') return ui.branches[ui.branchCursor];
|
|
22
19
|
if (ui.pane === 'commits') {
|
|
23
20
|
const entry = listedCommits(ui.commits.commits)[ui.commitCursor];
|
|
24
|
-
const canCommit =
|
|
21
|
+
const canCommit = ui.commits.staged;
|
|
25
22
|
const unstagedCurrent = !ui.rev && !ui.revShort;
|
|
26
23
|
return { ...entry, canCommit, unstagedCurrent };
|
|
27
24
|
}
|
|
28
25
|
if (ui.pane !== 'unit') return ui.current();
|
|
29
26
|
const item = ui.current();
|
|
30
|
-
const lines = ui
|
|
27
|
+
const lines = unitBodyLines(ui);
|
|
31
28
|
if (!lines.length) return item;
|
|
32
29
|
const line = lines[ui.nav.unitLine] ?? null;
|
|
33
30
|
const lineDiff = lineHasDiff(line);
|
|
@@ -53,6 +50,7 @@ const HANDLERS = {
|
|
|
53
50
|
next: filesPane.onNext,
|
|
54
51
|
prev: filesPane.onPrev,
|
|
55
52
|
layout: filesPane.onLayout,
|
|
53
|
+
lines: filesPane.onLineNumbers,
|
|
56
54
|
theme: filesPane.onTheme,
|
|
57
55
|
files: filesPane.onFiles,
|
|
58
56
|
open: (ui) => {
|
|
@@ -97,6 +95,10 @@ const HANDLERS = {
|
|
|
97
95
|
if (ui.pane === 'tasks') return void ui.composer.tasks.removeFocusedTask();
|
|
98
96
|
ui.gitBranches.onDropBranch();
|
|
99
97
|
},
|
|
98
|
+
taskUp: (ui) => ui.composer.tasks.moveIssue(-1),
|
|
99
|
+
taskDown: (ui) => ui.composer.tasks.moveIssue(1),
|
|
100
|
+
plan: (ui) => ui.composer.tasks.togglePlanMenu(),
|
|
101
|
+
import: (ui) => startImport(ui),
|
|
100
102
|
npm: (ui) => ui.npm.open(),
|
|
101
103
|
npmEdit: (ui) => ui.npm.edit(),
|
|
102
104
|
npmNew: (ui) => ui.npm.create(),
|
|
@@ -106,9 +108,16 @@ const HANDLERS = {
|
|
|
106
108
|
packageWanted: (ui) => ui.packages.updateWanted(),
|
|
107
109
|
packageLatest: (ui) => ui.packages.updateLatest(),
|
|
108
110
|
npmLogs: (ui) => ui.npm.askLogs(),
|
|
109
|
-
npmStop: (ui) => ui.npm.
|
|
111
|
+
npmStop: (ui) => ui.npm.stop(),
|
|
110
112
|
npmVerbose: (ui) => ui.npm.toggleVerbose(),
|
|
111
113
|
npmRerun: (ui) => ui.npm.rerun(),
|
|
114
|
+
agentModel: (ui) => ui.agents.openPick('model'),
|
|
115
|
+
agentEffort: (ui) => ui.agents.openPick('effort'),
|
|
116
|
+
agentFast: (ui) => ui.agents.toggleFast(),
|
|
117
|
+
agentContext: (ui) => ui.agents.openPick('context'),
|
|
118
|
+
agentReview: (ui) => ui.agents.openPick('plan'),
|
|
119
|
+
agentStop: (ui) => ui.agents.stop(),
|
|
120
|
+
agentRerun: (ui) => ui.agents.rerun(),
|
|
112
121
|
quit: (ui) => ui.onQuit(),
|
|
113
122
|
repoLeft: (ui) => ui.workspace.move(-1, 0),
|
|
114
123
|
repoRight: (ui) => ui.workspace.move(1, 0),
|
|
@@ -119,10 +128,15 @@ const HANDLERS = {
|
|
|
119
128
|
|
|
120
129
|
const dispatchAction = (ui, action) => {
|
|
121
130
|
if (CONFIRM_MODE.includes(ui.mode)) return;
|
|
131
|
+
if (ui.mode === 'import') stopImport(ui);
|
|
132
|
+
if (action === 'lines' && (ui.pane === 'diff' || ui.pane === 'unit')) {
|
|
133
|
+
return void filesPane.onLineNumbers(ui);
|
|
134
|
+
}
|
|
122
135
|
if (ui.mode === 'compose') {
|
|
123
136
|
if (!COMPOSE_LEAVE.includes(action)) return;
|
|
124
|
-
const
|
|
125
|
-
|
|
137
|
+
const after = () => dispatchAction(ui, action);
|
|
138
|
+
const result = ui.composer.saveCompose({ after });
|
|
139
|
+
if (result.kind === 'saving') return;
|
|
126
140
|
}
|
|
127
141
|
const pane = ui.pane;
|
|
128
142
|
if (pane === 'repos' && !REPOS_ALLOWED.includes(action)) return;
|
|
@@ -137,8 +151,7 @@ const dispatchAction = (ui, action) => {
|
|
|
137
151
|
|
|
138
152
|
const CONFIRMATIONS = {
|
|
139
153
|
confirmQuit: {
|
|
140
|
-
|
|
141
|
-
editing: (ui) => ui.finishQuit('editing'),
|
|
154
|
+
confirm: (ui) => ui.confirmQuit(),
|
|
142
155
|
cancel: (ui) => ui.cancelQuit(),
|
|
143
156
|
},
|
|
144
157
|
confirmUpdate: {
|
|
@@ -164,6 +177,7 @@ const CONFIRMATIONS = {
|
|
|
164
177
|
cancel: (ui) => ui.gitBranches.cancelPush(),
|
|
165
178
|
},
|
|
166
179
|
confirmCommit: {
|
|
180
|
+
update: (ui) => ui.commits.chooseCommit('update'),
|
|
167
181
|
commit: (ui) => ui.commits.chooseCommit('commit'),
|
|
168
182
|
amend: (ui) => ui.commits.chooseCommit('amend'),
|
|
169
183
|
fixup: (ui) => ui.commits.chooseCommit('fixup'),
|
|
@@ -179,6 +193,7 @@ const confirmChoice = (ui, key) => {
|
|
|
179
193
|
|
|
180
194
|
const NPM_VIEW_KEYS = {
|
|
181
195
|
escape: (ui) => ui.npm.closeView(),
|
|
196
|
+
s: (ui) => ui.npm.stop(),
|
|
182
197
|
r: (ui) => ui.npm.rerun(),
|
|
183
198
|
v: (ui) => ui.npm.toggleVerbose(),
|
|
184
199
|
e: () => {},
|
|
@@ -190,31 +205,80 @@ const NPM_LIST_KEYS = {
|
|
|
190
205
|
'ctrl-down': (ui) => ui.npm.reorder(1),
|
|
191
206
|
up: (ui) => ui.npm.move(-1),
|
|
192
207
|
down: (ui) => ui.npm.move(1),
|
|
208
|
+
right: (ui) => ui.npm.focusRuns(),
|
|
209
|
+
left: (ui) => ui.npm.focusCommands(),
|
|
210
|
+
tab: (ui) => ui.npm.toggleFocus(),
|
|
211
|
+
'shift-tab': (ui) => ui.npm.toggleFocus(),
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const AGENT_VIEW_KEYS = {
|
|
215
|
+
escape: (ui) => ui.agents.closeView(),
|
|
216
|
+
s: (ui) => ui.agents.stop(),
|
|
217
|
+
r: (ui) => ui.agents.rerun(),
|
|
218
|
+
e: () => {},
|
|
219
|
+
m: () => {},
|
|
220
|
+
a: () => {},
|
|
221
|
+
t: () => {},
|
|
222
|
+
f: () => {},
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const AGENT_LIST_KEYS = {
|
|
226
|
+
right: (ui) => ui.agents.focusRuns(),
|
|
227
|
+
left: (ui) => ui.agents.focusCli(),
|
|
228
|
+
tab: (ui) => ui.agents.toggleFocus(),
|
|
229
|
+
'shift-tab': (ui) => ui.agents.toggleFocus(),
|
|
193
230
|
};
|
|
194
231
|
|
|
195
232
|
const npmKey = (ui, key) => {
|
|
196
233
|
if (ui.pane !== 'npm') return null;
|
|
197
|
-
if (ui.npm.viewing
|
|
198
|
-
return NPM_VIEW_KEYS[key];
|
|
234
|
+
if (ui.npm.viewing) {
|
|
235
|
+
if (Object.hasOwn(NPM_VIEW_KEYS, key)) return NPM_VIEW_KEYS[key];
|
|
236
|
+
if (key === 'up' || key === 'down') return NPM_LIST_KEYS[key];
|
|
237
|
+
return null;
|
|
199
238
|
}
|
|
200
239
|
return Object.hasOwn(NPM_LIST_KEYS, key) ? NPM_LIST_KEYS[key] : null;
|
|
201
240
|
};
|
|
202
241
|
|
|
242
|
+
const agentKey = (ui, key) => {
|
|
243
|
+
if (ui.pane !== 'agents') return null;
|
|
244
|
+
if (ui.agents.pick) return () => ui.agents.onPickKey(key);
|
|
245
|
+
const keys = ui.agents.viewing ? AGENT_VIEW_KEYS : AGENT_LIST_KEYS;
|
|
246
|
+
return Object.hasOwn(keys, key) ? keys[key] : null;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const planMenuKey = (ui, key) => {
|
|
250
|
+
if (!ui.composer.tasks.planOpen || ui.pane !== 'tasks') return false;
|
|
251
|
+
ui.composer.tasks.onPlanKey(key);
|
|
252
|
+
return true;
|
|
253
|
+
};
|
|
254
|
+
|
|
203
255
|
const handleKey = (ui, key) => {
|
|
204
256
|
if (CONFIRM_MODE.includes(ui.mode)) return void confirmChoice(ui, key);
|
|
257
|
+
if (planMenuKey(ui, key)) return;
|
|
258
|
+
if (ui.pane === 'tasks' && (key === 'ctrl-up' || key === 'ctrl-down')) {
|
|
259
|
+
if (ui.mode === 'import') stopImport(ui);
|
|
260
|
+
const delta = key === 'ctrl-up' ? -1 : 1;
|
|
261
|
+
return void ui.composer.tasks.moveIssue(delta);
|
|
262
|
+
}
|
|
263
|
+
if (key === 'ctrl-l' && (ui.pane === 'diff' || ui.pane === 'unit')) {
|
|
264
|
+
return void filesPane.onLineNumbers(ui);
|
|
265
|
+
}
|
|
205
266
|
if (ui.mode === 'compose') {
|
|
206
267
|
return void ui.runComposeCommand(ui.composer.handleKey(key));
|
|
207
268
|
}
|
|
208
269
|
if (ui.mode === 'find') return void onFindKey(ui, key);
|
|
270
|
+
if (ui.mode === 'import') return void onImportKey(ui, key);
|
|
209
271
|
if (key === '/' && FIND_PANES.includes(ui.pane)) return void startFind(ui);
|
|
210
272
|
const onNpmKey = npmKey(ui, key);
|
|
211
273
|
if (onNpmKey) return void onNpmKey(ui);
|
|
274
|
+
const onAgentKey = agentKey(ui, key);
|
|
275
|
+
if (onAgentKey) return void onAgentKey(ui);
|
|
212
276
|
if (key === 'escape') return void filesPane.onEscape(ui);
|
|
213
277
|
const tasks = ui.composer.tasks;
|
|
214
278
|
const toggle = key === ' ';
|
|
215
279
|
if (toggle && tasks.toggleFocusedTask()) return;
|
|
216
280
|
if (tasks.typeIntoTask(key)) return;
|
|
217
|
-
const action = actionFromKey(key, ui.pane
|
|
281
|
+
const action = actionFromKey(key, ui.pane);
|
|
218
282
|
if (action) ui.dispatch(action);
|
|
219
283
|
};
|
|
220
284
|
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const {
|
|
6
|
-
const {
|
|
7
|
-
const
|
|
8
|
-
const {
|
|
9
|
-
const
|
|
10
|
-
const actions = require('./actions.js');
|
|
11
|
-
const { LIST_PANES } = actions;
|
|
12
|
-
const { setFileScope, openUnitFile, moveUnitBlock } = unit;
|
|
3
|
+
const { clamp } = require('../common/utilities.js');
|
|
4
|
+
const { THEME_NAMES, setTheme, themeName } = require('../term/ansi.js');
|
|
5
|
+
const { isTasksEntry, TASKS_FILE } = require('../common/files.js');
|
|
6
|
+
const { logViewRows } = require('../render/log.js');
|
|
7
|
+
const { setFileScope, openUnitFile, moveUnitBlock } = require('./unit.js');
|
|
8
|
+
const { LIST_PANES } = require('../input/actions.js');
|
|
9
|
+
const { saveUiPrefs, LAYOUT_LABEL } = require('./prefs.js');
|
|
13
10
|
|
|
14
11
|
const LAYOUTS = ['unified', 'mixed', 'side'];
|
|
15
12
|
|
|
@@ -31,12 +28,8 @@ const syncFileCursor = (ui) => {
|
|
|
31
28
|
|
|
32
29
|
const showFiles = (ui) => {
|
|
33
30
|
const nav = ui.nav;
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
nav.pane === 'branches' ||
|
|
37
|
-
nav.pane === 'commits' ||
|
|
38
|
-
nav.pane === 'npm' ||
|
|
39
|
-
nav.pane === 'packages';
|
|
31
|
+
const listed = nav.pane !== 'files' && LIST_PANES.includes(nav.pane);
|
|
32
|
+
const held = nav.tasksOpen === true || listed;
|
|
40
33
|
nav.pane = 'files';
|
|
41
34
|
nav.resetListScroll('files');
|
|
42
35
|
nav.clearSelection();
|
|
@@ -67,15 +60,22 @@ const showDashboard = (ui) => {
|
|
|
67
60
|
ui.dashboard.enter();
|
|
68
61
|
};
|
|
69
62
|
|
|
70
|
-
const HOME_CHILDREN = ['files', 'branches', 'commits', 'npm', 'packages'];
|
|
71
|
-
|
|
72
63
|
const returnsHome = (ui) => {
|
|
73
64
|
if (!ui.dashboardHome) return false;
|
|
74
65
|
const { pane, tasksOpen } = ui.nav;
|
|
75
|
-
return
|
|
66
|
+
return LIST_PANES.includes(pane) || tasksOpen === true;
|
|
76
67
|
};
|
|
77
68
|
|
|
78
69
|
const onEscape = (ui) => {
|
|
70
|
+
if (ui.nav.pane === 'agents' && ui.agents.pick) {
|
|
71
|
+
return void ui.agents.closePick();
|
|
72
|
+
}
|
|
73
|
+
if (ui.nav.pane === 'agents' && ui.agents.viewing) {
|
|
74
|
+
return void ui.agents.closeView();
|
|
75
|
+
}
|
|
76
|
+
if (ui.nav.pane === 'npm' && ui.npm.viewing) {
|
|
77
|
+
return void ui.npm.closeView();
|
|
78
|
+
}
|
|
79
79
|
if (ui.nav.pane === 'repos') return void ui.onQuit();
|
|
80
80
|
if (ui.nav.pane === 'dashboard' && ui.workspaceRoot) {
|
|
81
81
|
return void ui.workspace.show();
|
|
@@ -112,6 +112,7 @@ const onOpenFile = (ui) => {
|
|
|
112
112
|
}
|
|
113
113
|
if (ui.nav.pane === 'commits') return void ui.commits.onShowDiff();
|
|
114
114
|
if (ui.nav.pane === 'npm') return void ui.npm.run();
|
|
115
|
+
if (ui.nav.pane === 'agents') return void ui.agents.start();
|
|
115
116
|
if (ui.nav.pane !== 'files') {
|
|
116
117
|
if (ui.nav.tasksOpen) ui.composer.tasks.editFocusedTask();
|
|
117
118
|
return;
|
|
@@ -144,7 +145,7 @@ const onFileMove = (ui, delta) => {
|
|
|
144
145
|
}
|
|
145
146
|
const last = list.length - 1;
|
|
146
147
|
const moved = ui.nav.fileCursor + delta;
|
|
147
|
-
const next =
|
|
148
|
+
const next = clamp(moved, 0, last);
|
|
148
149
|
if (next === ui.nav.fileCursor) return;
|
|
149
150
|
ui.nav.fileCursor = next;
|
|
150
151
|
const entry = list[next];
|
|
@@ -191,7 +192,8 @@ const scrollStep = (ui, fraction) => {
|
|
|
191
192
|
const fallback = Math.max(1, rows - 4);
|
|
192
193
|
const bodyH = frame?.bodyH ?? fallback;
|
|
193
194
|
const viewing = ui.nav.pane === 'npm' && ui.npm.viewing;
|
|
194
|
-
const
|
|
195
|
+
const agentLog = ui.nav.pane === 'agents' && ui.agents.viewing;
|
|
196
|
+
const viewRows = viewing || agentLog ? logViewRows(bodyH) : bodyH;
|
|
195
197
|
const height = Math.max(1, viewRows);
|
|
196
198
|
const span = Math.floor(height * Math.abs(fraction));
|
|
197
199
|
const n = Math.max(1, span);
|
|
@@ -200,6 +202,10 @@ const scrollStep = (ui, fraction) => {
|
|
|
200
202
|
};
|
|
201
203
|
|
|
202
204
|
const onScroll = (ui, delta) => {
|
|
205
|
+
if (ui.composer.tasks.planOpen && ui.nav.pane === 'tasks') {
|
|
206
|
+
const step = delta < 0 ? -1 : 1;
|
|
207
|
+
return void ui.composer.tasks.movePlan(step);
|
|
208
|
+
}
|
|
203
209
|
if (ui.nav.pane === 'dashboard') return;
|
|
204
210
|
if (ui.nav.pane === 'files') return void onFileMove(ui, delta);
|
|
205
211
|
if (ui.nav.pane === 'branches') {
|
|
@@ -209,12 +215,13 @@ const onScroll = (ui, delta) => {
|
|
|
209
215
|
return void ui.commits.onCommitMove(delta);
|
|
210
216
|
}
|
|
211
217
|
if (ui.nav.pane === 'npm') return void ui.npm.move(delta);
|
|
218
|
+
if (ui.nav.pane === 'agents') return void ui.agents.move(delta);
|
|
212
219
|
if (ui.nav.pane === 'packages') {
|
|
213
220
|
const count = ui.dashboard.packageCount();
|
|
214
221
|
const nav = ui.nav;
|
|
215
222
|
const next = nav.packagesCursor + delta;
|
|
216
223
|
const last = Math.max(0, count - 1);
|
|
217
|
-
nav.packagesCursor =
|
|
224
|
+
nav.packagesCursor = clamp(next, 0, last);
|
|
218
225
|
ui.status = '';
|
|
219
226
|
return;
|
|
220
227
|
}
|
|
@@ -253,10 +260,22 @@ const onLayout = (ui) => {
|
|
|
253
260
|
const i = LAYOUTS.indexOf(ui.layout);
|
|
254
261
|
const next = (i < 0 ? 0 : i + 1) % LAYOUTS.length;
|
|
255
262
|
ui.layout = LAYOUTS[next];
|
|
256
|
-
|
|
257
|
-
ui.status = name;
|
|
263
|
+
ui.status = LAYOUT_LABEL[ui.layout] || ui.layout;
|
|
258
264
|
ui.nav.scroll = 0;
|
|
259
265
|
ui.nav.clearSelection();
|
|
266
|
+
saveUiPrefs(ui.top || ui.cwd, { layout: ui.layout });
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const saveLineNumbers = (ui) => {
|
|
270
|
+
const shown = ui.lineNumbers === true;
|
|
271
|
+
saveUiPrefs(ui.top || ui.cwd, { lineNumbers: shown });
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const onLineNumbers = (ui) => {
|
|
275
|
+
ui.lineNumbers = ui.lineNumbers !== true;
|
|
276
|
+
ui.status = ui.lineNumbers ? 'line numbers' : 'no line numbers';
|
|
277
|
+
saveLineNumbers(ui);
|
|
278
|
+
ui.composer.syncCodeScroll();
|
|
260
279
|
};
|
|
261
280
|
|
|
262
281
|
const onTheme = (ui) => {
|
|
@@ -264,12 +283,13 @@ const onTheme = (ui) => {
|
|
|
264
283
|
const next = THEME_NAMES[(i + 1) % THEME_NAMES.length];
|
|
265
284
|
setTheme(next);
|
|
266
285
|
ui.status = next;
|
|
286
|
+
saveUiPrefs(ui.top || ui.cwd, { theme: next });
|
|
267
287
|
};
|
|
268
288
|
|
|
269
289
|
const onHome = (ui) => onJump(ui, false);
|
|
270
290
|
const onEnd = (ui) => onJump(ui, true);
|
|
271
|
-
const onFileScope = (ui) => setFileScope(ui, 'file');
|
|
272
|
-
const onDiffScope = (ui) => setFileScope(ui, 'diff');
|
|
291
|
+
const onFileScope = (ui, quiet) => setFileScope(ui, 'file', quiet === true);
|
|
292
|
+
const onDiffScope = (ui, quiet) => setFileScope(ui, 'diff', quiet === true);
|
|
273
293
|
|
|
274
294
|
module.exports = {
|
|
275
295
|
fileCursorEntry,
|
|
@@ -287,6 +307,7 @@ module.exports = {
|
|
|
287
307
|
onHome,
|
|
288
308
|
onEnd,
|
|
289
309
|
onLayout,
|
|
310
|
+
onLineNumbers,
|
|
290
311
|
onTheme,
|
|
291
312
|
onFileScope,
|
|
292
313
|
onDiffScope,
|
package/lib/session/find.js
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const {
|
|
5
|
-
const
|
|
6
|
-
const { fileMatches } = find;
|
|
3
|
+
const { isTasksEntry, TASKS_FILE } = require('../common/files.js');
|
|
4
|
+
const { fileMatches } = require('../common/find.js');
|
|
5
|
+
const { lineKey, lineField } = require('../input/line-edit.js');
|
|
7
6
|
|
|
8
7
|
const FIND_PANES = ['files', 'diff'];
|
|
9
8
|
|
|
10
|
-
const isTypeKey = (key) =>
|
|
11
|
-
Boolean(key) && key.length === 1 && key.charCodeAt(0) >= 32;
|
|
12
|
-
|
|
13
9
|
const startFind = (ui) => {
|
|
14
10
|
if (ui.mode !== 'review') return;
|
|
15
11
|
if (!FIND_PANES.includes(ui.pane)) return;
|
|
16
12
|
ui.mode = 'find';
|
|
17
|
-
|
|
13
|
+
const find = lineField('query');
|
|
14
|
+
find.at = 0;
|
|
15
|
+
ui.nav.find = find;
|
|
18
16
|
ui.status = '';
|
|
19
17
|
};
|
|
20
18
|
|
|
@@ -56,21 +54,6 @@ const showHit = (ui, jump) => {
|
|
|
56
54
|
focusMatch(ui, hits[at], jump);
|
|
57
55
|
};
|
|
58
56
|
|
|
59
|
-
const typeFind = (ui, key) => {
|
|
60
|
-
const state = ui.nav.find;
|
|
61
|
-
state.query += key;
|
|
62
|
-
state.at = 0;
|
|
63
|
-
showHit(ui, true);
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const eraseFind = (ui) => {
|
|
67
|
-
const state = ui.nav.find;
|
|
68
|
-
if (!state.query) return void stopFind(ui);
|
|
69
|
-
state.query = state.query.slice(0, -1);
|
|
70
|
-
state.at = 0;
|
|
71
|
-
showHit(ui, true);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
57
|
const moveFind = (ui, delta) => {
|
|
75
58
|
const state = ui.nav.find;
|
|
76
59
|
if (!state.query) return;
|
|
@@ -83,12 +66,16 @@ const onFindKey = (ui, key) => {
|
|
|
83
66
|
ui.mode = 'review';
|
|
84
67
|
return;
|
|
85
68
|
}
|
|
86
|
-
if (key === 'ctrl-c') return void ui.onQuit();
|
|
87
69
|
if (key === 'escape' || key === 'enter') return void stopFind(ui);
|
|
88
|
-
if (key === 'backspace') return void
|
|
89
|
-
|
|
90
|
-
if (
|
|
91
|
-
|
|
70
|
+
if (key === 'backspace' && !ui.nav.find.query) return void stopFind(ui);
|
|
71
|
+
const handled = lineKey(ui.nav.find.editor, key, ui, true);
|
|
72
|
+
if (handled === 'text') {
|
|
73
|
+
ui.nav.find.at = 0;
|
|
74
|
+
showHit(ui, true);
|
|
75
|
+
}
|
|
76
|
+
if (handled) return;
|
|
77
|
+
if (key === 'up') return void moveFind(ui, -1);
|
|
78
|
+
if (key === 'down') moveFind(ui, 1);
|
|
92
79
|
};
|
|
93
80
|
|
|
94
|
-
module.exports = { FIND_PANES, startFind,
|
|
81
|
+
module.exports = { FIND_PANES, startFind, onFindKey };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { remoteKind, selectChangeSource } = require('../source/source.js');
|
|
4
|
+
const { lineKey, lineField } = require('../input/line-edit.js');
|
|
5
|
+
|
|
6
|
+
const startImport = (ui) => {
|
|
7
|
+
if (ui.mode !== 'review' || ui.pane !== 'tasks') return;
|
|
8
|
+
ui.composer.tasks.closePlanMenu();
|
|
9
|
+
ui.mode = 'import';
|
|
10
|
+
ui.nav.import = lineField('url');
|
|
11
|
+
ui.status = '';
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const stopImport = (ui) => {
|
|
15
|
+
ui.mode = 'review';
|
|
16
|
+
ui.nav.import = null;
|
|
17
|
+
ui.status = '';
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const noteImport = (ui, message) => {
|
|
21
|
+
ui.status = message;
|
|
22
|
+
if (ui.uiOpen) ui.paint();
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const finishImport = (ui, store, loaded) => {
|
|
26
|
+
const imported = loaded && loaded.imported;
|
|
27
|
+
if (!imported || ui.review.store !== store) {
|
|
28
|
+
noteImport(ui, 'import failed');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
store.applyImportedNotes(imported);
|
|
32
|
+
ui.flushReview();
|
|
33
|
+
noteImport(ui, 'imported');
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const runImport = (ui, selected) => {
|
|
37
|
+
const kind = remoteKind(selected);
|
|
38
|
+
if (!kind) return Promise.resolve(null);
|
|
39
|
+
const load = ui[kind.option] ?? kind.load;
|
|
40
|
+
const target = kind.target(selected);
|
|
41
|
+
if (!load || !target) return Promise.resolve(null);
|
|
42
|
+
const fetch = ui.fetchImpl ?? globalThis.fetch;
|
|
43
|
+
const options = { cwd: ui.top || ui.cwd, token: kind.token(), fetch };
|
|
44
|
+
return Promise.resolve().then(() => load(target, options));
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const submitImport = (ui) => {
|
|
48
|
+
const state = ui.nav.import;
|
|
49
|
+
const url = state ? state.url.trim() : '';
|
|
50
|
+
const store = ui.review.store;
|
|
51
|
+
stopImport(ui);
|
|
52
|
+
if (!url) return;
|
|
53
|
+
const selected = selectChangeSource([url]);
|
|
54
|
+
if (!remoteKind(selected)) {
|
|
55
|
+
ui.status = 'bad url';
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
ui.status = 'importing';
|
|
59
|
+
const pending = runImport(ui, selected);
|
|
60
|
+
ui.importPromise = pending;
|
|
61
|
+
pending.then(
|
|
62
|
+
(loaded) => finishImport(ui, store, loaded),
|
|
63
|
+
(error) => {
|
|
64
|
+
const message = error instanceof Error ? error.message : '';
|
|
65
|
+
noteImport(ui, message || 'import failed');
|
|
66
|
+
},
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const onImportKey = (ui, key) => {
|
|
71
|
+
const state = ui.nav.import;
|
|
72
|
+
if (!state) {
|
|
73
|
+
ui.mode = 'review';
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (key === 'escape') return void stopImport(ui);
|
|
77
|
+
if (key === 'enter') return void submitImport(ui);
|
|
78
|
+
if (key === 'backspace' && !state.url) return void stopImport(ui);
|
|
79
|
+
lineKey(state.editor, key, ui, true);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
module.exports = { startImport, stopImport, onImportKey };
|
package/lib/session/items.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
const {
|
|
4
|
+
itemPath,
|
|
5
|
+
TASKS_FILE,
|
|
6
|
+
isTaskItem,
|
|
7
|
+
groupByPath,
|
|
8
|
+
} = require('../common/files.js');
|
|
9
|
+
const { feedbackKey } = require('../review/review.js');
|
|
10
|
+
const { refreshIndexPatches } = require('../diff/diff.js');
|
|
9
11
|
|
|
10
12
|
const depChangeKey = (item) => {
|
|
11
13
|
const change = item.dep && item.dep.change;
|
|
@@ -72,17 +74,6 @@ const takeBucket = (map, key, used) => {
|
|
|
72
74
|
return null;
|
|
73
75
|
};
|
|
74
76
|
|
|
75
|
-
const groupByPath = (items) => {
|
|
76
|
-
const groups = new Map();
|
|
77
|
-
for (const item of items) {
|
|
78
|
-
const rel = itemPath(item) || '';
|
|
79
|
-
const list = groups.get(rel) ?? [];
|
|
80
|
-
list.push(item);
|
|
81
|
-
groups.set(rel, list);
|
|
82
|
-
}
|
|
83
|
-
return groups;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
77
|
const alignGroup = (prev, next) => {
|
|
87
78
|
if (!prev.length) return next;
|
|
88
79
|
if (!next.length) return [];
|