post create pane sync

This commit is contained in:
2026-06-19 16:44:16 +02:00
parent 5a50ce62f3
commit cff4fba81c
5 changed files with 29 additions and 1 deletions

View File

@@ -155,6 +155,7 @@ split_regex = ","
# One of: "none", "cd", "create_panes", "create_panes_floating". # One of: "none", "cd", "create_panes", "create_panes_floating".
post_create_action = "none" post_create_action = "none"
commands = [] commands = []
sync_panes = false
[env.override] [env.override]
ZELLIJ_SESSION_NAME = "" ZELLIJ_SESSION_NAME = ""
@@ -199,6 +200,7 @@ paste = "CTRL+SHIFT+V"
`create_panes`, or create one floating pane per worktree with `create_panes_floating`. `create_panes`, or create one floating pane per worktree with `create_panes_floating`.
`worktree.commands`, for example `["npm install", "git status"]`, can run commands in created `worktree.commands`, for example `["npm install", "git status"]`, can run commands in created
panes; commands are assigned in order and repeat when fewer commands than panes are created. panes; commands are assigned in order and repeat when fewer commands than panes are created.
`worktree.sync_panes = true` syncs those created panes after the configured commands are sent.
- `Alt+y`: enter pane-sync selection mode, commit the selection, or stop an active pane sync - `Alt+y`: enter pane-sync selection mode, commit the selection, or stop an active pane sync
- `Space`: toggle the focused pane in the sync set while pane-sync selection mode is active - `Space`: toggle the focused pane in the sync set while pane-sync selection mode is active
- Once committed, input typed or pasted into any synced pane is mirrored to the other synced panes - Once committed, input typed or pasted into any synced pane is mirrored to the other synced panes

View File

@@ -25,6 +25,7 @@ split_regex = ","
# One of: "none", "cd", "create_panes", "create_panes_floating". # One of: "none", "cd", "create_panes", "create_panes_floating".
post_create_action = "none" post_create_action = "none"
commands = [] commands = []
sync_panes = false
[env.override] [env.override]
ZELLIJ_SESSION_NAME = "" ZELLIJ_SESSION_NAME = ""

View File

@@ -33,6 +33,7 @@ public record AppConfig(
String worktreeSplitRegex, String worktreeSplitRegex,
String worktreePostCreateAction, String worktreePostCreateAction,
List<String> worktreeCommands, List<String> worktreeCommands,
boolean worktreeSyncPanes,
String closeSignal, String closeSignal,
Map<String, String> envOverride, Map<String, String> envOverride,
Map<String, KeyBinding> keybindings Map<String, KeyBinding> keybindings
@@ -83,6 +84,7 @@ public record AppConfig(
stringValue(document, "worktree.split_regex", defaults.worktreeSplitRegex), stringValue(document, "worktree.split_regex", defaults.worktreeSplitRegex),
stringValue(document, "worktree.post_create_action", defaults.worktreePostCreateAction), stringValue(document, "worktree.post_create_action", defaults.worktreePostCreateAction),
stringListValue(document, "worktree.commands", defaults.worktreeCommands), stringListValue(document, "worktree.commands", defaults.worktreeCommands),
booleanValue(document, "worktree.sync_panes", defaults.worktreeSyncPanes),
closeSignalValue(document, defaults.closeSignal), closeSignalValue(document, defaults.closeSignal),
envOverride(document, defaults.envOverride), envOverride(document, defaults.envOverride),
keybindings(document, defaults) keybindings(document, defaults)
@@ -109,6 +111,7 @@ public record AppConfig(
",", ",",
"none", "none",
List.of(), List.of(),
false,
"SIGTERM", "SIGTERM",
Map.of(), Map.of(),
Map.ofEntries( Map.ofEntries(
@@ -150,6 +153,7 @@ public record AppConfig(
worktreeSplitRegex, worktreeSplitRegex,
worktreePostCreateAction, worktreePostCreateAction,
worktreeCommands, worktreeCommands,
worktreeSyncPanes,
closeSignal, closeSignal,
envOverride, envOverride,
keybindings keybindings
@@ -256,7 +260,8 @@ public record AppConfig(
builder.append("relative_worktree_path = ").append(quoted(worktreeRelativePath)).append('\n'); builder.append("relative_worktree_path = ").append(quoted(worktreeRelativePath)).append('\n');
builder.append("split_regex = ").append(quoted(worktreeSplitRegex)).append('\n'); builder.append("split_regex = ").append(quoted(worktreeSplitRegex)).append('\n');
builder.append("post_create_action = ").append(quoted(worktreePostCreateAction)).append('\n'); builder.append("post_create_action = ").append(quoted(worktreePostCreateAction)).append('\n');
builder.append("commands = ").append(quotedList(worktreeCommands)).append("\n\n"); builder.append("commands = ").append(quotedList(worktreeCommands)).append('\n');
builder.append("sync_panes = ").append(worktreeSyncPanes).append("\n\n");
builder.append("[env.override]\n"); builder.append("[env.override]\n");
for (Map.Entry<String, String> entry : envOverride.entrySet()) { for (Map.Entry<String, String> entry : envOverride.entrySet()) {
builder.append(entry.getKey()).append(" = ").append(quoted(entry.getValue())).append('\n'); builder.append(entry.getKey()).append(" = ").append(quoted(entry.getValue())).append('\n');

View File

@@ -188,6 +188,19 @@ public final class Compositor {
.toList(); .toList();
} }
public void syncPanes(List<TerminalPane> panes) {
paneSyncSelectMode = false;
paneSyncSelection.clear();
paneSyncPanes.clear();
for (TerminalPane pane : panes) {
if (pane != null) {
paneSyncPanes.add(pane);
}
}
prunePaneSyncState();
layoutVersion++;
}
public void toggleFloating() { public void toggleFloating() {
mutateCurrentTab(() -> currentTab().toggleFloating()); mutateCurrentTab(() -> currentTab().toggleFloating());
} }

View File

@@ -385,10 +385,14 @@ final class TerminalWindow {
private void createWorktreePanes(List<String> worktreePaths, boolean floating) { private void createWorktreePanes(List<String> worktreePaths, boolean floating) {
List<String> commands = config.worktreeCommands(); List<String> commands = config.worktreeCommands();
List<TerminalPane> createdPanes = new ArrayList<>();
for (int i = 0; i < worktreePaths.size(); i++) { for (int i = 0; i < worktreePaths.size(); i++) {
TerminalPane pane = floating TerminalPane pane = floating
? compositor.createFloatingPaneInDirectory(worktreePaths.get(i)) ? compositor.createFloatingPaneInDirectory(worktreePaths.get(i))
: compositor.createTiledPane(worktreePaths.get(i)); : compositor.createTiledPane(worktreePaths.get(i));
if (pane != null) {
createdPanes.add(pane);
}
if (pane != null && !commands.isEmpty()) { if (pane != null && !commands.isEmpty()) {
String command = commands.get(i % commands.size()); String command = commands.get(i % commands.size());
if (command != null && !command.isBlank()) { if (command != null && !command.isBlank()) {
@@ -396,6 +400,9 @@ final class TerminalWindow {
} }
} }
} }
if (config.worktreeSyncPanes() && !createdPanes.isEmpty()) {
compositor.syncPanes(createdPanes);
}
} }
private List<String> readCreatedWorktreePaths(Path createdFile) { private List<String> readCreatedWorktreePaths(Path createdFile) {