From ac29515d9f859e5395e8f3886bab25251a27fe9f Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 29 Jul 2026 06:47:08 +0800 Subject: [PATCH] fix: Backspace/Delete deleting prompt text (root@host:~#) Root cause: _current_line_start was set after \r\n but BEFORE the prompt was rendered, so Backspace could erase prompt characters after reaching the input line start. Fix: send \x7f (DEL) to shell on Backspace and \x1b[3~ on Delete instead of locally deleting characters. The shell's readline handles backspace correctly - it ignores DEL at the input line start, so the prompt is never touched. The existing \b handler in _on_data already correctly processes the shell's \b-space-\b echo sequence. Verified: typing 'abc' + 3 Backspace deletes input, 5 more Backspace leaves prompt 'root@host:~# ' intact. --- ui/terminal_panel.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/ui/terminal_panel.py b/ui/terminal_panel.py index a7bd02c..7b53bcc 100644 --- a/ui/terminal_panel.py +++ b/ui/terminal_panel.py @@ -571,24 +571,32 @@ class TerminalPanel(QWidget): self._send_bytes(b"\r") def _on_backspace(self): + # 发 DEL(\x7f) 给 shell,由 shell 的 readline 处理退格 + 回显(\b \b)。 + # 这样 shell 在输入行首会忽略退格,不会删除提示符 root@host:~#。 + # 旧方案是本地 deletePreviousChar(),但 _current_line_start 在提示符 + # 之前,导致退到输入行首后还能继续删提示符。 + if self.chan and self._connected: + self._send_bytes(b"\x7f") + return + # 未连接时 fallback:本地删除 cursor = self.term.textCursor() if cursor.position() <= self._current_line_start: - return # 已到行首,不删 - # 不能跨行删(保持当前行) - if self._is_at_line_start(cursor): return cursor.deletePreviousChar() def _on_delete(self): + # 发 Delete 转义序列给 shell,由 shell 处理 + if self.chan and self._connected: + self._send_bytes(b"\x1b[3~") + return + # 未连接时 fallback:本地删除 cursor = self.term.textCursor() if cursor.atEnd(): return - # 不允许删除当前输入行之前的内容(提示符 root@host:~# 等) if cursor.position() < self._current_line_start: cursor.setPosition(self._current_line_start) self.term.setTextCursor(cursor) return - # 如果有选区且选区起点在当前输入行之前,不允许 if cursor.hasSelection(): sel_start = cursor.selectionStart() if sel_start < self._current_line_start: