R
Reinblacks supper coding — VS Code Reinblacks supper coding — Visual Studio Code

Reinblacks supper coding

A VS Code-inspired coding environment

Click files in the Explorer to start coding ✨

TERMINAL Output Problems
Welcome to Reinblacks supper coding terminal! Type 'help' for available commands.
~/reinblacks $
main No file open
Ln 1, Col 1 Spaces: 2 UTF-8 Plain Text ⊞ Terminal
` }, 'app.js': { type: 'file', language: 'javascript', content: `// Reinblacks supper coding - Main Application import { initApp, setupRouter } from './modules/core.js'; const CONFIG = { appName: 'Reinblacks supper coding', version: '1.0.0', debug: true, port: 3000 }; /** * Initialize the main application * @returns {Promise} */ async function main() { console.log(\`Starting \${CONFIG.appName} v\${CONFIG.version}\`); try { await initApp(CONFIG); setupRouter(); const server = await startServer(CONFIG.port); console.log(\`Server running on port \${CONFIG.port}\`); } catch (error) { console.error('Failed to initialize:', error.message); process.exit(1); } } async function startServer(port) { return new Promise((resolve) => { setTimeout(() => resolve({ port, status: 'running' }), 500); }); } // Run the app main().then(() => { if (CONFIG.debug) { console.log('App started in debug mode'); } });` }, 'styles.css': { type: 'file', language: 'css', content: `/* Reinblacks supper coding - Styles */ :root { --primary: #007acc; --secondary: #28a0ff; --bg-dark: #1e1e1e; --text-light: #cccccc; --border-radius: 8px; --transition-speed: 0.25s; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', sans-serif; background: var(--bg-dark); color: var(--text-light); line-height: 1.6; min-height: 100vh; } .main-header { display: flex; justify-content: space-between; align-items: center; padding: 16px 32px; background: #252526; border-bottom: 2px solid var(--primary); } .main-header h1 { font-size: 1.5rem; font-weight: 600; color: #ffffff; } .cta-btn { padding: 12px 28px; background: var(--primary); color: #fff; border: none; border-radius: var(--border-radius); cursor: pointer; font-size: 1rem; transition: all var(--transition-speed); } .cta-btn:hover { background: var(--secondary); transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0, 122, 204, 0.4); }` } } }, 'package.json': { type: 'file', language: 'json', content: `{ "name": "reinblacks-supper-coding", "version": "1.0.0", "description": "A VS Code-inspired coding environment", "main": "src/app.js", "scripts": { "start": "node src/app.js", "dev": "nodemon src/app.js", "build": "webpack --mode production", "test": "jest --coverage" }, "dependencies": { "express": "^4.18.2", "cors": "^2.8.5", "dotenv": "^16.3.1" }, "devDependencies": { "nodemon": "^3.0.1", "jest": "^29.7.0", "webpack": "^5.89.0" }, "author": "Reinblacks", "license": "MIT" }` }, 'README.md': { type: 'file', language: 'markdown', content: `# Reinblacks supper coding 🚀 A fully-featured **VS Code-inspired** coding environment built with HTML, CSS, and JavaScript. ## Features - 📁 **File Explorer** with collapsible folders - 📝 **Multi-tab Editor** with syntax highlighting - 💻 **Integrated Terminal** with command support - 🎨 **Dark Theme** matching VS Code's aesthetic - 🔍 **Activity Bar** with icon navigation - 📊 **Status Bar** with file info ## Getting Started \`\`\`bash npm install npm run dev \`\`\` ## Project Structure - \`src/index.html\` - Main HTML file - \`src/app.js\` - Application logic - \`src/styles.css\` - Stylesheet - \`package.json\` - Dependencies ## License MIT © Reinblacks 2026 ` } }; // ============ APP STATE ============ const state = { openTabs: [], // [{path: 'src/app.js', name: 'app.js', language: 'javascript', dirty: false}] activeTabPath: null, sidebarVisible: true, panelVisible: true, panelHeight: 200, activeSidebar: 'explorer', isDraggingPanel: false, expandedFolders: new Set(['src']), selectedTreeItem: null, }; // ============ DOM REFERENCES ============ const $ = (sel) => document.querySelector(sel); const $$ = (sel) => document.querySelectorAll(sel); const dom = { sidebar: $('#sidebar'), fileExplorer: $('#file-explorer'), tabsBar: $('#tabs-bar'), editorCode: $('#editor-code'), lineNumbers: $('#line-numbers'), codeContent: $('#code-content'), welcomeScreen: $('#welcome-screen'), panelArea: $('#panel-area'), panelContent: $('#panel-content'), terminalInput: $('#terminal-input'), statusFileInfo: $('#status-file-info'), statusLn: $('#status-ln'), statusLang: $('#status-lang'), panelResizeHandle: $('#panel-resize-handle'), activityIcons: $$('.activity-icon[data-sidebar]'), }; // ============ SYNTAX HIGHLIGHTING ENGINE ============ function highlightCode(code, language) { let html = ''; const lines = code.split('\n'); lines.forEach((line, i) => { let highlighted = escapeHTML(line); switch (language) { case 'javascript': // Comments highlighted = highlighted.replace( /(\/\/.*$|\/\*[\s\S]*?\*\/)/gm, '$1'); // Strings highlighted = highlighted.replace( /('.*?'|".*?"|`.*?`)/g, '$1'); // Keywords highlighted = highlighted.replace( /\b(const|let|var|function|async|await|return|if|else|for|while|try|catch|throw|new|class|import|export|from|default|switch|case|break|continue|typeof|instanceof|this|super|extends|static|get|set|yield|do|in|of)\b/g, '$1'); // Booleans & null highlighted = highlighted.replace( /\b(true|false|null|undefined|NaN)\b/g, '$1'); // Numbers highlighted = highlighted.replace( /\b(\d+\.?\d*)\b/g, '$1'); // Function calls highlighted = highlighted.replace( /\b([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(/g, '$1('); break; case 'html': // Comments highlighted = highlighted.replace( /(<!--[\s\S]*?-->)/g, '$1'); // Tags highlighted = highlighted.replace( /(<\/?\s*[\w-]+)/g, '$1'); highlighted = highlighted.replace( /(\/?)>/g, '$1>'); // Attributes highlighted = highlighted.replace( /\b([\w-]+)=(".*?")/g, '$1=$2'); break; case 'css': // Comments highlighted = highlighted.replace( /(\/\*[\s\S]*?\*\/)/g, '$1'); // Properties highlighted = highlighted.replace( /^(\s*)([\w-]+)(\s*:)/gm, '$1$2$3'); // Values highlighted = highlighted.replace( /:\s*([^;{]+)/g, ': $1'); // Selectors highlighted = highlighted.replace( /(^[^{]+)(\{)/gm, '$1$2'); break; case 'json': // Keys highlighted = highlighted.replace( /("[\w-]+")(\s*:)/g, '$1$2'); // Strings (values) highlighted = highlighted.replace( /:\s*("[^"]*")/g, ': $1'); // Numbers highlighted = highlighted.replace( /:\s*(\d+\.?\d*)/g, ': $1'); // Booleans highlighted = highlighted.replace( /:\s*(true|false|null)/g, ': $1'); break; case 'markdown': // Headers highlighted = highlighted.replace( /^(#{1,6}\s.*)$/gm, '$1'); // Bold highlighted = highlighted.replace( /(\*\*.*?\*\*)/g, '$1'); // Code blocks highlighted = highlighted.replace( /(`.*?`)/g, '$1'); // Links highlighted = highlighted.replace( /\[(.*?)\]\((.*?)\)/g, '[$1]($2)'); break; } html += highlighted; if (i < lines.length - 1) html += '\n'; }); return html; } function escapeHTML(str) { const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } // ============ FILE SYSTEM HELPERS ============ function getFileByPath(path) { const parts = path.split('/'); let current = fileSystem; for (const part of parts) { if (!current || !current.children || !current.children[part]) return null; current = current.children[part]; } return current && current.type === 'file' ? current : null; } function getAllFiles(obj, prefix = '') { let files = []; for (const [name, item] of Object.entries(obj)) { const path = prefix ? `${prefix}/${name}` : name; if (item.type === 'file') { files.push({ path, name, language: item.language, ...item }); } else if (item.type === 'folder' && item.children) { files = files.concat(getAllFiles(item.children, path)); } } return files; } // ============ FILE EXPLORER RENDERING ============ function renderFileExplorer() { dom.fileExplorer.innerHTML = ''; renderTreeItems(fileSystem, '', 0); } function renderTreeItems(items, parentPath, depth) { // Sort: folders first, then files, alphabetically const entries = Object.entries(items).sort((a, b) => { if (a[1].type !== b[1].type) return a[1].type === 'folder' ? -1 : 1; return a[0].localeCompare(b[0]); }); for (const [name, item] of entries) { const path = parentPath ? `${parentPath}/${name}` : name; const isFolder = item.type === 'folder'; const isExpanded = state.expandedFolders.has(path); const itemDiv = document.createElement('div'); itemDiv.className = 'tree-item'; if (isFolder) itemDiv.classList.add('folder'); if (state.selectedTreeItem === path) itemDiv.classList.add('selected'); itemDiv.style.paddingLeft = `${8 + depth * 16}px`; itemDiv.dataset.path = path; itemDiv.dataset.type = item.type; // Arrow for folders const arrow = document.createElement('span'); arrow.className = 'arrow'; if (isFolder) { arrow.textContent = '▶'; if (isExpanded) arrow.classList.add('expanded'); } arrow.style.width = '16px'; arrow.style.display = 'inline-block'; arrow.style.textAlign = 'center'; arrow.style.flexShrink = '0'; // Icon const icon = document.createElement('span'); icon.className = 'icon'; if (isFolder) { icon.textContent = isExpanded ? '📂' : '📁'; icon.classList.add('file-icon-folder'); } else { const ext = name.split('.').pop(); const iconMap = { html: '🌐', js: '📜', css: '🎨', json: '📋', md: '📝', }; icon.textContent = iconMap[ext] || '📄'; icon.classList.add('file-icon-' + (ext || 'default')); } const label = document.createElement('span'); label.textContent = name; label.style.overflow = 'hidden'; label.style.textOverflow = 'ellipsis'; itemDiv.appendChild(arrow); itemDiv.appendChild(icon); itemDiv.appendChild(label); // Click handler itemDiv.addEventListener('click', (e) => { e.stopPropagation(); if (isFolder) { toggleFolder(path, itemDiv); } else { openFile(path); state.selectedTreeItem = path; renderFileExplorer(); } }); dom.fileExplorer.appendChild(itemDiv); // Render children for folders if (isFolder && item.children) { const childrenContainer = document.createElement('div'); childrenContainer.className = 'tree-children'; if (!isExpanded) childrenContainer.classList.add('collapsed'); childrenContainer.dataset.path = path; dom.fileExplorer.appendChild(childrenContainer); // We'll render children into this container renderTreeItemsIntoContainer(item.children, path, depth + 1, childrenContainer); } } } function renderTreeItemsIntoContainer(items, parentPath, depth, container) { const entries = Object.entries(items).sort((a, b) => { if (a[1].type !== b[1].type) return a[1].type === 'folder' ? -1 : 1; return a[0].localeCompare(b[0]); }); for (const [name, item] of entries) { const path = `${parentPath}/${name}`; const isFolder = item.type === 'folder'; const isExpanded = state.expandedFolders.has(path); const itemDiv = document.createElement('div'); itemDiv.className = 'tree-item'; if (isFolder) itemDiv.classList.add('folder'); if (state.selectedTreeItem === path) itemDiv.classList.add('selected'); itemDiv.style.paddingLeft = `${8 + depth * 16}px`; itemDiv.dataset.path = path; itemDiv.dataset.type = item.type; const arrow = document.createElement('span'); arrow.className = 'arrow'; if (isFolder) { arrow.textContent = '▶'; if (isExpanded) arrow.classList.add('expanded'); } arrow.style.width = '16px'; arrow.style.display = 'inline-block'; arrow.style.textAlign = 'center'; arrow.style.flexShrink = '0'; const icon = document.createElement('span'); icon.className = 'icon'; if (isFolder) { icon.textContent = isExpanded ? '📂' : '📁'; icon.classList.add('file-icon-folder'); } else { const ext = name.split('.').pop(); const iconMap = { html: '🌐', js: '📜', css: '🎨', json: '📋', md: '📝' }; icon.textContent = iconMap[ext] || '📄'; icon.classList.add('file-icon-' + (ext || 'default')); } const label = document.createElement('span'); label.textContent = name; label.style.overflow = 'hidden'; label.style.textOverflow = 'ellipsis'; itemDiv.appendChild(arrow); itemDiv.appendChild(icon); itemDiv.appendChild(label); itemDiv.addEventListener('click', (e) => { e.stopPropagation(); if (isFolder) { toggleFolder(path, itemDiv); } else { openFile(path); state.selectedTreeItem = path; renderFileExplorer(); } }); container.appendChild(itemDiv); if (isFolder && item.children) { const childrenContainer = document.createElement('div'); childrenContainer.className = 'tree-children'; if (!isExpanded) childrenContainer.classList.add('collapsed'); childrenContainer.dataset.path = path; container.appendChild(childrenContainer); renderTreeItemsIntoContainer(item.children, path, depth + 1, childrenContainer); } } } function toggleFolder(path, itemDiv) { if (state.expandedFolders.has(path)) { state.expandedFolders.delete(path); } else { state.expandedFolders.add(path); } renderFileExplorer(); // Re-select if needed if (state.selectedTreeItem) { const sel = document.querySelector(`.tree-item[data-path="${state.selectedTreeItem}"]`); if (sel) sel.classList.add('selected'); } } // ============ TAB MANAGEMENT ============ function openFile(path) { const file = getFileByPath(path); if (!file) return; // Check if already open const existingTab = state.openTabs.find(t => t.path === path); if (existingTab) { state.activeTabPath = path; } else { state.openTabs.push({ path, name: path.split('/').pop(), language: file.language, dirty: false, }); state.activeTabPath = path; } state.selectedTreeItem = path; renderTabs(); renderEditor(); updateStatusBar(); dom.welcomeScreen.classList.add('hidden'); dom.editorCode.style.display = 'flex'; } function closeTab(path) { const idx = state.openTabs.findIndex(t => t.path === path); if (idx === -1) return; state.openTabs.splice(idx, 1); if (state.openTabs.length === 0) { state.activeTabPath = null; dom.welcomeScreen.classList.remove('hidden'); dom.editorCode.style.display = 'none'; state.selectedTreeItem = null; renderFileExplorer(); } else if (state.activeTabPath === path) { state.activeTabPath = state.openTabs[Math.min(idx, state.openTabs.length - 1)].path; } renderTabs(); if (state.activeTabPath) { renderEditor(); state.selectedTreeItem = state.activeTabPath; renderFileExplorer(); } updateStatusBar(); } function renderTabs() { dom.tabsBar.innerHTML = ''; state.openTabs.forEach(tab => { const tabDiv = document.createElement('div'); tabDiv.className = 'editor-tab'; if (tab.path === state.activeTabPath) tabDiv.classList.add('active'); if (tab.dirty) tabDiv.classList.add('dirty'); const nameSpan = document.createElement('span'); nameSpan.className = 'tab-name'; nameSpan.textContent = tab.name; nameSpan.title = tab.path; const closeBtn = document.createElement('span'); closeBtn.className = 'tab-close'; closeBtn.textContent = '×'; closeBtn.title = 'Close'; closeBtn.addEventListener('click', (e) => { e.stopPropagation(); closeTab(tab.path); }); tabDiv.appendChild(nameSpan); tabDiv.appendChild(closeBtn); tabDiv.addEventListener('click', () => { state.activeTabPath = tab.path; state.selectedTreeItem = tab.path; renderTabs(); renderEditor(); updateStatusBar(); renderFileExplorer(); dom.welcomeScreen.classList.add('hidden'); dom.editorCode.style.display = 'flex'; }); // Middle-click to close tabDiv.addEventListener('mousedown', (e) => { if (e.button === 1) { e.preventDefault(); closeTab(tab.path); } }); dom.tabsBar.appendChild(tabDiv); }); } function renderEditor() { if (!state.activeTabPath) return; const file = getFileByPath(state.activeTabPath); if (!file) return; const highlighted = highlightCode(file.content, file.language); dom.codeContent.innerHTML = highlighted + ''; // Line numbers const lineCount = file.content.split('\n').length; let lnHTML = ''; for (let i = 1; i <= lineCount; i++) { lnHTML += `${i}`; } dom.lineNumbers.innerHTML = lnHTML; // Sync scroll dom.codeContent.scrollTop = 0; dom.lineNumbers.scrollTop = 0; dom.statusLang.textContent = getLanguageLabel(file.language); } function getLanguageLabel(lang) { const map = { html: 'HTML', javascript: 'JavaScript', css: 'CSS', json: 'JSON', markdown: 'Markdown', }; return map[lang] || 'Plain Text'; } function updateStatusBar() { if (state.activeTabPath) { dom.statusFileInfo.textContent = state.activeTabPath; const file = getFileByPath(state.activeTabPath); if (file) { dom.statusLang.textContent = getLanguageLabel(file.language); } } else { dom.statusFileInfo.textContent = 'No file open'; dom.statusLang.textContent = 'Plain Text'; } dom.statusLn.textContent = 'Ln 1, Col 1'; } // ============ TERMINAL ============ function setupTerminal() { const input = dom.terminalInput; const content = dom.panelContent; input.addEventListener('keydown', function(e) { if (e.key === 'Enter') { const cmd = input.value.trim(); if (cmd) { executeCommand(cmd); } input.value = ''; e.preventDefault(); } }); // Click on panel content focuses input content.addEventListener('click', () => { input.focus(); }); } function executeCommand(cmd) { const content = dom.panelContent; const input = dom.terminalInput; // Add the command line to output const cmdLine = document.createElement('div'); cmdLine.className = 'terminal-line'; cmdLine.innerHTML = ` ~/reinblacks $ ${escapeHTML(cmd)}`; content.insertBefore(cmdLine, input.parentElement); let output = ''; let outputClass = 'output'; switch (cmd.toLowerCase().split(' ')[0]) { case 'help': output = `Available commands: ───────────────────────── help Show this help ls List files pwd Print working directory echo [text] Print text date Show current date/time clear Clear terminal node --version Show Node.js version npm --version Show npm version whoami Show current user cat [file] Display file contents welcome Show welcome message`; break; case 'ls': output = listFiles(fileSystem, ''); break; case 'pwd': output = '/home/user/reinblacks'; break; case 'echo': output = cmd.slice(5) || ''; break; case 'date': output = new Date().toString(); break; case 'clear': // Remove all terminal lines except the prompt const lines = content.querySelectorAll('.terminal-line'); lines.forEach(l => l.remove()); return; case 'node': if (cmd.includes('--version')) output = 'v20.10.0'; else output = 'Usage: node [options] [script]'; break; case 'npm': if (cmd.includes('--version')) output = '10.2.3'; else output = 'Usage: npm '; break; case 'whoami': output = 'reinblacks'; break; case 'cat': const filePath = cmd.slice(4).trim(); if (filePath) { const file = getFileByPath(filePath); if (file) { output = file.content; } else { output = `cat: ${filePath}: No such file or directory`; outputClass = 'error'; } } else { output = 'Usage: cat '; outputClass = 'error'; } break; case 'welcome': output = '🌟 Welcome to Reinblacks supper coding! 🌟\nBuilt with love for coders everywhere.'; outputClass = 'success'; break; default: output = `bash: ${cmd.split(' ')[0]}: command not found. Type 'help' for available commands.`; outputClass = 'error'; } if (output) { const outDiv = document.createElement('div'); outDiv.className = `terminal-line ${outputClass}`; outDiv.textContent = output; content.insertBefore(outDiv, input.parentElement); } // Scroll to bottom content.scrollTop = content.scrollHeight; input.focus(); } function listFiles(obj, prefix) { let result = ''; const entries = Object.entries(obj); for (const [name, item] of entries) { if (item.type === 'folder') { result += `${name}/\n`; } else { result += `${name}\n`; } } return result.trim(); } // ============ PANEL RESIZE ============ function setupPanelResize() { const handle = dom.panelResizeHandle; const panel = dom.panelArea; let startY, startHeight; handle.addEventListener('mousedown', (e) => { state.isDraggingPanel = true; startY = e.clientY; startHeight = panel.offsetHeight; document.body.style.cursor = 'ns-resize'; document.body.style.userSelect = 'none'; e.preventDefault(); }); document.addEventListener('mousemove', (e) => { if (!state.isDraggingPanel) return; const delta = startY - e.clientY; const newHeight = Math.max(60, Math.min(500, startHeight + delta)); panel.style.height = newHeight + 'px'; state.panelHeight = newHeight; }); document.addEventListener('mouseup', () => { if (state.isDraggingPanel) { state.isDraggingPanel = false; document.body.style.cursor = ''; document.body.style.userSelect = ''; } }); } function togglePanel() { if (state.panelVisible) { dom.panelArea.classList.add('collapsed'); state.panelVisible = false; } else { dom.panelArea.classList.remove('collapsed'); dom.panelArea.style.height = state.panelHeight + 'px'; state.panelVisible = true; setTimeout(() => dom.terminalInput.focus(), 100); } } // ============ SIDEBAR TOGGLE ============ function toggleSidebar() { if (state.sidebarVisible) { dom.sidebar.classList.add('collapsed'); state.sidebarVisible = false; } else { dom.sidebar.classList.remove('collapsed'); state.sidebarVisible = true; } } // ============ MENU SYSTEM ============ function setupMenus() { const menuItems = $$('#menubar .menu-item'); menuItems.forEach(item => { item.addEventListener('click', function(e) { e.stopPropagation(); // Close all other menus menuItems.forEach(mi => { if (mi !== item) mi.classList.remove('active'); }); item.classList.toggle('active'); }); }); // Close menus when clicking elsewhere document.addEventListener('click', () => { menuItems.forEach(mi => mi.classList.remove('active')); }); // Menu action handlers document.addEventListener('click', function(e) { const actionItem = e.target.closest('.menu-dropdown-item[data-action]'); if (!actionItem) return; const action = actionItem.dataset.action; switch (action) { case 'new-file': showToast('📄 New file created: untitled.txt'); break; case 'save': showToast('💾 File saved successfully!'); break; case 'save-all': showToast('📑 All files saved!'); break; case 'close-editor': if (state.activeTabPath) closeTab(state.activeTabPath); break; case 'toggle-sidebar': toggleSidebar(); break; case 'toggle-terminal': togglePanel(); break; case 'run-code': showToast('▶ Running code... Check terminal for output'); if (!state.panelVisible) togglePanel(); executeCommand('echo "Code execution simulated!"'); break; case 'new-terminal': if (!state.panelVisible) togglePanel(); dom.terminalInput.focus(); break; case 'open-file': showToast('📂 Open File dialog (simulated)'); break; } // Close menus $$('#menubar .menu-item').forEach(mi => mi.classList.remove('active')); }); } function showToast(message) { const toast = document.createElement('div'); toast.className = 'toast'; toast.textContent = message; document.body.appendChild(toast); setTimeout(() => { toast.style.opacity = '0'; toast.style.transition = 'opacity 0.3s'; setTimeout(() => toast.remove(), 300); }, 2000); } // ============ ACTIVITY BAR ============ function setupActivityBar() { dom.activityIcons.forEach(icon => { icon.addEventListener('click', function() { const sidebar = this.dataset.sidebar; state.activeSidebar = sidebar; // Update active state dom.activityIcons.forEach(i => i.classList.remove('active')); this.classList.add('active'); // Show sidebar if hidden if (!state.sidebarVisible) toggleSidebar(); // Update sidebar header const headerMap = { explorer: 'EXPLORER', search: 'SEARCH', git: 'SOURCE CONTROL', debug: 'RUN AND DEBUG', extensions: 'EXTENSIONS', }; $('#sidebar-header span').textContent = headerMap[sidebar] || sidebar.toUpperCase(); if (sidebar === 'explorer') { renderFileExplorer(); } else { dom.fileExplorer.innerHTML = `

