cli-sim-2-kl / index.html
dokii's picture
Add 3 files
0e5268d verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>KickLang CLI Simulator</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
font-family: 'Courier New', monospace;
}
.blink {
animation: blink 1s infinite;
}
@keyframes blink {
0%, 50%, 100% { opacity: 1; }
25%, 75% { opacity: 0; }
}
.terminal {
height: 100vh;
overflow-y: auto;
}
</style>
</head>
<body class="bg-black text-green-400 p-4">
<div id="app" class="max-w-3xl mx-auto flex flex-col h-screen">
<div id="output" class="flex-grow overflow-y-auto terminal p-4"></div>
<div class="flex items-center mt-2">
<span id="prompt" class="mr-2">$</span>
<input id="input" class="bg-transparent outline-none flex-grow" autofocus />
<span class="blink">|</span>
</div>
</div>
<script>
const output = document.getElementById('output');
const input = document.getElementById('input');
const prompt = document.getElementById('prompt');
// Simulated file system (in-memory object)
const vfs = {
'/': {
type: 'dir',
children: {
'home': {
type: 'dir',
children: {
'user': {
type: 'dir',
children: {
'README.md': {
type: 'file',
content: 'Welcome to KickLang CLI Simulator!'
},
'projects': {
type: 'dir',
children: {}
}
}
}
}
}
}
}
};
let currentPath = '/home/user';
let history = [];
let historyIndex = 0;
const commands = {
help: () => {
return `Available commands:\n- help\n- ls\n- cd <dir>\n- cat <file>\n- echo <text>\n- clear\n- history\n- mkdir <dir>\n- touch <file>\n- rm <file|dir>\n- generate kicklang`;
},
ls: () => {
const node = getNode(currentPath);
if (!node || node.type !== 'dir') return 'Not a directory';
return Object.keys(node.children).join(' ');
},
cd: (args) => {
if (!args[0]) return `Usage: cd <dir>`;
const target = resolvePath(currentPath, args[0]);
const node = getNode(target);
if (!node || node.type !== 'dir') return `No such directory: ${args[0]}`;
currentPath = target;
prompt.textContent = `${currentPath}$`;
return '';
},
cat: (args) => {
if (!args[0]) return `Usage: cat <file>`;
const path = resolvePath(currentPath, args[0]);
const node = getNode(path);
if (!node || node.type !== 'file') return `No such file: ${args[0]}`;
return node.content;
},
echo: (args) => {
return args.join(' ');
},
clear: () => {
output.innerHTML = '';
return '';
},
history: () => {
return history.join('\n');
},
mkdir: (args) => {
if (!args[0]) return `Usage: mkdir <dir>`;
const path = resolvePath(currentPath, args[0]);
const parentPath = path.split('/').slice(0, -1).join('/') || '/';
const dirName = path.split('/').pop();
const parent = getNode(parentPath);
if (!parent || parent.type !== 'dir') return `Invalid parent directory`;
if (parent.children[dirName]) return `Directory already exists: ${dirName}`;
parent.children[dirName] = { type: 'dir', children: {} };
return '';
},
touch: (args) => {
if (!args[0]) return `Usage: touch <file>`;
const path = resolvePath(currentPath, args[0]);
const parentPath = path.split('/').slice(0, -1).join('/') || '/';
const fileName = path.split('/').pop();
const parent = getNode(parentPath);
if (!parent || parent.type !== 'dir') return `Invalid path`;
if (parent.children[fileName]) return `File already exists: ${fileName}`;
parent.children[fileName] = { type: 'file', content: '' };
return '';
},
rm: (args) => {
if (!args[0]) return `Usage: rm <file|dir>`;
const path = resolvePath(currentPath, args[0]);
const parentPath = path.split('/').slice(0, -1).join('/') || '/';
const name = path.split('/').pop();
const parent = getNode(parentPath);
if (!parent || parent.type !== 'dir') return `Invalid path`;
if (!parent.children[name]) return `No such file or directory: ${name}`;
delete parent.children[name];
return '';
},
generate: (args) => {
if (args[0] !== 'kicklang') return 'Usage: generate kicklang';
return generateKickLangScript();
}
};
function getNode(path) {
const parts = path.split('/').filter(p => p);
let node = vfs['/'];
for (let part of parts) {
if (!node || node.type !== 'dir' || !node.children[part]) return null;
node = node.children[part];
}
return node;
}
function resolvePath(base, relative) {
if (relative.startsWith('/')) return relative;
const baseParts = base.split('/').filter(p => p);
const relParts = relative.split('/').filter(p => p);
for (let part of relParts) {
if (part === '..') baseParts.pop();
else if (part !== '.') baseParts.push(part);
}
return '/' + baseParts.join('/');
}
function addOutput(lines, className = '') {
const div = document.createElement('div');
div.className = className;
div.textContent = lines;
output.appendChild(div);
output.scrollTop = output.scrollHeight;
}
function executeCommand(cmd) {
const [command, ...args] = cmd.trim().split(' ');
const handler = commands[command];
if (handler) {
const result = handler(args);
return result;
} else {
return `Command not found: ${command}`;
}
}
function generateKickLangScript() {
const script = [];
script.push('// KickLang Script Template\n');
script.push(`// Initial VFS State\nconst vfs = ${JSON.stringify(vfs, null, 2)};`);
script.push('\n// KickLang Simulation Logic\nfunction simulateCLI() {');
script.push(' let currentPath = "' + currentPath + '";');
script.push(' let history = ' + JSON.stringify(history) + ';\n');
script.push(' // Define commands here...\n');
script.push(' // Add logic to simulate CLI behavior...\n');
script.push(' console.log("KickLang simulation started");');
script.push('}');
script.push('\nsimulateCLI();');
return script.join('\n');
}
input.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
const cmd = input.value;
if (cmd.trim()) {
history.push(`$ ${cmd}`);
addOutput(`$ ${cmd}`);
const result = executeCommand(cmd);
if (result) addOutput(result);
historyIndex = history.length;
}
input.value = '';
} else if (e.key === 'ArrowUp') {
if (historyIndex > 0) {
historyIndex--;
input.value = history[historyIndex].replace(/^\$ /, '');
}
} else if (e.key === 'ArrowDown') {
if (historyIndex < history.length) {
historyIndex++;
input.value = historyIndex < history.length
? history[historyIndex].replace(/^\$ /, '')
: '';
}
}
});
// Initial prompt
addOutput('Welcome to KickLang CLI Simulator. Type "help" to get started.');
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-qwensite.hf.space/logo.svg" alt="qwensite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-qwensite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >QwenSite</a> - 🧬 <a href="https://enzostvs-qwensite.hf.space?remix=dokii/cli-sim-2-kl" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>