reslop 0.2.3 → 0.2.4
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 +14 -1
- package/README.md +8 -3
- package/bin/reslop.js +4 -2
- package/lib/api.js +2 -1
- package/lib/cli.js +19 -10
- package/lib/clipboard.js +6 -3
- package/lib/deps-diff.js +61 -115
- package/lib/deps.js +24 -61
- package/lib/detect.js +4 -2
- package/lib/diff/align.js +2 -1
- package/lib/diff/diff.js +6 -3
- package/lib/diff/display.js +2 -1
- package/lib/diff/inline.js +2 -1
- package/lib/diff/patch.js +2 -1
- package/lib/diff/unit.js +4 -2
- package/lib/editor.js +22 -4
- package/lib/files.js +38 -12
- package/lib/git-branches.js +107 -154
- package/lib/git-deps.js +20 -60
- package/lib/git-worktree.js +508 -0
- package/lib/git.js +23 -580
- package/lib/github.js +2 -1
- package/lib/gitlab.js +2 -1
- package/lib/highlight/bash.js +2 -1
- package/lib/highlight/css.js +2 -1
- package/lib/highlight/csv.js +2 -1
- package/lib/highlight/dot.js +2 -1
- package/lib/highlight/html.js +2 -1
- package/lib/highlight/json.js +2 -1
- package/lib/highlight/log.js +2 -1
- package/lib/highlight/txt.js +2 -1
- package/lib/highlight.js +2 -1
- package/lib/keys.js +2 -2
- package/lib/manifest.js +4 -2
- package/lib/npm-commands.js +83 -4
- package/lib/remote.js +20 -13
- package/lib/render/branches.js +6 -15
- package/lib/render/chrome.js +27 -7
- package/lib/render/commits.js +158 -46
- package/lib/render/diff.js +130 -47
- package/lib/render/files.js +4 -12
- package/lib/render/frame.js +3 -9
- package/lib/render/notes.js +4 -11
- package/lib/render/npm.js +1 -13
- package/lib/render/present.js +2 -1
- package/lib/render/primitives.js +28 -15
- package/lib/render/render.js +2 -1
- package/lib/render/unit.js +14 -11
- package/lib/report-model.js +6 -4
- package/lib/report-parse.js +8 -13
- package/lib/report-render.js +38 -21
- package/lib/report-run.js +12 -10
- package/lib/report-test.js +5 -4
- package/lib/report-tools.js +44 -18
- package/lib/review-merge.js +2 -1
- package/lib/review.js +6 -2
- package/lib/session/actions.js +49 -65
- package/lib/session/branches.js +13 -49
- package/lib/session/change-actions.js +2 -1
- package/lib/session/commit.js +34 -49
- package/lib/session/compose.js +37 -11
- package/lib/session/dispatch.js +17 -25
- package/lib/session/files-pane.js +6 -27
- package/lib/session/items.js +6 -3
- package/lib/session/lifecycle.js +8 -4
- package/lib/session/load.js +4 -2
- package/lib/session/navigation.js +1 -0
- package/lib/session/npm.js +54 -1
- package/lib/session/ops.js +15 -1
- package/lib/session/pointer.js +22 -3
- package/lib/session/review.js +2 -1
- package/lib/session/terminal.js +4 -2
- package/lib/session/update.js +2 -1
- package/lib/session/view.js +29 -3
- package/lib/session.js +37 -23
- package/lib/source.js +6 -3
- package/lib/update.js +5 -9
- package/lib/utilities.js +4 -2
- package/lib/wrap.js +3 -1
- package/package.json +1 -1
package/lib/session/actions.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const LIST_PANES = ['files', 'branches', 'commits', 'npm'];
|
|
4
|
+
|
|
3
5
|
const ACTIONS = {
|
|
4
6
|
add: ['a'],
|
|
5
7
|
unstage: ['u'],
|
|
@@ -42,6 +44,8 @@ const NPM_ACTIONS = {
|
|
|
42
44
|
npm: ['n'],
|
|
43
45
|
npmEdit: ['e'],
|
|
44
46
|
npmNew: ['n'],
|
|
47
|
+
npmDrop: ['d'],
|
|
48
|
+
npmLogs: ['c'],
|
|
45
49
|
npmStop: ['escape'],
|
|
46
50
|
npmRerun: ['r'],
|
|
47
51
|
};
|
|
@@ -61,6 +65,8 @@ const ACTION_LABEL = {
|
|
|
61
65
|
newBranch: 'new',
|
|
62
66
|
npmEdit: 'edit',
|
|
63
67
|
npmNew: 'new',
|
|
68
|
+
npmDrop: 'delete',
|
|
69
|
+
npmLogs: 'cleanup',
|
|
64
70
|
npmStop: 'esc',
|
|
65
71
|
npmRerun: 're-run',
|
|
66
72
|
quit: 'q',
|
|
@@ -121,39 +127,8 @@ const BRANCHES_DISABLED = [
|
|
|
121
127
|
'prev',
|
|
122
128
|
'next',
|
|
123
129
|
];
|
|
124
|
-
const COMMITS_DISABLED =
|
|
125
|
-
|
|
126
|
-
'unstage',
|
|
127
|
-
'revert',
|
|
128
|
-
'layout',
|
|
129
|
-
'feedback',
|
|
130
|
-
'todo',
|
|
131
|
-
'code',
|
|
132
|
-
'check',
|
|
133
|
-
'branch',
|
|
134
|
-
'file',
|
|
135
|
-
'diff',
|
|
136
|
-
'prev',
|
|
137
|
-
'next',
|
|
138
|
-
];
|
|
139
|
-
const NPM_DISABLED = [
|
|
140
|
-
'add',
|
|
141
|
-
'unstage',
|
|
142
|
-
'revert',
|
|
143
|
-
'commit',
|
|
144
|
-
'layout',
|
|
145
|
-
'feedback',
|
|
146
|
-
'todo',
|
|
147
|
-
'code',
|
|
148
|
-
'check',
|
|
149
|
-
'branch',
|
|
150
|
-
'file',
|
|
151
|
-
'diff',
|
|
152
|
-
'prev',
|
|
153
|
-
'next',
|
|
154
|
-
'pull',
|
|
155
|
-
'push',
|
|
156
|
-
];
|
|
130
|
+
const COMMITS_DISABLED = BRANCHES_DISABLED.filter((id) => id !== 'commit');
|
|
131
|
+
const NPM_DISABLED = [...BRANCHES_DISABLED, 'pull', 'push'];
|
|
157
132
|
|
|
158
133
|
const isTodosTarget = (item) =>
|
|
159
134
|
!!(item && (item.kind === 'todos' || item.origin === 'todo'));
|
|
@@ -176,8 +151,16 @@ const isFixupCommit = (item) =>
|
|
|
176
151
|
`${item && item.subject ? item.subject : ''}`.startsWith('fixup!');
|
|
177
152
|
|
|
178
153
|
const commitWriteDisabled = (item) => {
|
|
179
|
-
|
|
180
|
-
|
|
154
|
+
const pending = Boolean(item && item.pending);
|
|
155
|
+
const unstaged = Boolean(item && item.unstagedCurrent);
|
|
156
|
+
if (!item || !item.sha) {
|
|
157
|
+
const off = ['reword', 'fixup', 'drop'];
|
|
158
|
+
if (pending) return off;
|
|
159
|
+
return ['amend', 'apply', ...off];
|
|
160
|
+
}
|
|
161
|
+
if (unstaged) return [];
|
|
162
|
+
if (isFixupCommit(item)) return ['amend'];
|
|
163
|
+
return ['amend', 'apply'];
|
|
181
164
|
};
|
|
182
165
|
|
|
183
166
|
const commitGitDisabled = (item) => {
|
|
@@ -224,26 +207,29 @@ const SCROLL = {
|
|
|
224
207
|
delete: 'removeTodo',
|
|
225
208
|
};
|
|
226
209
|
|
|
227
|
-
const
|
|
210
|
+
const keysForActions = (actions) => {
|
|
211
|
+
const keys = {};
|
|
212
|
+
for (const [id, shortcuts] of Object.entries(actions)) {
|
|
213
|
+
for (const key of shortcuts) keys[key] = id;
|
|
214
|
+
}
|
|
215
|
+
return keys;
|
|
216
|
+
};
|
|
217
|
+
|
|
228
218
|
const PANE_ONLY = ['branch', 'file', 'diff'];
|
|
229
|
-
const FILES_KEYS = {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
const COMMIT_KEYS = {};
|
|
239
|
-
for (const id of Object.keys(COMMIT_ACTIONS)) {
|
|
240
|
-
for (const key of COMMIT_ACTIONS[id]) COMMIT_KEYS[key] = id;
|
|
241
|
-
}
|
|
219
|
+
const FILES_KEYS = keysForActions({
|
|
220
|
+
branch: ACTIONS.branch,
|
|
221
|
+
pull: BRANCH_ACTIONS.pull,
|
|
222
|
+
push: BRANCH_ACTIONS.push,
|
|
223
|
+
npm: NPM_ACTIONS.npm,
|
|
224
|
+
});
|
|
225
|
+
const BRANCH_KEYS = keysForActions(BRANCH_ACTIONS);
|
|
226
|
+
const COMMIT_KEYS = keysForActions(COMMIT_ACTIONS);
|
|
242
227
|
const NPM_KEYS = {
|
|
243
228
|
e: 'npmEdit',
|
|
244
229
|
n: 'npmNew',
|
|
230
|
+
d: 'npmDrop',
|
|
231
|
+
c: 'npmLogs',
|
|
245
232
|
};
|
|
246
|
-
FILES_KEYS.n = 'npm';
|
|
247
233
|
const PANE_KEYS = {
|
|
248
234
|
files: FILES_KEYS,
|
|
249
235
|
branches: BRANCH_KEYS,
|
|
@@ -251,23 +237,20 @@ const PANE_KEYS = {
|
|
|
251
237
|
npm: NPM_KEYS,
|
|
252
238
|
};
|
|
253
239
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
240
|
+
const KEY_TO_ACTION = {
|
|
241
|
+
...keysForActions(
|
|
242
|
+
Object.fromEntries(
|
|
243
|
+
Object.entries(ACTIONS).filter(([id]) => !PANE_ONLY.includes(id)),
|
|
244
|
+
),
|
|
245
|
+
),
|
|
246
|
+
...SCROLL,
|
|
247
|
+
...HIDDEN_KEYS,
|
|
248
|
+
};
|
|
263
249
|
|
|
264
250
|
const actionFromKey = (key, pane, fileScope) => {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
pane === 'commits' ||
|
|
269
|
-
pane === 'npm';
|
|
270
|
-
if (listPane && (key === 'left' || key === 'right')) return null;
|
|
251
|
+
if (LIST_PANES.includes(pane) && (key === 'left' || key === 'right')) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
271
254
|
const paneKeys = PANE_KEYS[pane];
|
|
272
255
|
if (paneKeys && paneKeys[key]) return paneKeys[key];
|
|
273
256
|
if (pane === 'files') {
|
|
@@ -370,6 +353,7 @@ const promptFromChoices = (choices) =>
|
|
|
370
353
|
choices.map((choice) => `${choice.lead}${choice.label}`).join('');
|
|
371
354
|
|
|
372
355
|
module.exports = {
|
|
356
|
+
LIST_PANES,
|
|
373
357
|
ACTIONS,
|
|
374
358
|
ACTION_IDS,
|
|
375
359
|
BRANCH_ACTIONS,
|
package/lib/session/branches.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const accessors = require('./accessors.js');
|
|
4
|
+
const { stateView } = accessors;
|
|
4
5
|
|
|
5
|
-
const
|
|
6
|
+
const ops = require('./ops.js');
|
|
7
|
+
const { pickRepoWrite } = ops;
|
|
6
8
|
|
|
7
9
|
const selectedBranch = (api) => {
|
|
8
10
|
const cursor = api.ui.nav.branchCursor;
|
|
@@ -95,12 +97,6 @@ const onCheckoutBranch = (api) => {
|
|
|
95
97
|
if (!api.ui.status) api.ui.status = done;
|
|
96
98
|
};
|
|
97
99
|
|
|
98
|
-
const rebaseAsync = (api, onto, done, write) => {
|
|
99
|
-
const run = (top) => write(top, onto);
|
|
100
|
-
const after = () => refreshAfterWrite(api, { doneStatus: done });
|
|
101
|
-
return void api.ui.ops.runBusy('rebasing', done, run, after);
|
|
102
|
-
};
|
|
103
|
-
|
|
104
100
|
const onRebaseBranch = (api) => {
|
|
105
101
|
if (api.ui.nav.pane !== 'branches') return;
|
|
106
102
|
if (!api.ui.commits.canCommit()) return;
|
|
@@ -108,17 +104,9 @@ const onRebaseBranch = (api) => {
|
|
|
108
104
|
if (!entry || entry.current) return;
|
|
109
105
|
const onto = entry.name;
|
|
110
106
|
const done = `rebased onto ${onto}`;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return void rebaseAsync(api, onto, done, picked.write);
|
|
115
|
-
}
|
|
116
|
-
const ok = api.ui.ops.runRepo(done, (top) => {
|
|
117
|
-
api.ui.repo.rebase(top, onto);
|
|
118
|
-
});
|
|
119
|
-
if (!ok) return;
|
|
120
|
-
refreshAfterWrite(api);
|
|
121
|
-
if (!api.ui.status) api.ui.status = done;
|
|
107
|
+
api.ui.ops.runWrite('rebase', [onto], 'rebasing', done, (extra) =>
|
|
108
|
+
refreshAfterWrite(api, extra),
|
|
109
|
+
);
|
|
122
110
|
};
|
|
123
111
|
|
|
124
112
|
const onDropBranch = (api) => {
|
|
@@ -137,29 +125,15 @@ const cancelDropBranch = (api) => {
|
|
|
137
125
|
api.ui.status = '';
|
|
138
126
|
};
|
|
139
127
|
|
|
140
|
-
const dropAsync = (api, name, done, write) => {
|
|
141
|
-
const run = (top) => write(top, name);
|
|
142
|
-
const after = () => refreshAfterWrite(api, { doneStatus: done });
|
|
143
|
-
return void api.ui.ops.runBusy('dropping', done, run, after);
|
|
144
|
-
};
|
|
145
|
-
|
|
146
128
|
const confirmDropBranch = (api) => {
|
|
147
129
|
const name = api.state.dropName;
|
|
148
130
|
api.ui.mode = 'review';
|
|
149
131
|
api.state.dropName = '';
|
|
150
132
|
if (!name) return;
|
|
151
133
|
const done = `dropped ${name}`;
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return void dropAsync(api, name, done, picked.write);
|
|
156
|
-
}
|
|
157
|
-
const ok = api.ui.ops.runRepo(done, (top) => {
|
|
158
|
-
api.ui.repo.drop(top, name);
|
|
159
|
-
});
|
|
160
|
-
if (!ok) return;
|
|
161
|
-
refreshAfterWrite(api);
|
|
162
|
-
if (!api.ui.status) api.ui.status = done;
|
|
134
|
+
api.ui.ops.runWrite('drop', [name], 'dropping', done, (extra) =>
|
|
135
|
+
refreshAfterWrite(api, extra),
|
|
136
|
+
);
|
|
163
137
|
};
|
|
164
138
|
|
|
165
139
|
const onNewBranch = (api) => {
|
|
@@ -201,19 +175,9 @@ const finishCreateBranch = (api) => {
|
|
|
201
175
|
|
|
202
176
|
const onPull = (api) => {
|
|
203
177
|
if (!api.ui.commits.canCommit()) return;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const after = () => refreshAfterWrite(api);
|
|
208
|
-
const write = (top) => picked.write(top);
|
|
209
|
-
return void api.ui.ops.runBusy('pulling', 'pulled', write, after);
|
|
210
|
-
}
|
|
211
|
-
const ok = api.ui.ops.runRepo('pulled', (top) => {
|
|
212
|
-
repo.pull(top);
|
|
213
|
-
});
|
|
214
|
-
if (!ok) return;
|
|
215
|
-
refreshAfterWrite(api);
|
|
216
|
-
if (!api.ui.status) api.ui.status = 'pulled';
|
|
178
|
+
api.ui.ops.runWrite('pull', [], 'pulling', 'pulled', (extra) =>
|
|
179
|
+
refreshAfterWrite(api, extra),
|
|
180
|
+
);
|
|
217
181
|
};
|
|
218
182
|
|
|
219
183
|
const startPush = (api, force) => {
|
|
@@ -4,7 +4,8 @@ const files = require('../files.js');
|
|
|
4
4
|
const { listPath, isTodoItem, isTodosEntry, isReadOnlyOrigin } = files;
|
|
5
5
|
const items = require('./items.js');
|
|
6
6
|
const { needsReload, npmBusyKind, sameBlock } = items;
|
|
7
|
-
const
|
|
7
|
+
const diff = require('../diff/diff.js');
|
|
8
|
+
const { hunkKey } = diff;
|
|
8
9
|
|
|
9
10
|
const nextUnstageOrigin = (item) => {
|
|
10
11
|
if (item.file.isNew === true) return 'untracked';
|
package/lib/session/commit.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
const accessors = require('./accessors.js');
|
|
4
|
+
const { stateView } = accessors;
|
|
5
|
+
|
|
6
|
+
const files = require('../files.js');
|
|
7
|
+
const { isReadOnlyOrigin } = files;
|
|
8
|
+
const actions = require('./actions.js');
|
|
9
|
+
const { isFixupCommit } = actions;
|
|
10
|
+
const ops = require('./ops.js');
|
|
11
|
+
const { pickRepoWrite } = ops;
|
|
12
|
+
const commits = require('../render/commits.js');
|
|
13
|
+
const { commitLine, commitText, splitMessage } = commits;
|
|
13
14
|
|
|
14
15
|
const COMMIT_STATUS = {
|
|
15
16
|
commit: 'committed',
|
|
@@ -181,11 +182,23 @@ const onCommit = (api) => {
|
|
|
181
182
|
startGitCommit(api, 'commit');
|
|
182
183
|
};
|
|
183
184
|
|
|
185
|
+
const openLoadedDiff = (ui) => {
|
|
186
|
+
ui.nav.todoOpen = false;
|
|
187
|
+
ui.nav.scroll = 0;
|
|
188
|
+
ui.nav.index = 0;
|
|
189
|
+
ui.nav.pane = ui.items.length ? 'diff' : 'files';
|
|
190
|
+
ui.syncReviewPath();
|
|
191
|
+
ui.syncFileCursor();
|
|
192
|
+
ui.status = '';
|
|
193
|
+
};
|
|
194
|
+
|
|
184
195
|
const showSelectedDiff = (api) => {
|
|
185
196
|
if (api.ui.mode === 'compose') return;
|
|
186
197
|
const entry = selectedCommit(api);
|
|
187
198
|
if (!entry) return;
|
|
188
199
|
const ui = api.ui;
|
|
200
|
+
const viewingCommit = Boolean(ui.rev || ui.revShort);
|
|
201
|
+
if (isPending(entry) && !viewingCommit) return void onCommit(api);
|
|
189
202
|
if (isPending(entry) || !entry.sha) {
|
|
190
203
|
ui.rev = '';
|
|
191
204
|
ui.revShort = '';
|
|
@@ -193,16 +206,10 @@ const showSelectedDiff = (api) => {
|
|
|
193
206
|
ui.rev = entry.sha;
|
|
194
207
|
ui.revShort = entry.shortSha || '';
|
|
195
208
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
ui.nav.pane = ui.items.length ? 'diff' : 'files';
|
|
201
|
-
ui.syncReviewPath();
|
|
202
|
-
ui.syncFileCursor();
|
|
203
|
-
ui.status = '';
|
|
204
|
-
};
|
|
205
|
-
ui.refreshFromRepo({ keepEmpty: true, afterLoad: openDiff });
|
|
209
|
+
ui.refreshFromRepo({
|
|
210
|
+
keepEmpty: true,
|
|
211
|
+
afterLoad: () => openLoadedDiff(ui),
|
|
212
|
+
});
|
|
206
213
|
};
|
|
207
214
|
|
|
208
215
|
const onAmend = (api) => {
|
|
@@ -226,18 +233,9 @@ const applyFixupNow = (api) => {
|
|
|
226
233
|
api.ui.status = 'read only';
|
|
227
234
|
return;
|
|
228
235
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
const after = () => refreshAfterWrite(api, { doneStatus: done });
|
|
233
|
-
return void api.ui.ops.runBusy('applying', done, run, after);
|
|
234
|
-
}
|
|
235
|
-
const ok = api.ui.ops.runRepo(done, (top) => {
|
|
236
|
-
repo.applyFixup(top, entry.sha);
|
|
237
|
-
});
|
|
238
|
-
if (!ok) return;
|
|
239
|
-
refreshAfterWrite(api);
|
|
240
|
-
if (!api.ui.status) api.ui.status = done;
|
|
236
|
+
api.ui.ops.runWrite('applyFixup', [entry.sha], 'applying', done, (extra) =>
|
|
237
|
+
refreshAfterWrite(api, extra),
|
|
238
|
+
);
|
|
241
239
|
};
|
|
242
240
|
|
|
243
241
|
const onApply = (api) => {
|
|
@@ -360,12 +358,6 @@ const cancelDropCommit = (api) => {
|
|
|
360
358
|
api.ui.status = '';
|
|
361
359
|
};
|
|
362
360
|
|
|
363
|
-
const dropAsync = (api, sha, done, write) => {
|
|
364
|
-
const run = (top) => write(top, sha);
|
|
365
|
-
const after = () => refreshAfterWrite(api, { doneStatus: done });
|
|
366
|
-
return void api.ui.ops.runBusy('dropping', done, run, after);
|
|
367
|
-
};
|
|
368
|
-
|
|
369
361
|
const confirmDropCommit = (api) => {
|
|
370
362
|
const sha = api.state.dropSha;
|
|
371
363
|
const name = api.state.dropName;
|
|
@@ -379,17 +371,9 @@ const confirmDropCommit = (api) => {
|
|
|
379
371
|
api.ui.status = 'read only';
|
|
380
372
|
return;
|
|
381
373
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
return void dropAsync(api, sha, done, picked.write);
|
|
386
|
-
}
|
|
387
|
-
const ok = api.ui.ops.runRepo(done, (top) => {
|
|
388
|
-
repo.dropCommit(top, sha);
|
|
389
|
-
});
|
|
390
|
-
if (!ok) return;
|
|
391
|
-
refreshAfterWrite(api);
|
|
392
|
-
if (!api.ui.status) api.ui.status = done;
|
|
374
|
+
api.ui.ops.runWrite('dropCommit', [sha], 'dropping', done, (extra) =>
|
|
375
|
+
refreshAfterWrite(api, extra),
|
|
376
|
+
);
|
|
393
377
|
};
|
|
394
378
|
|
|
395
379
|
const onView = (api) => {
|
|
@@ -442,6 +426,7 @@ const createCommitController = (ui) => {
|
|
|
442
426
|
|
|
443
427
|
module.exports = {
|
|
444
428
|
COMMIT_STATUS,
|
|
429
|
+
hasStagedChanges,
|
|
445
430
|
createCommitController,
|
|
446
431
|
listedCommits,
|
|
447
432
|
};
|
package/lib/session/compose.js
CHANGED
|
@@ -4,18 +4,24 @@ const wrap = require('../wrap.js');
|
|
|
4
4
|
const { cursorInWrap, wrapDoc } = wrap;
|
|
5
5
|
const render = require('../render/render.js');
|
|
6
6
|
const { noteInnerWidth, codeInnerWidth, todoBodyWidth } = render;
|
|
7
|
-
const
|
|
8
|
-
const {
|
|
9
|
-
const
|
|
7
|
+
const commits = require('../render/commits.js');
|
|
8
|
+
const { commitMessageWidth } = commits;
|
|
9
|
+
const commit = require('./commit.js');
|
|
10
|
+
const { listedCommits } = commit;
|
|
11
|
+
const editor = require('../editor.js');
|
|
12
|
+
const { Editor } = editor;
|
|
10
13
|
const files = require('../files.js');
|
|
11
14
|
const { itemPath, isTodoItem, listPath, isReadOnlyOrigin } = files;
|
|
12
|
-
const
|
|
15
|
+
const diff = require('../diff/diff.js');
|
|
16
|
+
const { blockAddText } = diff;
|
|
13
17
|
const items = require('./items.js');
|
|
14
18
|
const { itemFeedKey, canEditCode } = items;
|
|
15
19
|
const review = require('../review.js');
|
|
16
20
|
const { setFeedback, setCode, checkLabel, rememberTemplate } = review;
|
|
17
|
-
const
|
|
18
|
-
const {
|
|
21
|
+
const templates = require('./templates.js');
|
|
22
|
+
const { createTemplatePick } = templates;
|
|
23
|
+
const todos = require('./todos.js');
|
|
24
|
+
const { createTodoCompose } = todos;
|
|
19
25
|
const unit = require('./unit.js');
|
|
20
26
|
|
|
21
27
|
const COMPOSE_EDITS = ['backspace', 'delete', 'ctrl-z', 'ctrl-y'];
|
|
@@ -112,6 +118,16 @@ const tickBlink = (api) => {
|
|
|
112
118
|
|
|
113
119
|
const viewSize = (api) => api.ui.lastSize ?? api.ui.getSize();
|
|
114
120
|
|
|
121
|
+
const syncCodeScroll = (api) => {
|
|
122
|
+
const kind = api.state.composeKind;
|
|
123
|
+
if (kind !== 'code' && kind !== 'file') return;
|
|
124
|
+
const ed = api.state.editor;
|
|
125
|
+
if (!ed) return;
|
|
126
|
+
const size = viewSize(api);
|
|
127
|
+
const inner = codeInnerWidth(size.width, api.ui.layout);
|
|
128
|
+
ed.reveal(inner);
|
|
129
|
+
};
|
|
130
|
+
|
|
115
131
|
const followFileEdit = (api) => {
|
|
116
132
|
if (api.state.composeKind !== 'file') return;
|
|
117
133
|
const text = api.state.editor ? api.state.editor.text : null;
|
|
@@ -426,7 +442,9 @@ const codeOverlayView = (api) => {
|
|
|
426
442
|
api.state.composeKind === 'code' || api.state.composeKind === 'file';
|
|
427
443
|
const editor = api.state.editor;
|
|
428
444
|
const cursor = editing && editor ? editor.cursor : null;
|
|
429
|
-
|
|
445
|
+
const picked = editing && editor ? editor.scrollCol : 0;
|
|
446
|
+
const scrollCol = picked ?? 0;
|
|
447
|
+
return { text, keepEmpty: editing, cursor, scrollCol };
|
|
430
448
|
};
|
|
431
449
|
|
|
432
450
|
const idleNoteText = (api) => {
|
|
@@ -511,9 +529,8 @@ const moveComposeLine = (api, delta) => {
|
|
|
511
529
|
return void api.todos.moveTodoCompose(delta, inner);
|
|
512
530
|
}
|
|
513
531
|
if (move === 'code') {
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
return void api.state.editor.moveLine(delta, inner);
|
|
532
|
+
api.state.editor.moveLine(delta);
|
|
533
|
+
return void syncCodeScroll(api);
|
|
517
534
|
}
|
|
518
535
|
if (fullCommitEdit(api)) return void moveCommitLine(api, delta);
|
|
519
536
|
moveNoteLine(api, delta);
|
|
@@ -581,6 +598,7 @@ const onUnitEdit = (api) => {
|
|
|
581
598
|
openCompose(api, 'file', at.text);
|
|
582
599
|
api.state.fileEditRows = at.rows ?? null;
|
|
583
600
|
api.state.editor.cursor = Math.min(at.cursor, at.text.length);
|
|
601
|
+
syncCodeScroll(api);
|
|
584
602
|
followFileEdit(api);
|
|
585
603
|
};
|
|
586
604
|
|
|
@@ -602,6 +620,7 @@ const onCode = (api) => {
|
|
|
602
620
|
: notes.code.get(itemFeedKey(item));
|
|
603
621
|
const text = prev ? prev.text : original;
|
|
604
622
|
openCompose(api, 'code', text);
|
|
623
|
+
syncCodeScroll(api);
|
|
605
624
|
};
|
|
606
625
|
|
|
607
626
|
const insertNewline = (api) => {
|
|
@@ -667,7 +686,11 @@ const COMPOSE_SPECIAL = {
|
|
|
667
686
|
};
|
|
668
687
|
|
|
669
688
|
const handleKey = (api, key) => {
|
|
670
|
-
if (key === 'enter')
|
|
689
|
+
if (key === 'enter') {
|
|
690
|
+
const result = enterCompose(api);
|
|
691
|
+
syncCodeScroll(api);
|
|
692
|
+
return result;
|
|
693
|
+
}
|
|
671
694
|
if (key === 'escape' || key === 'ctrl-s') return leaveCompose(api, key);
|
|
672
695
|
const special = COMPOSE_SPECIAL[key];
|
|
673
696
|
if (special) {
|
|
@@ -675,6 +698,7 @@ const handleKey = (api, key) => {
|
|
|
675
698
|
if (COMPOSE_EDITS.includes(key)) api.templates.clearTemplatePick();
|
|
676
699
|
resetBlink(api);
|
|
677
700
|
followFileEdit(api);
|
|
701
|
+
syncCodeScroll(api);
|
|
678
702
|
return result ?? null;
|
|
679
703
|
}
|
|
680
704
|
if (!key.length) return null;
|
|
@@ -684,6 +708,7 @@ const handleKey = (api, key) => {
|
|
|
684
708
|
api.state.editor.insert(key);
|
|
685
709
|
resetBlink(api);
|
|
686
710
|
followFileEdit(api);
|
|
711
|
+
syncCodeScroll(api);
|
|
687
712
|
}
|
|
688
713
|
return null;
|
|
689
714
|
};
|
|
@@ -696,6 +721,7 @@ const applyDiskText = (api, text) => {
|
|
|
696
721
|
api.state.editor.cursor = Math.min(cursor, text.length);
|
|
697
722
|
api.state.composeBaseline = text;
|
|
698
723
|
api.state.fileEditRows = unit.linesFor(api.ui, api.nav.reviewPath, null);
|
|
724
|
+
syncCodeScroll(api);
|
|
699
725
|
followFileEdit(api);
|
|
700
726
|
};
|
|
701
727
|
|
package/lib/session/dispatch.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const compose = require('./compose.js');
|
|
4
|
-
const
|
|
4
|
+
const commit = require('./commit.js');
|
|
5
|
+
const { hasStagedChanges, listedCommits } = commit;
|
|
5
6
|
const { COMPOSE_LEAVE } = compose;
|
|
6
7
|
const actions = require('./actions.js');
|
|
7
|
-
const {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
const {
|
|
9
|
+
LIST_PANES,
|
|
10
|
+
CONFIRM_MODE,
|
|
11
|
+
disabledActions,
|
|
12
|
+
actionFromKey,
|
|
13
|
+
applyConfirm,
|
|
14
|
+
} = actions;
|
|
13
15
|
|
|
14
16
|
const currentTarget = (ui) => {
|
|
15
17
|
if (ui.pane === 'files') return ui.fileCursorEntry();
|
|
@@ -18,9 +20,9 @@ const currentTarget = (ui) => {
|
|
|
18
20
|
}
|
|
19
21
|
if (ui.pane === 'commits') {
|
|
20
22
|
const entry = listedCommits(ui.commits.commits)[ui.commitCursor];
|
|
21
|
-
const staged =
|
|
22
|
-
|
|
23
|
-
return { ...entry, canCommit: staged };
|
|
23
|
+
const staged = hasStagedChanges(ui);
|
|
24
|
+
const unstagedCurrent = !ui.rev && !ui.revShort;
|
|
25
|
+
return { ...entry, canCommit: staged, unstagedCurrent };
|
|
24
26
|
}
|
|
25
27
|
return ui.current();
|
|
26
28
|
};
|
|
@@ -62,6 +64,8 @@ const createDispatcher = (ui) => {
|
|
|
62
64
|
npm: ui.npm.open,
|
|
63
65
|
npmEdit: ui.npm.edit,
|
|
64
66
|
npmNew: ui.npm.create,
|
|
67
|
+
npmDrop: () => ui.npm.askDrop(),
|
|
68
|
+
npmLogs: () => ui.npm.askLogs(),
|
|
65
69
|
npmStop: () => ui.npm.closeView(),
|
|
66
70
|
npmRerun: () => ui.npm.rerun(),
|
|
67
71
|
check: () => ui.composer.toggleFocusedTodo(),
|
|
@@ -88,21 +92,9 @@ const createDispatcher = (ui) => {
|
|
|
88
92
|
if (result && result.kind === 'error') return;
|
|
89
93
|
}
|
|
90
94
|
const pane = ui.pane;
|
|
91
|
-
if (pane === '
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
if (pane === 'branches') {
|
|
96
|
-
if (action === 'next') return void ui.gitBranches.onBranchMove(1);
|
|
97
|
-
if (action === 'prev') return void ui.gitBranches.onBranchMove(-1);
|
|
98
|
-
}
|
|
99
|
-
if (pane === 'commits') {
|
|
100
|
-
if (action === 'next') return void ui.commits.onCommitMove(1);
|
|
101
|
-
if (action === 'prev') return void ui.commits.onCommitMove(-1);
|
|
102
|
-
}
|
|
103
|
-
if (pane === 'npm') {
|
|
104
|
-
if (action === 'next') return void ui.npm.move(1);
|
|
105
|
-
if (action === 'prev') return void ui.npm.move(-1);
|
|
95
|
+
if (LIST_PANES.includes(pane) && (action === 'next' || action === 'prev')) {
|
|
96
|
+
ui.filesPane.onScroll(action === 'next' ? 1 : -1);
|
|
97
|
+
return;
|
|
106
98
|
}
|
|
107
99
|
const hidden = disabledActions(pane, currentTarget(ui));
|
|
108
100
|
if (hidden.includes(action)) return;
|
|
@@ -4,8 +4,11 @@ const ansi = require('../ansi.js');
|
|
|
4
4
|
const files = require('../files.js');
|
|
5
5
|
const { THEME_NAMES, setTheme, themeName } = ansi;
|
|
6
6
|
const { isTodosEntry, TODO_FILE } = files;
|
|
7
|
-
const
|
|
7
|
+
const npm = require('../render/npm.js');
|
|
8
|
+
const { logViewRows } = npm;
|
|
8
9
|
const unit = require('./unit.js');
|
|
10
|
+
const actions = require('./actions.js');
|
|
11
|
+
const { LIST_PANES } = actions;
|
|
9
12
|
const { setFileScope, openUnitFile, moveUnitBlock } = unit;
|
|
10
13
|
|
|
11
14
|
const LAYOUTS = ['unified', 'mixed', 'side'];
|
|
@@ -41,13 +44,6 @@ const showFiles = (ui) => {
|
|
|
41
44
|
};
|
|
42
45
|
|
|
43
46
|
const onEscape = (ui) => {
|
|
44
|
-
if (
|
|
45
|
-
ui.nav.pane === 'branches' ||
|
|
46
|
-
ui.nav.pane === 'commits' ||
|
|
47
|
-
ui.nav.pane === 'npm'
|
|
48
|
-
) {
|
|
49
|
-
return void showFiles(ui);
|
|
50
|
-
}
|
|
51
47
|
if (ui.nav.pane === 'files') return void ui.onQuit();
|
|
52
48
|
showFiles(ui);
|
|
53
49
|
};
|
|
@@ -193,26 +189,9 @@ const onScroll = (ui, delta) => {
|
|
|
193
189
|
};
|
|
194
190
|
|
|
195
191
|
const onJump = (ui, toEnd) => {
|
|
196
|
-
if (ui.nav.pane
|
|
197
|
-
const list = ui.fileList();
|
|
198
|
-
if (!list.length) {
|
|
199
|
-
ui.status = 'nothing to review';
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
const target = toEnd ? list.length - 1 : 0;
|
|
203
|
-
return void onFileMove(ui, target - ui.nav.fileCursor);
|
|
204
|
-
}
|
|
205
|
-
if (ui.nav.pane === 'branches') {
|
|
206
|
-
const delta = toEnd ? Number.MAX_SAFE_INTEGER : -Number.MAX_SAFE_INTEGER;
|
|
207
|
-
return void ui.gitBranches.onBranchMove(delta);
|
|
208
|
-
}
|
|
209
|
-
if (ui.nav.pane === 'commits') {
|
|
210
|
-
const delta = toEnd ? Number.MAX_SAFE_INTEGER : -Number.MAX_SAFE_INTEGER;
|
|
211
|
-
return void ui.commits.onCommitMove(delta);
|
|
212
|
-
}
|
|
213
|
-
if (ui.nav.pane === 'npm') {
|
|
192
|
+
if (LIST_PANES.includes(ui.nav.pane)) {
|
|
214
193
|
const delta = toEnd ? Number.MAX_SAFE_INTEGER : -Number.MAX_SAFE_INTEGER;
|
|
215
|
-
return void ui
|
|
194
|
+
return void onScroll(ui, delta);
|
|
216
195
|
}
|
|
217
196
|
if (ui.nav.todoOpen && ui.composer.todoRowCount() > 0) {
|
|
218
197
|
const last = ui.composer.todoRowCount() - 1;
|
package/lib/session/items.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const accessors = require('./accessors.js');
|
|
4
|
+
const { stateView } = accessors;
|
|
4
5
|
|
|
5
6
|
const files = require('../files.js');
|
|
6
7
|
const { itemPath, TODO_FILE, isTodoItem } = files;
|
|
7
|
-
const
|
|
8
|
-
const {
|
|
8
|
+
const review = require('../review.js');
|
|
9
|
+
const { feedbackKey } = review;
|
|
10
|
+
const diff = require('../diff/diff.js');
|
|
11
|
+
const { refreshIndexPatches } = diff;
|
|
9
12
|
|
|
10
13
|
const depChangeKey = (item) => {
|
|
11
14
|
const change = item.dep && item.dep.change;
|