aboutsummaryrefslogtreecommitdiff
path: root/modules/ext/editor.js
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-06-22 18:00:43 +0200
committerAgando <roduccomm@gmail.com>2026-06-22 18:00:43 +0200
commit6f6161562c5f1028256f3163083b665719741646 (patch)
treeccc9ab59e8433555557b6db8b6c1d4940b8652a4 /modules/ext/editor.js
parent82270d6f2685d84d5c9b4a454ae7260de75d34cf (diff)
auto: 2026-06-22_18:00 changes
Diffstat (limited to 'modules/ext/editor.js')
-rw-r--r--modules/ext/editor.js47
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');