pi-zellij 0.4.0 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +86 -2
- package/extensions/git-core.ts +1 -1
- package/extensions/index.ts +3 -1
- package/extensions/zv-continue.ts +5 -3
- package/extensions/zv-core.ts +155 -29
- package/extensions/zv-highlight.ts +523 -0
- package/extensions/zv-open.ts +150 -8
- package/extensions/zv-review.ts +10 -4
- package/extensions/zv-split.ts +278 -22
- package/extensions/zv-zoxide.ts +10 -4
- package/package.json +6 -3
package/CHANGELOG.md
CHANGED
|
@@ -13,6 +13,20 @@
|
|
|
13
13
|
- Added `/zz` and `/zzh` to open a new pane from a zoxide match or direct directory path and start Pi there.
|
|
14
14
|
- Added `zv-review` with `/zrv` and `/zrh`, plus bundled `code-review` skill and `/review` / `/review-diff` prompt templates for focused review workflows, including GitHub pull request review via `gh` when given a PR URL.
|
|
15
15
|
- Added `zv-continue` with `/zcv` and `/zch` for split-based task handoff in the current checkout or by creating a git worktree branch with `-c <branch>`.
|
|
16
|
+
- Added opt-in `paneHighlight` settings so Pi can tint the current zellij pane when an agent turn completes, with optional working-state colors.
|
|
17
|
+
- Added an agent-facing `zellij_open_terminal` tool so Pi can open explicitly requested interactive terminal commands in right or lower splits, tabs, and floating panes.
|
|
18
|
+
- Added an agent-facing `zellij_start_pi` tool for fresh Pi sessions in right or lower splits and tabs, with optional initial prompts, model settings, pane titles, and explicit history inheritance through a separate cloned session.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- Explicit history inheritance now rejects branches with no conversation messages before creating a cloned session or opening a pane.
|
|
23
|
+
- Expanded `zellij_open_terminal` prompt guidance so agents recognize requests to start another Pi session and prefer the dedicated `zellij_start_pi` interface when available.
|
|
24
|
+
- Pi launch command construction now supports quoted provider, model, and thinking options and stops option parsing before initial prompts.
|
|
25
|
+
- When zellij reports created pane or tab IDs, `pi-zellij` now shows them in success notifications for split, floating, zoxide, review, continuation, and tab commands.
|
|
26
|
+
- `/zt` now uses `zellij action new-tab -- <command>` when available instead of always simulating typed input, while keeping the previous typed-input path as a compatibility fallback.
|
|
27
|
+
- Pane highlights now clear on the next submitted input or when the pane is focused again after being elsewhere, instead of waiting for the next agent start event. Aborted runs no longer apply the done-state tint.
|
|
28
|
+
- Pane focus polling no longer writes transient zellij query timeout warnings into the Pi editor; refocus-based clearing is skipped if focus state cannot be queried reliably.
|
|
29
|
+
- Done-state pane tint is now only applied while the Pi pane is unfocused, so the editor is reset immediately instead of staying green while typing in the active pane.
|
|
16
30
|
|
|
17
31
|
### Removed
|
|
18
32
|
|
package/README.md
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# pi-zellij
|
|
2
2
|
|
|
3
|
-
Pi package with zellij-powered terminal integrations for [Pi](https://pi.dev).
|
|
3
|
+
Pi package with [zellij](https://zellij.dev)-powered terminal integrations for [Pi](https://pi.dev). Make your workflow agent driven.
|
|
4
|
+
|
|
5
|
+
## Workflow
|
|
6
|
+
|
|
7
|
+

|
|
4
8
|
|
|
5
9
|
## Why
|
|
6
10
|
|
|
7
11
|
[Pi](https://pi.dev) works well in the terminal, but pane orchestration is better handled by a terminal multiplexer. `pi-zellij` adds zellij-native split workflows for Pi.
|
|
8
12
|
|
|
9
|
-
It includes split and tab commands, generic tool launchers, settings-driven floating app shortcuts, zoxide jumps, review workflows, and split-based task handoff.
|
|
13
|
+
It includes split and tab commands, generic tool launchers, agent-facing zellij tools, settings-driven floating app shortcuts, opt-in pane highlighting for completed agent turns, zoxide jumps, review workflows, and split-based task handoff.
|
|
10
14
|
|
|
11
15
|
## Usage
|
|
12
16
|
|
|
@@ -34,6 +38,13 @@ If pi is already running, use:
|
|
|
34
38
|
- pane, tab, and floating commands must be run from inside an active zellij session
|
|
35
39
|
- `zoxide` is required for the zoxide commands
|
|
36
40
|
|
|
41
|
+
### Recommended zellij version
|
|
42
|
+
|
|
43
|
+
| zellij version | status | notes |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| `0.44.0+` | recommended | `pi-zellij` can show created pane/tab IDs in success notifications, and `/zt` can launch its initial command directly via `zellij action new-tab -- <command>` |
|
|
46
|
+
| older versions | supported with fallback | commands still work, but zellij may not expose created IDs and `/zt` may fall back to the older typed-input startup path |
|
|
47
|
+
|
|
37
48
|
## Feature overview
|
|
38
49
|
|
|
39
50
|
### Pane and tab workflows
|
|
@@ -49,6 +60,8 @@ If pi is already running, use:
|
|
|
49
60
|
|
|
50
61
|
- `pi-zellij.commands` in `settings.json`
|
|
51
62
|
- registers floating app shortcuts such as `/zh` for `hx` or `/zg` for `lazygit`
|
|
63
|
+
- `pi-zellij.paneHighlight` in `settings.json`
|
|
64
|
+
- optionally tints the current zellij pane when Pi finishes a turn and is waiting for input
|
|
52
65
|
|
|
53
66
|
### Review and handoff workflows
|
|
54
67
|
|
|
@@ -66,6 +79,7 @@ If pi is already running, use:
|
|
|
66
79
|
Extensions:
|
|
67
80
|
- `zv-split`
|
|
68
81
|
- `zv-open`
|
|
82
|
+
- `zv-highlight`
|
|
69
83
|
- `zv-zoxide`
|
|
70
84
|
- `zv-review`
|
|
71
85
|
- `zv-continue`
|
|
@@ -118,6 +132,29 @@ Examples:
|
|
|
118
132
|
|
|
119
133
|
Commands are executed via `sh -lc` in the current project directory.
|
|
120
134
|
|
|
135
|
+
### Agent-opened Pi sessions and terminals
|
|
136
|
+
|
|
137
|
+
`pi-zellij` registers two agent-facing tools:
|
|
138
|
+
|
|
139
|
+
- `zellij_start_pi` starts another interactive Pi session with an optional initial prompt and model settings.
|
|
140
|
+
- `zellij_open_terminal` opens arbitrary interactive terminal commands.
|
|
141
|
+
|
|
142
|
+
Example requests:
|
|
143
|
+
|
|
144
|
+
```text
|
|
145
|
+
start a fresh Pi agent in a right split and ask it to review the auth flow
|
|
146
|
+
continue this conversation in a lower Pi pane and focus on the failing tests
|
|
147
|
+
start Pi in a new tab using openai/gpt-4o with high thinking
|
|
148
|
+
open k9s in a new tab
|
|
149
|
+
open lazygit in a right split
|
|
150
|
+
open npm run dev below
|
|
151
|
+
open htop in a floating pane
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`zellij_start_pi` supports `tab`, `right`, and `down` placements and defaults to `tab`. It starts a fresh session by default. The agent must set `continueSession` explicitly to inherit history; pi-zellij then clones the current active conversation into a separate session instead of opening the same session file in two processes. History inheritance requires a persisted source session with conversation history. The tool accepts `prompt`, `provider`, `model`, `thinking`, and `title` options, and handles the Pi command and shell quoting internally.
|
|
155
|
+
|
|
156
|
+
`zellij_open_terminal` supports `tab`, `right`, `down`, and `floating` placements and also defaults to `tab`. Floating terminals use the same 90% by 90% pane size as configured floating commands. Use it for TUIs, log tails, dev servers, watches, and other terminal views that should remain interactive instead of being captured through the normal shell tool.
|
|
157
|
+
|
|
121
158
|
### Configured floating commands
|
|
122
159
|
|
|
123
160
|
You can register your own floating app shortcuts in Pi's main settings file under `pi-zellij.commands`.
|
|
@@ -184,6 +221,53 @@ Configured command names cannot reuse built-in Pi commands such as `/settings`,
|
|
|
184
221
|
|
|
185
222
|
If the same command exists in both global and project settings, the project setting wins. After changing settings, run `/reload` in Pi.
|
|
186
223
|
|
|
224
|
+
### Pane highlight on completion
|
|
225
|
+
|
|
226
|
+
You can optionally tint the current zellij pane when Pi finishes a turn and is waiting for input.
|
|
227
|
+
|
|
228
|
+
Supported locations:
|
|
229
|
+
- `~/.pi/agent/settings.json` for global settings
|
|
230
|
+
- `.pi/settings.json` for project-local settings
|
|
231
|
+
|
|
232
|
+
During the rename from `pi-zv` to `pi-zellij`, legacy `pi-zv.paneHighlight` is still accepted for compatibility. If both keys exist, `pi-zellij.paneHighlight` wins.
|
|
233
|
+
|
|
234
|
+
Minimal form:
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"pi-zellij": {
|
|
239
|
+
"paneHighlight": true
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
That enables a default done-state background tint. The feature is zellij-only and does nothing outside an active zellij session.
|
|
245
|
+
|
|
246
|
+
Object form:
|
|
247
|
+
|
|
248
|
+
```json
|
|
249
|
+
{
|
|
250
|
+
"pi-zellij": {
|
|
251
|
+
"paneHighlight": {
|
|
252
|
+
"enabled": true,
|
|
253
|
+
"doneBg": "#17352a",
|
|
254
|
+
"doneFg": "#e7fff0",
|
|
255
|
+
"workingBg": "#2f2415"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Supported keys:
|
|
262
|
+
- `enabled`
|
|
263
|
+
- set to `false` to disable the feature
|
|
264
|
+
- `doneBg`, `doneFg`
|
|
265
|
+
- pane colors to apply after `agent_end` when the pane is not currently focused
|
|
266
|
+
- `workingBg`, `workingFg`
|
|
267
|
+
- optional pane colors to apply while Pi is working; if omitted, `pi-zellij` resets the pane to its default colors when the next input is submitted or when the pane is focused again after being elsewhere
|
|
268
|
+
|
|
269
|
+
When enabled, `pi-zellij` resets the pane color on session start, session switch, the next submitted input, pane refocus when zellij focus state is available, and session shutdown so completed-turn highlights do not linger across sessions. If the pane is already focused when a turn completes, the done-state tint is skipped so the Pi editor does not stay tinted while you type. Aborted runs do not apply the done-state tint. After changing these settings, run `/reload` in Pi.
|
|
270
|
+
|
|
187
271
|
### Zoxide jump commands
|
|
188
272
|
|
|
189
273
|
- `/zz <query>`
|
package/extensions/git-core.ts
CHANGED
package/extensions/index.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import zvSplitExtension from "./zv-split.ts";
|
|
3
3
|
import zvZoxideExtension from "./zv-zoxide.ts";
|
|
4
4
|
import zvReviewExtension from "./zv-review.ts";
|
|
5
5
|
import zvContinueExtension from "./zv-continue.ts";
|
|
6
6
|
import zvOpenExtension from "./zv-open.ts";
|
|
7
|
+
import zvHighlightExtension from "./zv-highlight.ts";
|
|
7
8
|
|
|
8
9
|
export default function piZellijExtensionBundle(pi: ExtensionAPI) {
|
|
9
10
|
zvSplitExtension(pi);
|
|
@@ -11,4 +12,5 @@ export default function piZellijExtensionBundle(pi: ExtensionAPI) {
|
|
|
11
12
|
zvReviewExtension(pi);
|
|
12
13
|
zvContinueExtension(pi);
|
|
13
14
|
zvOpenExtension(pi);
|
|
15
|
+
zvHighlightExtension(pi);
|
|
14
16
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { SessionManager, type ExtensionAPI, type ExtensionCommandContext } from "@
|
|
4
|
+
import { SessionManager, type ExtensionAPI, type ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
5
5
|
import {
|
|
6
6
|
buildPiCommand,
|
|
7
|
+
formatPaneSuccessMessage,
|
|
7
8
|
openCommandInNewSplit,
|
|
9
|
+
type PaneOpenResult,
|
|
8
10
|
type SplitDirection,
|
|
9
11
|
} from "./zv-core.ts";
|
|
10
12
|
import {
|
|
@@ -388,7 +390,7 @@ async function openContinueSplit(
|
|
|
388
390
|
ctx: ExtensionCommandContext,
|
|
389
391
|
direction: SplitDirection,
|
|
390
392
|
request: ContinueRequest,
|
|
391
|
-
): Promise<
|
|
393
|
+
): Promise<PaneOpenResult> {
|
|
392
394
|
const handoffTarget = await resolveHandoffTarget(pi, ctx, request);
|
|
393
395
|
if (!handoffTarget.ok) {
|
|
394
396
|
return handoffTarget;
|
|
@@ -422,7 +424,7 @@ function registerContinueCommand(
|
|
|
422
424
|
|
|
423
425
|
const result = await openContinueSplit(pi, ctx, direction, parsed.request);
|
|
424
426
|
if (result.ok) {
|
|
425
|
-
ctx.ui.notify(successMessage, "info");
|
|
427
|
+
ctx.ui.notify(formatPaneSuccessMessage(successMessage, result.paneId), "info");
|
|
426
428
|
} else {
|
|
427
429
|
ctx.ui.notify(`continuation split failed: ${result.error}`, "error");
|
|
428
430
|
}
|
package/extensions/zv-core.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
|
|
3
3
|
const ZELLIJ_TIMEOUT_MS = 5000;
|
|
4
4
|
|
|
5
5
|
export type SplitDirection = "right" | "down";
|
|
6
|
+
export type PiThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
7
|
+
export type PaneOpenResult = { ok: true; paneId?: string } | { ok: false; error: string };
|
|
8
|
+
export type TabOpenResult = { ok: true; tabId?: string } | { ok: false; error: string };
|
|
9
|
+
|
|
10
|
+
export interface PiCommandOptions {
|
|
11
|
+
sessionFile?: string;
|
|
12
|
+
prompt?: string;
|
|
13
|
+
provider?: string;
|
|
14
|
+
model?: string;
|
|
15
|
+
thinking?: PiThinkingLevel;
|
|
16
|
+
}
|
|
6
17
|
|
|
7
18
|
interface ZellijExecResult {
|
|
8
19
|
ok: boolean;
|
|
@@ -11,22 +22,70 @@ interface ZellijExecResult {
|
|
|
11
22
|
error?: string;
|
|
12
23
|
}
|
|
13
24
|
|
|
14
|
-
function isInsideZellijSession(): boolean {
|
|
25
|
+
export function isInsideZellijSession(): boolean {
|
|
15
26
|
return Boolean(process.env.ZELLIJ || process.env.ZELLIJ_SESSION_NAME || process.env.ZELLIJ_PANE_ID);
|
|
16
27
|
}
|
|
17
28
|
|
|
29
|
+
function getLastNonEmptyLine(value: string): string | undefined {
|
|
30
|
+
const lines = value
|
|
31
|
+
.split(/\r?\n/)
|
|
32
|
+
.map((line) => line.trim())
|
|
33
|
+
.filter((line) => line.length > 0);
|
|
34
|
+
return lines.length > 0 ? lines[lines.length - 1] : undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function normalizePaneId(value: string): string | undefined {
|
|
38
|
+
const trimmed = value.trim();
|
|
39
|
+
if (!trimmed) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
if (/^(?:terminal|plugin)_\d+$/.test(trimmed)) {
|
|
43
|
+
return trimmed;
|
|
44
|
+
}
|
|
45
|
+
if (/^\d+$/.test(trimmed)) {
|
|
46
|
+
return `terminal_${trimmed}`;
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function getCreatedPaneId(stdout: string): string | undefined {
|
|
52
|
+
return normalizePaneId(getLastNonEmptyLine(stdout) ?? "");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function getCreatedTabId(stdout: string): string | undefined {
|
|
56
|
+
const candidate = getLastNonEmptyLine(stdout);
|
|
57
|
+
return candidate && /^\d+$/.test(candidate) ? candidate : undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function formatPaneSuccessMessage(message: string, paneId?: string): string {
|
|
61
|
+
return paneId ? `${message} (${paneId})` : message;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function formatTabSuccessMessage(message: string, tabId?: string): string {
|
|
65
|
+
return tabId ? `${message} (tab ${tabId})` : message;
|
|
66
|
+
}
|
|
67
|
+
|
|
18
68
|
export function shellEscape(value: string): string {
|
|
19
69
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
20
70
|
}
|
|
21
71
|
|
|
22
|
-
export function buildPiCommand(cwd: string, options?:
|
|
72
|
+
export function buildPiCommand(cwd: string, options?: PiCommandOptions): string {
|
|
23
73
|
const commandParts = ["cd", shellEscape(cwd), "&&", "exec", "pi"];
|
|
24
74
|
if (options?.sessionFile) {
|
|
25
75
|
commandParts.push("--session", shellEscape(options.sessionFile));
|
|
26
76
|
}
|
|
77
|
+
if (options?.provider) {
|
|
78
|
+
commandParts.push("--provider", shellEscape(options.provider));
|
|
79
|
+
}
|
|
80
|
+
if (options?.model) {
|
|
81
|
+
commandParts.push("--model", shellEscape(options.model));
|
|
82
|
+
}
|
|
83
|
+
if (options?.thinking) {
|
|
84
|
+
commandParts.push("--thinking", shellEscape(options.thinking));
|
|
85
|
+
}
|
|
27
86
|
const prompt = options?.prompt?.trim();
|
|
28
87
|
if (prompt) {
|
|
29
|
-
commandParts.push(shellEscape(prompt));
|
|
88
|
+
commandParts.push("--", shellEscape(prompt));
|
|
30
89
|
}
|
|
31
90
|
return commandParts.join(" ");
|
|
32
91
|
}
|
|
@@ -60,28 +119,110 @@ async function execZellij(pi: ExtensionAPI, args: string[]): Promise<ZellijExecR
|
|
|
60
119
|
};
|
|
61
120
|
}
|
|
62
121
|
|
|
122
|
+
function getCurrentPaneTargetArgs(): string[] {
|
|
123
|
+
return process.env.ZELLIJ_PANE_ID ? ["-p", process.env.ZELLIJ_PANE_ID] : [];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export async function resetCurrentPaneColor(pi: ExtensionAPI): Promise<{ ok: true } | { ok: false; error: string }> {
|
|
127
|
+
if (!isInsideZellijSession()) {
|
|
128
|
+
return { ok: false, error: "This command must be run from inside an active zellij session" };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const result = await execZellij(pi, ["action", "set-pane-color", ...getCurrentPaneTargetArgs(), "--reset"]);
|
|
132
|
+
if (!result.ok) {
|
|
133
|
+
return { ok: false, error: result.error || "Failed to reset zellij pane color" };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return { ok: true };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export async function setCurrentPaneColor(
|
|
140
|
+
pi: ExtensionAPI,
|
|
141
|
+
options: { bg?: string; fg?: string },
|
|
142
|
+
): Promise<{ ok: true } | { ok: false; error: string }> {
|
|
143
|
+
if (!isInsideZellijSession()) {
|
|
144
|
+
return { ok: false, error: "This command must be run from inside an active zellij session" };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const paneTargetArgs = getCurrentPaneTargetArgs();
|
|
148
|
+
const args = ["action", "set-pane-color", ...paneTargetArgs];
|
|
149
|
+
if (options.bg) {
|
|
150
|
+
args.push("--bg", options.bg);
|
|
151
|
+
}
|
|
152
|
+
if (options.fg) {
|
|
153
|
+
args.push("--fg", options.fg);
|
|
154
|
+
}
|
|
155
|
+
if (args.length === 2 + paneTargetArgs.length) {
|
|
156
|
+
return resetCurrentPaneColor(pi);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const result = await execZellij(pi, args);
|
|
160
|
+
if (!result.ok) {
|
|
161
|
+
return { ok: false, error: result.error || "Failed to set zellij pane color" };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return { ok: true };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function buildNewTabArgs(cwd: string, options?: { name?: string }): string[] {
|
|
168
|
+
const args = ["action", "new-tab", "--cwd", cwd];
|
|
169
|
+
if (options?.name) {
|
|
170
|
+
args.push("--name", options.name);
|
|
171
|
+
}
|
|
172
|
+
return args;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async function openCommandInNewTabLegacy(
|
|
176
|
+
pi: ExtensionAPI,
|
|
177
|
+
cwd: string,
|
|
178
|
+
command: string,
|
|
179
|
+
options?: { name?: string },
|
|
180
|
+
): Promise<TabOpenResult> {
|
|
181
|
+
const newTabResult = await execZellij(pi, buildNewTabArgs(cwd, options));
|
|
182
|
+
if (!newTabResult.ok) {
|
|
183
|
+
return { ok: false, error: newTabResult.error || "Failed to open a new zellij tab" };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const writeCommandResult = await execZellij(pi, ["action", "write-chars", command]);
|
|
187
|
+
if (!writeCommandResult.ok) {
|
|
188
|
+
return { ok: false, error: writeCommandResult.error || "Failed to write command to new zellij tab" };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const submitCommandResult = await execZellij(pi, ["action", "write", "10"]);
|
|
192
|
+
if (!submitCommandResult.ok) {
|
|
193
|
+
return { ok: false, error: submitCommandResult.error || "Failed to start command in new zellij tab" };
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return { ok: true, tabId: getCreatedTabId(newTabResult.stdout) };
|
|
197
|
+
}
|
|
198
|
+
|
|
63
199
|
export async function openCommandInNewSplit(
|
|
64
200
|
pi: ExtensionAPI,
|
|
65
201
|
direction: SplitDirection,
|
|
66
202
|
command: string,
|
|
67
|
-
|
|
203
|
+
options?: { name?: string },
|
|
204
|
+
): Promise<PaneOpenResult> {
|
|
68
205
|
if (!isInsideZellijSession()) {
|
|
69
206
|
return { ok: false, error: "This command must be run from inside an active zellij session" };
|
|
70
207
|
}
|
|
71
208
|
|
|
72
|
-
const
|
|
209
|
+
const args = ["run", "--direction", direction];
|
|
210
|
+
if (options?.name) args.push("--name", options.name);
|
|
211
|
+
args.push("--", "sh", "-lc", command);
|
|
212
|
+
|
|
213
|
+
const result = await execZellij(pi, args);
|
|
73
214
|
if (!result.ok) {
|
|
74
215
|
return { ok: false, error: result.error || "Failed to open a new zellij pane" };
|
|
75
216
|
}
|
|
76
217
|
|
|
77
|
-
return { ok: true };
|
|
218
|
+
return { ok: true, paneId: getCreatedPaneId(result.stdout) };
|
|
78
219
|
}
|
|
79
220
|
|
|
80
221
|
export async function openCommandInFloatingPane(
|
|
81
222
|
pi: ExtensionAPI,
|
|
82
223
|
command: string,
|
|
83
224
|
options?: { name?: string; width?: string; height?: string; x?: string; y?: string },
|
|
84
|
-
): Promise<
|
|
225
|
+
): Promise<PaneOpenResult> {
|
|
85
226
|
if (!isInsideZellijSession()) {
|
|
86
227
|
return { ok: false, error: "This command must be run from inside an active zellij session" };
|
|
87
228
|
}
|
|
@@ -99,7 +240,7 @@ export async function openCommandInFloatingPane(
|
|
|
99
240
|
return { ok: false, error: result.error || "Failed to open a new floating zellij pane" };
|
|
100
241
|
}
|
|
101
242
|
|
|
102
|
-
return { ok: true };
|
|
243
|
+
return { ok: true, paneId: getCreatedPaneId(result.stdout) };
|
|
103
244
|
}
|
|
104
245
|
|
|
105
246
|
export async function openCommandInNewTab(
|
|
@@ -107,30 +248,15 @@ export async function openCommandInNewTab(
|
|
|
107
248
|
cwd: string,
|
|
108
249
|
command: string,
|
|
109
250
|
options?: { name?: string },
|
|
110
|
-
): Promise<
|
|
251
|
+
): Promise<TabOpenResult> {
|
|
111
252
|
if (!isInsideZellijSession()) {
|
|
112
253
|
return { ok: false, error: "This command must be run from inside an active zellij session" };
|
|
113
254
|
}
|
|
114
255
|
|
|
115
|
-
const
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const newTabResult = await execZellij(pi, newTabArgs);
|
|
121
|
-
if (!newTabResult.ok) {
|
|
122
|
-
return { ok: false, error: newTabResult.error || "Failed to open a new zellij tab" };
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const writeCommandResult = await execZellij(pi, ["action", "write-chars", command]);
|
|
126
|
-
if (!writeCommandResult.ok) {
|
|
127
|
-
return { ok: false, error: writeCommandResult.error || "Failed to write command to new zellij tab" };
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const submitCommandResult = await execZellij(pi, ["action", "write", "10"]);
|
|
131
|
-
if (!submitCommandResult.ok) {
|
|
132
|
-
return { ok: false, error: submitCommandResult.error || "Failed to start command in new zellij tab" };
|
|
256
|
+
const newTabResult = await execZellij(pi, [...buildNewTabArgs(cwd, options), "--", "sh", "-lc", command]);
|
|
257
|
+
if (newTabResult.ok) {
|
|
258
|
+
return { ok: true, tabId: getCreatedTabId(newTabResult.stdout) };
|
|
133
259
|
}
|
|
134
260
|
|
|
135
|
-
return
|
|
261
|
+
return openCommandInNewTabLegacy(pi, cwd, command, options);
|
|
136
262
|
}
|