@spences10/pi-git-ui 0.0.1
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/LICENSE +21 -0
- package/README.md +31 -0
- package/dist/commit-composer.d.ts +22 -0
- package/dist/commit-composer.js +108 -0
- package/dist/commit-composer.js.map +1 -0
- package/dist/git.d.ts +31 -0
- package/dist/git.js +163 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/render.d.ts +11 -0
- package/dist/render.js +81 -0
- package/dist/render.js.map +1 -0
- package/dist/stage-body.d.ts +42 -0
- package/dist/stage-body.js +297 -0
- package/dist/stage-body.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Scott Spence
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# @spences10/pi-git-ui
|
|
2
|
+
|
|
3
|
+
Interactive Git staging, diff review, and commit UI for Pi.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pi install npm:@spences10/pi-git-ui
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Then run:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
/git-ui
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Controls:
|
|
18
|
+
|
|
19
|
+
- `↑`/`↓` or `j`/`k` — move file selection
|
|
20
|
+
- `←`/`→` or `h`/`l` — scroll the diff preview
|
|
21
|
+
- `space` — safely stage/unstage selected file; disabled for
|
|
22
|
+
partial/conflicted files
|
|
23
|
+
- `s` — stage selected file explicitly
|
|
24
|
+
- `x` — unstage selected file explicitly
|
|
25
|
+
- `c` — commit staged changes with a Conventional Commit helper or raw
|
|
26
|
+
message
|
|
27
|
+
- `a` — safely stage all; blocked if partial/conflicted files exist
|
|
28
|
+
- `A` — force stage all
|
|
29
|
+
- `u` — unstage all
|
|
30
|
+
- `r` — refresh
|
|
31
|
+
- `esc`/`q` — close
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Focusable } from '@earendil-works/pi-tui';
|
|
2
|
+
import type { ModalTheme } from '@spences10/pi-tui-modal';
|
|
3
|
+
export declare class CommitComposer implements Focusable {
|
|
4
|
+
private readonly theme;
|
|
5
|
+
private readonly staged_count;
|
|
6
|
+
private readonly on_commit;
|
|
7
|
+
private readonly on_cancel;
|
|
8
|
+
private step;
|
|
9
|
+
private selected_type;
|
|
10
|
+
private conventional;
|
|
11
|
+
private readonly input;
|
|
12
|
+
constructor(theme: ModalTheme, staged_count: number, on_commit: (message: string) => void, on_cancel: () => void);
|
|
13
|
+
get focused(): boolean;
|
|
14
|
+
set focused(value: boolean);
|
|
15
|
+
render(width: number): string[];
|
|
16
|
+
handleInput(data: string): void;
|
|
17
|
+
invalidate(): void;
|
|
18
|
+
private render_type_picker;
|
|
19
|
+
private render_summary;
|
|
20
|
+
private submit;
|
|
21
|
+
private build_message;
|
|
22
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Input, Text } from '@earendil-works/pi-tui';
|
|
2
|
+
import { truncate_plain } from './render.js';
|
|
3
|
+
const TYPES = [
|
|
4
|
+
{ key: 'f', type: 'feat', label: 'feature' },
|
|
5
|
+
{ key: 'x', type: 'fix', label: 'bug fix' },
|
|
6
|
+
{ key: 'd', type: 'docs', label: 'docs' },
|
|
7
|
+
{ key: 'r', type: 'refactor', label: 'refactor' },
|
|
8
|
+
{ key: 't', type: 'test', label: 'tests' },
|
|
9
|
+
{ key: 'h', type: 'chore', label: 'chore' },
|
|
10
|
+
];
|
|
11
|
+
export class CommitComposer {
|
|
12
|
+
theme;
|
|
13
|
+
staged_count;
|
|
14
|
+
on_commit;
|
|
15
|
+
on_cancel;
|
|
16
|
+
step = 'type';
|
|
17
|
+
selected_type = 'feat';
|
|
18
|
+
conventional = true;
|
|
19
|
+
input = new Input();
|
|
20
|
+
constructor(theme, staged_count, on_commit, on_cancel) {
|
|
21
|
+
this.theme = theme;
|
|
22
|
+
this.staged_count = staged_count;
|
|
23
|
+
this.on_commit = on_commit;
|
|
24
|
+
this.on_cancel = on_cancel;
|
|
25
|
+
this.input.onSubmit = (summary) => this.submit(summary);
|
|
26
|
+
this.input.onEscape = () => this.on_cancel();
|
|
27
|
+
}
|
|
28
|
+
get focused() {
|
|
29
|
+
return this.input.focused;
|
|
30
|
+
}
|
|
31
|
+
set focused(value) {
|
|
32
|
+
this.input.focused = value;
|
|
33
|
+
}
|
|
34
|
+
render(width) {
|
|
35
|
+
if (this.step === 'type')
|
|
36
|
+
return this.render_type_picker(width);
|
|
37
|
+
return this.render_summary(width);
|
|
38
|
+
}
|
|
39
|
+
handleInput(data) {
|
|
40
|
+
if (this.step === 'type') {
|
|
41
|
+
if (data === '\x1B' || data === 'q') {
|
|
42
|
+
this.on_cancel();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (data === 'n') {
|
|
46
|
+
this.conventional = false;
|
|
47
|
+
this.step = 'summary';
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const match = TYPES.find((type) => type.key === data);
|
|
51
|
+
if (match) {
|
|
52
|
+
this.selected_type = match.type;
|
|
53
|
+
this.conventional = true;
|
|
54
|
+
this.step = 'summary';
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
this.input.handleInput(data);
|
|
59
|
+
}
|
|
60
|
+
invalidate() {
|
|
61
|
+
this.input.invalidate();
|
|
62
|
+
}
|
|
63
|
+
render_type_picker(width) {
|
|
64
|
+
const lines = [
|
|
65
|
+
this.theme.bold('Commit staged changes'),
|
|
66
|
+
this.theme.fg('muted', `${this.staged_count} staged file${this.staged_count === 1 ? '' : 's'}`),
|
|
67
|
+
'',
|
|
68
|
+
'Choose commit format:',
|
|
69
|
+
];
|
|
70
|
+
for (const item of TYPES) {
|
|
71
|
+
lines.push(` ${this.theme.fg('accent', item.key)} ${item.type.padEnd(8)} ${this.theme.fg('dim', item.label)}`);
|
|
72
|
+
}
|
|
73
|
+
lines.push(` ${this.theme.fg('accent', 'n')} raw ${this.theme.fg('dim', 'plain git commit message')}`, '', this.theme.fg('dim', 'esc/q cancel'));
|
|
74
|
+
return lines.flatMap((line) => new Text(line, 0, 0).render(width));
|
|
75
|
+
}
|
|
76
|
+
render_summary(width) {
|
|
77
|
+
const preview = this.build_message(this.input.getValue().trim());
|
|
78
|
+
const lines = [
|
|
79
|
+
this.theme.bold('Commit message'),
|
|
80
|
+
this.theme.fg('muted', `${this.staged_count} staged file${this.staged_count === 1 ? '' : 's'}`),
|
|
81
|
+
'',
|
|
82
|
+
this.conventional
|
|
83
|
+
? `Format: ${this.theme.fg('accent', `${this.selected_type}(git-ui): <summary>`)}`
|
|
84
|
+
: 'Format: raw commit message',
|
|
85
|
+
`Preview: ${preview ? this.theme.fg('success', truncate_plain(preview, Math.max(10, width - 9))) : this.theme.fg('dim', 'waiting for summary…')}`,
|
|
86
|
+
'',
|
|
87
|
+
'Summary:',
|
|
88
|
+
...this.input.render(width),
|
|
89
|
+
'',
|
|
90
|
+
this.theme.fg('dim', 'enter commit • esc cancel'),
|
|
91
|
+
];
|
|
92
|
+
return lines;
|
|
93
|
+
}
|
|
94
|
+
submit(summary) {
|
|
95
|
+
const message = this.build_message(summary.trim());
|
|
96
|
+
if (!message)
|
|
97
|
+
return;
|
|
98
|
+
this.on_commit(message);
|
|
99
|
+
}
|
|
100
|
+
build_message(summary) {
|
|
101
|
+
if (!summary)
|
|
102
|
+
return '';
|
|
103
|
+
if (!this.conventional)
|
|
104
|
+
return summary;
|
|
105
|
+
return `${this.selected_type}(git-ui): ${summary}`;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=commit-composer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commit-composer.js","sourceRoot":"","sources":["../src/commit-composer.ts"],"names":[],"mappings":"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"}
|
package/dist/git.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type FileState = 'staged' | 'changed' | 'mixed' | 'untracked' | 'conflicted';
|
|
2
|
+
export interface GitFile {
|
|
3
|
+
path: string;
|
|
4
|
+
index_status: string;
|
|
5
|
+
worktree_status: string;
|
|
6
|
+
state: FileState;
|
|
7
|
+
}
|
|
8
|
+
export interface GitStatus {
|
|
9
|
+
branch: string;
|
|
10
|
+
upstream?: string;
|
|
11
|
+
ahead: number;
|
|
12
|
+
behind: number;
|
|
13
|
+
files: GitFile[];
|
|
14
|
+
}
|
|
15
|
+
export interface DiffView {
|
|
16
|
+
path: string;
|
|
17
|
+
lines: string[];
|
|
18
|
+
}
|
|
19
|
+
export declare const EMPTY_STATUS: GitStatus;
|
|
20
|
+
export declare function read_status(cwd: string): Promise<GitStatus>;
|
|
21
|
+
export declare function parse_porcelain_z(raw: string): GitFile[];
|
|
22
|
+
export declare function stage_file(cwd: string, file: GitFile): Promise<void>;
|
|
23
|
+
export declare function unstage_file(cwd: string, file: GitFile): Promise<void>;
|
|
24
|
+
export declare function toggle_file(cwd: string, file: GitFile): Promise<void>;
|
|
25
|
+
export declare function stage_all(cwd: string): Promise<void>;
|
|
26
|
+
export declare function unstage_all(cwd: string): Promise<void>;
|
|
27
|
+
export declare function commit(cwd: string, message: string): Promise<void>;
|
|
28
|
+
export declare function read_diff(cwd: string, file: GitFile): Promise<DiffView>;
|
|
29
|
+
export declare function format_git_error(error: unknown): string;
|
|
30
|
+
export declare function has_staged_changes(files: GitFile[]): boolean;
|
|
31
|
+
export declare function staged_file_count(files: GitFile[]): number;
|
package/dist/git.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
const exec_file = promisify(execFile);
|
|
4
|
+
export const EMPTY_STATUS = {
|
|
5
|
+
branch: 'unknown',
|
|
6
|
+
ahead: 0,
|
|
7
|
+
behind: 0,
|
|
8
|
+
files: [],
|
|
9
|
+
};
|
|
10
|
+
async function git(args, cwd) {
|
|
11
|
+
const { stdout } = await exec_file('git', args, {
|
|
12
|
+
cwd,
|
|
13
|
+
encoding: 'utf8',
|
|
14
|
+
maxBuffer: 1024 * 1024 * 8,
|
|
15
|
+
});
|
|
16
|
+
return stdout;
|
|
17
|
+
}
|
|
18
|
+
export async function read_status(cwd) {
|
|
19
|
+
const [branch, upstream, raw] = await Promise.all([
|
|
20
|
+
git(['branch', '--show-current'], cwd).catch(() => 'detached'),
|
|
21
|
+
git([
|
|
22
|
+
'rev-parse',
|
|
23
|
+
'--abbrev-ref',
|
|
24
|
+
'--symbolic-full-name',
|
|
25
|
+
'@{upstream}',
|
|
26
|
+
], cwd).catch(() => ''),
|
|
27
|
+
git(['status', '--porcelain=v1', '-z'], cwd),
|
|
28
|
+
]);
|
|
29
|
+
const counts = upstream.trim()
|
|
30
|
+
? await read_ahead_behind(cwd)
|
|
31
|
+
: { ahead: 0, behind: 0 };
|
|
32
|
+
return {
|
|
33
|
+
branch: branch.trim() || 'detached',
|
|
34
|
+
upstream: upstream.trim() || undefined,
|
|
35
|
+
...counts,
|
|
36
|
+
files: parse_porcelain_z(raw),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
async function read_ahead_behind(cwd) {
|
|
40
|
+
const raw = await git(['rev-list', '--left-right', '--count', '@{upstream}...HEAD'], cwd).catch(() => '');
|
|
41
|
+
const [behind = '0', ahead = '0'] = raw.trim().split(/\s+/);
|
|
42
|
+
return { ahead: Number(ahead) || 0, behind: Number(behind) || 0 };
|
|
43
|
+
}
|
|
44
|
+
export function parse_porcelain_z(raw) {
|
|
45
|
+
if (!raw)
|
|
46
|
+
return [];
|
|
47
|
+
const entries = raw.split('\0').filter(Boolean);
|
|
48
|
+
const files = [];
|
|
49
|
+
for (let i = 0; i < entries.length; i++) {
|
|
50
|
+
const entry = entries[i];
|
|
51
|
+
const index_status = entry[0] ?? ' ';
|
|
52
|
+
const worktree_status = entry[1] ?? ' ';
|
|
53
|
+
let path = entry.slice(3);
|
|
54
|
+
if (index_status === 'R' || index_status === 'C') {
|
|
55
|
+
const original = entries[++i];
|
|
56
|
+
if (original)
|
|
57
|
+
path = `${original} → ${path}`;
|
|
58
|
+
}
|
|
59
|
+
files.push({
|
|
60
|
+
path,
|
|
61
|
+
index_status,
|
|
62
|
+
worktree_status,
|
|
63
|
+
state: get_file_state(index_status, worktree_status),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return files.sort((a, b) => state_rank(a.state) - state_rank(b.state) ||
|
|
67
|
+
a.path.localeCompare(b.path));
|
|
68
|
+
}
|
|
69
|
+
function get_file_state(index_status, worktree_status) {
|
|
70
|
+
if (index_status === '?' && worktree_status === '?')
|
|
71
|
+
return 'untracked';
|
|
72
|
+
if (index_status === 'U' ||
|
|
73
|
+
worktree_status === 'U' ||
|
|
74
|
+
(index_status === 'A' && worktree_status === 'A') ||
|
|
75
|
+
(index_status === 'D' && worktree_status === 'D')) {
|
|
76
|
+
return 'conflicted';
|
|
77
|
+
}
|
|
78
|
+
const has_index = index_status !== ' ';
|
|
79
|
+
const has_worktree = worktree_status !== ' ';
|
|
80
|
+
if (has_index && has_worktree)
|
|
81
|
+
return 'mixed';
|
|
82
|
+
if (has_index)
|
|
83
|
+
return 'staged';
|
|
84
|
+
return 'changed';
|
|
85
|
+
}
|
|
86
|
+
function state_rank(state) {
|
|
87
|
+
return [
|
|
88
|
+
'conflicted',
|
|
89
|
+
'changed',
|
|
90
|
+
'untracked',
|
|
91
|
+
'mixed',
|
|
92
|
+
'staged',
|
|
93
|
+
].indexOf(state);
|
|
94
|
+
}
|
|
95
|
+
function git_path(file) {
|
|
96
|
+
const arrow = ' → ';
|
|
97
|
+
return file.path.includes(arrow)
|
|
98
|
+
? file.path.split(arrow).at(-1)
|
|
99
|
+
: file.path;
|
|
100
|
+
}
|
|
101
|
+
export async function stage_file(cwd, file) {
|
|
102
|
+
await git(['add', '--', git_path(file)], cwd);
|
|
103
|
+
}
|
|
104
|
+
export async function unstage_file(cwd, file) {
|
|
105
|
+
await git(['restore', '--staged', '--', git_path(file)], cwd);
|
|
106
|
+
}
|
|
107
|
+
export async function toggle_file(cwd, file) {
|
|
108
|
+
if (file.state === 'mixed') {
|
|
109
|
+
throw new Error('Partial file: space is disabled. Use s to stage worktree changes or x to unstage staged changes.');
|
|
110
|
+
}
|
|
111
|
+
if (file.state === 'conflicted') {
|
|
112
|
+
throw new Error('Conflicted file: resolve conflicts, then stage explicitly with s.');
|
|
113
|
+
}
|
|
114
|
+
if (file.state === 'staged')
|
|
115
|
+
await unstage_file(cwd, file);
|
|
116
|
+
else
|
|
117
|
+
await stage_file(cwd, file);
|
|
118
|
+
}
|
|
119
|
+
export async function stage_all(cwd) {
|
|
120
|
+
await git(['add', '--all'], cwd);
|
|
121
|
+
}
|
|
122
|
+
export async function unstage_all(cwd) {
|
|
123
|
+
await git(['restore', '--staged', '--', ':/'], cwd);
|
|
124
|
+
}
|
|
125
|
+
export async function commit(cwd, message) {
|
|
126
|
+
await git(['commit', '-m', message], cwd);
|
|
127
|
+
}
|
|
128
|
+
export async function read_diff(cwd, file) {
|
|
129
|
+
const path = git_path(file);
|
|
130
|
+
if (file.state === 'untracked') {
|
|
131
|
+
return {
|
|
132
|
+
path: file.path,
|
|
133
|
+
lines: [
|
|
134
|
+
'Untracked file',
|
|
135
|
+
'',
|
|
136
|
+
'Press space or s to stage it.',
|
|
137
|
+
'No diff is available until Git starts tracking the path.',
|
|
138
|
+
],
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const sections = [];
|
|
142
|
+
const staged = await git(['diff', '--cached', '--', path], cwd).catch((error) => format_git_error(error));
|
|
143
|
+
const unstaged = await git(['diff', '--', path], cwd).catch((error) => format_git_error(error));
|
|
144
|
+
if (staged.trim())
|
|
145
|
+
sections.push('STAGED', '', ...staged.split('\n'));
|
|
146
|
+
if (staged.trim() && unstaged.trim())
|
|
147
|
+
sections.push('', '');
|
|
148
|
+
if (unstaged.trim())
|
|
149
|
+
sections.push('UNSTAGED', '', ...unstaged.split('\n'));
|
|
150
|
+
if (sections.length === 0)
|
|
151
|
+
sections.push('No textual diff for this file.');
|
|
152
|
+
return { path: file.path, lines: sections };
|
|
153
|
+
}
|
|
154
|
+
export function format_git_error(error) {
|
|
155
|
+
return error instanceof Error ? error.message : String(error);
|
|
156
|
+
}
|
|
157
|
+
export function has_staged_changes(files) {
|
|
158
|
+
return files.some((file) => file.index_status !== ' ' && file.index_status !== '?');
|
|
159
|
+
}
|
|
160
|
+
export function staged_file_count(files) {
|
|
161
|
+
return files.filter((file) => file.index_status !== ' ' && file.index_status !== '?').length;
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AA6BtC,MAAM,CAAC,MAAM,YAAY,GAAc;IACtC,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,EAAE;CACT,CAAC;AAEF,KAAK,UAAU,GAAG,CAAC,IAAc,EAAE,GAAW;IAC7C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;QAC/C,GAAG;QACH,QAAQ,EAAE,MAAM;QAChB,SAAS,EAAE,IAAI,GAAG,IAAI,GAAG,CAAC;KAC1B,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC5C,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACjD,GAAG,CAAC,CAAC,QAAQ,EAAE,gBAAgB,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC;QAC9D,GAAG,CACF;YACC,WAAW;YACX,cAAc;YACd,sBAAsB;YACtB,aAAa;SACb,EACD,GAAG,CACH,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;QACjB,GAAG,CAAC,CAAC,QAAQ,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC;KAC5C,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE;QAC7B,CAAC,CAAC,MAAM,iBAAiB,CAAC,GAAG,CAAC;QAC9B,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IAE3B,OAAO;QACN,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,UAAU;QACnC,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,SAAS;QACtC,GAAG,MAAM;QACT,KAAK,EAAE,iBAAiB,CAAC,GAAG,CAAC;KAC7B,CAAC;AACH,CAAC;AAED,KAAK,UAAU,iBAAiB,CAC/B,GAAW;IAEX,MAAM,GAAG,GAAG,MAAM,GAAG,CACpB,CAAC,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,oBAAoB,CAAC,EAC7D,GAAG,CACH,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAClB,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC5C,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,KAAK,GAAc,EAAE,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;QAC1B,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;QACrC,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;QACxC,IAAI,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAE1B,IAAI,YAAY,KAAK,GAAG,IAAI,YAAY,KAAK,GAAG,EAAE,CAAC;YAClD,MAAM,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;YAC9B,IAAI,QAAQ;gBAAE,IAAI,GAAG,GAAG,QAAQ,MAAM,IAAI,EAAE,CAAC;QAC9C,CAAC;QAED,KAAK,CAAC,IAAI,CAAC;YACV,IAAI;YACJ,YAAY;YACZ,eAAe;YACf,KAAK,EAAE,cAAc,CAAC,YAAY,EAAE,eAAe,CAAC;SACpD,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAChB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACR,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC;QACzC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAC7B,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CACtB,YAAoB,EACpB,eAAuB;IAEvB,IAAI,YAAY,KAAK,GAAG,IAAI,eAAe,KAAK,GAAG;QAClD,OAAO,WAAW,CAAC;IACpB,IACC,YAAY,KAAK,GAAG;QACpB,eAAe,KAAK,GAAG;QACvB,CAAC,YAAY,KAAK,GAAG,IAAI,eAAe,KAAK,GAAG,CAAC;QACjD,CAAC,YAAY,KAAK,GAAG,IAAI,eAAe,KAAK,GAAG,CAAC,EAChD,CAAC;QACF,OAAO,YAAY,CAAC;IACrB,CAAC;IACD,MAAM,SAAS,GAAG,YAAY,KAAK,GAAG,CAAC;IACvC,MAAM,YAAY,GAAG,eAAe,KAAK,GAAG,CAAC;IAC7C,IAAI,SAAS,IAAI,YAAY;QAAE,OAAO,OAAO,CAAC;IAC9C,IAAI,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC/B,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,UAAU,CAAC,KAAgB;IACnC,OAAO;QACN,YAAY;QACZ,SAAS;QACT,WAAW;QACX,OAAO;QACP,QAAQ;KACR,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,QAAQ,CAAC,IAAa;IAC9B,MAAM,KAAK,GAAG,KAAK,CAAC;IACpB,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC/B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE;QAChC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC/B,GAAW,EACX,IAAa;IAEb,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CACjC,GAAW,EACX,IAAa;IAEb,MAAM,GAAG,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,GAAW,EACX,IAAa;IAEb,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACd,kGAAkG,CAClG,CAAC;IACH,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACd,mEAAmE,CACnE,CAAC;IACH,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ;QAAE,MAAM,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;;QACtD,MAAM,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW;IAC1C,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC5C,MAAM,GAAG,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAC3B,GAAW,EACX,OAAe;IAEf,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC9B,GAAW,EACX,IAAa;IAEb,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,IAAI,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;QAChC,OAAO;YACN,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE;gBACN,gBAAgB;gBAChB,EAAE;gBACF,+BAA+B;gBAC/B,0DAA0D;aAC1D;SACD,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,MAAM,GAAG,CACvB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,EAChC,GAAG,CACH,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,CAC1D,CAAC,KAAK,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAClC,CAAC;IAEF,IAAI,MAAM,CAAC,IAAI,EAAE;QAChB,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,IAAI,MAAM,CAAC,IAAI,EAAE,IAAI,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAC5D,IAAI,QAAQ,CAAC,IAAI,EAAE;QAClB,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACxD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IAEjD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC9C,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAgB;IAClD,OAAO,KAAK,CAAC,IAAI,CAChB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,KAAK,GAAG,IAAI,IAAI,CAAC,YAAY,KAAK,GAAG,CAChE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAgB;IACjD,OAAO,KAAK,CAAC,MAAM,CAClB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,KAAK,GAAG,IAAI,IAAI,CAAC,YAAY,KAAK,GAAG,CAChE,CAAC,MAAM,CAAC;AACV,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { show_modal } from '@spences10/pi-tui-modal';
|
|
2
|
+
import { GitStageBody } from './stage-body.js';
|
|
3
|
+
async function show_git_ui(ctx) {
|
|
4
|
+
if (!ctx.hasUI || typeof ctx.ui.custom !== 'function') {
|
|
5
|
+
ctx.ui.notify('Git UI requires interactive mode.', 'warning');
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
await show_modal(ctx, {
|
|
9
|
+
title: 'Source Control',
|
|
10
|
+
subtitle: 'Review diffs, safely stage files, and commit staged changes',
|
|
11
|
+
footer: '↑↓/jk move • ←→/hl scroll diff • space safe toggle • s stage • x unstage • c commit • a safe stage all • A force stage all • u unstage all • r refresh • esc/q close',
|
|
12
|
+
overlay_options: {
|
|
13
|
+
width: '92%',
|
|
14
|
+
minWidth: 80,
|
|
15
|
+
maxHeight: '88%',
|
|
16
|
+
},
|
|
17
|
+
style: { border: 'rounded', border_color: 'accent' },
|
|
18
|
+
}, ({ done }, theme, _layout, tui) => {
|
|
19
|
+
const body = new GitStageBody(ctx.cwd, theme, () => tui.requestRender(), done);
|
|
20
|
+
void body.load();
|
|
21
|
+
return body;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export default function git_ui_extension(pi) {
|
|
25
|
+
pi.registerCommand('git-ui', {
|
|
26
|
+
description: 'Open an interactive Git staging UI',
|
|
27
|
+
handler: async (_args, ctx) => {
|
|
28
|
+
await show_git_ui(ctx);
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,KAAK,UAAU,WAAW,CACzB,GAA4B;IAE5B,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACvD,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,mCAAmC,EAAE,SAAS,CAAC,CAAC;QAC9D,OAAO;IACR,CAAC;IAED,MAAM,UAAU,CACf,GAAG,EACH;QACC,KAAK,EAAE,gBAAgB;QACvB,QAAQ,EACP,6DAA6D;QAC9D,MAAM,EACL,sKAAsK;QACvK,eAAe,EAAE;YAChB,KAAK,EAAE,KAAK;YACZ,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE,KAAK;SAChB;QACD,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE;KACpD,EACD,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE;QACjC,MAAM,IAAI,GAAG,IAAI,YAAY,CAC5B,GAAG,CAAC,GAAG,EACP,KAAK,EACL,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,EAAE,EACzB,IAAI,CACJ,CAAC;QACF,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC;IACb,CAAC,CACD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAgB;IACxD,EAAE,CAAC,eAAe,CAAC,QAAQ,EAAE;QAC5B,WAAW,EAAE,oCAAoC;QACjD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC7B,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/render.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FileState, GitFile } from './git.js';
|
|
2
|
+
export declare function state_label(state: FileState): string;
|
|
3
|
+
export declare function state_icon(state: FileState): string;
|
|
4
|
+
export declare function status_code(file: GitFile): string;
|
|
5
|
+
export declare function state_counts(files: GitFile[]): string;
|
|
6
|
+
export declare function key_is_up(data: string): boolean;
|
|
7
|
+
export declare function key_is_down(data: string): boolean;
|
|
8
|
+
export declare function strip_ansi(text: string): string;
|
|
9
|
+
export declare function truncate_plain(text: string, width: number): string;
|
|
10
|
+
export declare function pad_plain(text: string, width: number): string;
|
|
11
|
+
export declare function pad_ansi(text: string, width: number): string;
|
package/dist/render.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export function state_label(state) {
|
|
2
|
+
switch (state) {
|
|
3
|
+
case 'staged':
|
|
4
|
+
return 'staged';
|
|
5
|
+
case 'mixed':
|
|
6
|
+
return 'partial';
|
|
7
|
+
case 'untracked':
|
|
8
|
+
return 'untracked';
|
|
9
|
+
case 'conflicted':
|
|
10
|
+
return 'conflict';
|
|
11
|
+
case 'changed':
|
|
12
|
+
return 'changed';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function state_icon(state) {
|
|
16
|
+
switch (state) {
|
|
17
|
+
case 'conflicted':
|
|
18
|
+
return '!';
|
|
19
|
+
case 'changed':
|
|
20
|
+
return '±';
|
|
21
|
+
case 'untracked':
|
|
22
|
+
return '?';
|
|
23
|
+
case 'mixed':
|
|
24
|
+
return '◐';
|
|
25
|
+
case 'staged':
|
|
26
|
+
return '✓';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function status_code(file) {
|
|
30
|
+
const index = file.index_status === ' ' ? '·' : file.index_status;
|
|
31
|
+
const worktree = file.worktree_status === ' ' ? '·' : file.worktree_status;
|
|
32
|
+
return `${index}${worktree}`;
|
|
33
|
+
}
|
|
34
|
+
export function state_counts(files) {
|
|
35
|
+
const counts = new Map();
|
|
36
|
+
for (const file of files)
|
|
37
|
+
counts.set(file.state, (counts.get(file.state) ?? 0) + 1);
|
|
38
|
+
return ['conflicted', 'changed', 'untracked', 'mixed', 'staged']
|
|
39
|
+
.filter((state) => counts.has(state))
|
|
40
|
+
.map((state) => `${state_label(state)} ${counts.get(state)}`)
|
|
41
|
+
.join(' • ');
|
|
42
|
+
}
|
|
43
|
+
export function key_is_up(data) {
|
|
44
|
+
return data === 'k' || data === '\x1B[A';
|
|
45
|
+
}
|
|
46
|
+
export function key_is_down(data) {
|
|
47
|
+
return data === 'j' || data === '\x1B[B';
|
|
48
|
+
}
|
|
49
|
+
export function strip_ansi(text) {
|
|
50
|
+
const escape = String.fromCharCode(27);
|
|
51
|
+
let output = '';
|
|
52
|
+
for (let i = 0; i < text.length; i++) {
|
|
53
|
+
if (text[i] !== escape) {
|
|
54
|
+
output += text[i];
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (text[i + 1] !== '[')
|
|
58
|
+
continue;
|
|
59
|
+
i += 2;
|
|
60
|
+
while (i < text.length && !is_ansi_final_byte(text.charCodeAt(i)))
|
|
61
|
+
i++;
|
|
62
|
+
}
|
|
63
|
+
return output;
|
|
64
|
+
}
|
|
65
|
+
function is_ansi_final_byte(code) {
|
|
66
|
+
return code >= 0x40 && code <= 0x7e;
|
|
67
|
+
}
|
|
68
|
+
export function truncate_plain(text, width) {
|
|
69
|
+
if (width <= 0)
|
|
70
|
+
return '';
|
|
71
|
+
if (text.length <= width)
|
|
72
|
+
return text;
|
|
73
|
+
return `${text.slice(0, Math.max(0, width - 1))}…`;
|
|
74
|
+
}
|
|
75
|
+
export function pad_plain(text, width) {
|
|
76
|
+
return text + ' '.repeat(Math.max(0, width - text.length));
|
|
77
|
+
}
|
|
78
|
+
export function pad_ansi(text, width) {
|
|
79
|
+
return (text + ' '.repeat(Math.max(0, width - strip_ansi(text).length)));
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type Focusable } from '@earendil-works/pi-tui';
|
|
2
|
+
import type { ModalBody, ModalTheme } from '@spences10/pi-tui-modal';
|
|
3
|
+
export declare class GitStageBody implements ModalBody, Focusable {
|
|
4
|
+
private readonly cwd;
|
|
5
|
+
private readonly theme;
|
|
6
|
+
private readonly request_render;
|
|
7
|
+
private readonly done;
|
|
8
|
+
private selected;
|
|
9
|
+
private diff_scroll;
|
|
10
|
+
private status;
|
|
11
|
+
private diff?;
|
|
12
|
+
private diff_for_path;
|
|
13
|
+
private busy;
|
|
14
|
+
private message;
|
|
15
|
+
private composer?;
|
|
16
|
+
private _focused;
|
|
17
|
+
constructor(cwd: string, theme: ModalTheme, request_render: () => void, done: () => void);
|
|
18
|
+
get focused(): boolean;
|
|
19
|
+
set focused(value: boolean);
|
|
20
|
+
load(preferred_path?: string): Promise<void>;
|
|
21
|
+
render(width: number): string[];
|
|
22
|
+
handleInput(data: string): void;
|
|
23
|
+
invalidate(): void;
|
|
24
|
+
private restore_selection;
|
|
25
|
+
private render_header;
|
|
26
|
+
private render_message;
|
|
27
|
+
private render_workbench;
|
|
28
|
+
private render_file_list;
|
|
29
|
+
private render_diff;
|
|
30
|
+
private format_diff_line;
|
|
31
|
+
private selected_file;
|
|
32
|
+
private move_selection;
|
|
33
|
+
private scroll_diff;
|
|
34
|
+
private load_diff;
|
|
35
|
+
private toggle_selected;
|
|
36
|
+
private stage_selected;
|
|
37
|
+
private stage_all_safely;
|
|
38
|
+
private unstage_selected;
|
|
39
|
+
private open_commit_composer;
|
|
40
|
+
private commit_staged;
|
|
41
|
+
private run;
|
|
42
|
+
}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { Text } from '@earendil-works/pi-tui';
|
|
2
|
+
import { CommitComposer } from './commit-composer.js';
|
|
3
|
+
import { commit, EMPTY_STATUS, format_git_error, has_staged_changes, read_diff, read_status, stage_all, stage_file, staged_file_count, toggle_file, unstage_all, unstage_file, } from './git.js';
|
|
4
|
+
import { key_is_down, key_is_up, pad_ansi, pad_plain, state_counts, state_icon, state_label, status_code, truncate_plain, } from './render.js';
|
|
5
|
+
export class GitStageBody {
|
|
6
|
+
cwd;
|
|
7
|
+
theme;
|
|
8
|
+
request_render;
|
|
9
|
+
done;
|
|
10
|
+
selected = 0;
|
|
11
|
+
diff_scroll = 0;
|
|
12
|
+
status = EMPTY_STATUS;
|
|
13
|
+
diff;
|
|
14
|
+
diff_for_path = '';
|
|
15
|
+
busy = false;
|
|
16
|
+
message = '';
|
|
17
|
+
composer;
|
|
18
|
+
_focused = false;
|
|
19
|
+
constructor(cwd, theme, request_render, done) {
|
|
20
|
+
this.cwd = cwd;
|
|
21
|
+
this.theme = theme;
|
|
22
|
+
this.request_render = request_render;
|
|
23
|
+
this.done = done;
|
|
24
|
+
}
|
|
25
|
+
get focused() {
|
|
26
|
+
return this._focused;
|
|
27
|
+
}
|
|
28
|
+
set focused(value) {
|
|
29
|
+
this._focused = value;
|
|
30
|
+
if (this.composer)
|
|
31
|
+
this.composer.focused = value;
|
|
32
|
+
}
|
|
33
|
+
async load(preferred_path) {
|
|
34
|
+
this.busy = true;
|
|
35
|
+
this.message = 'Loading git status…';
|
|
36
|
+
this.request_render();
|
|
37
|
+
try {
|
|
38
|
+
this.status = await read_status(this.cwd);
|
|
39
|
+
this.restore_selection(preferred_path);
|
|
40
|
+
this.message =
|
|
41
|
+
this.status.files.length === 0 ? 'Working tree clean' : '';
|
|
42
|
+
await this.load_diff();
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
this.status = EMPTY_STATUS;
|
|
46
|
+
this.diff = undefined;
|
|
47
|
+
this.message = format_git_error(error);
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
this.busy = false;
|
|
51
|
+
this.request_render();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
render(width) {
|
|
55
|
+
if (this.composer)
|
|
56
|
+
return this.composer.render(width);
|
|
57
|
+
const lines = this.render_header(width);
|
|
58
|
+
if (this.message)
|
|
59
|
+
lines.push(...this.render_message(width));
|
|
60
|
+
if (this.status.files.length === 0)
|
|
61
|
+
return lines;
|
|
62
|
+
return [...lines, ...this.render_workbench(width)];
|
|
63
|
+
}
|
|
64
|
+
handleInput(data) {
|
|
65
|
+
if (this.composer) {
|
|
66
|
+
this.composer.handleInput(data);
|
|
67
|
+
this.request_render();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (this.busy)
|
|
71
|
+
return;
|
|
72
|
+
if (data === 'q' || data === '\x1B') {
|
|
73
|
+
this.done();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (key_is_up(data))
|
|
77
|
+
this.move_selection(-1);
|
|
78
|
+
else if (key_is_down(data))
|
|
79
|
+
this.move_selection(1);
|
|
80
|
+
else if (data === '\x1B[C' || data === 'l')
|
|
81
|
+
this.scroll_diff(4);
|
|
82
|
+
else if (data === '\x1B[D' || data === 'h')
|
|
83
|
+
this.scroll_diff(-4);
|
|
84
|
+
else if (data === ' ')
|
|
85
|
+
void this.toggle_selected();
|
|
86
|
+
else if (data === 's')
|
|
87
|
+
void this.stage_selected();
|
|
88
|
+
else if (data === 'x')
|
|
89
|
+
void this.unstage_selected();
|
|
90
|
+
else if (data === 'a')
|
|
91
|
+
void this.stage_all_safely();
|
|
92
|
+
else if (data === 'A')
|
|
93
|
+
void this.run(() => stage_all(this.cwd), 'Force-staged all changes');
|
|
94
|
+
else if (data === 'u')
|
|
95
|
+
void this.run(() => unstage_all(this.cwd), 'Unstaged all changes');
|
|
96
|
+
else if (data === 'c')
|
|
97
|
+
this.open_commit_composer();
|
|
98
|
+
else if (data === 'r')
|
|
99
|
+
void this.load(this.selected_file()?.path);
|
|
100
|
+
this.request_render();
|
|
101
|
+
}
|
|
102
|
+
invalidate() {
|
|
103
|
+
this.composer?.invalidate();
|
|
104
|
+
}
|
|
105
|
+
restore_selection(preferred_path) {
|
|
106
|
+
const path = preferred_path ?? this.status.files[this.selected]?.path;
|
|
107
|
+
const index = path
|
|
108
|
+
? this.status.files.findIndex((file) => file.path === path)
|
|
109
|
+
: -1;
|
|
110
|
+
this.selected =
|
|
111
|
+
index >= 0
|
|
112
|
+
? index
|
|
113
|
+
: Math.min(this.selected, Math.max(0, this.status.files.length - 1));
|
|
114
|
+
}
|
|
115
|
+
render_header(width) {
|
|
116
|
+
const upstream = this.status.upstream
|
|
117
|
+
? ` • ${this.status.upstream} ↑${this.status.ahead} ↓${this.status.behind}`
|
|
118
|
+
: '';
|
|
119
|
+
const counts = state_counts(this.status.files);
|
|
120
|
+
const staged = staged_file_count(this.status.files);
|
|
121
|
+
const text = `branch ${this.status.branch}${upstream} • ${this.status.files.length} files • staged ${staged}${counts ? ` • ${counts}` : ''}`;
|
|
122
|
+
return new Text(this.theme.fg('muted', text), 0, 0).render(width);
|
|
123
|
+
}
|
|
124
|
+
render_message(width) {
|
|
125
|
+
const color = this.busy
|
|
126
|
+
? 'accent'
|
|
127
|
+
: this.message.includes('disabled') ||
|
|
128
|
+
this.message.includes('conflict') ||
|
|
129
|
+
this.message.includes('blocked')
|
|
130
|
+
? 'warning'
|
|
131
|
+
: 'dim';
|
|
132
|
+
return new Text(this.theme.fg(color, this.message), 0, 0).render(width);
|
|
133
|
+
}
|
|
134
|
+
render_workbench(width) {
|
|
135
|
+
const gap = width >= 96 ? 3 : 1;
|
|
136
|
+
const list_width = Math.min(42, Math.max(28, Math.floor(width * 0.42)));
|
|
137
|
+
const diff_width = Math.max(20, width - list_width - gap);
|
|
138
|
+
const list = this.render_file_list(list_width);
|
|
139
|
+
const diff = this.render_diff(diff_width, list.length);
|
|
140
|
+
const height = Math.max(list.length, diff.length);
|
|
141
|
+
const lines = [];
|
|
142
|
+
for (let i = 0; i < height; i++) {
|
|
143
|
+
const left = pad_ansi(list[i] ?? '', list_width);
|
|
144
|
+
lines.push(`${left}${' '.repeat(gap)}${diff[i] ?? ''}`);
|
|
145
|
+
}
|
|
146
|
+
return lines;
|
|
147
|
+
}
|
|
148
|
+
render_file_list(width) {
|
|
149
|
+
const lines = [this.theme.bold('Files')];
|
|
150
|
+
let last_state;
|
|
151
|
+
for (let i = 0; i < this.status.files.length; i++) {
|
|
152
|
+
const file = this.status.files[i];
|
|
153
|
+
if (file.state !== last_state) {
|
|
154
|
+
lines.push(this.theme.fg('dim', state_label(file.state).toUpperCase()));
|
|
155
|
+
last_state = file.state;
|
|
156
|
+
}
|
|
157
|
+
const selected = i === this.selected;
|
|
158
|
+
const prefix = selected ? '› ' : ' ';
|
|
159
|
+
const label_width = Math.max(8, width - 14);
|
|
160
|
+
const label = truncate_plain(file.path, label_width);
|
|
161
|
+
const meta = `${state_icon(file.state)} ${status_code(file)}`;
|
|
162
|
+
const line = `${prefix}${pad_plain(label, label_width)} ${meta}`;
|
|
163
|
+
lines.push(selected
|
|
164
|
+
? this.theme.fg('accent', this.theme.bold(line))
|
|
165
|
+
: line);
|
|
166
|
+
}
|
|
167
|
+
return lines;
|
|
168
|
+
}
|
|
169
|
+
render_diff(width, height) {
|
|
170
|
+
const selected = this.selected_file();
|
|
171
|
+
const title = selected
|
|
172
|
+
? `Diff: ${truncate_plain(selected.path, Math.max(0, width - 6))}`
|
|
173
|
+
: 'Diff';
|
|
174
|
+
const lines = [this.theme.bold(title)];
|
|
175
|
+
if (!this.diff || this.diff.path !== this.diff_for_path) {
|
|
176
|
+
lines.push(this.theme.fg('dim', 'Loading diff…'));
|
|
177
|
+
return lines;
|
|
178
|
+
}
|
|
179
|
+
const visible = Math.max(1, height - 1);
|
|
180
|
+
const max_scroll = Math.max(0, this.diff.lines.length - visible);
|
|
181
|
+
this.diff_scroll = Math.min(this.diff_scroll, max_scroll);
|
|
182
|
+
const body = this.diff.lines.slice(this.diff_scroll, this.diff_scroll + visible);
|
|
183
|
+
for (const raw of body)
|
|
184
|
+
lines.push(this.format_diff_line(raw, width));
|
|
185
|
+
if (max_scroll > 0) {
|
|
186
|
+
lines[0] = `${lines[0]} ${this.theme.fg('dim', `${this.diff_scroll + 1}-${Math.min(this.diff_scroll + visible, this.diff.lines.length)}/${this.diff.lines.length}`)}`;
|
|
187
|
+
}
|
|
188
|
+
return lines;
|
|
189
|
+
}
|
|
190
|
+
format_diff_line(raw, width) {
|
|
191
|
+
const text = truncate_plain(raw.replace(/\t/g, ' '), width);
|
|
192
|
+
if (raw === 'STAGED' || raw === 'UNSTAGED')
|
|
193
|
+
return this.theme.fg('accent', this.theme.bold(text));
|
|
194
|
+
if (raw.startsWith('+++') || raw.startsWith('---'))
|
|
195
|
+
return this.theme.fg('muted', text);
|
|
196
|
+
if (raw.startsWith('@@'))
|
|
197
|
+
return this.theme.fg('accent', text);
|
|
198
|
+
if (raw.startsWith('+'))
|
|
199
|
+
return this.theme.fg('success', text);
|
|
200
|
+
if (raw.startsWith('-'))
|
|
201
|
+
return this.theme.fg('warning', text);
|
|
202
|
+
return text;
|
|
203
|
+
}
|
|
204
|
+
selected_file() {
|
|
205
|
+
return this.status.files[this.selected];
|
|
206
|
+
}
|
|
207
|
+
move_selection(delta) {
|
|
208
|
+
const next = Math.max(0, Math.min(this.status.files.length - 1, this.selected + delta));
|
|
209
|
+
if (next === this.selected)
|
|
210
|
+
return;
|
|
211
|
+
this.selected = next;
|
|
212
|
+
this.diff_scroll = 0;
|
|
213
|
+
void this.load_diff();
|
|
214
|
+
}
|
|
215
|
+
scroll_diff(delta) {
|
|
216
|
+
this.diff_scroll = Math.max(0, this.diff_scroll + delta);
|
|
217
|
+
}
|
|
218
|
+
async load_diff() {
|
|
219
|
+
const file = this.selected_file();
|
|
220
|
+
if (!file) {
|
|
221
|
+
this.diff = undefined;
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const path = file.path;
|
|
225
|
+
this.diff_for_path = path;
|
|
226
|
+
try {
|
|
227
|
+
this.diff = await read_diff(this.cwd, file);
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
this.diff = { path, lines: [format_git_error(error)] };
|
|
231
|
+
}
|
|
232
|
+
this.request_render();
|
|
233
|
+
}
|
|
234
|
+
async toggle_selected() {
|
|
235
|
+
const file = this.selected_file();
|
|
236
|
+
if (!file)
|
|
237
|
+
return;
|
|
238
|
+
const verb = file.state === 'staged' ? 'Unstaged' : 'Staged';
|
|
239
|
+
await this.run(() => toggle_file(this.cwd, file), `${verb} ${file.path}`);
|
|
240
|
+
}
|
|
241
|
+
async stage_selected() {
|
|
242
|
+
const file = this.selected_file();
|
|
243
|
+
if (!file)
|
|
244
|
+
return;
|
|
245
|
+
await this.run(() => stage_file(this.cwd, file), `Staged ${file.path}`);
|
|
246
|
+
}
|
|
247
|
+
async stage_all_safely() {
|
|
248
|
+
const unsafe = this.status.files.find((file) => file.state === 'mixed' || file.state === 'conflicted');
|
|
249
|
+
if (unsafe) {
|
|
250
|
+
this.message = `Stage all blocked by ${state_label(unsafe.state)} file ${unsafe.path}. Use A to force.`;
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
await this.run(() => stage_all(this.cwd), 'Staged all changes');
|
|
254
|
+
}
|
|
255
|
+
async unstage_selected() {
|
|
256
|
+
const file = this.selected_file();
|
|
257
|
+
if (!file)
|
|
258
|
+
return;
|
|
259
|
+
await this.run(() => unstage_file(this.cwd, file), `Unstaged ${file.path}`);
|
|
260
|
+
}
|
|
261
|
+
open_commit_composer() {
|
|
262
|
+
if (!has_staged_changes(this.status.files)) {
|
|
263
|
+
this.message = 'No staged changes to commit.';
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
this.composer = new CommitComposer(this.theme, staged_file_count(this.status.files), (message) => void this.commit_staged(message), () => {
|
|
267
|
+
this.composer = undefined;
|
|
268
|
+
});
|
|
269
|
+
this.composer.focused = this.focused;
|
|
270
|
+
}
|
|
271
|
+
async commit_staged(message) {
|
|
272
|
+
this.composer = undefined;
|
|
273
|
+
await this.run(() => commit(this.cwd, message), `Committed ${message}`);
|
|
274
|
+
}
|
|
275
|
+
async run(action, success) {
|
|
276
|
+
const path = this.selected_file()?.path;
|
|
277
|
+
this.busy = true;
|
|
278
|
+
this.message = 'Working…';
|
|
279
|
+
this.request_render();
|
|
280
|
+
try {
|
|
281
|
+
await action();
|
|
282
|
+
this.message = success;
|
|
283
|
+
this.status = await read_status(this.cwd);
|
|
284
|
+
this.restore_selection(path);
|
|
285
|
+
this.diff_scroll = 0;
|
|
286
|
+
await this.load_diff();
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
this.message = format_git_error(error);
|
|
290
|
+
}
|
|
291
|
+
finally {
|
|
292
|
+
this.busy = false;
|
|
293
|
+
this.request_render();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=stage-body.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage-body.js","sourceRoot":"","sources":["../src/stage-body.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@spences10/pi-git-ui",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Interactive Git staging UI for Pi",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"git",
|
|
7
|
+
"pi",
|
|
8
|
+
"pi-package",
|
|
9
|
+
"tui"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"author": "Scott Spence <me@scottspence.com>",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/spences10/my-pi.git",
|
|
16
|
+
"directory": "packages/pi-git-ui"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"type": "module",
|
|
23
|
+
"main": "./dist/index.js",
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@earendil-works/pi-coding-agent": "^0.74.0",
|
|
33
|
+
"@earendil-works/pi-tui": "^0.74.0",
|
|
34
|
+
"@spences10/pi-tui-modal": "0.0.12"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^25.8.0",
|
|
38
|
+
"typescript": "^6.0.3"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=24.15.0"
|
|
42
|
+
},
|
|
43
|
+
"pi": {
|
|
44
|
+
"extensions": [
|
|
45
|
+
"./dist/index.js"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "pnpm --filter \"$npm_package_name^...\" run build:self && pnpm run build:self",
|
|
50
|
+
"build:self": "tsc -p tsconfig.build.json",
|
|
51
|
+
"check": "pnpm --filter \"$npm_package_name^...\" run build:self && pnpm run check:self",
|
|
52
|
+
"check:self": "tsc --noEmit",
|
|
53
|
+
"test": "pnpm --filter \"$npm_package_name^...\" run build:self && pnpm run test:self",
|
|
54
|
+
"test:self": "node -e \"process.exit(0)\""
|
|
55
|
+
}
|
|
56
|
+
}
|