document.addEventListener("DOMContentLoaded", function() { const input = document.getElementById("command-input"); if (!input) return; let commandHistory = JSON.parse(sessionStorage.getItem("commandHistory")) || []; let historyIndex = commandHistory.length; let tabIndex = -1; let tabMatches = []; document.querySelector("form").addEventListener("submit", function(event) { const command = input.value.trim(); if (command) { commandHistory.push(command); sessionStorage.setItem("commandHistory", JSON.stringify(commandHistory)); historyIndex = commandHistory.length; } }); // window.addEventListener("keydown", function(event) { input.addEventListener("keydown", function(event) { if (document.activeElement !== input) return; const cursorPos = input.selectionStart; const textLength = input.value.length; // Prevent default behavior for specific Ctrl+Key shortcuts const key = event.key.toLowerCase(); if ( // event.ctrlKey && [" ", "b", "f", "w", "n", "p", "h", "e", "a", "k", "u", "d", "r", "t"].includes(key)) || // event.altKey && ["b", "d", "f"].includes(key) { event.ctrlKey && [" ", "w", "n", "p", "h", "e", "a", "k", "u", "d", "r", "t"].includes(key)) { event.preventDefault(); event.stopPropagation(); } // Ctrl+A: Move cursor to the beginning if (event.ctrlKey && key === "a") { input.setSelectionRange(0, 0); } // Ctrl+E: Move cursor to the end else if (event.ctrlKey && key === "e") { input.setSelectionRange(textLength, textLength); } // Ctrl+U: Clear the input field else if (event.ctrlKey && key === "u") { input.value = ""; } // Ctrl+K: Delete everything after the cursor else if (event.ctrlKey && key === "k") { input.value = input.value.substring(0, cursorPos); } // Ctrl+W: Delete the previous word else if (event.ctrlKey && key === " ") { const beforeCursor = input.value.substring(0, cursorPos); const afterCursor = input.value.substring(cursorPos); const newBeforeCursor = beforeCursor.replace(/\S+\s*$/, ""); // Delete last word input.value = newBeforeCursor + afterCursor; input.setSelectionRange(newBeforeCursor.length, newBeforeCursor.length); } // Ctrl+H: Delete the previous character (Backspace) else if (event.ctrlKey && key === "h") { if (cursorPos > 0) { input.value = input.value.substring(0, cursorPos - 1) + input.value.substring(cursorPos); input.setSelectionRange(cursorPos - 1, cursorPos - 1); } } // Ctrl+D: Delete character under cursor (or clear input if empty) else if (event.ctrlKey && key === "d") { if (textLength === 0) { console.log("Ctrl+D: No input, simulating EOF"); } else if (cursorPos < textLength) { input.value = input.value.substring(0, cursorPos) + input.value.substring(cursorPos + 1); input.setSelectionRange(cursorPos, cursorPos); } } // Ctrl+P: Previous command (up) else if (event.ctrlKey && key === "p") { if (historyIndex > 0) { historyIndex--; input.value = commandHistory[historyIndex]; } else if (historyIndex === 0) { input.value = commandHistory[0]; } } // Ctrl+N: Next command (down) else if (event.ctrlKey && key === "n") { if (historyIndex < commandHistory.length - 1) { historyIndex++; input.value = commandHistory[historyIndex]; } else { historyIndex = commandHistory.length; input.value = ""; } } // Ctrl+R: Prevent page reload (for future reverse search) else if (event.ctrlKey && key === "r") { console.log("Reverse search triggered (not yet implemented)"); } // Ctrl+B: Move back one character // else if (event.ctrlKey && key === "b") { // event.preventDefault(); // input.setSelectionRange( // Math.max(0, cursorPos - 1), // Math.max(0, cursorPos - 1) // ); // } // Ctrl + F: Move Forward one character // else if (event.ctrlKey && key === "f") { // event.preventDefault(); // input.setSelectionRange( // Math.max(0, cursorPos + 1), // Math.max(0, cursorPos + 1) // ); // } // Alt + B: Move back one word // else if (event.altKey && key === "b") { // event.preventDefault(); // const before = input.value.substring(0, cursorPos); // // Skip whitespace // let pos = before.length; // while(pos > 0 && /\s/.test(before[pos - 1])) pos--; // // Skip word characters // while (pos > 0 && !/\s/.test(before[pos - 1])) pos--; // input.setSelectionRange(pos, pos); // } // Alt + F: Move forward one word // else if (event.altKey && key == "f") { // event.preventDefault(); // const after = input.value.subtring(cursorPos); // let offset = 0; // // Skip current word // while (offset < after.length && !/\s/.test(after[offset])) offset++; // // Skip following whitespace // while (offset < after.length && /\s/.test(after[offset])) offset++; // const newPos = cursorPos + offset; // input.setSelectionRange(newPos, newPos); // } // Alt + D: Delete word after cursor // else if (event.altkey && key == "d") { // event.preventDefault(); // const before = input.value.substring(0, cursorPos); // const after = input.value.substring(cursorPos); // const newAfter = after.replace(/^\s*\S+\s*/, ""); // input.value = before + newAfter; // input.setSelectionRange(cursorPos, cursorPos); // } // Tab Completion else if (event.key === "Tab") { event.preventDefault(); const currentText = input.value.trim(); if (currentText === "") return; // Find all matching commands from history if (tabIndex === -1) { tabMatches = commandHistory.filter(cmd => cmd.startsWith(currentText)); if (tabMatches.length === 0) return; } // Cycle through matches if (event.shiftKey) { tabIndex = tabIndex > 0 ? tabIndex - 1 : tabMatches.length - 1; // Shift+Tab goes backward } else { tabIndex = (tabIndex + 1) % tabMatches.length; } input.value = tabMatches[tabIndex]; } // Allow Enter key to submit form if (event.key === "Enter") { tabIndex = -1; // Reset tab completion cycle return; } }, true); });