Smart Ctrl+C: copy on selection, double-tap for SIGINT

Single Ctrl+C with selection → copies text to clipboard.
Single Ctrl+C without selection → sends SIGINT.
Double Ctrl+C (within 300ms) → always sends SIGINT.
Protects against accidentally killing programs when trying to copy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chrome-storm-c442
2026-02-23 15:03:03 -05:00
parent 1e2c98453a
commit 80e22e4507

View File

@@ -6,6 +6,7 @@ DECCKM, bracketed paste, mouse tracking, and professional copy/paste UX.
import codecs import codecs
import copy import copy
import time
import tkinter as tk import tkinter as tk
import tkinter.font as tkfont import tkinter.font as tkfont
import pyte import pyte
@@ -209,6 +210,7 @@ class TerminalWidget(tk.Frame):
# ── Selection tracking for copy ── # ── Selection tracking for copy ──
self._selecting = False self._selecting = False
self._last_ctrl_c: float = 0.0
# ── Status bar ── # ── Status bar ──
self._status_frame = tk.Frame(self, bg="#2d2d44", height=22) self._status_frame = tk.Frame(self, bg="#2d2d44", height=22)
@@ -519,6 +521,27 @@ class TerminalWidget(tk.Frame):
def _on_ctrl_c(self, event): def _on_ctrl_c(self, event):
if event.state & 0x1: # Shift held → Ctrl+Shift+C → copy if event.state & 0x1: # Shift held → Ctrl+Shift+C → copy
return self._on_copy(event) return self._on_copy(event)
now = time.monotonic()
double = (now - self._last_ctrl_c) < 0.3
self._last_ctrl_c = now
if double:
# Double Ctrl+C → always SIGINT (force kill)
self._send(b"\x03")
return "break"
# Single Ctrl+C: copy if there is a selection, otherwise SIGINT
try:
sel = self._text.get("sel.first", "sel.last")
if sel:
self.clipboard_clear()
self.clipboard_append(sel)
return "break"
except tk.TclError:
pass
# No selection → SIGINT
self._send(b"\x03") self._send(b"\x03")
return "break" return "break"