reslop 0.2.0 → 0.2.3
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 +27 -1
- package/README.md +13 -2
- package/lib/ansi.js +263 -6
- package/lib/api.js +2 -0
- package/lib/capabilities.js +6 -0
- package/lib/cli.js +13 -2
- package/lib/deps.js +43 -3
- package/lib/git-branches.js +228 -17
- package/lib/git-reword-todo.js +20 -0
- package/lib/git.js +20 -3
- package/lib/keys.js +10 -4
- package/lib/npm-commands.js +513 -0
- package/lib/render/branches.js +23 -58
- package/lib/render/chrome.js +156 -99
- package/lib/render/commits.js +643 -31
- package/lib/render/diff.js +4 -4
- package/lib/render/frame.js +51 -5
- package/lib/render/notes.js +22 -5
- package/lib/render/npm.js +228 -0
- package/lib/render/primitives.js +48 -34
- package/lib/render/render.js +3 -3
- package/lib/report-model.js +127 -0
- package/lib/report-parse.js +94 -0
- package/lib/report-render.js +87 -0
- package/lib/report-run.js +164 -0
- package/lib/report-test.js +506 -0
- package/lib/report-tools.js +311 -0
- package/lib/review-merge.js +270 -0
- package/lib/review.js +38 -6
- package/lib/session/actions.js +81 -5
- package/lib/session/commit.js +187 -19
- package/lib/session/compose.js +96 -32
- package/lib/session/dispatch.js +36 -2
- package/lib/session/files-pane.js +36 -6
- package/lib/session/lifecycle.js +116 -16
- package/lib/session/navigation.js +1 -0
- package/lib/session/npm.js +335 -0
- package/lib/session/pointer.js +12 -1
- package/lib/session/todos.js +29 -1
- package/lib/session/view.js +14 -3
- package/lib/session/watch.js +120 -8
- package/lib/session.js +11 -2
- package/package.json +7 -7
package/lib/git-branches.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const os = require('node:os');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
|
|
3
7
|
const { oneLine, requireOk, runGit, runGitAsync } = require('./git.js');
|
|
4
8
|
|
|
5
9
|
const BRANCH_FORMAT = [
|
|
@@ -20,27 +24,59 @@ const PUSH_REJECTED = [
|
|
|
20
24
|
'updates were rejected',
|
|
21
25
|
];
|
|
22
26
|
|
|
23
|
-
const
|
|
24
|
-
const
|
|
27
|
+
const commitMessage = (top, sha) => {
|
|
28
|
+
const spec = `${sha ?? ''}`.trim() || 'HEAD';
|
|
29
|
+
const result = runGit(['log', '-1', '--format=%B', spec], top);
|
|
25
30
|
if (result.status !== 0) return '';
|
|
26
31
|
return (result.stdout ?? '').replace(/\s+$/, '');
|
|
27
32
|
};
|
|
28
33
|
|
|
29
|
-
const
|
|
34
|
+
const lastMessage = (top) => commitMessage(top, 'HEAD');
|
|
35
|
+
|
|
36
|
+
const COMMIT_FIELDS = ['%H', '%h', '%an', '%ae', '%ar', '%ci', '%D', '%s'];
|
|
37
|
+
const COMMIT_FORMAT = `${COMMIT_FIELDS.join('%x1f')}%x1e%B`;
|
|
30
38
|
const COMMIT_LIMIT = 256;
|
|
31
39
|
const UNIT = '\x1f';
|
|
40
|
+
const RECORD = '\x1e';
|
|
41
|
+
const TAG_REF = /^tag: /;
|
|
42
|
+
const REMOTE_HEAD = /\/HEAD(?: -> |$)/;
|
|
43
|
+
|
|
44
|
+
const formatCommitRefs = (raw) => {
|
|
45
|
+
const text = `${raw ?? ''}`.trim();
|
|
46
|
+
if (!text) return '';
|
|
47
|
+
const names = [];
|
|
48
|
+
for (const part of text.split(', ')) {
|
|
49
|
+
const name = part.trim();
|
|
50
|
+
if (!name || TAG_REF.test(name)) continue;
|
|
51
|
+
if (name !== 'HEAD' && REMOTE_HEAD.test(name)) continue;
|
|
52
|
+
names.push(name);
|
|
53
|
+
}
|
|
54
|
+
return names.join(', ');
|
|
55
|
+
};
|
|
32
56
|
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
if (
|
|
57
|
+
const parseCommitRecord = (record, index) => {
|
|
58
|
+
const cut = record.indexOf(RECORD);
|
|
59
|
+
if (cut < 0) return null;
|
|
60
|
+
const parts = record.slice(0, cut).split(UNIT);
|
|
61
|
+
if (parts.length < COMMIT_FIELDS.length) return null;
|
|
36
62
|
const sha = (parts[0] ?? '').trim();
|
|
37
63
|
if (!sha) return null;
|
|
64
|
+
const body = record.slice(cut + 1).replace(/\s+$/, '');
|
|
65
|
+
const read = (spec) => {
|
|
66
|
+
const at = COMMIT_FIELDS.indexOf(spec);
|
|
67
|
+
return (parts[at] ?? '').trim();
|
|
68
|
+
};
|
|
69
|
+
const subject = read('%s') || body.split('\n')[0].trim();
|
|
38
70
|
return {
|
|
39
71
|
sha,
|
|
40
|
-
shortSha: (
|
|
41
|
-
author: (
|
|
42
|
-
|
|
43
|
-
|
|
72
|
+
shortSha: read('%h') || sha.slice(0, 7),
|
|
73
|
+
author: read('%an'),
|
|
74
|
+
email: read('%ae'),
|
|
75
|
+
date: read('%ar'),
|
|
76
|
+
when: read('%ci'),
|
|
77
|
+
refs: formatCommitRefs(read('%D')),
|
|
78
|
+
subject,
|
|
79
|
+
body,
|
|
44
80
|
head: index === 0,
|
|
45
81
|
};
|
|
46
82
|
};
|
|
@@ -48,14 +84,15 @@ const parseCommitLine = (line, index) => {
|
|
|
48
84
|
const listCommits = (top) => {
|
|
49
85
|
const args = [
|
|
50
86
|
'log',
|
|
87
|
+
'-z',
|
|
51
88
|
`--format=${COMMIT_FORMAT}`,
|
|
52
89
|
`--max-count=${COMMIT_LIMIT}`,
|
|
53
90
|
];
|
|
54
91
|
const result = requireOk(runGit(args, top), 'log failed');
|
|
55
92
|
const commits = [];
|
|
56
|
-
for (const
|
|
57
|
-
if (!
|
|
58
|
-
const entry =
|
|
93
|
+
for (const record of result.stdout.split('\0')) {
|
|
94
|
+
if (!record) continue;
|
|
95
|
+
const entry = parseCommitRecord(record, commits.length);
|
|
59
96
|
if (entry) commits.push(entry);
|
|
60
97
|
}
|
|
61
98
|
return commits;
|
|
@@ -120,6 +157,179 @@ const dropCommitAsync = async (top, sha) => {
|
|
|
120
157
|
await dropOlderCommitAsync(top, target);
|
|
121
158
|
};
|
|
122
159
|
|
|
160
|
+
const FIXUP_MARK = 'fixup!';
|
|
161
|
+
const AUTOSQUASH_ARGS = [
|
|
162
|
+
'-c',
|
|
163
|
+
'sequence.editor=:',
|
|
164
|
+
'rebase',
|
|
165
|
+
'--interactive',
|
|
166
|
+
'--autosquash',
|
|
167
|
+
];
|
|
168
|
+
|
|
169
|
+
const isFixupSubject = (subject) =>
|
|
170
|
+
`${subject ?? ''}`.trim().startsWith(FIXUP_MARK);
|
|
171
|
+
|
|
172
|
+
const fixupRest = (subject) => {
|
|
173
|
+
let text = `${subject ?? ''}`.trim();
|
|
174
|
+
while (text.startsWith(FIXUP_MARK)) {
|
|
175
|
+
text = text.slice(FIXUP_MARK.length).trim();
|
|
176
|
+
}
|
|
177
|
+
return text;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const commitSubject = (top, sha) => {
|
|
181
|
+
const args = ['log', '-1', '--format=%s', sha];
|
|
182
|
+
const result = requireOk(runGit(args, top), 'log failed');
|
|
183
|
+
return (result.stdout ?? '').trim();
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const ancestorWithSubject = (top, sha, want) => {
|
|
187
|
+
const args = ['log', '--format=%H%x1f%s', `${sha}^`];
|
|
188
|
+
const result = runGit(args, top);
|
|
189
|
+
if (result.status !== 0) return '';
|
|
190
|
+
for (const line of result.stdout.split('\n')) {
|
|
191
|
+
const cut = line.indexOf(UNIT);
|
|
192
|
+
if (cut < 0) continue;
|
|
193
|
+
const subject = line.slice(cut + 1).trim();
|
|
194
|
+
if (subject !== want) continue;
|
|
195
|
+
return line.slice(0, cut).trim();
|
|
196
|
+
}
|
|
197
|
+
return '';
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const applyAutosquash = (top, ontoArgs) => {
|
|
201
|
+
const result = runGit([...AUTOSQUASH_ARGS, ...ontoArgs], top);
|
|
202
|
+
const failed = rebaseFailed(result);
|
|
203
|
+
if (!failed) return;
|
|
204
|
+
runGit(['rebase', '--abort'], top);
|
|
205
|
+
throw new Error(oneLine(failed));
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const applyAutosquashAsync = async (top, ontoArgs) => {
|
|
209
|
+
const result = await runGitAsync([...AUTOSQUASH_ARGS, ...ontoArgs], top);
|
|
210
|
+
const failed = rebaseFailed(result);
|
|
211
|
+
if (!failed) return;
|
|
212
|
+
await runGitAsync(['rebase', '--abort'], top);
|
|
213
|
+
throw new Error(oneLine(failed));
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const applyFixupOnto = (top, original, applyRange) => {
|
|
217
|
+
const parent = runGit(['rev-parse', '--verify', `${original}^`], top);
|
|
218
|
+
if (parent.status !== 0) return applyRange(top, ['--root']);
|
|
219
|
+
return applyRange(top, [(parent.stdout ?? '').trim()]);
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const applyFixup = (top, sha) => {
|
|
223
|
+
const spec = namedCommit(sha);
|
|
224
|
+
const commit = resolveCommit(top, spec);
|
|
225
|
+
const subject = commitSubject(top, commit);
|
|
226
|
+
if (!isFixupSubject(subject)) throw new Error('not a fixup commit');
|
|
227
|
+
const want = fixupRest(subject);
|
|
228
|
+
if (!want) throw new Error('no fixup target');
|
|
229
|
+
const original = ancestorWithSubject(top, commit, want);
|
|
230
|
+
if (!original) throw new Error('no fixup target');
|
|
231
|
+
applyFixupOnto(top, original, applyAutosquash);
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const applyFixupAsync = async (top, sha) => {
|
|
235
|
+
const spec = namedCommit(sha);
|
|
236
|
+
const commit = resolveCommit(top, spec);
|
|
237
|
+
const subject = commitSubject(top, commit);
|
|
238
|
+
if (!isFixupSubject(subject)) throw new Error('not a fixup commit');
|
|
239
|
+
const want = fixupRest(subject);
|
|
240
|
+
if (!want) throw new Error('no fixup target');
|
|
241
|
+
const original = ancestorWithSubject(top, commit, want);
|
|
242
|
+
if (!original) throw new Error('no fixup target');
|
|
243
|
+
await applyFixupOnto(top, original, applyAutosquashAsync);
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const messageBody = (message) => {
|
|
247
|
+
const text = `${message ?? ''}`;
|
|
248
|
+
return text.endsWith('\n') ? text : `${text}\n`;
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
const rewordHead = (top, message) => {
|
|
252
|
+
const args = ['commit', '--amend', '--only', '-F', '-'];
|
|
253
|
+
requireOk(runGit(args, top, messageBody(message)));
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const REWORD_TODO = path.join(__dirname, 'git-reword-todo.js');
|
|
257
|
+
|
|
258
|
+
const prepareRewordEditor = (message) => {
|
|
259
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'reslop-reword-'));
|
|
260
|
+
const msgFile = path.join(dir, 'MSG');
|
|
261
|
+
fs.writeFileSync(msgFile, messageBody(message));
|
|
262
|
+
const node = JSON.stringify(process.execPath);
|
|
263
|
+
const script = JSON.stringify(REWORD_TODO);
|
|
264
|
+
return {
|
|
265
|
+
dir,
|
|
266
|
+
env: {
|
|
267
|
+
GIT_SEQUENCE_EDITOR: `${node} ${script}`,
|
|
268
|
+
RESLOP_REWORD_FILE: msgFile,
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
const rewordRange = (top, sha, env) => {
|
|
274
|
+
const parent = runGit(['rev-parse', '--verify', `${sha}^`], top);
|
|
275
|
+
const onto =
|
|
276
|
+
parent.status !== 0 ? ['--root'] : [(parent.stdout ?? '').trim()];
|
|
277
|
+
return runGit(['rebase', '--interactive', ...onto], top, undefined, { env });
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const rewordRangeAsync = async (top, sha, env) => {
|
|
281
|
+
const parent = runGit(['rev-parse', '--verify', `${sha}^`], top);
|
|
282
|
+
const onto =
|
|
283
|
+
parent.status !== 0 ? ['--root'] : [(parent.stdout ?? '').trim()];
|
|
284
|
+
return runGitAsync(['rebase', '--interactive', ...onto], top, { env });
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
const finishRewordRebase = (top, result) => {
|
|
288
|
+
const failed = rebaseFailed(result);
|
|
289
|
+
if (!failed) return;
|
|
290
|
+
runGit(['rebase', '--abort'], top);
|
|
291
|
+
throw new Error(oneLine(failed));
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const rewordOlder = (top, sha, message) => {
|
|
295
|
+
const prepared = prepareRewordEditor(message);
|
|
296
|
+
try {
|
|
297
|
+
const result = rewordRange(top, sha, prepared.env);
|
|
298
|
+
finishRewordRebase(top, result);
|
|
299
|
+
} finally {
|
|
300
|
+
fs.rmSync(prepared.dir, { recursive: true, force: true });
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
const rewordOlderAsync = async (top, sha, message) => {
|
|
305
|
+
const prepared = prepareRewordEditor(message);
|
|
306
|
+
try {
|
|
307
|
+
const result = await rewordRangeAsync(top, sha, prepared.env);
|
|
308
|
+
const failed = rebaseFailed(result);
|
|
309
|
+
if (!failed) return;
|
|
310
|
+
await runGitAsync(['rebase', '--abort'], top);
|
|
311
|
+
throw new Error(oneLine(failed));
|
|
312
|
+
} finally {
|
|
313
|
+
fs.rmSync(prepared.dir, { recursive: true, force: true });
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
const rewordCommit = (top, sha, message) => {
|
|
318
|
+
const spec = namedCommit(sha);
|
|
319
|
+
const commit = resolveCommit(top, spec);
|
|
320
|
+
const head = resolveCommit(top, 'HEAD');
|
|
321
|
+
if (commit === head) return void rewordHead(top, message);
|
|
322
|
+
rewordOlder(top, commit, message);
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const rewordCommitAsync = async (top, sha, message) => {
|
|
326
|
+
const spec = namedCommit(sha);
|
|
327
|
+
const commit = resolveCommit(top, spec);
|
|
328
|
+
const head = resolveCommit(top, 'HEAD');
|
|
329
|
+
if (commit === head) return void rewordHead(top, message);
|
|
330
|
+
await rewordOlderAsync(top, commit, message);
|
|
331
|
+
};
|
|
332
|
+
|
|
123
333
|
const parseTrack = (text) => {
|
|
124
334
|
const raw = `${text ?? ''}`.trim().replace(/^\[|\]$/g, '');
|
|
125
335
|
if (!raw) return { ahead: 0, behind: 0, gone: false };
|
|
@@ -338,10 +548,6 @@ const hasStaged = (top) => {
|
|
|
338
548
|
};
|
|
339
549
|
|
|
340
550
|
const commitPlan = (kind, message) => {
|
|
341
|
-
if (kind === 'fixup') {
|
|
342
|
-
const target = (message ?? '').trim() || 'HEAD';
|
|
343
|
-
return { args: ['commit', `--fixup=${target}`], body: undefined };
|
|
344
|
-
}
|
|
345
551
|
const args = ['commit'];
|
|
346
552
|
if (kind === 'amend') args.push('--amend');
|
|
347
553
|
args.push('-F', '-');
|
|
@@ -362,6 +568,7 @@ const commitChangesAsync = async (top, kind, message) => {
|
|
|
362
568
|
|
|
363
569
|
module.exports = {
|
|
364
570
|
lastMessage,
|
|
571
|
+
commitMessage,
|
|
365
572
|
listCommits,
|
|
366
573
|
listBranches,
|
|
367
574
|
checkoutBranch,
|
|
@@ -372,6 +579,10 @@ module.exports = {
|
|
|
372
579
|
rebaseBranchAsync,
|
|
373
580
|
dropCommit,
|
|
374
581
|
dropCommitAsync,
|
|
582
|
+
applyFixup,
|
|
583
|
+
applyFixupAsync,
|
|
584
|
+
rewordCommit,
|
|
585
|
+
rewordCommitAsync,
|
|
375
586
|
dropBranch,
|
|
376
587
|
dropBranchAsync,
|
|
377
588
|
pullChanges,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
|
|
5
|
+
const file = process.argv[process.argv.length - 1];
|
|
6
|
+
const msg = process.env.RESLOP_REWORD_FILE;
|
|
7
|
+
if (!file || !msg) process.exit(1);
|
|
8
|
+
const text = fs.readFileSync(file, 'utf8');
|
|
9
|
+
const rows = text.split('\n');
|
|
10
|
+
const out = [];
|
|
11
|
+
let seen = false;
|
|
12
|
+
for (const row of rows) {
|
|
13
|
+
out.push(row);
|
|
14
|
+
if (seen) continue;
|
|
15
|
+
if (!/^(pick|p)\s+/.test(row)) continue;
|
|
16
|
+
const spec = JSON.stringify(msg);
|
|
17
|
+
out.push(`exec git commit --amend --only -F ${spec}`);
|
|
18
|
+
seen = true;
|
|
19
|
+
}
|
|
20
|
+
fs.writeFileSync(file, out.join('\n'));
|
package/lib/git.js
CHANGED
|
@@ -25,7 +25,7 @@ const GIT_MAX_BUFFER = proc.DEFAULT_MAX_BUFFER;
|
|
|
25
25
|
|
|
26
26
|
const gitProcOptions = (cwd, extra = {}) => ({
|
|
27
27
|
cwd,
|
|
28
|
-
env: { ...process.env, GIT_OPTIONAL_LOCKS: '0' },
|
|
28
|
+
env: { ...process.env, GIT_OPTIONAL_LOCKS: '0', ...extra.env },
|
|
29
29
|
encoding: GIT_ENCODING,
|
|
30
30
|
maxBuffer: GIT_MAX_BUFFER,
|
|
31
31
|
input: extra.input,
|
|
@@ -45,8 +45,8 @@ const requireOk = (result, fallback = 'git failed') => {
|
|
|
45
45
|
throw new Error(oneLine(msg, fallback));
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
const runGit = (args, cwd, input) => {
|
|
49
|
-
const options = gitProcOptions(cwd, { input });
|
|
48
|
+
const runGit = (args, cwd, input, extra = {}) => {
|
|
49
|
+
const options = gitProcOptions(cwd, { input, env: extra.env });
|
|
50
50
|
return gitResult(runProcSync('git', args, options));
|
|
51
51
|
};
|
|
52
52
|
|
|
@@ -503,6 +503,11 @@ const writeFile = (top, rel, text) => {
|
|
|
503
503
|
writeWorktree(abs, text);
|
|
504
504
|
};
|
|
505
505
|
|
|
506
|
+
const stagePath = (top, rel) => {
|
|
507
|
+
if (!rel) return;
|
|
508
|
+
requireOk(runGit(['add', '--', rel], top));
|
|
509
|
+
};
|
|
510
|
+
|
|
506
511
|
module.exports = {
|
|
507
512
|
oneLine,
|
|
508
513
|
requireOk,
|
|
@@ -521,6 +526,7 @@ module.exports = {
|
|
|
521
526
|
readSnapshotAsync,
|
|
522
527
|
editItem,
|
|
523
528
|
writeFile,
|
|
529
|
+
stagePath,
|
|
524
530
|
};
|
|
525
531
|
|
|
526
532
|
const branches = require('./git-branches.js');
|
|
@@ -590,10 +596,12 @@ const createGitRepo = () =>
|
|
|
590
596
|
revertFile: revertGitFile,
|
|
591
597
|
edit: editItem,
|
|
592
598
|
writeFile,
|
|
599
|
+
stagePath,
|
|
593
600
|
commit: branches.commitChanges,
|
|
594
601
|
commitAsync: branches.commitChangesAsync,
|
|
595
602
|
hasStaged: branches.hasStaged,
|
|
596
603
|
lastMessage: branches.lastMessage,
|
|
604
|
+
commitMessage: branches.commitMessage,
|
|
597
605
|
listBranches: branches.listBranches,
|
|
598
606
|
listCommits: branches.listCommits,
|
|
599
607
|
currentBranch,
|
|
@@ -607,6 +615,10 @@ const createGitRepo = () =>
|
|
|
607
615
|
dropAsync: branches.dropBranchAsync,
|
|
608
616
|
dropCommit: branches.dropCommit,
|
|
609
617
|
dropCommitAsync: branches.dropCommitAsync,
|
|
618
|
+
applyFixup: branches.applyFixup,
|
|
619
|
+
applyFixupAsync: branches.applyFixupAsync,
|
|
620
|
+
reword: branches.rewordCommit,
|
|
621
|
+
rewordAsync: branches.rewordCommitAsync,
|
|
610
622
|
pull: branches.pullChanges,
|
|
611
623
|
pullAsync: branches.pullChangesAsync,
|
|
612
624
|
push: branches.pushChanges,
|
|
@@ -628,6 +640,7 @@ module.exports.commitChangesAsync = branches.commitChangesAsync;
|
|
|
628
640
|
module.exports.hasStaged = branches.hasStaged;
|
|
629
641
|
module.exports.currentBranch = currentBranch;
|
|
630
642
|
module.exports.lastMessage = branches.lastMessage;
|
|
643
|
+
module.exports.commitMessage = branches.commitMessage;
|
|
631
644
|
module.exports.listBranches = branches.listBranches;
|
|
632
645
|
module.exports.listCommits = branches.listCommits;
|
|
633
646
|
module.exports.checkoutBranch = branches.checkoutBranch;
|
|
@@ -640,6 +653,10 @@ module.exports.dropBranch = branches.dropBranch;
|
|
|
640
653
|
module.exports.dropBranchAsync = branches.dropBranchAsync;
|
|
641
654
|
module.exports.dropCommit = branches.dropCommit;
|
|
642
655
|
module.exports.dropCommitAsync = branches.dropCommitAsync;
|
|
656
|
+
module.exports.applyFixup = branches.applyFixup;
|
|
657
|
+
module.exports.applyFixupAsync = branches.applyFixupAsync;
|
|
658
|
+
module.exports.rewordCommit = branches.rewordCommit;
|
|
659
|
+
module.exports.rewordCommitAsync = branches.rewordCommitAsync;
|
|
643
660
|
module.exports.pullChanges = branches.pullChanges;
|
|
644
661
|
module.exports.pullChangesAsync = branches.pullChangesAsync;
|
|
645
662
|
module.exports.pushChanges = branches.pushChanges;
|
package/lib/keys.js
CHANGED
|
@@ -6,7 +6,7 @@ const { ACTIONS, ACTION_IDS, BRANCH_ACTIONS, COMMIT_ACTIONS } = actions;
|
|
|
6
6
|
const { DIFF_DISABLED, FILES_DISABLED, FILES_GIT_DISABLED } = actions;
|
|
7
7
|
const { FILES_HIDDEN, FILES_TODO_DISABLED, TODO_DISABLED, BRANCHES_DISABLED } =
|
|
8
8
|
actions;
|
|
9
|
-
const { COMMITS_DISABLED, UNIT_DISABLED } = actions;
|
|
9
|
+
const { COMMITS_DISABLED, UNIT_DISABLED, NPM_DISABLED } = actions;
|
|
10
10
|
const { disabledActions, diffGitDisabled, branchGitDisabled } = actions;
|
|
11
11
|
const { commitGitDisabled } = actions;
|
|
12
12
|
const { actionFromKey, actionHot, actionLetter, buttonWord } = actions;
|
|
@@ -65,15 +65,20 @@ const parseCsiSeq = (rest) => {
|
|
|
65
65
|
return { params: body.slice(0, i), final: body[i], eat: 2 + i + 1 };
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
+
const ctrlHeld = (modText) => {
|
|
69
|
+
const mod = parseInt(modText, 10);
|
|
70
|
+
return Number.isFinite(mod) && ((mod - 1) & 4) !== 0;
|
|
71
|
+
};
|
|
72
|
+
|
|
68
73
|
const keyFromCsi = (paramsText, final) => {
|
|
69
74
|
const params = paramsText ? paramsText.split(';') : [];
|
|
70
75
|
if (final === '~') return CSI_TILDE[params[0]] ?? null;
|
|
71
76
|
const base = CSI_KEYS[final];
|
|
72
77
|
if (!base) return null;
|
|
73
78
|
if (params.length < 2) return base;
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
if (
|
|
79
|
+
const arrow =
|
|
80
|
+
base === 'left' || base === 'right' || base === 'up' || base === 'down';
|
|
81
|
+
if (ctrlHeld(params[1]) && arrow) return `ctrl-${base}`;
|
|
77
82
|
return base;
|
|
78
83
|
};
|
|
79
84
|
|
|
@@ -193,6 +198,7 @@ module.exports = {
|
|
|
193
198
|
TODO_DISABLED,
|
|
194
199
|
BRANCHES_DISABLED,
|
|
195
200
|
COMMITS_DISABLED,
|
|
201
|
+
NPM_DISABLED,
|
|
196
202
|
UNIT_DISABLED,
|
|
197
203
|
disabledActions,
|
|
198
204
|
diffGitDisabled,
|