🔍

${headerMap[sidebar]} panel

(simulated)

`; } }); }); } // ============ KEYBOARD SHORTCUTS ============ function setupKeyboardShortcuts() { document.addEventListener('keydown', function(e) { // Ctrl+B - Toggle sidebar if (e.ctrlKey && e.key === 'b') { e.preventDefault(); toggleSidebar(); } // Ctrl+` - Toggle terminal if (e.ctrlKey && e.key === '`') { e.preventDefault(); togglePanel(); } // Ctrl+W - Close active tab if (e.ctrlKey && e.key === 'w' && state.activeTabPath) { e.preventDefault(); closeTab(state.activeTabPath); } // Escape - close menus if (e.key === 'Escape') { $$('#menubar .menu-item').forEach(mi => mi.classList.remove('active')); } }); } // ============ INITIALIZATION ============ function init() { renderFileExplorer(); setupTerminal(); setupPanelResize(); setupMenus(); setupActivityBar(); setupKeyboardShortcuts(); // Welcome screen buttons $('#btn-open-explorer').addEventListener('click', () => { if (!state.sidebarVisible) toggleSidebar(); state.activeSidebar = 'explorer'; dom.activityIcons.forEach(i => i.classList.remove('active')); const explorerIcon = document.querySelector('.activity-icon[data-sidebar="explorer"]'); if (explorerIcon) explorerIcon.classList.add('active'); $('#sidebar-header span').textContent = 'EXPLORER'; renderFileExplorer(); }); $('#btn-new-welcome').addEventListener('click', () => { showToast('📄 New file created! Open a file from the Explorer.'); }); $('#btn-toggle-term').addEventListener('click', togglePanel); // Sidebar buttons $('#btn-new-file').addEventListener('click', () => { showToast('📄 New file created: untitled.txt'); }); $('#btn-collapse-all').addEventListener('click', () => { state.expandedFolders.clear(); renderFileExplorer(); }); // Close panel button $('#btn-close-panel').addEventListener('click', togglePanel); // Toggle panel from status bar $('#btn-toggle-panel-status').addEventListener('click', togglePanel); // Panel tab switching $$('#panel-tabs .panel-tab').forEach(tab => { tab.addEventListener('click', function() { $$('#panel-tabs .panel-tab').forEach(t => t.classList.remove( 'active')); this.classList.add('active'); if (this.textContent.trim() === 'TERMINAL') { dom.terminalInput.style.display = ''; dom.terminalInput.focus(); } }); }); // Sync scroll between line numbers and code dom.codeContent.addEventListener('scroll', () => { dom.lineNumbers.scrollTop = dom.codeContent.scrollTop; }); // Focus terminal input on panel click dom.panelContent.addEventListener('click', (e) => { if (e.target === dom.panelContent || e.target.closest('.terminal-line')) { dom.terminalInput.focus(); } }); // Initial terminal focus setTimeout(() => dom.terminalInput.focus(), 300); console.log('🚀 Reinblacks supper coding - VS Code clone initialized!'); console.log('💡 Try clicking files in the Explorer, or type commands in the terminal!'); } // Start the app init(); })();