reslop 0.1.1 → 0.1.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 +21 -6
- package/README.md +29 -26
- package/bin/reslop.js +2 -2
- package/lib/ansi.js +0 -1
- package/lib/cli.js +62 -47
- package/lib/clipboard.js +1 -1
- package/lib/deps.js +1440 -0
- package/lib/detect.js +6 -4
- package/lib/diff.js +31 -55
- package/lib/editor.js +1 -1
- package/lib/files.js +58 -15
- package/lib/git.js +649 -69
- package/lib/github.js +28 -34
- package/lib/highlight.js +282 -141
- package/lib/keys.js +35 -39
- package/lib/render.js +250 -153
- package/lib/review.js +22 -42
- package/lib/select.js +16 -18
- package/lib/session.js +301 -227
- package/lib/source.js +7 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,24 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased][unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.1.3][] - 2026-09-12
|
|
6
|
+
|
|
7
|
+
- Showed added/removed and staged/total counts in the file list
|
|
8
|
+
- Highlighted JSX and TSX syntax, including
|
|
9
|
+
- Added vim-style j/k navigation and Ctrl scrolling
|
|
10
|
+
- Improved TUI/UX with background git and npm checks to avoid a freeze
|
|
11
|
+
|
|
12
|
+
## [0.1.2][] - 2026-09-11
|
|
13
|
+
|
|
14
|
+
- Review each dependency once across package.json and package-lock
|
|
15
|
+
- Mark unused npm dependencies that are not imported or used
|
|
16
|
+
- Propose unused dependency removals and run npm uninstall
|
|
17
|
+
- Mark dependency review items and show npm audit findings
|
|
18
|
+
- Show npm outdated and npm audit updates as proposed diffs
|
|
19
|
+
- Propose a lockfile version bump for transitive dependencies
|
|
20
|
+
|
|
5
21
|
## [0.1.1][] - 2026-09-10
|
|
6
22
|
|
|
7
23
|
- Open a GitHub pull request by URL and review its diff
|
|
8
24
|
- Import GitHub pull request review comments into the local review
|
|
9
25
|
- Improve TUI navigation and hotkeys
|
|
10
26
|
- CLI simplification and optimisation
|
|
11
|
-
-
|
|
27
|
+
- Fix diff highlighting for snake_case identifier changes
|
|
12
28
|
- Updated package metadata and README
|
|
13
29
|
|
|
14
30
|
## [0.1.0][] - 2026-09-07
|
|
15
31
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- Interactive terminal review of uncommitted git diffs with stage, unstage,
|
|
19
|
-
revert, and skip
|
|
32
|
+
- Interactive review of uncommitted git diffs with stage, unstage, revert
|
|
20
33
|
- Feedback and todos that produce a repair plan for an agent
|
|
21
34
|
- Intra-line highlighting in unified, mixed, and side-by-side layouts
|
|
22
35
|
|
|
23
|
-
[unreleased]: https://github.com/tshemsedinov/reslop/compare/v0.1.
|
|
36
|
+
[unreleased]: https://github.com/tshemsedinov/reslop/compare/v0.1.3...HEAD
|
|
37
|
+
[0.1.3]: https://github.com/tshemsedinov/reslop/compare/v0.1.2...v0.1.3
|
|
38
|
+
[0.1.2]: https://github.com/tshemsedinov/reslop/compare/v0.1.1...v0.1.2
|
|
24
39
|
[0.1.1]: https://github.com/tshemsedinov/reslop/compare/v0.1.0...v0.1.1
|
|
25
40
|
[0.1.0]: https://github.com/tshemsedinov/reslop/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -2,20 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
> Turn generated changes into owned changes
|
|
4
4
|
|
|
5
|
+
Open a change, leave findings and todos, and prepare a repair plan
|
|
6
|
+
for the agent.
|
|
7
|
+
|
|
5
8
|
```text
|
|
6
9
|
Review → Plan → Repair → Verify
|
|
7
10
|
```
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
12
|
+
- Review uncommitted git diffs, a given commit, or a GitHub pull request.
|
|
13
|
+
- Stage, unstage, or revert each contiguous block of diff lines.
|
|
14
|
+
- Leave feedback and todos that become a repair plan for the agent.
|
|
15
|
+
- Import GitHub pull request review comments into the local plan for AI.
|
|
16
|
+
- Review each npm dependency once across `package.json` and the lockfile.
|
|
17
|
+
- Propose unused removals, npm audit fixes, and outdated updates as diffs.
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
add review and todos. Commit and pull request review is read-only.
|
|
19
|
+
Commit and pull request review is read-only. Applying a dependency
|
|
20
|
+
proposal stages the files and runs `npm i` or `npm uninstall`.
|
|
19
21
|
|
|
20
22
|
Intra-line highlighting paints the words that actually changed in a
|
|
21
23
|
stronger red/green. A close edit inside one word still marks only
|
|
@@ -46,23 +48,24 @@ Reviews go in `.review/YYYY-MM-DD-NN.md` with frontmatter `status`:
|
|
|
46
48
|
|
|
47
49
|
## Keys and buttons
|
|
48
50
|
|
|
49
|
-
| Key
|
|
50
|
-
|
|
|
51
|
-
| `a`
|
|
52
|
-
| `u`
|
|
53
|
-
| `r`
|
|
54
|
-
| `
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
| `
|
|
58
|
-
|
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
| `
|
|
65
|
-
|
|
|
51
|
+
| Key | Action |
|
|
52
|
+
| ------------------- | ---------------------------------------- |
|
|
53
|
+
| `a` | Stage this block (`git add`) |
|
|
54
|
+
| `u` | Unstage this block (keep worktree) |
|
|
55
|
+
| `r` | Restore this block to the last commit |
|
|
56
|
+
| `f` | Feedback on this diff block |
|
|
57
|
+
| `t` | New todo for this file |
|
|
58
|
+
| `l` | File list (git status of this scope) |
|
|
59
|
+
| `m` | Cycle unified / mixed / side-by-side |
|
|
60
|
+
| `⏎` | Open the selected file |
|
|
61
|
+
| `Esc` | Quit file list or a tool |
|
|
62
|
+
| `→` / `j` | Next remaining block / next file |
|
|
63
|
+
| `←` / `k` | Previous remaining block / previous file |
|
|
64
|
+
| `Ctrl-e` / `Ctrl-y` | Scroll one line down / up |
|
|
65
|
+
| `Ctrl-f` / `Ctrl-b` | Scroll page down / up |
|
|
66
|
+
| `Ctrl-d` / `Ctrl-u` | Scroll half-page down / up |
|
|
67
|
+
| `⌫` / `Del` | Remove the selected todo |
|
|
68
|
+
| `q` | Quit |
|
|
66
69
|
|
|
67
70
|
## License
|
|
68
71
|
|
package/bin/reslop.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const { run,
|
|
4
|
+
const { run, failLine } = require('../lib/cli.js');
|
|
5
5
|
const { LEAVE_TERM } = require('../lib/session.js');
|
|
6
6
|
|
|
7
7
|
const fail = (reason) => {
|
|
8
8
|
try {
|
|
9
9
|
process.stdout.write(LEAVE_TERM);
|
|
10
10
|
} catch {}
|
|
11
|
-
process.stderr.write(
|
|
11
|
+
process.stderr.write(failLine(reason));
|
|
12
12
|
process.exit(1);
|
|
13
13
|
};
|
|
14
14
|
|
package/lib/ansi.js
CHANGED
package/lib/cli.js
CHANGED
|
@@ -21,8 +21,10 @@ const errorMessage = (reason) => {
|
|
|
21
21
|
return `${reason}`;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
+
const failLine = (reason) => `reslop: ${errorMessage(reason)}\n`;
|
|
25
|
+
|
|
24
26
|
const fail = (stderr, reason) => {
|
|
25
|
-
stderr.write(
|
|
27
|
+
stderr.write(failLine(reason));
|
|
26
28
|
return 1;
|
|
27
29
|
};
|
|
28
30
|
|
|
@@ -70,7 +72,7 @@ const resolveScope = (cwd, paths, repo, statSync = fs.statSync) => {
|
|
|
70
72
|
if (pathExists(cwd, first, statSync)) {
|
|
71
73
|
return { rev: null, paths };
|
|
72
74
|
}
|
|
73
|
-
const resolved = repo.resolveRev
|
|
75
|
+
const resolved = repo.resolveRev(cwd, first);
|
|
74
76
|
if (resolved) {
|
|
75
77
|
if (paths.length > 1) {
|
|
76
78
|
throw new Error('use a commit or a path, not both');
|
|
@@ -85,30 +87,41 @@ const resolveScope = (cwd, paths, repo, statSync = fs.statSync) => {
|
|
|
85
87
|
|
|
86
88
|
const isColorEnabled = (stdout, env) => stdout.isTTY === true && !env.NO_COLOR;
|
|
87
89
|
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
const sessionOptions = (proc, deps, args, env, extra) => ({
|
|
91
|
+
cwd: deps.cwd ?? proc.cwd(),
|
|
92
|
+
stdin: proc.stdin,
|
|
93
|
+
stdout: proc.stdout,
|
|
94
|
+
color: isColorEnabled(proc.stdout, env),
|
|
95
|
+
getSize: deps.getSize,
|
|
96
|
+
startPane: 'files',
|
|
97
|
+
newReview: args.newReview,
|
|
98
|
+
audit: true,
|
|
99
|
+
...extra,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const startSession = (options, extra = {}) => {
|
|
103
|
+
const session = new Session(options);
|
|
104
|
+
if (extra.load) session.load();
|
|
105
|
+
return session;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const openLocalSession = (proc, deps, args, selected, env) => {
|
|
91
109
|
const cwd = deps.cwd ?? proc.cwd();
|
|
110
|
+
const repo = deps.repo ?? createGitRepo();
|
|
92
111
|
const statSync = deps.statSync ?? fs.statSync;
|
|
93
|
-
const scope = resolveScope(cwd,
|
|
94
|
-
const session =
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
getSize: deps.getSize,
|
|
103
|
-
startPane: 'files',
|
|
104
|
-
newReview: args.newReview,
|
|
105
|
-
});
|
|
106
|
-
session.load();
|
|
112
|
+
const scope = resolveScope(cwd, selected.paths, repo, statSync);
|
|
113
|
+
const session = startSession(
|
|
114
|
+
sessionOptions(proc, deps, args, env, {
|
|
115
|
+
repo,
|
|
116
|
+
paths: scope.paths,
|
|
117
|
+
rev: scope.rev,
|
|
118
|
+
}),
|
|
119
|
+
);
|
|
120
|
+
session.ensureRepo();
|
|
107
121
|
return session;
|
|
108
122
|
};
|
|
109
123
|
|
|
110
124
|
const openPullRequestSession = async (proc, deps, args, selected, env) => {
|
|
111
|
-
const stdout = proc.stdout;
|
|
112
125
|
const cwd = deps.cwd ?? proc.cwd();
|
|
113
126
|
const loader = deps.loadPullRequest ?? loadPullRequest;
|
|
114
127
|
const token = githubToken(env);
|
|
@@ -117,27 +130,20 @@ const openPullRequestSession = async (proc, deps, args, selected, env) => {
|
|
|
117
130
|
paths: selected.paths,
|
|
118
131
|
token,
|
|
119
132
|
fetch: deps.fetch,
|
|
120
|
-
env,
|
|
121
133
|
});
|
|
122
134
|
const change = loaded.change ?? null;
|
|
123
135
|
const repository = change ? change.repository : '';
|
|
124
136
|
const repo = deps.repo ?? createLoadedSource(loaded);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
repoName: repository,
|
|
136
|
-
sourceLabel: loaded.sourceLabel,
|
|
137
|
-
change,
|
|
138
|
-
});
|
|
139
|
-
session.load();
|
|
140
|
-
return session;
|
|
137
|
+
return startSession(
|
|
138
|
+
sessionOptions(proc, deps, args, env, {
|
|
139
|
+
repo,
|
|
140
|
+
paths: selected.paths,
|
|
141
|
+
repoName: repository,
|
|
142
|
+
sourceLabel: loaded.sourceLabel,
|
|
143
|
+
change,
|
|
144
|
+
}),
|
|
145
|
+
{ load: true },
|
|
146
|
+
);
|
|
141
147
|
};
|
|
142
148
|
|
|
143
149
|
const loadSession = async (proc, deps, args) => {
|
|
@@ -146,7 +152,14 @@ const loadSession = async (proc, deps, args) => {
|
|
|
146
152
|
if (selected.kind === 'github-pr') {
|
|
147
153
|
return openPullRequestSession(proc, deps, args, selected, env);
|
|
148
154
|
}
|
|
149
|
-
return openLocalSession(proc, deps, args, env);
|
|
155
|
+
return openLocalSession(proc, deps, args, selected, env);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const runUi = async (session, proc) => {
|
|
159
|
+
const code = await session.startUi();
|
|
160
|
+
if (session.loadError) return fail(proc.stderr, session.loadError);
|
|
161
|
+
if (session.emptyReview) proc.stdout.write('nothing to review\n');
|
|
162
|
+
return code;
|
|
150
163
|
};
|
|
151
164
|
|
|
152
165
|
const run = async (proc, deps = {}) => {
|
|
@@ -164,22 +177,24 @@ const run = async (proc, deps = {}) => {
|
|
|
164
177
|
} catch (error) {
|
|
165
178
|
return fail(stderr, error);
|
|
166
179
|
}
|
|
180
|
+
const tty = proc.stdin.isTTY === true && stdout.isTTY === true;
|
|
181
|
+
if (tty) return runUi(session, proc);
|
|
182
|
+
try {
|
|
183
|
+
await session.loadReady();
|
|
184
|
+
} catch (error) {
|
|
185
|
+
return fail(stderr, error);
|
|
186
|
+
}
|
|
167
187
|
if (!session.items.length) {
|
|
168
188
|
stdout.write('nothing to review\n');
|
|
169
189
|
return 0;
|
|
170
190
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return 1;
|
|
174
|
-
}
|
|
175
|
-
return session.startUi();
|
|
191
|
+
stderr.write('reslop: interactive terminal required\n');
|
|
192
|
+
return 1;
|
|
176
193
|
};
|
|
177
194
|
|
|
178
195
|
module.exports = {
|
|
179
|
-
|
|
196
|
+
failLine,
|
|
180
197
|
parseArgv,
|
|
181
198
|
resolveScope,
|
|
182
|
-
|
|
183
|
-
selectChangeSource,
|
|
184
|
-
errorMessage,
|
|
199
|
+
run,
|
|
185
200
|
};
|
package/lib/clipboard.js
CHANGED