diff --git a/src/renderer/index.html b/src/renderer/index.html
index efa2e76..96ff10c 100644
--- a/src/renderer/index.html
+++ b/src/renderer/index.html
@@ -69,6 +69,14 @@
SSH Lite Client
+
diff --git a/src/renderer/renderer.js b/src/renderer/renderer.js
index f7a605e..eb834ca 100644
--- a/src/renderer/renderer.js
+++ b/src/renderer/renderer.js
@@ -21,6 +21,9 @@ const fileList = document.getElementById('fileList');
const editorHost = document.getElementById('editorHost');
const saveBtn = document.getElementById('saveBtn');
const closeFileBtn = document.getElementById('closeFileBtn');
+const findBtn = document.getElementById('findBtn');
+const replaceBtn = document.getElementById('replaceBtn');
+const goToLineBtn = document.getElementById('goToLineBtn');
const currentFileEl = document.getElementById('currentFile');
const editorTabBtn = document.getElementById('editorTabBtn');
const terminalTabBtn = document.getElementById('terminalTabBtn');
@@ -74,9 +77,12 @@ let suppressDirtyTracking = false;
function updateCurrentFileLabel() {
if (!currentFile) {
currentFileEl.textContent = 'No file open';
+ document.title = 'SSH Lite Client';
return;
}
currentFileEl.textContent = isDirty ? `${currentFile} *` : currentFile;
+ const fileName = currentFile.split('/').pop() || currentFile;
+ document.title = `${isDirty ? '* ' : ''}${fileName} - SSH Lite Client`;
}
async function ensureMonacoReady() {
@@ -192,6 +198,26 @@ function updateEditorTheme() {
monacoApi?.editor.setTheme(theme);
}
+async function runEditorAction(kind) {
+ if (!(await ensureMonacoReady()) || !monacoEditor) return;
+ showEditorView();
+ monacoEditor.focus();
+
+ if (kind === 'find') {
+ monacoEditor.trigger('ui', 'actions.find', null);
+ return;
+ }
+
+ if (kind === 'replace') {
+ monacoEditor.trigger('ui', 'editor.action.startFindReplaceAction', null);
+ return;
+ }
+
+ if (kind === 'goto') {
+ monacoEditor.trigger('ui', 'editor.action.gotoLine', null);
+ }
+}
+
function focusEditorSoon() {
const tryFocus = () => {
document.body.classList.remove('resizing');
@@ -774,6 +800,18 @@ closeFileBtn.onclick = async () => {
closeCurrentFile();
};
+findBtn.onclick = () => {
+ void runEditorAction('find');
+};
+
+replaceBtn.onclick = () => {
+ void runEditorAction('replace');
+};
+
+goToLineBtn.onclick = () => {
+ void runEditorAction('goto');
+};
+
pickKeyBtn.onclick = async () => {
const res = await window.api.pickPrivateKey();
if (!res.ok) {
diff --git a/src/renderer/styles.css b/src/renderer/styles.css
index 765e907..a33e316 100644
--- a/src/renderer/styles.css
+++ b/src/renderer/styles.css
@@ -257,6 +257,25 @@ body.resizing {
gap: 8px;
}
+.editor-tools {
+ border-bottom: 1px solid var(--border);
+ padding: 8px 10px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 10px;
+}
+
+.editor-tool-buttons {
+ display: flex;
+ gap: 6px;
+}
+
+.editor-shortcuts {
+ font-size: 12px;
+ color: var(--muted);
+}
+
.view-tabs {
display: flex;
gap: 6px;
@@ -449,4 +468,8 @@ body.resizing {
.editor-top {
flex-wrap: wrap;
}
+
+ .editor-tools {
+ flex-wrap: wrap;
+ }
}