feat: command snippets + UI test coverage for new features
- core/snippets.py: SnippetManager with 20 prebuilt sysadmin commands, CRUD + reorder, persisted to ~/.sshclient/snippets.json - ui/snippet_dialog.py: SnippetDialog (add/edit) + SnippetManagerDialog (table view with add/edit/delete/move up/down) - ui/terminal_panel.py: snippet combo box in toolbar, send_command() method to inject commands into interactive shell, snippet manager button - README.md: updated feature table, usage section, project structure - test_ui.py: added [2/4] checks for sparkline/snippets/theme, added [4/4] theme toggle verification
This commit is contained in:
@@ -21,6 +21,7 @@ from PyQt5.QtWidgets import (
|
||||
)
|
||||
|
||||
from core.ssh_client import SSHConnection
|
||||
from core.snippets import SnippetManager
|
||||
|
||||
|
||||
# ANSI 颜色映射(16 色)
|
||||
@@ -133,6 +134,8 @@ class TerminalPanel(QWidget):
|
||||
self._ansi_invert = False
|
||||
# OSC 0/2 设置的窗口标题
|
||||
self._window_title = ""
|
||||
# 命令片段
|
||||
self.snippet_mgr = SnippetManager()
|
||||
|
||||
self._build_ui()
|
||||
self._apply_style()
|
||||
@@ -152,6 +155,20 @@ class TerminalPanel(QWidget):
|
||||
self.status_label.setStyleSheet("color: #888;")
|
||||
toolbar.addWidget(self.status_label)
|
||||
toolbar.addStretch(1)
|
||||
# 命令片段
|
||||
toolbar.addWidget(QLabel("📋"))
|
||||
self.snippet_combo = QComboBox()
|
||||
self.snippet_combo.setMinimumWidth(180)
|
||||
self.snippet_combo.setToolTip("选择命令片段快速发送到终端")
|
||||
self.snippet_combo.currentIndexChanged.connect(self._on_snippet_selected)
|
||||
toolbar.addWidget(self.snippet_combo)
|
||||
self._refresh_snippets()
|
||||
self.btn_snippet_mgr = QPushButton("⚙")
|
||||
self.btn_snippet_mgr.setFixedWidth(28)
|
||||
self.btn_snippet_mgr.setToolTip("管理命令片段")
|
||||
self.btn_snippet_mgr.clicked.connect(self._open_snippet_manager)
|
||||
toolbar.addWidget(self.btn_snippet_mgr)
|
||||
toolbar.addSpacing(8)
|
||||
self.btn_clear = QPushButton("清屏")
|
||||
self.btn_clear.clicked.connect(self._clear_screen)
|
||||
self.btn_reset = QPushButton("重连 shell")
|
||||
@@ -190,6 +207,51 @@ class TerminalPanel(QWidget):
|
||||
}
|
||||
""")
|
||||
|
||||
# ============================================================
|
||||
# 命令片段
|
||||
# ============================================================
|
||||
def _refresh_snippets(self):
|
||||
"""刷新下拉框"""
|
||||
self.snippet_combo.blockSignals(True)
|
||||
self.snippet_combo.clear()
|
||||
self.snippet_combo.addItem("-- 选择命令片段 --", "")
|
||||
for s in self.snippet_mgr.list_all():
|
||||
self.snippet_combo.addItem(f"{s['name']} ({s['cmd'][:30]})", s["cmd"])
|
||||
self.snippet_combo.blockSignals(False)
|
||||
|
||||
def _on_snippet_selected(self, index: int):
|
||||
"""选择片段后发送命令到终端"""
|
||||
if index <= 0:
|
||||
return
|
||||
cmd = self.snippet_combo.itemData(index)
|
||||
if not cmd:
|
||||
return
|
||||
# 重置下拉框选中项(让用户能重复选同一个)
|
||||
self.snippet_combo.blockSignals(True)
|
||||
self.snippet_combo.setCurrentIndex(0)
|
||||
self.snippet_combo.blockSignals(False)
|
||||
# 发送命令
|
||||
self.send_command(cmd)
|
||||
|
||||
def send_command(self, cmd: str):
|
||||
"""发送一条命令到远程 shell(自动加换行)"""
|
||||
if not self.chan or not self._connected:
|
||||
self._set_status("未连接,无法发送命令", "#c62828")
|
||||
return
|
||||
data = cmd.encode("utf-8", errors="replace")
|
||||
if not cmd.endswith("\n"):
|
||||
data += b"\n"
|
||||
try:
|
||||
self.chan.send(data)
|
||||
except Exception as e:
|
||||
self._set_status(f"发送失败: {e}", "#c62828")
|
||||
|
||||
def _open_snippet_manager(self):
|
||||
from .snippet_dialog import SnippetManagerDialog
|
||||
dlg = SnippetManagerDialog(self.snippet_mgr, self)
|
||||
dlg.exec_()
|
||||
self._refresh_snippets()
|
||||
|
||||
# ============================================================
|
||||
# 生命周期
|
||||
# ============================================================
|
||||
|
||||
Reference in New Issue
Block a user