|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Linux Practice Tool</title> |
|
<style> |
|
body { |
|
font-family: 'Courier New', monospace; |
|
background-color: #300a24; |
|
color: #ffffff; |
|
margin: 0; |
|
padding: 10px; |
|
} |
|
#terminal { |
|
width: 100%; |
|
height: 100vh; |
|
overflow-y: auto; |
|
} |
|
#output { |
|
white-space: pre-wrap; |
|
} |
|
#input-line { |
|
display: flex; |
|
margin-top: 10px; |
|
} |
|
#prompt { |
|
color: #4e9a06; |
|
margin-right: 5px; |
|
} |
|
#command-input { |
|
flex-grow: 1; |
|
background-color: transparent; |
|
border: none; |
|
color: #ffffff; |
|
font-family: inherit; |
|
font-size: inherit; |
|
outline: none; |
|
} |
|
.directory { color: #3465a4; } |
|
.executable { color: #4e9a06; } |
|
.image { color: #75507b; } |
|
.archive { color: #c4a000; } |
|
.text { color: #cc0000; } |
|
</style> |
|
</head> |
|
<body> |
|
<div id="terminal"> |
|
<div id="output"></div> |
|
<div id="input-line"> |
|
<span id="prompt">$</span> |
|
<input type="text" id="command-input" autofocus> |
|
</div> |
|
</div> |
|
<script> |
|
const output = document.getElementById('output'); |
|
const input = document.getElementById('command-input'); |
|
let commandHistory = []; |
|
let historyIndex = -1; |
|
let currentDirectory = '/'; |
|
|
|
input.addEventListener('keydown', async (event) => { |
|
if (event.key === 'Enter') { |
|
event.preventDefault(); |
|
const command = input.value.trim(); |
|
if (command) { |
|
commandHistory.push(command); |
|
historyIndex = commandHistory.length; |
|
await executeCommand(command); |
|
} |
|
input.value = ''; |
|
} else if (event.key === 'ArrowUp') { |
|
event.preventDefault(); |
|
if (historyIndex > 0) { |
|
historyIndex--; |
|
input.value = commandHistory[historyIndex]; |
|
} |
|
} else if (event.key === 'ArrowDown') { |
|
event.preventDefault(); |
|
if (historyIndex < commandHistory.length - 1) { |
|
historyIndex++; |
|
input.value = commandHistory[historyIndex]; |
|
} else { |
|
historyIndex = commandHistory.length; |
|
input.value = ''; |
|
} |
|
} |
|
}); |
|
|
|
async function executeCommand(command) { |
|
if (command.toLowerCase() === 'help') { |
|
displayHelp(); |
|
} else { |
|
output.innerHTML += `<span id="prompt">$</span> ${command}\n`; |
|
|
|
try { |
|
const response = await fetch('/execute', { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
}, |
|
body: JSON.stringify({ command, currentDirectory }), |
|
}); |
|
|
|
const data = await response.json(); |
|
|
|
if (response.ok) { |
|
if (command.startsWith('cd ')) { |
|
currentDirectory = data.currentDirectory; |
|
} |
|
output.innerHTML += colorize(data.output); |
|
if (data.error) { |
|
output.innerHTML += `<span style="color: #cc0000;">Error: ${data.error}</span>\n`; |
|
} |
|
} else { |
|
output.innerHTML += `<span style="color: #cc0000;">Error: ${data.detail}</span>\n`; |
|
} |
|
} catch (error) { |
|
output.innerHTML += `<span style="color: #cc0000;">Error: ${error.message}</span>\n`; |
|
} |
|
} |
|
|
|
output.scrollTop = output.scrollHeight; |
|
} |
|
|
|
function colorize(text) { |
|
const lines = text.split('\n'); |
|
return lines.map(line => { |
|
return line.replace(/(\S+)/g, (match) => { |
|
if (match.endsWith('/')) return `<span class="directory">${match}</span>`; |
|
if (match.endsWith('.exe') || match.endsWith('.sh')) return `<span class="executable">${match}</span>`; |
|
if (match.match(/\.(jpg|jpeg|png|gif|bmp)$/i)) return `<span class="image">${match}</span>`; |
|
if (match.match(/\.(zip|tar|gz|rar)$/i)) return `<span class="archive">${match}</span>`; |
|
if (match.match(/\.(txt|md|log)$/i)) return `<span class="text">${match}</span>`; |
|
return match; |
|
}); |
|
}).join('\n'); |
|
} |
|
|
|
function displayHelp() { |
|
const helpText = ` |
|
Available commands: |
|
- ls: List directory contents |
|
- cd: Change directory |
|
- pwd: Print working directory |
|
- echo: Display a line of text |
|
- cat: Concatenate files and print on the standard output |
|
- grep: Print lines that match patterns |
|
- find: Search for files in a directory hierarchy |
|
- touch: Change file timestamps |
|
- mkdir: Make directories |
|
- rm: Remove files or directories |
|
- cp: Copy files and directories |
|
- mv: Move (rename) files |
|
|
|
Type 'help' to see this message again. |
|
`; |
|
output.innerHTML += helpText; |
|
} |
|
|
|
|
|
document.getElementById('terminal').addEventListener('click', () => { |
|
input.focus(); |
|
}); |
|
|
|
|
|
output.innerHTML = "Welcome to the Linux Practice Tool!\nType 'help' for a list of available commands.\n\n"; |
|
</script> |
|
</body> |
|
</html> |