ayoub-edit-code / index.html
ayoubghilmi's picture
Add 2 files
2cad0aa verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PyWeb - Online Python Editor</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<style>
.editor-container {
}
.editor {
height: 100%;
font-size: 14px;
line-height: 1.5;
tab-size: 4;
}
.output {
height: 100%;
overflow-y: auto;
white-space: pre-wrap;
background-color: #1e1e1e;
color: #d4d4d4;
font-family: 'Courier New', monospace;
padding: 10px;
}
.sidebar {
transition: all 0.3s ease;
}
.sidebar.collapsed {
width: 50px;
}
.sidebar-item {
transition: all 0.2s ease;
}
.sidebar-item:hover {
background-color: rgba(255, 255, 255, 0.1);
}
.tab {
transition: all 0.2s ease;
}
.tab.active {
border-bottom: 2px solid #3b82f6;
}
.autocomplete-list {
position: absolute;
background: #2d2d2d;
border: 1px solid #444;
max-height: 200px;
overflow-y: auto;
z-index: 100;
width: 200px;
}
.autocomplete-item {
padding: 5px 10px;
cursor: pointer;
}
.autocomplete-item:hover {
background-color: #3b82f6;
}
.line-numbers {
background-color: #1e1e1e;
color: #858585;
text-align: right;
padding-right: 10px;
user-select: none;
}
.python-keyword {
color: #569cd6;
}
.python-string {
color: #ce9178;
}
.python-comment {
color: #6a9955;
}
.python-function {
color: #dcdcaa;
}
.python-number {
color: #b5cea8;
}
.terminal {
height: 100%;
background-color: #1e1e1e;
color: #d4d4d4;
font-family: 'Courier New', monospace;
padding: 10px;
overflow-y: auto;
}
.terminal-input {
background-color: transparent;
border: none;
outline: none;
color: #d4d4d4;
font-family: 'Courier New', monospace;
width: 90%;
}
.terminal-prompt {
color: #4CAF50;
}
.terminal-cursor {
display: inline-block;
width: 10px;
height: 15px;
background-color: #d4d4d4;
animation: blink 1s infinite;
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
.terminal-output {
margin-bottom: 10px;
white-space: pre-wrap;
}
</style>
</head>
<body class="bg-gray-900 text-white">
<div class="flex flex-col h-screen">
<!-- Top Navigation -->
<div class="bg-gray-800 px-4 py-2 flex items-center justify-between border-b border-gray-700">
<div class="flex items-center space-x-4">
<div class="flex items-center">
<i class="fab fa-python text-blue-400 text-2xl mr-2"></i>
<h1 class="text-xl font-bold">PyWeb</h1>
</div>
<div class="hidden md:flex space-x-2">
<button class="px-3 py-1 rounded hover:bg-gray-700 flex items-center">
<i class="fas fa-file mr-1"></i> New
</button>
<button class="px-3 py-1 rounded hover:bg-gray-700 flex items-center">
<i class="fas fa-folder-open mr-1"></i> Open
</button>
<button class="px-3 py-1 rounded hover:bg-gray-700 flex items-center">
<i class="fas fa-save mr-1"></i> Save
</button>
</div>
</div>
<div class="flex items-center space-x-4">
<button id="run-btn" class="bg-green-600 hover:bg-green-700 px-4 py-1 rounded flex items-center">
<i class="fas fa-play mr-1"></i> Run
</button>
<div class="relative">
<button class="px-3 py-1 rounded hover:bg-gray-700">
<i class="fas fa-cog"></i>
</button>
</div>
</div>
</div>
<!-- Main Content -->
<div class="flex flex-1 overflow-hidden">
<!-- Sidebar -->
<div id="sidebar" class="sidebar bg-gray-800 w-64 flex flex-col border-r border-gray-700">
<div class="p-3 border-b border-gray-700 flex justify-between items-center">
<h2 class="font-semibold">Explorer</h2>
<button id="sidebar-toggle" class="text-gray-400 hover:text-white">
<i class="fas fa-chevron-left"></i>
</button>
</div>
<div class="flex-1 overflow-y-auto">
<div class="py-2">
<div class="sidebar-item px-4 py-2 flex items-center cursor-pointer">
<i class="fas fa-folder-open text-blue-400 mr-2"></i>
<span>Project</span>
</div>
<div class="ml-6">
<div class="sidebar-item px-4 py-2 flex items-center cursor-pointer">
<i class="fas fa-file-code text-yellow-400 mr-2"></i>
<span>main.py</span>
</div>
<div class="sidebar-item px-4 py-2 flex items-center cursor-pointer">
<i class="fas fa-file-code text-yellow-400 mr-2"></i>
<span>utils.py</span>
</div>
</div>
</div>
<div class="py-2 border-t border-gray-700">
<div class="sidebar-item px-4 py-2 flex items-center cursor-pointer">
<i class="fas fa-search text-purple-400 mr-2"></i>
<span>Search</span>
</div>
</div>
<div class="py-2 border-t border-gray-700">
<div id="terminal-tab" class="sidebar-item px-4 py-2 flex items-center cursor-pointer">
<i class="fas fa-terminal text-green-400 mr-2"></i>
<span>Terminal</span>
</div>
</div>
</div>
</div>
<!-- Editor Area -->
<div class="flex-1 flex flex-col overflow-hidden">
<!-- Tabs -->
<div class="bg-gray-800 border-b border-gray-700 flex overflow-x-auto">
<div id="editor-tab" class="tab active px-4 py-2 flex items-center border-r border-gray-700 cursor-pointer">
<i class="fas fa-file-code text-yellow-400 mr-2"></i>
<span>main.py</span>
<i class="fas fa-times ml-2 text-gray-400 hover:text-white"></i>
</div>
<div class="tab px-4 py-2 flex items-center border-r border-gray-700 cursor-pointer">
<i class="fas fa-file-code text-yellow-400 mr-2"></i>
<span>utils.py</span>
<i class="fas fa-times ml-2 text-gray-400 hover:text-white"></i>
</div>
<div class="px-4 py-2 flex items-center cursor-pointer hover:bg-gray-700">
<i class="fas fa-plus text-gray-400"></i>
</div>
</div>
<!-- Editor and Output -->
<div id="editor-container" class="editor-container flex flex-col md:flex-row flex-1 overflow-hidden">
<!-- Editor -->
<div class="flex-1 flex overflow-hidden">
<div class="line-numbers overflow-y-auto"></div>
<textarea id="editor" class="editor flex-1 bg-gray-900 text-white p-4 outline-none resize-none overflow-auto" spellcheck="false"># Welcome to PyWeb - Python Editor
# Write your Python code here and click Run
def greet(name):
"""A simple greeting function"""
return f"Hello, {name}!"
print(greet("World"))
# Try some math
result = 42 + 3.14 * 2
print(f"The answer is {result}")
# List comprehension example
squares = [x**2 for x in range(10)]
print(f"Squares: {squares}")</textarea>
</div>
<!-- Output -->
<div class="w-full md:w-1/3 bg-gray-800 border-t md:border-t-0 md:border-l border-gray-700 flex flex-col">
<div class="bg-gray-700 px-4 py-2 flex justify-between items-center">
<h3 class="font-semibold">Output</h3>
<div class="flex space-x-2">
<button id="clear-output" class="text-gray-400 hover:text-white">
<i class="fas fa-trash-alt"></i>
</button>
<button class="text-gray-400 hover:text-white">
<i class="fas fa-expand"></i>
</button>
</div>
</div>
<pre id="output" class="output flex-1"></pre>
</div>
</div>
<!-- Terminal (hidden by default) -->
<div id="terminal-container" class="editor-container flex flex-col flex-1 overflow-hidden" style="display: none;">
<div class="terminal flex-1 flex flex-col">
<div class="bg-gray-700 px-4 py-2 flex justify-between items-center">
<h3 class="font-semibold">Terminal</h3>
<div class="flex space-x-2">
<button id="clear-terminal" class="text-gray-400 hover:text-white">
<i class="fas fa-trash-alt"></i>
</button>
<button id="close-terminal" class="text-gray-400 hover:text-white">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<div id="terminal-content" class="flex-1 overflow-y-auto p-2">
<div class="terminal-output">
PyWeb Terminal v1.0<br>
Type 'help' for a list of commands<br><br>
</div>
<div class="terminal-line flex items-center">
<span class="terminal-prompt">user@pyweb:~$&nbsp;</span>
<input id="terminal-input" class="terminal-input" type="text" autofocus>
<span class="terminal-cursor"></span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Status Bar -->
<div class="bg-gray-800 px-4 py-1 flex justify-between items-center text-sm border-t border-gray-700">
<div class="flex items-center space-x-4">
<div class="flex items-center">
<i class="fab fa-python text-blue-400 mr-1"></i>
<span>Python 3.10</span>
</div>
<div class="hidden md:flex items-center">
<i class="fas fa-code-branch text-purple-400 mr-1"></i>
<span>main</span>
</div>
</div>
<div class="flex items-center space-x-4">
<div class="flex items-center">
<i class="fas fa-memory text-yellow-400 mr-1"></i>
<span>128 MB</span>
</div>
<div class="flex items-center">
<i class="fas fa-bolt text-green-400 mr-1"></i>
<span id="status-ready">Ready</span>
</div>
</div>
</div>
</div>
<script>
// DOM Elements
const editor = document.getElementById('editor');
const output = document.getElementById('output');
const runBtn = document.getElementById('run-btn');
const clearOutputBtn = document.getElementById('clear-output');
const sidebar = document.getElementById('sidebar');
const sidebarToggle = document.getElementById('sidebar-toggle');
const statusReady = document.getElementById('status-ready');
const terminalTab = document.getElementById('terminal-tab');
const editorTab = document.getElementById('editor-tab');
const terminalContainer = document.getElementById('terminal-container');
const editorContainer = document.getElementById('editor-container');
const terminalContent = document.getElementById('terminal-content');
const terminalInput = document.getElementById('terminal-input');
const clearTerminalBtn = document.getElementById('clear-terminal');
const closeTerminalBtn = document.getElementById('close-terminal');
// Terminal state
let terminalHistory = [];
let historyIndex = -1;
let currentDirectory = '~';
// Initialize line numbers
function updateLineNumbers() {
const lineNumbers = document.querySelector('.line-numbers');
const lines = editor.value.split('\n');
lineNumbers.innerHTML = '';
for (let i = 1; i <= lines.length; i++) {
const lineNumber = document.createElement('div');
lineNumber.textContent = i;
lineNumbers.appendChild(lineNumber);
}
}
// Syntax highlighting (simplified)
function applySyntaxHighlighting() {
// This is a simplified version - a real implementation would use a proper lexer
const code = editor.value;
// Keywords to highlight
const keywords = ['def', 'return', 'if', 'else', 'elif', 'for', 'while', 'in', 'and', 'or', 'not', 'True', 'False', 'None', 'import', 'from', 'as', 'class', 'try', 'except', 'finally', 'with', 'raise', 'is', 'lambda', 'nonlocal', 'global', 'yield', 'async', 'await'];
// Simple regex-based highlighting
let highlighted = code
.replace(/(".*?"|'.*?')/g, '<span class="python-string">$1</span>')
.replace(/#.*$/gm, '<span class="python-comment">$&</span>')
.replace(/\b\d+\.?\d*\b/g, '<span class="python-number">$&</span>')
.replace(new RegExp(`\\b(${keywords.join('|')})\\b`, 'g'), '<span class="python-keyword">$1</span>')
.replace(/\b(def|class)\s+(\w+)\b/g, '<span class="python-keyword">$1</span> <span class="python-function">$2</span>');
// Create a temporary div to hold the highlighted code
const tempDiv = document.createElement('div');
tempDiv.innerHTML = highlighted;
// Get the cursor position
const cursorPos = editor.selectionStart;
// Replace the editor content (this will lose the cursor position)
// In a real implementation, we would use a proper code editor library
// that maintains cursor position during highlighting
// For now, we'll just update the line numbers
updateLineNumbers();
}
// Run Python code
async function runPythonCode() {
const code = editor.value;
output.textContent = 'Running...';
statusReady.textContent = 'Running';
runBtn.disabled = true;
runBtn.classList.remove('bg-green-600', 'hover:bg-green-700');
runBtn.classList.add('bg-gray-600', 'cursor-not-allowed');
try {
// In a real implementation, you would send this to a backend service
// that can execute Python code safely. For this demo, we'll simulate
// execution with a timeout and some example output.
// Simulate network delay
await new Promise(resolve => setTimeout(resolve, 500));
// Simulate execution
const result = simulatePythonExecution(code);
output.textContent = result;
statusReady.textContent = 'Ready';
} catch (error) {
output.textContent = `Error: ${error.message}`;
statusReady.textContent = 'Error';
} finally {
runBtn.disabled = false;
runBtn.classList.add('bg-green-600', 'hover:bg-green-700');
runBtn.classList.remove('bg-gray-600', 'cursor-not-allowed');
}
}
// Simulate Python execution (for demo purposes)
function simulatePythonExecution(code) {
// This is just for demonstration - in a real app, you'd use a proper Python interpreter
// Check for some common patterns to simulate different outputs
if (code.includes('import os') && code.includes('os.system')) {
return "Error: Restricted system call (os.system)";
}
if (code.includes('while True:')) {
return "Error: Potential infinite loop detected";
}
if (code.includes('import sys') && code.includes('sys.exit')) {
return "Process finished with exit code 0";
}
// Default simulated output
return `Hello, World!
The answer is 48.28
Squares: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Process finished with exit code 0`;
}
// Clear output
function clearOutput() {
output.textContent = '';
}
// Toggle sidebar
function toggleSidebar() {
sidebar.classList.toggle('collapsed');
const icon = sidebarToggle.querySelector('i');
if (sidebar.classList.contains('collapsed')) {
icon.classList.remove('fa-chevron-left');
icon.classList.add('fa-chevron-right');
} else {
icon.classList.remove('fa-chevron-right');
icon.classList.add('fa-chevron-left');
}
}
// Terminal functions
function showTerminal() {
editorContainer.style.display = 'none';
terminalContainer.style.display = 'flex';
terminalInput.focus();
}
function showEditor() {
terminalContainer.style.display = 'none';
editorContainer.style.display = 'flex';
}
function clearTerminal() {
terminalContent.innerHTML = `
<div class="terminal-output">
PyWeb Terminal v1.0<br>
Type 'help' for a list of commands<br><br>
</div>
<div class="terminal-line flex items-center">
<span class="terminal-prompt">user@pyweb:~$&nbsp;</span>
<input id="terminal-input" class="terminal-input" type="text" autofocus>
<span class="terminal-cursor"></span>
</div>
`;
terminalInput = document.getElementById('terminal-input');
terminalInput.focus();
setupTerminalInput();
}
function setupTerminalInput() {
terminalInput.addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
const command = terminalInput.value.trim();
if (command) {
terminalHistory.push(command);
historyIndex = terminalHistory.length;
processCommand(command);
}
} else if (e.key === 'ArrowUp') {
if (terminalHistory.length > 0 && historyIndex > 0) {
historyIndex--;
terminalInput.value = terminalHistory[historyIndex];
e.preventDefault();
}
} else if (e.key === 'ArrowDown') {
if (terminalHistory.length > 0 && historyIndex < terminalHistory.length - 1) {
historyIndex++;
terminalInput.value = terminalHistory[historyIndex];
e.preventDefault();
} else if (historyIndex === terminalHistory.length - 1) {
historyIndex = terminalHistory.length;
terminalInput.value = '';
e.preventDefault();
}
}
});
}
function processCommand(command) {
// Add the command to the terminal output
const outputDiv = document.createElement('div');
outputDiv.className = 'terminal-output';
outputDiv.innerHTML = `<span class="terminal-prompt">user@pyweb:~$&nbsp;</span>${command}`;
terminalContent.insertBefore(outputDiv, terminalContent.lastElementChild);
// Process the command
let response = '';
const args = command.split(' ');
const cmd = args[0].toLowerCase();
switch (cmd) {
case 'help':
response = `Available commands:<br>
help - Show this help message<br>
clear - Clear the terminal<br>
ls - List files<br>
cd [dir] - Change directory<br>
run - Run the current Python code<br>
python [code] - Execute Python code<br>
exit - Close the terminal`;
break;
case 'clear':
clearTerminal();
return;
case 'ls':
response = `main.py<br>utils.py<br>README.md`;
break;
case 'cd':
if (args.length > 1) {
currentDirectory = args[1];
response = `Changed directory to ${currentDirectory}`;
} else {
response = `Usage: cd [directory]`;
}
break;
case 'run':
runPythonCode();
response = `Running Python code from editor...`;
break;
case 'python':
if (args.length > 1) {
const pythonCode = args.slice(1).join(' ');
try {
// This is just for demo - in a real app you'd use a proper interpreter
if (pythonCode.includes('print')) {
response = pythonCode.includes('"') ?
pythonCode.match(/"([^"]*)"/)[1] :
pythonCode.match(/'([^']*)'/)[1];
} else {
response = `Executed: ${pythonCode}`;
}
} catch (e) {
response = `Error: ${e.message}`;
}
} else {
response = `Usage: python [code]`;
}
break;
case 'exit':
showEditor();
return;
default:
response = `Command not found: ${cmd}. Type 'help' for available commands.`;
}
// Add the response to the terminal
const responseDiv = document.createElement('div');
responseDiv.className = 'terminal-output';
responseDiv.innerHTML = response;
terminalContent.insertBefore(responseDiv, terminalContent.lastElementChild);
// Add a new input line
const newInputDiv = document.createElement('div');
newInputDiv.className = 'terminal-line flex items-center';
newInputDiv.innerHTML = `
<span class="terminal-prompt">user@pyweb:${currentDirectory}$&nbsp;</span>
<input id="terminal-input" class="terminal-input" type="text" autofocus>
<span class="terminal-cursor"></span>
`;
terminalContent.appendChild(newInputDiv);
// Remove the old input
terminalContent.removeChild(terminalContent.lastElementChild.previousElementSibling);
// Set up the new input
terminalInput = document.getElementById('terminal-input');
setupTerminalInput();
terminalInput.focus();
}
// Event Listeners
editor.addEventListener('input', updateLineNumbers);
editor.addEventListener('keydown', function(e) {
if (e.key === 'Tab') {
e.preventDefault();
const start = this.selectionStart;
const end = this.selectionEnd;
// Insert tab character
this.value = this.value.substring(0, start) + ' ' + this.value.substring(end);
// Move cursor
this.selectionStart = this.selectionEnd = start + 4;
updateLineNumbers();
}
});
runBtn.addEventListener('click', runPythonCode);
clearOutputBtn.addEventListener('click', clearOutput);
sidebarToggle.addEventListener('click', toggleSidebar);
terminalTab.addEventListener('click', showTerminal);
editorTab.addEventListener('click', showEditor);
clearTerminalBtn.addEventListener('click', clearTerminal);
closeTerminalBtn.addEventListener('click', showEditor);
// Initialize
updateLineNumbers();
setupTerminalInput();
// Auto-resize editor when window resizes
window.addEventListener('resize', function() {
updateLineNumbers();
});
</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-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=ayoubghilmi/ayoub-edit-code" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>