diff options
Diffstat (limited to 'modules/ext/editor.js')
| -rw-r--r-- | modules/ext/editor.js | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/modules/ext/editor.js b/modules/ext/editor.js index 3a5f269..07205b9 100644 --- a/modules/ext/editor.js +++ b/modules/ext/editor.js @@ -24,6 +24,8 @@ class EditorModule { const modal = document.getElementById('code-editor'); const title = document.getElementById('code-editor-title'); const textarea = document.getElementById('code-editor-textarea'); + const gutter = document.getElementById('code-editor-gutter'); + const statusEl = document.getElementById('code-editor-status'); if (!modal || !textarea) return this.terminal.print('Editor modal not found', 'error'); // Read existing file content or use empty for new files const content = this.terminal.fs.readFile(path); @@ -34,6 +36,51 @@ class EditorModule { textarea.value = fileContent; modal.style.display = 'flex'; textarea.focus(); + // Editor enhancements: line numbers, Tab, Ctrl+S + const updateGutter = () => { + const lines = textarea.value.split('\n').length; + let html = ''; + for (let i = 1; i <= lines; i++) html += i + '\n'; + gutter.textContent = ''; + gutter.textContent = html; + }; + const syncScroll = () => { gutter.scrollTop = textarea.scrollTop; }; + const updateStatus = () => { + const lines = textarea.value.split('\n').length; + const chars = textarea.value.length; + statusEl.textContent = `${lines} lines ยท ${chars} chars`; + }; + updateGutter(); + updateStatus(); + textarea.onscroll = syncScroll; + textarea.oninput = () => { updateGutter(); updateStatus(); }; + textarea.onkeydown = (e) => { + if (e.key === 'Tab') { e.preventDefault(); insertTab(textarea, e.shiftKey); updateGutter(); } + if ((e.ctrlKey || e.metaKey) && e.key === 's') { e.preventDefault(); saveBtn.click(); } + }; + function insertTab(el, shift) { + const s = el.selectionStart, e2 = el.selectionEnd; + if (shift) { + const before = el.value.substring(0, s); + const lineStart = before.lastIndexOf('\n') + 1; + if (lineStart < s && el.value.substring(lineStart, lineStart + 1) === '\t') { + el.value = el.value.substring(0, lineStart) + el.value.substring(lineStart + 1); + el.selectionStart = el.selectionEnd = s - 1; + } + } else { + el.value = el.value.substring(0, s) + '\t' + el.value.substring(e2); + el.selectionStart = el.selectionEnd = s + 1; + } + } + // Fullscreen toggle + window._editorToggleFullscreen = () => { + const content = modal.querySelector('.modal-content'); + if (content.style.maxWidth === '100vw') { + content.style.maxWidth = '90vw'; content.style.maxHeight = '90vh'; content.style.width = '900px'; content.style.height = '80vh'; + } else { + content.style.maxWidth = '100vw'; content.style.maxHeight = '100vh'; content.style.width = '100vw'; content.style.height = '100vh'; + } + }; // Override save button to write back to VFS const saveBtn = modal.querySelector('.modal-footer .btn:last-child'); const cancelBtn = modal.querySelector('.modal-footer .btn-danger'); |