diff --git a/README.md b/README.md index 60558a9..a8fdeac 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,7 @@ editor_command = "vi {file}" [worktree] relative_worktree_path = "./.worktrees" +split_regex = "," [env.override] ZELLIJ_SESSION_NAME = "" @@ -188,8 +189,9 @@ paste = "CTRL+SHIFT+V" - `Alt+Shift+h` / `Alt+Shift+l`: previous / next tab - `Alt+t`: open the font selector - `Alt+s`: open the active pane scrollback in `$EDITOR` -- `Alt+w`: edit a worktree name, then run `git worktree add /` - from the previously focused pane's working directory +- `Alt+w`: edit one or more worktree names, split by `worktree.split_regex`, then run + `git worktree add /` for each name from the previously focused + pane's working directory - `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 - Once committed, input typed or pasted into any synced pane is mirrored to the other synced panes diff --git a/config.example.toml b/config.example.toml index a3875f6..98b8f4c 100644 --- a/config.example.toml +++ b/config.example.toml @@ -21,6 +21,7 @@ editor_command = "vi {file}" [worktree] relative_worktree_path = "./.worktrees" +split_regex = "," [env.override] ZELLIJ_SESSION_NAME = "" diff --git a/src/main/java/com/gregor/jprototerm/AppConfig.java b/src/main/java/com/gregor/jprototerm/AppConfig.java index 876c875..882ec5e 100644 --- a/src/main/java/com/gregor/jprototerm/AppConfig.java +++ b/src/main/java/com/gregor/jprototerm/AppConfig.java @@ -30,6 +30,7 @@ public record AppConfig( boolean kittyGraphics, String scrollbackEditorCommand, String worktreeRelativePath, + String worktreeSplitRegex, String closeSignal, Map envOverride, Map keybindings @@ -77,6 +78,7 @@ public record AppConfig( booleanValue(document, "kitty_graphics.enabled", defaults.kittyGraphics), stringValue(document, "scrollback.editor_command", defaults.scrollbackEditorCommand), stringValue(document, "worktree.relative_worktree_path", defaults.worktreeRelativePath), + stringValue(document, "worktree.split_regex", defaults.worktreeSplitRegex), closeSignalValue(document, defaults.closeSignal), envOverride(document, defaults.envOverride), keybindings(document, defaults) @@ -100,6 +102,7 @@ public record AppConfig( true, defaultScrollbackEditorCommand(), "./.worktrees", + ",", "SIGTERM", Map.of(), Map.ofEntries( @@ -138,6 +141,7 @@ public record AppConfig( kittyGraphics, scrollbackEditorCommand, worktreeRelativePath, + worktreeSplitRegex, closeSignal, envOverride, keybindings @@ -241,7 +245,8 @@ public record AppConfig( builder.append("[scrollback]\n"); builder.append("editor_command = ").append(quoted(scrollbackEditorCommand)).append("\n\n"); builder.append("[worktree]\n"); - builder.append("relative_worktree_path = ").append(quoted(worktreeRelativePath)).append("\n\n"); + builder.append("relative_worktree_path = ").append(quoted(worktreeRelativePath)).append('\n'); + builder.append("split_regex = ").append(quoted(worktreeSplitRegex)).append("\n\n"); builder.append("[env.override]\n"); for (Map.Entry entry : envOverride.entrySet()) { builder.append(entry.getKey()).append(" = ").append(quoted(entry.getValue())).append('\n'); diff --git a/src/main/java/com/gregor/jprototerm/TerminalWindow.java b/src/main/java/com/gregor/jprototerm/TerminalWindow.java index 0601b5a..678cab7 100644 --- a/src/main/java/com/gregor/jprototerm/TerminalWindow.java +++ b/src/main/java/com/gregor/jprototerm/TerminalWindow.java @@ -313,14 +313,32 @@ final class TerminalWindow { if (relativePath == null || relativePath.isBlank()) { relativePath = "./.worktrees"; } + String splitRegex = config.worktreeSplitRegex(); + if (splitRegex == null || splitRegex.isBlank()) { + splitRegex = ","; + } return editorCommand(file) + "; editor_status=$?" - + "; name=$(cat " + quotedFile + ")" - + "; if [ \"$editor_status\" -eq 0 ] && [ -n \"$name\" ]; then" + + "; git_status=$editor_status" + + "; if [ \"$editor_status\" -eq 0 ]; then" + + " if names_file=$(mktemp); then" + + " if awk -v re=" + shellQuote(splitRegex) + + " '{ text = text $0 \"\\n\" }" + + " END { n = split(text, names, re); for (i = 1; i <= n; i++)" + + " { name = names[i]; sub(/^[[:space:]]+/, \"\", name);" + + " sub(/[[:space:]]+$/, \"\", name); if (name != \"\") print name; } }'" + + " " + quotedFile + " > \"$names_file\"; then" + + " git_status=0" + + "; while IFS= read -r name; do" + " git worktree add " + shellQuote(relativePath) + "/\"$name\"" - + "; git_status=$?" - + "; else git_status=$editor_status" + + " || { git_status=$?; break; }" + + "; done < \"$names_file\"" + + "; else git_status=$?" + + "; fi" + + "; rm -f \"$names_file\"" + + "; else git_status=$?" + + "; fi" + "; fi" + "; rm -f " + quotedFile + "; exit \"$git_status\"";