provisorisches run
This commit is contained in:
parent
d9a46ba701
commit
da1d22ec56
@ -1,12 +1,41 @@
|
|||||||
class ExecutionEngine:
|
import subprocess
|
||||||
"""
|
import sys
|
||||||
Platzhalter für die Code-Ausführung [1]
|
from pathlib import Path
|
||||||
"""
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def execute_code(self):
|
|
||||||
"""
|
class ExecutionEngine:
|
||||||
Führt Code nicht aus, sondern gibt einen Status aus [1]
|
def run_file(self, filepath: str) -> dict:
|
||||||
"""
|
path = Path(filepath)
|
||||||
return "Code wurde nicht ausgeführt (Platzhalter)"
|
|
||||||
|
if not path.exists():
|
||||||
|
return {"stdout": "", "stderr": f"File not found: {filepath}", "returncode": -1}
|
||||||
|
|
||||||
|
ext = path.suffix.lower()
|
||||||
|
if ext == ".py":
|
||||||
|
cmd = [sys.executable, str(path)]
|
||||||
|
elif ext == ".js":
|
||||||
|
cmd = ["node", str(path)]
|
||||||
|
elif ext == ".sh":
|
||||||
|
cmd = ["bash", str(path)]
|
||||||
|
else:
|
||||||
|
return {"stdout": "", "stderr": f"Unsupported file type: {ext}", "returncode": -1}
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
cmd,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
timeout=30,
|
||||||
|
cwd=str(path.parent),
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
"stdout": result.stdout,
|
||||||
|
"stderr": result.stderr,
|
||||||
|
"returncode": result.returncode,
|
||||||
|
}
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
return {"stdout": "", "stderr": "Timed out after 30 seconds.", "returncode": -1}
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
return {"stdout": "", "stderr": f"Runtime not found: {e}", "returncode": -1}
|
||||||
|
except Exception as e:
|
||||||
|
return {"stdout": "", "stderr": f"Error: {e}", "returncode": -1}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
class FileManager:
|
class FileManager:
|
||||||
"""
|
"""
|
||||||
Handles file reading and writing
|
Handles file reading and writing
|
||||||
|
|||||||
132
src/main.py
132
src/main.py
@ -1,89 +1,109 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import filedialog
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import streamlit as st
|
import streamlit as st
|
||||||
from streamlit_tree_select import tree_select
|
from streamlit_tree_select import tree_select
|
||||||
|
|
||||||
# ---------------- PATH FIX ----------------
|
# ---------------- PATH FIX ----------------
|
||||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
# ---------------- BACKEND ----------------
|
# ---------------- BACKEND ----------------
|
||||||
from backend.file_manager import FileManager
|
from backend.file_manager import FileManager
|
||||||
|
|
||||||
from ui.navigation import FileNavigation
|
from ui.navigation import FileNavigation
|
||||||
from ui.chat import ChatInterface
|
from ui.chat import ChatInterface
|
||||||
from ui.editor import CodeEditor
|
from ui.editor import CodeEditor
|
||||||
from ui.output import OutputDisplay
|
|
||||||
|
|
||||||
from backend.chat_manager import ChatManager
|
from backend.chat_manager import ChatManager
|
||||||
from backend.execution_engine import ExecutionEngine
|
from backend.execution_engine import ExecutionEngine
|
||||||
|
|
||||||
|
# ---------------- PAGE CONFIG ----------------
|
||||||
# ---------------- PAGE ----------------
|
|
||||||
st.set_page_config(
|
st.set_page_config(
|
||||||
page_title="AI Code Editor",
|
page_title="AI Code Editor",
|
||||||
page_icon="💻",
|
page_icon="💻",
|
||||||
layout="wide"
|
layout="wide",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# ---------------- FOLDER PICKER ----------------
|
||||||
|
def pick_folder():
|
||||||
|
root = tk.Tk()
|
||||||
|
root.withdraw()
|
||||||
|
root.wm_attributes("-topmost", 1)
|
||||||
|
folder = filedialog.askdirectory(title="Select project folder")
|
||||||
|
root.destroy()
|
||||||
|
return folder if folder else None
|
||||||
|
|
||||||
# ---------------- SIDEBAR ----------------
|
# ---------------- SIDEBAR ----------------
|
||||||
def render_sidebar():
|
def render_sidebar():
|
||||||
|
st.sidebar.title("File Explorer")
|
||||||
|
|
||||||
st.sidebar.title("📁 File Explorer")
|
root_folder = st.session_state.get("root_folder")
|
||||||
|
|
||||||
navigation = FileNavigation()
|
|
||||||
tree_data = navigation.build_tree(Path.cwd())
|
|
||||||
|
|
||||||
with st.sidebar:
|
with st.sidebar:
|
||||||
selection = tree_select(
|
# --- Button on top ---
|
||||||
tree_data,
|
if st.button("📂 Choose Folder", key="pick_folder"):
|
||||||
check_model="leaf",
|
picked = pick_folder()
|
||||||
only_leaf_checkboxes=True
|
if picked:
|
||||||
)
|
st.session_state.root_folder = picked
|
||||||
|
st.rerun()
|
||||||
|
|
||||||
if selection and selection.get("checked"):
|
if root_folder:
|
||||||
return selection["checked"][0]
|
st.caption(f" {Path(root_folder).name}")
|
||||||
|
|
||||||
|
st.markdown("---")
|
||||||
|
|
||||||
|
# --- Tree below ---
|
||||||
|
if root_folder:
|
||||||
|
try:
|
||||||
|
root_path = Path(root_folder)
|
||||||
|
if root_path.exists() and root_path.is_dir():
|
||||||
|
navigation = FileNavigation()
|
||||||
|
tree_data = navigation.build_tree(root_path)
|
||||||
|
selection = tree_select(
|
||||||
|
tree_data,
|
||||||
|
check_model="leaf",
|
||||||
|
only_leaf_checkboxes=True
|
||||||
|
)
|
||||||
|
if selection and selection.get("checked"):
|
||||||
|
return selection["checked"][0]
|
||||||
|
else:
|
||||||
|
st.warning("Folder not found.")
|
||||||
|
except Exception:
|
||||||
|
st.error("Could not load folder.")
|
||||||
|
else:
|
||||||
|
st.info("No folder selected yet.")
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
# ---------------- MAIN ----------------
|
# ---------------- MAIN ----------------
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
file_manager = FileManager()
|
file_manager = FileManager()
|
||||||
chat_manager = ChatManager()
|
chat_manager = ChatManager()
|
||||||
execution_engine = ExecutionEngine()
|
execution_engine = ExecutionEngine()
|
||||||
|
|
||||||
# ---------------- STATE ----------------
|
# ---------------- STATE ----------------
|
||||||
|
if "root_folder" not in st.session_state:
|
||||||
|
st.session_state.root_folder = None
|
||||||
if "selected_file" not in st.session_state:
|
if "selected_file" not in st.session_state:
|
||||||
st.session_state.selected_file = None
|
st.session_state.selected_file = None
|
||||||
|
|
||||||
if "active_file" not in st.session_state:
|
if "active_file" not in st.session_state:
|
||||||
st.session_state.active_file = None
|
st.session_state.active_file = None
|
||||||
|
|
||||||
if "editor_content" not in st.session_state:
|
if "editor_content" not in st.session_state:
|
||||||
st.session_state.editor_content = ""
|
st.session_state.editor_content = ""
|
||||||
|
|
||||||
if "last_applied_content" not in st.session_state:
|
if "last_applied_content" not in st.session_state:
|
||||||
st.session_state.last_applied_content = ""
|
st.session_state.last_applied_content = ""
|
||||||
|
if "run_result" not in st.session_state:
|
||||||
|
st.session_state.run_result = None
|
||||||
|
|
||||||
# ---------------- FILE SELECT ----------------
|
# ---------------- FILE SELECT ----------------
|
||||||
selected_file = render_sidebar()
|
selected_file = render_sidebar()
|
||||||
|
|
||||||
if selected_file:
|
if selected_file:
|
||||||
st.session_state.selected_file = selected_file
|
st.session_state.selected_file = selected_file
|
||||||
|
|
||||||
current_file = st.session_state.selected_file
|
current_file = st.session_state.selected_file
|
||||||
|
|
||||||
|
|
||||||
# ---------------- FILE SWITCH ----------------
|
# ---------------- FILE SWITCH ----------------
|
||||||
if current_file != st.session_state.active_file:
|
if current_file != st.session_state.active_file:
|
||||||
|
|
||||||
st.session_state.active_file = current_file
|
st.session_state.active_file = current_file
|
||||||
|
st.session_state.run_result = None # clear output on file switch
|
||||||
if current_file:
|
if current_file:
|
||||||
content = file_manager.read_file(current_file)
|
content = file_manager.read_file(current_file)
|
||||||
st.session_state.editor_content = content
|
st.session_state.editor_content = content
|
||||||
@ -91,55 +111,63 @@ def main():
|
|||||||
else:
|
else:
|
||||||
st.session_state.editor_content = ""
|
st.session_state.editor_content = ""
|
||||||
|
|
||||||
|
|
||||||
st.sidebar.markdown("---")
|
st.sidebar.markdown("---")
|
||||||
st.sidebar.caption("AI Code Editor")
|
st.sidebar.caption("AI Code Editor")
|
||||||
|
|
||||||
|
|
||||||
# ---------------- MAIN UI ----------------
|
# ---------------- MAIN UI ----------------
|
||||||
if st.session_state.active_file:
|
if st.session_state.active_file:
|
||||||
|
|
||||||
col1, col2 = st.columns([3, 2])
|
col1, col2 = st.columns([3, 2])
|
||||||
|
|
||||||
with col1:
|
with col1:
|
||||||
|
# --- File name + Run button on same row ---
|
||||||
st.subheader(f"Editing: {Path(st.session_state.active_file).name}")
|
title_col, btn_col = st.columns([5, 1])
|
||||||
|
with title_col:
|
||||||
|
st.subheader(f"✏️ {Path(st.session_state.active_file).name}")
|
||||||
|
with btn_col:
|
||||||
|
run_clicked = st.button("▶ Run", type="primary", use_container_width=True)
|
||||||
|
|
||||||
editor = CodeEditor()
|
editor = CodeEditor()
|
||||||
|
|
||||||
# IMPORTANT: only updates AFTER APPLY
|
|
||||||
new_value = editor.display_code(
|
new_value = editor.display_code(
|
||||||
st.session_state.editor_content,
|
st.session_state.editor_content,
|
||||||
filename=st.session_state.active_file
|
filename=st.session_state.active_file
|
||||||
)
|
)
|
||||||
|
|
||||||
# ---------------- APPLY DETECTION ----------------
|
|
||||||
# Apply only triggers when Streamlit reruns with new value
|
|
||||||
if new_value is not None:
|
if new_value is not None:
|
||||||
|
|
||||||
if new_value != st.session_state.last_applied_content:
|
if new_value != st.session_state.last_applied_content:
|
||||||
|
|
||||||
st.session_state.editor_content = new_value
|
st.session_state.editor_content = new_value
|
||||||
st.session_state.last_applied_content = new_value
|
st.session_state.last_applied_content = new_value
|
||||||
|
file_manager.save_file(st.session_state.active_file, new_value)
|
||||||
|
st.success("Saved ✔")
|
||||||
|
|
||||||
file_manager.save_file(
|
# --- Run execution ---
|
||||||
st.session_state.active_file,
|
if run_clicked:
|
||||||
new_value
|
with st.spinner("Running…"):
|
||||||
|
st.session_state.run_result = execution_engine.run_file(
|
||||||
|
st.session_state.active_file
|
||||||
)
|
)
|
||||||
|
|
||||||
st.success("Saved via Apply ✔")
|
|
||||||
|
|
||||||
with col2:
|
with col2:
|
||||||
|
|
||||||
chat = ChatInterface()
|
chat = ChatInterface()
|
||||||
chat.display_chat(chat_manager)
|
chat.display_chat(chat_manager)
|
||||||
|
|
||||||
output = OutputDisplay()
|
# --- Output panel ---
|
||||||
output.display_execution(execution_engine)
|
result = st.session_state.run_result
|
||||||
|
if result is not None:
|
||||||
|
st.markdown("---")
|
||||||
|
success = result["returncode"] == 0
|
||||||
|
|
||||||
|
status = "✅ Exited 0" if success else f"❌ Exited {result['returncode']}"
|
||||||
|
st.caption(f"Output — {status}")
|
||||||
|
|
||||||
|
if result["stdout"]:
|
||||||
|
st.code(result["stdout"], language="text")
|
||||||
|
|
||||||
|
if result["stderr"]:
|
||||||
|
st.code(result["stderr"], language="text")
|
||||||
|
|
||||||
|
if not result["stdout"] and not result["stderr"]:
|
||||||
|
st.caption("No output.")
|
||||||
else:
|
else:
|
||||||
st.info("Select a file from the explorer 👈")
|
st.info("Select a file from the explorer")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
@ -28,7 +28,6 @@ class CodeEditor:
|
|||||||
language=language,
|
language=language,
|
||||||
theme="chrome",
|
theme="chrome",
|
||||||
key=f"ace_{filename}",
|
key=f"ace_{filename}",
|
||||||
height=500,
|
|
||||||
font_size=14,
|
font_size=14,
|
||||||
tab_size=4,
|
tab_size=4,
|
||||||
wrap=False,
|
wrap=False,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user