Migrate terminal Shift+Return bindings
Update existing terminal configs to encode Shift+Return as CSI-u so Codex and other TUIs can distinguish it from Return without tmux seeing it as Alt+Return. Also ensures Alt+Shift+Return CSI-u bindings remain present for tmux horizontal splits across Kitty, Ghostty, and Foot.
This commit is contained in:
@@ -0,0 +1,172 @@
|
|||||||
|
echo "Make Shift+Enter distinguishable for terminals and Codex"
|
||||||
|
|
||||||
|
alacritty_config="$HOME/.config/alacritty/alacritty.toml"
|
||||||
|
foot_config="$HOME/.config/foot/foot.ini"
|
||||||
|
ghostty_config="$HOME/.config/ghostty/config"
|
||||||
|
kitty_config="$HOME/.config/kitty/kitty.conf"
|
||||||
|
|
||||||
|
ensure_alacritty_shift_return() {
|
||||||
|
local config="$1"
|
||||||
|
|
||||||
|
[[ -f $config ]] || return 0
|
||||||
|
|
||||||
|
if grep -q 'key = "Return", mods = "Shift", chars = "\\u001B\\r"' "$config"; then
|
||||||
|
sed -i 's/{ key = "Return", mods = "Shift", chars = "\\u001B\\r" }/{ key = "Return", mods = "Shift", chars = "\\u001B[13;2u" }/' "$config"
|
||||||
|
elif ! grep -q 'key = "Return", mods = "Shift", chars = "\\u001B\[13;2u"' "$config"; then
|
||||||
|
if grep -qxF '{ key = "Return", mods = "Alt|Shift", chars = "\u001B[13;4u" }' "$config"; then
|
||||||
|
sed -i '/^{ key = "Return", mods = "Alt|Shift", chars = "\\u001B\[13;4u" }$/i # Send Shift+Return as CSI-u so TUIs can distinguish it from Return without treating it as Alt+Return.\n{ key = "Return", mods = "Shift", chars = "\\u001B[13;2u" },' "$config"
|
||||||
|
elif grep -qxF '{ key = "Insert", mods = "Control", action = "Copy" },' "$config"; then
|
||||||
|
sed -i '/^{ key = "Insert", mods = "Control", action = "Copy" },$/a # Send Shift+Return as CSI-u so TUIs can distinguish it from Return without treating it as Alt+Return.\n{ key = "Return", mods = "Shift", chars = "\\u001B[13;2u" },' "$config"
|
||||||
|
else
|
||||||
|
printf '\n# Send Shift+Return as CSI-u so TUIs can distinguish it from Return without treating it as Alt+Return.\n{ key = "Return", mods = "Shift", chars = "\\u001B[13;2u" }\n' >>"$config"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_ghostty_binding() {
|
||||||
|
local config="$1"
|
||||||
|
local key="$2"
|
||||||
|
local binding="$3"
|
||||||
|
local comment="$4"
|
||||||
|
local key_regex
|
||||||
|
|
||||||
|
[[ -f $config ]] || return 0
|
||||||
|
|
||||||
|
key_regex=$(printf '%s\n' "$key" | sed 's/[][\\.^$*+?{}|()\/]/\\&/g')
|
||||||
|
|
||||||
|
if grep -Eq "^keybind = $key_regex=.*13;[24]u" "$config"; then
|
||||||
|
sed -i "s/^keybind = $key_regex=.*/keybind = $key=$binding/" "$config"
|
||||||
|
elif ! grep -qF "keybind = $key=" "$config"; then
|
||||||
|
if grep -qxF 'keybind = control+insert=copy_to_clipboard' "$config"; then
|
||||||
|
sed -i "/^keybind = control+insert=copy_to_clipboard$/a $comment\nkeybind = $key=$binding" "$config"
|
||||||
|
else
|
||||||
|
printf '\n%s\nkeybind = %s=%s\n' "$comment" "$key" "$binding" >>"$config"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_kitty_binding() {
|
||||||
|
local config="$1"
|
||||||
|
local key="$2"
|
||||||
|
local binding="$3"
|
||||||
|
local comment="$4"
|
||||||
|
local key_regex
|
||||||
|
local tmp
|
||||||
|
|
||||||
|
[[ -f $config ]] || return 0
|
||||||
|
|
||||||
|
key_regex=$(printf '%s\n' "$key" | sed 's/[][\\.^$*+?{}|()\/]/\\&/g')
|
||||||
|
|
||||||
|
if grep -Eq "^map[[:space:]]+$key_regex[[:space:]].*13;[24]u" "$config"; then
|
||||||
|
tmp=$(mktemp)
|
||||||
|
KEY="$key" BINDING="$binding" awk '
|
||||||
|
BEGIN {
|
||||||
|
key = ENVIRON["KEY"]
|
||||||
|
binding = ENVIRON["BINDING"]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
split($0, parts, /[[:space:]]+/)
|
||||||
|
if (parts[1] == "map" && parts[2] == key && $0 ~ /13;[24]u/) {
|
||||||
|
$0 = "map " key " " binding
|
||||||
|
}
|
||||||
|
print
|
||||||
|
}
|
||||||
|
' "$config" >"$tmp" && mv "$tmp" "$config"
|
||||||
|
elif ! grep -Eq "^map[[:space:]]+$key_regex[[:space:]]" "$config"; then
|
||||||
|
if grep -qxF 'map shift+insert paste_from_clipboard' "$config"; then
|
||||||
|
tmp=$(mktemp)
|
||||||
|
KEY="$key" BINDING="$binding" COMMENT="$comment" awk '
|
||||||
|
BEGIN {
|
||||||
|
key = ENVIRON["KEY"]
|
||||||
|
binding = ENVIRON["BINDING"]
|
||||||
|
comment = ENVIRON["COMMENT"]
|
||||||
|
}
|
||||||
|
{ print }
|
||||||
|
!inserted && $0 == "map shift+insert paste_from_clipboard" {
|
||||||
|
print comment
|
||||||
|
print "map " key " " binding
|
||||||
|
inserted = 1
|
||||||
|
}
|
||||||
|
' "$config" >"$tmp" && mv "$tmp" "$config"
|
||||||
|
else
|
||||||
|
printf '\n%s\nmap %s %s\n' "$comment" "$key" "$binding" >>"$config"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_foot_text_binding() {
|
||||||
|
local config="$1"
|
||||||
|
local sequence="$2"
|
||||||
|
local binding="$3"
|
||||||
|
local comment="$4"
|
||||||
|
local tmp
|
||||||
|
|
||||||
|
[[ -f $config ]] || return 0
|
||||||
|
|
||||||
|
if grep -qF "$sequence=" "$config"; then
|
||||||
|
tmp=$(mktemp)
|
||||||
|
SEQUENCE="$sequence" BINDING="$binding" awk '
|
||||||
|
BEGIN {
|
||||||
|
sequence = ENVIRON["SEQUENCE"]
|
||||||
|
binding = ENVIRON["BINDING"]
|
||||||
|
}
|
||||||
|
index($0, sequence "=") == 1 { $0 = sequence "=" binding }
|
||||||
|
{ print }
|
||||||
|
' "$config" >"$tmp" && mv "$tmp" "$config"
|
||||||
|
elif grep -qxF '[text-bindings]' "$config"; then
|
||||||
|
tmp=$(mktemp)
|
||||||
|
SEQUENCE="$sequence" BINDING="$binding" COMMENT="$comment" awk '
|
||||||
|
BEGIN {
|
||||||
|
sequence = ENVIRON["SEQUENCE"]
|
||||||
|
binding = ENVIRON["BINDING"]
|
||||||
|
comment = ENVIRON["COMMENT"]
|
||||||
|
}
|
||||||
|
{ print }
|
||||||
|
!inserted && $0 == "[text-bindings]" {
|
||||||
|
print comment
|
||||||
|
print sequence "=" binding
|
||||||
|
inserted = 1
|
||||||
|
}
|
||||||
|
' "$config" >"$tmp" && mv "$tmp" "$config"
|
||||||
|
else
|
||||||
|
printf '\n[text-bindings]\n%s\n%s=%s\n' "$comment" "$sequence" "$binding" >>"$config"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_alacritty_shift_return "$alacritty_config"
|
||||||
|
|
||||||
|
ensure_ghostty_binding \
|
||||||
|
"$ghostty_config" \
|
||||||
|
"shift+enter" \
|
||||||
|
"csi:13;2u" \
|
||||||
|
"# Send Shift+Enter as CSI-u so TUIs can distinguish it from Enter."
|
||||||
|
|
||||||
|
ensure_ghostty_binding \
|
||||||
|
"$ghostty_config" \
|
||||||
|
"alt+shift+enter" \
|
||||||
|
"csi:13;4u" \
|
||||||
|
"# Legacy encoding sends Alt+Shift+Enter the same as Alt+Enter; send CSI-u so tmux can match M-S-Enter."
|
||||||
|
|
||||||
|
ensure_kitty_binding \
|
||||||
|
"$kitty_config" \
|
||||||
|
"shift+enter" \
|
||||||
|
"send_text all \\e[13;2u" \
|
||||||
|
"# Send Shift+Enter as CSI-u so TUIs can distinguish it from Enter."
|
||||||
|
|
||||||
|
ensure_kitty_binding \
|
||||||
|
"$kitty_config" \
|
||||||
|
"alt+shift+enter" \
|
||||||
|
"send_text all \\e[13;4u" \
|
||||||
|
"# Kitty legacy encoding sends Alt+Shift+Enter the same as Alt+Enter; send CSI-u so tmux can match M-S-Enter."
|
||||||
|
|
||||||
|
ensure_foot_text_binding \
|
||||||
|
"$foot_config" \
|
||||||
|
"\\x1b[13;2u" \
|
||||||
|
"Shift+Return" \
|
||||||
|
"# Send Shift+Return as CSI-u so TUIs can distinguish it from Return."
|
||||||
|
|
||||||
|
ensure_foot_text_binding \
|
||||||
|
"$foot_config" \
|
||||||
|
"\\x1b[13;4u" \
|
||||||
|
"Mod1+Shift+Return" \
|
||||||
|
"# Send Alt+Shift+Return as CSI-u so tmux can match M-S-Enter."
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source "$(dirname "${BASH_SOURCE[0]}")/base-test.sh"
|
||||||
|
|
||||||
|
migration=$(grep -rl 'Make Shift+Enter distinguishable for terminals and Codex' "$ROOT/migrations" | head -n 1 || true)
|
||||||
|
[[ -n $migration ]] || fail "terminal Shift+Enter migration exists"
|
||||||
|
|
||||||
|
TMPDIR=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$TMPDIR"' EXIT
|
||||||
|
|
||||||
|
test_home="$TMPDIR/home"
|
||||||
|
mkdir -p \
|
||||||
|
"$test_home/.config/alacritty" \
|
||||||
|
"$test_home/.config/foot" \
|
||||||
|
"$test_home/.config/ghostty" \
|
||||||
|
"$test_home/.config/kitty"
|
||||||
|
|
||||||
|
cp "$ROOT/config/alacritty/alacritty.toml" "$test_home/.config/alacritty/alacritty.toml"
|
||||||
|
sed -i 's/\\u001B\[13;2u/\\u001B\\r/' "$test_home/.config/alacritty/alacritty.toml"
|
||||||
|
|
||||||
|
cp "$ROOT/config/kitty/kitty.conf" "$test_home/.config/kitty/kitty.conf"
|
||||||
|
sed -i '/shift+enter/d' "$test_home/.config/kitty/kitty.conf"
|
||||||
|
|
||||||
|
cp "$ROOT/config/ghostty/config" "$test_home/.config/ghostty/config"
|
||||||
|
sed -i '/shift+enter/d' "$test_home/.config/ghostty/config"
|
||||||
|
|
||||||
|
cp "$ROOT/config/foot/foot.ini" "$test_home/.config/foot/foot.ini"
|
||||||
|
sed -i '/text-bindings/,$d' "$test_home/.config/foot/foot.ini"
|
||||||
|
|
||||||
|
HOME="$test_home" bash "$migration" >/dev/null
|
||||||
|
|
||||||
|
grep -qxF '{ key = "Return", mods = "Shift", chars = "\u001B[13;2u" },' "$test_home/.config/alacritty/alacritty.toml" ||
|
||||||
|
fail "migration updates Alacritty Shift+Return to CSI-u"
|
||||||
|
pass "migration updates Alacritty Shift+Return to CSI-u"
|
||||||
|
|
||||||
|
grep -qxF 'map shift+enter send_text all \e[13;2u' "$test_home/.config/kitty/kitty.conf" ||
|
||||||
|
fail "migration adds Kitty Shift+Enter CSI-u binding"
|
||||||
|
grep -qxF 'map alt+shift+enter send_text all \e[13;4u' "$test_home/.config/kitty/kitty.conf" ||
|
||||||
|
fail "migration adds Kitty Alt+Shift+Enter CSI-u binding"
|
||||||
|
pass "migration adds Kitty CSI-u bindings"
|
||||||
|
|
||||||
|
grep -qxF 'keybind = shift+enter=csi:13;2u' "$test_home/.config/ghostty/config" ||
|
||||||
|
fail "migration adds Ghostty Shift+Enter CSI-u binding"
|
||||||
|
grep -qxF 'keybind = alt+shift+enter=csi:13;4u' "$test_home/.config/ghostty/config" ||
|
||||||
|
fail "migration adds Ghostty Alt+Shift+Enter CSI-u binding"
|
||||||
|
pass "migration adds Ghostty CSI-u bindings"
|
||||||
|
|
||||||
|
grep -qxF '\x1b[13;2u=Shift+Return' "$test_home/.config/foot/foot.ini" ||
|
||||||
|
fail "migration adds Foot Shift+Return CSI-u binding"
|
||||||
|
grep -qxF '\x1b[13;4u=Mod1+Shift+Return' "$test_home/.config/foot/foot.ini" ||
|
||||||
|
fail "migration adds Foot Alt+Shift+Return CSI-u binding"
|
||||||
|
pass "migration adds Foot CSI-u bindings"
|
||||||
|
|
||||||
|
before=$(find "$test_home/.config" -type f -print0 | sort -z | xargs -0 sha256sum)
|
||||||
|
HOME="$test_home" bash "$migration" >/dev/null
|
||||||
|
after=$(find "$test_home/.config" -type f -print0 | sort -z | xargs -0 sha256sum)
|
||||||
|
|
||||||
|
[[ $before == "$after" ]] || fail "terminal Shift+Enter migration is idempotent"
|
||||||
|
pass "terminal Shift+Enter migration is idempotent"
|
||||||
Reference in New Issue
Block a user