pi-fancy-footer 0.3.0 → 0.3.2
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/README.md
CHANGED
|
@@ -4,11 +4,13 @@ A [pi](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent)
|
|
|
4
4
|
extension that replaces the default footer with a compact, two-line fancy status
|
|
5
5
|
footer.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## 📦 Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pi install npm:pi-fancy-footer
|
|
13
|
+
```
|
|
12
14
|
|
|
13
15
|
## 📊 What it shows
|
|
14
16
|
|
|
@@ -19,13 +21,21 @@ footer.
|
|
|
19
21
|
- Repo / path, branch, commit, and open PR number
|
|
20
22
|
- Git diff stats and ahead/behind status
|
|
21
23
|
|
|
22
|
-
##
|
|
24
|
+
## 📸 Screenshots
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
<!-- markdownlint-disable MD033 -->
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
<img src="screenshots/light-blocks.png" alt="light theme – blocks style" width="600" /><br/>
|
|
29
|
+
<img src="screenshots/light-bars.png" alt="light theme – bars style" width="600" /><br/>
|
|
30
|
+
<img src="screenshots/light-circles.png" alt="light theme – circles style" width="600" /><br/>
|
|
31
|
+
<img src="screenshots/light-stars.png" alt="light theme – stars style" width="600" />
|
|
32
|
+
|
|
33
|
+
<img src="screenshots/dark-yellow.png" alt="dark theme – yellow accent" width="600" /><br/>
|
|
34
|
+
<img src="screenshots/dark-blue.png" alt="dark theme – blue accent" width="600" /><br/>
|
|
35
|
+
<img src="screenshots/dark-green.png" alt="dark theme – green accent" width="600" /><br/>
|
|
36
|
+
<img src="screenshots/dark-red.png" alt="dark theme – red accent" width="600" />
|
|
37
|
+
|
|
38
|
+
<!-- markdownlint-enable MD033 -->
|
|
29
39
|
|
|
30
40
|
## 🎮 Commands
|
|
31
41
|
|
|
@@ -124,21 +134,21 @@ leading widget icon.
|
|
|
124
134
|
|
|
125
135
|
<!-- markdownlint-disable MD013 MD060 -->
|
|
126
136
|
|
|
127
|
-
| Widget | nerd
|
|
128
|
-
| ------------------ |
|
|
129
|
-
| `model` | ``
|
|
130
|
-
| `thinking` | ``
|
|
131
|
-
| `context-capacity` |
|
|
132
|
-
| `context-bar` | ``
|
|
133
|
-
| `context-usage` |
|
|
134
|
-
| `total-cost` | `$`
|
|
135
|
-
| `location` |
|
|
136
|
-
| `branch` |
|
|
137
|
-
| `commit` |
|
|
138
|
-
| `pull-request` |
|
|
139
|
-
| `diff-added` | `↗`
|
|
140
|
-
| `diff-removed` | `↘`
|
|
141
|
-
| `git-status` |
|
|
137
|
+
| Widget | nerd | emoji | unicode | ascii |
|
|
138
|
+
| ------------------ | ---- | ---------- | ------- | -------- |
|
|
139
|
+
| `model` | `` | `🤖` | `◉` | `%` |
|
|
140
|
+
| `thinking` | `` | `🧠` | `✦` | `?` |
|
|
141
|
+
| `context-capacity` | `` | `💾` | `□` | `[]` |
|
|
142
|
+
| `context-bar` | `` | `🔋` | `◧` | `\|` |
|
|
143
|
+
| `context-usage` | `` | `📈` | `■` | `~` |
|
|
144
|
+
| `total-cost` | `$` | `💲` | `$` | `$` |
|
|
145
|
+
| `location` | `` | `📁` | `⌂` | `/` |
|
|
146
|
+
| `branch` | `` | `🌿` | `⎇` | `*` |
|
|
147
|
+
| `commit` | `` | `🔖` | `#` | `#` |
|
|
148
|
+
| `pull-request` | `` | `🔀` | `⇄` | `@` |
|
|
149
|
+
| `diff-added` | `↗` | `➕` | `+` | `+` |
|
|
150
|
+
| `diff-removed` | `↘` | `➖` | `−` | `-` |
|
|
151
|
+
| `git-status` | `//` | `🔼/🔽/🔀` | `↑/↓/↕` | `^/_/<>` |
|
|
142
152
|
|
|
143
153
|
<!-- markdownlint-enable MD013 MD060 -->
|
|
144
154
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
2
|
import { join } from "node:path";
|
|
4
3
|
import {
|
|
4
|
+
getAgentDir,
|
|
5
5
|
getSettingsListTheme,
|
|
6
6
|
type Theme,
|
|
7
7
|
} from "@mariozechner/pi-coding-agent";
|
|
@@ -67,20 +67,6 @@ function readJsonObject(filePath: string): Record<string, unknown> | undefined {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
function expandHome(pathValue: string): string {
|
|
71
|
-
if (pathValue === "~") return homedir();
|
|
72
|
-
if (pathValue.startsWith("~/") || pathValue.startsWith("~\\")) {
|
|
73
|
-
return join(homedir(), pathValue.slice(2));
|
|
74
|
-
}
|
|
75
|
-
return pathValue;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function getAgentDir(): string {
|
|
79
|
-
return process.env.PI_CODING_AGENT_DIR
|
|
80
|
-
? expandHome(process.env.PI_CODING_AGENT_DIR)
|
|
81
|
-
: join(homedir(), ".pi", "agent");
|
|
82
|
-
}
|
|
83
|
-
|
|
84
70
|
export function coerceCompactionSettings(
|
|
85
71
|
value: unknown,
|
|
86
72
|
fallback: CompactionSettingsSnapshot = DEFAULT_COMPACTION_SETTINGS,
|
|
@@ -800,11 +786,13 @@ export function genericFooterSettingsItems(
|
|
|
800
786
|
label: "context bar style",
|
|
801
787
|
currentValue: formatContextBarStyleValue(draft.contextBarStyle),
|
|
802
788
|
values: CONTEXT_BAR_STYLE_IDS.map(formatContextBarStyleValue),
|
|
803
|
-
description:
|
|
789
|
+
description:
|
|
790
|
+
"Choose the character style for the context usage bar: " +
|
|
804
791
|
CONTEXT_BAR_STYLES.map((s, i) => {
|
|
805
792
|
const repr = s.label + " " + s.used + s.free + s.reserved;
|
|
806
793
|
return i === CONTEXT_BAR_STYLES.length - 1 ? "or " + repr : repr;
|
|
807
|
-
}).join(", ") +
|
|
794
|
+
}).join(", ") +
|
|
795
|
+
".",
|
|
808
796
|
},
|
|
809
797
|
{
|
|
810
798
|
id: "defaultTextColor",
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import test from "node:test";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
collectGitInfo,
|
|
5
|
+
collectPullRequestInfo,
|
|
6
|
+
shouldRefreshPullRequest,
|
|
7
|
+
} from "./git.ts";
|
|
4
8
|
|
|
5
9
|
interface ExecInvocation {
|
|
6
10
|
command: string;
|
|
@@ -15,30 +19,49 @@ interface ExecResult {
|
|
|
15
19
|
stderr: string;
|
|
16
20
|
}
|
|
17
21
|
|
|
18
|
-
function
|
|
22
|
+
function gitSubcommand(args: string[]): string {
|
|
23
|
+
return args[0] === "--no-optional-locks" ? (args[1] ?? "") : (args[0] ?? "");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function createPi(
|
|
27
|
+
execImpl: (call: ExecInvocation) => ExecResult | Promise<ExecResult>,
|
|
28
|
+
) {
|
|
19
29
|
const calls: ExecInvocation[] = [];
|
|
20
30
|
|
|
21
31
|
return {
|
|
22
32
|
calls,
|
|
23
33
|
pi: {
|
|
24
|
-
async exec(
|
|
25
|
-
|
|
34
|
+
async exec(
|
|
35
|
+
command: string,
|
|
36
|
+
args: string[],
|
|
37
|
+
options: { cwd: string; timeout?: number },
|
|
38
|
+
) {
|
|
39
|
+
const call = {
|
|
40
|
+
command,
|
|
41
|
+
args,
|
|
42
|
+
cwd: options.cwd,
|
|
43
|
+
timeout: options.timeout,
|
|
44
|
+
};
|
|
26
45
|
calls.push(call);
|
|
27
46
|
return await execImpl(call);
|
|
28
47
|
},
|
|
29
48
|
} as {
|
|
30
|
-
exec(
|
|
49
|
+
exec(
|
|
50
|
+
command: string,
|
|
51
|
+
args: string[],
|
|
52
|
+
options: { cwd: string; timeout?: number },
|
|
53
|
+
): Promise<ExecResult>;
|
|
31
54
|
},
|
|
32
55
|
};
|
|
33
56
|
}
|
|
34
57
|
|
|
35
58
|
test("collectPullRequestInfo ignores foreign branch-name matches and falls back to gh pr view", async () => {
|
|
36
59
|
const { pi, calls } = createPi(({ command, args }) => {
|
|
37
|
-
if (command === "git" && args
|
|
60
|
+
if (command === "git" && gitSubcommand(args) === "rev-parse") {
|
|
38
61
|
return { code: 0, stdout: "origin/fix-ci\n", stderr: "" };
|
|
39
62
|
}
|
|
40
63
|
|
|
41
|
-
if (command === "git" && args
|
|
64
|
+
if (command === "git" && gitSubcommand(args) === "config") {
|
|
42
65
|
return {
|
|
43
66
|
code: 0,
|
|
44
67
|
stdout: [
|
|
@@ -110,18 +133,29 @@ test("collectPullRequestInfo ignores foreign branch-name matches and falls back
|
|
|
110
133
|
assert.equal(result.pullRequestLookupEnabled, true);
|
|
111
134
|
assert.notEqual(result.pullRequestLookupAt, 0);
|
|
112
135
|
assert.equal(
|
|
113
|
-
calls.some(
|
|
136
|
+
calls.some(
|
|
137
|
+
(call) =>
|
|
138
|
+
call.command === "gh" &&
|
|
139
|
+
call.args[0] === "pr" &&
|
|
140
|
+
call.args[1] === "view",
|
|
141
|
+
),
|
|
142
|
+
true,
|
|
143
|
+
);
|
|
144
|
+
assert.equal(
|
|
145
|
+
calls
|
|
146
|
+
.filter((call) => call.command === "git")
|
|
147
|
+
.every((call) => call.args[0] === "--no-optional-locks"),
|
|
114
148
|
true,
|
|
115
149
|
);
|
|
116
150
|
});
|
|
117
151
|
|
|
118
152
|
test("collectPullRequestInfo skips GitHub CLI lookups when the repository has no GitHub remote", async () => {
|
|
119
153
|
const { pi, calls } = createPi(({ command, args }) => {
|
|
120
|
-
if (command === "git" && args
|
|
154
|
+
if (command === "git" && gitSubcommand(args) === "rev-parse") {
|
|
121
155
|
return { code: 0, stdout: "origin/main\n", stderr: "" };
|
|
122
156
|
}
|
|
123
157
|
|
|
124
|
-
if (command === "git" && args
|
|
158
|
+
if (command === "git" && gitSubcommand(args) === "config") {
|
|
125
159
|
return {
|
|
126
160
|
code: 0,
|
|
127
161
|
stdout: "remote.origin.url ssh://git.example.com/team/repo.git",
|
|
@@ -136,12 +170,19 @@ test("collectPullRequestInfo skips GitHub CLI lookups when the repository has no
|
|
|
136
170
|
|
|
137
171
|
assert.equal(result.pullRequest, undefined);
|
|
138
172
|
assert.equal(result.pullRequestLookupEnabled, false);
|
|
139
|
-
assert.equal(
|
|
173
|
+
assert.equal(
|
|
174
|
+
calls.every((call) => call.command === "git"),
|
|
175
|
+
true,
|
|
176
|
+
);
|
|
177
|
+
assert.equal(
|
|
178
|
+
calls.every((call) => call.args[0] === "--no-optional-locks"),
|
|
179
|
+
true,
|
|
180
|
+
);
|
|
140
181
|
});
|
|
141
182
|
|
|
142
183
|
test("collectGitInfo disables periodic PR refreshes for non-GitHub repositories", async () => {
|
|
143
|
-
const { pi } = createPi(({ command, args }) => {
|
|
144
|
-
if (command === "git" && args
|
|
184
|
+
const { pi, calls } = createPi(({ command, args }) => {
|
|
185
|
+
if (command === "git" && gitSubcommand(args) === "status") {
|
|
145
186
|
return {
|
|
146
187
|
code: 0,
|
|
147
188
|
stdout: [
|
|
@@ -154,7 +195,7 @@ test("collectGitInfo disables periodic PR refreshes for non-GitHub repositories"
|
|
|
154
195
|
};
|
|
155
196
|
}
|
|
156
197
|
|
|
157
|
-
if (command === "git" && args
|
|
198
|
+
if (command === "git" && gitSubcommand(args) === "config") {
|
|
158
199
|
return {
|
|
159
200
|
code: 0,
|
|
160
201
|
stdout: "remote.origin.url ssh://git.example.com/team/repo.git",
|
|
@@ -162,7 +203,7 @@ test("collectGitInfo disables periodic PR refreshes for non-GitHub repositories"
|
|
|
162
203
|
};
|
|
163
204
|
}
|
|
164
205
|
|
|
165
|
-
if (command === "git" && args
|
|
206
|
+
if (command === "git" && gitSubcommand(args) === "diff") {
|
|
166
207
|
return { code: 0, stdout: "", stderr: "" };
|
|
167
208
|
}
|
|
168
209
|
|
|
@@ -173,4 +214,8 @@ test("collectGitInfo disables periodic PR refreshes for non-GitHub repositories"
|
|
|
173
214
|
|
|
174
215
|
assert.equal(git.pullRequestLookupEnabled, false);
|
|
175
216
|
assert.equal(shouldRefreshPullRequest(git), false);
|
|
217
|
+
assert.equal(
|
|
218
|
+
calls.every((call) => call.args[0] === "--no-optional-locks"),
|
|
219
|
+
true,
|
|
220
|
+
);
|
|
176
221
|
});
|
|
@@ -5,7 +5,12 @@ import {
|
|
|
5
5
|
selectPullRequestFromGraphQL,
|
|
6
6
|
splitGitHubRepository,
|
|
7
7
|
} from "./pull-request.ts";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
EMPTY_GIT_INFO,
|
|
10
|
+
type GitInfo,
|
|
11
|
+
parseNumstat,
|
|
12
|
+
toNumber,
|
|
13
|
+
} from "./shared.ts";
|
|
9
14
|
|
|
10
15
|
interface ExecResult {
|
|
11
16
|
code: number;
|
|
@@ -16,6 +21,7 @@ interface ExecResult {
|
|
|
16
21
|
const DEFAULT_COMMAND_TIMEOUT_MS = 2_000;
|
|
17
22
|
const GITHUB_COMMAND_TIMEOUT_MS = 5_000;
|
|
18
23
|
const PULL_REQUEST_REFRESH_MS = 60_000;
|
|
24
|
+
const GIT_NO_OPTIONAL_LOCKS_ARG = "--no-optional-locks";
|
|
19
25
|
const PULL_REQUEST_QUERY = [
|
|
20
26
|
"query($owner: String!, $name: String!, $branch: String!) {",
|
|
21
27
|
" repository(owner: $owner, name: $name) {",
|
|
@@ -61,6 +67,31 @@ async function exec(
|
|
|
61
67
|
return result.stdout;
|
|
62
68
|
}
|
|
63
69
|
|
|
70
|
+
async function execGitResult(
|
|
71
|
+
pi: ExtensionAPI,
|
|
72
|
+
args: string[],
|
|
73
|
+
cwd: string,
|
|
74
|
+
timeout = DEFAULT_COMMAND_TIMEOUT_MS,
|
|
75
|
+
): Promise<ExecResult> {
|
|
76
|
+
return execResult(
|
|
77
|
+
pi,
|
|
78
|
+
"git",
|
|
79
|
+
[GIT_NO_OPTIONAL_LOCKS_ARG, ...args],
|
|
80
|
+
cwd,
|
|
81
|
+
timeout,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function execGit(
|
|
86
|
+
pi: ExtensionAPI,
|
|
87
|
+
args: string[],
|
|
88
|
+
cwd: string,
|
|
89
|
+
): Promise<string> {
|
|
90
|
+
const result = await execGitResult(pi, args, cwd);
|
|
91
|
+
if (result.code !== 0) return "";
|
|
92
|
+
return result.stdout;
|
|
93
|
+
}
|
|
94
|
+
|
|
64
95
|
async function collectPullRequestFromBaseRepository(
|
|
65
96
|
pi: ExtensionAPI,
|
|
66
97
|
cwd: string,
|
|
@@ -111,16 +142,28 @@ async function collectCurrentBranchPullRequest(
|
|
|
111
142
|
}
|
|
112
143
|
|
|
113
144
|
export function shouldRefreshPullRequest(
|
|
114
|
-
git: Pick<
|
|
145
|
+
git: Pick<
|
|
146
|
+
GitInfo,
|
|
147
|
+
"branch" | "pullRequestLookupEnabled" | "pullRequestLookupAt"
|
|
148
|
+
>,
|
|
115
149
|
): boolean {
|
|
116
|
-
return
|
|
150
|
+
return (
|
|
151
|
+
git.pullRequestLookupEnabled &&
|
|
152
|
+
!!git.branch &&
|
|
153
|
+
Date.now() - git.pullRequestLookupAt >= PULL_REQUEST_REFRESH_MS
|
|
154
|
+
);
|
|
117
155
|
}
|
|
118
156
|
|
|
119
157
|
export async function collectPullRequestInfo(
|
|
120
158
|
pi: ExtensionAPI,
|
|
121
159
|
cwd: string,
|
|
122
160
|
branch: string,
|
|
123
|
-
): Promise<
|
|
161
|
+
): Promise<
|
|
162
|
+
Pick<
|
|
163
|
+
GitInfo,
|
|
164
|
+
"pullRequest" | "pullRequestLookupEnabled" | "pullRequestLookupAt"
|
|
165
|
+
>
|
|
166
|
+
> {
|
|
124
167
|
if (!branch) {
|
|
125
168
|
return {
|
|
126
169
|
pullRequest: undefined,
|
|
@@ -130,8 +173,12 @@ export async function collectPullRequestInfo(
|
|
|
130
173
|
}
|
|
131
174
|
|
|
132
175
|
const [upstream, remoteUrls] = await Promise.all([
|
|
133
|
-
|
|
134
|
-
|
|
176
|
+
execGit(
|
|
177
|
+
pi,
|
|
178
|
+
["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}"],
|
|
179
|
+
cwd,
|
|
180
|
+
),
|
|
181
|
+
execGit(pi, ["config", "--get-regexp", "^remote\\..*\\.url$"], cwd),
|
|
135
182
|
]);
|
|
136
183
|
|
|
137
184
|
const repositoryContext = createGitHubRepositoryContext(remoteUrls, upstream);
|
|
@@ -146,7 +193,13 @@ export async function collectPullRequestInfo(
|
|
|
146
193
|
}
|
|
147
194
|
|
|
148
195
|
for (const baseRepository of plan.baseRepositories) {
|
|
149
|
-
const pullRequest = await collectPullRequestFromBaseRepository(
|
|
196
|
+
const pullRequest = await collectPullRequestFromBaseRepository(
|
|
197
|
+
pi,
|
|
198
|
+
cwd,
|
|
199
|
+
baseRepository,
|
|
200
|
+
branch,
|
|
201
|
+
plan.headOwners,
|
|
202
|
+
);
|
|
150
203
|
if (pullRequest) {
|
|
151
204
|
return {
|
|
152
205
|
pullRequest,
|
|
@@ -169,11 +222,20 @@ export async function collectPullRequestInfo(
|
|
|
169
222
|
export async function collectGitInfo(
|
|
170
223
|
pi: ExtensionAPI,
|
|
171
224
|
cwd: string,
|
|
172
|
-
previousGit:
|
|
225
|
+
previousGit:
|
|
226
|
+
| Pick<
|
|
227
|
+
GitInfo,
|
|
228
|
+
| "repository"
|
|
229
|
+
| "branch"
|
|
230
|
+
| "pullRequest"
|
|
231
|
+
| "pullRequestLookupEnabled"
|
|
232
|
+
| "pullRequestLookupAt"
|
|
233
|
+
>
|
|
234
|
+
| undefined = undefined,
|
|
173
235
|
): Promise<GitInfo> {
|
|
174
236
|
const [porcelainV2, remoteUrls] = await Promise.all([
|
|
175
|
-
|
|
176
|
-
|
|
237
|
+
execGit(pi, ["status", "--porcelain=2", "--branch"], cwd),
|
|
238
|
+
execGit(pi, ["config", "--get-regexp", "^remote\\..*\\.url$"], cwd),
|
|
177
239
|
]);
|
|
178
240
|
|
|
179
241
|
if (!porcelainV2) return { ...EMPTY_GIT_INFO };
|
|
@@ -221,7 +283,11 @@ export async function collectGitInfo(
|
|
|
221
283
|
continue;
|
|
222
284
|
}
|
|
223
285
|
|
|
224
|
-
if (
|
|
286
|
+
if (
|
|
287
|
+
line.startsWith("1 ") ||
|
|
288
|
+
line.startsWith("2 ") ||
|
|
289
|
+
line.startsWith("u ")
|
|
290
|
+
) {
|
|
225
291
|
const xy = line.split(" ")[1] || "..";
|
|
226
292
|
const x = xy[0] || ".";
|
|
227
293
|
const y = xy[1] || ".";
|
|
@@ -231,22 +297,23 @@ export async function collectGitInfo(
|
|
|
231
297
|
}
|
|
232
298
|
|
|
233
299
|
const repositoryContext = createGitHubRepositoryContext(remoteUrls, upstream);
|
|
234
|
-
const samePullRequestTarget =
|
|
235
|
-
|
|
236
|
-
|
|
300
|
+
const samePullRequestTarget =
|
|
301
|
+
previousGit !== undefined &&
|
|
302
|
+
previousGit.repository === repositoryContext.repository &&
|
|
303
|
+
previousGit.branch === branch;
|
|
237
304
|
|
|
238
305
|
let added = 0;
|
|
239
306
|
let removed = 0;
|
|
240
307
|
|
|
241
|
-
const headDiff = await
|
|
308
|
+
const headDiff = await execGit(pi, ["diff", "--numstat", "HEAD"], cwd);
|
|
242
309
|
if (headDiff) {
|
|
243
310
|
const stats = parseNumstat(headDiff);
|
|
244
311
|
added = stats.added;
|
|
245
312
|
removed = stats.removed;
|
|
246
313
|
} else {
|
|
247
314
|
const [stagedDiff, unstagedDiff] = await Promise.all([
|
|
248
|
-
|
|
249
|
-
|
|
315
|
+
execGit(pi, ["diff", "--numstat", "--cached"], cwd),
|
|
316
|
+
execGit(pi, ["diff", "--numstat"], cwd),
|
|
250
317
|
]);
|
|
251
318
|
const stagedStats = parseNumstat(stagedDiff);
|
|
252
319
|
const unstagedStats = parseNumstat(unstagedDiff);
|
|
@@ -260,7 +327,9 @@ export async function collectGitInfo(
|
|
|
260
327
|
commit,
|
|
261
328
|
pullRequest: samePullRequestTarget ? previousGit?.pullRequest : undefined,
|
|
262
329
|
pullRequestLookupEnabled: repositoryContext.pullRequestLookupEnabled,
|
|
263
|
-
pullRequestLookupAt: samePullRequestTarget
|
|
330
|
+
pullRequestLookupAt: samePullRequestTarget
|
|
331
|
+
? (previousGit?.pullRequestLookupAt ?? 0)
|
|
332
|
+
: 0,
|
|
264
333
|
added,
|
|
265
334
|
removed,
|
|
266
335
|
counts: {
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "@mariozechner/pi-coding-agent";
|
|
5
5
|
import {
|
|
6
6
|
Key,
|
|
7
|
-
|
|
7
|
+
getKeybindings,
|
|
8
8
|
matchesKey,
|
|
9
9
|
truncateToWidth,
|
|
10
10
|
visibleWidth,
|
|
@@ -543,19 +543,19 @@ export default function (pi: ExtensionAPI) {
|
|
|
543
543
|
return;
|
|
544
544
|
}
|
|
545
545
|
|
|
546
|
-
const kb =
|
|
546
|
+
const kb = getKeybindings();
|
|
547
547
|
|
|
548
|
-
if (kb.matches(data, "
|
|
548
|
+
if (kb.matches(data, "tui.select.up")) {
|
|
549
549
|
if (getActiveSectionItems().length > 0) moveSelection(-1);
|
|
550
|
-
} else if (kb.matches(data, "
|
|
550
|
+
} else if (kb.matches(data, "tui.select.down")) {
|
|
551
551
|
if (getActiveSectionItems().length > 0) moveSelection(1);
|
|
552
552
|
} else if (matchesKey(data, Key.tab)) {
|
|
553
553
|
moveSection(1);
|
|
554
554
|
} else if (matchesKey(data, Key.shift("tab"))) {
|
|
555
555
|
moveSection(-1);
|
|
556
|
-
} else if (kb.matches(data, "
|
|
556
|
+
} else if (kb.matches(data, "tui.select.confirm") || data === " ") {
|
|
557
557
|
activateCurrentItem();
|
|
558
|
-
} else if (kb.matches(data, "
|
|
558
|
+
} else if (kb.matches(data, "tui.select.cancel")) {
|
|
559
559
|
done(undefined);
|
|
560
560
|
return;
|
|
561
561
|
}
|