import streamlit as st import streamlit_ace as st_ace from pathlib import Path from backend.managers.file_manager import FileManager from backend.managers.execution_engine import ExecutionEngine from backend.managers.debug_logger import DebugLogger LANG_MAP = { ".py": "python", ".tex": "latex", ".js": "javascript", ".html": "html", ".css": "css", ".sh": "bash", ".json": "json", ".yaml": "yaml", ".yml": "yaml" } def run_active_file(): active_file = st.session_state.active_file if not active_file: st.warning("No active file to run.") return execution_engine = ExecutionEngine() debug_logger = DebugLogger() debug_logger.log(f"Executing code from {active_file}...") with st.spinner(f"Running {Path(active_file).name}..."): output = execution_engine.run_code(Path(active_file)) debug_logger.log("Execution completed.") st.session_state.code_execution_output = { "stdout": output["stdout"], "stderr": output["stderr"], "return_code": output["rc"] } result = st.session_state.code_execution_output return result def render_editor(): st.subheader("Code Editor") if not st.session_state.open_files: st.info("Please select a file to edit.") return else: fm = FileManager() try: active_index = st.session_state.open_files.index(st.session_state.active_file) except (ValueError, KeyError): active_index = 0 tab_names = [Path(f).name for f in st.session_state.open_files] tabs = st.tabs(tab_names) for idx, file_path in enumerate(st.session_state.open_files): with tabs[idx]: if file_path not in st.session_state.files_content: st.session_state.files_content[file_path] = fm.read_file(Path(file_path)) file_language = LANG_MAP.get(Path(file_path).suffix, "text") code = st_ace.st_ace( value=st.session_state.files_content[file_path], language=file_language, theme="monokai", key=f"code_editor_{file_path}", auto_update=True, height=400, # tab_size=4, # font_size=14, # show_gutter=True, # show_print_margin=False, # wrap=True ) if code != st.session_state.files_content[file_path]: st.session_state.files_content[file_path] = code cols = st.columns([1, 1, 1, 1]) with cols[0]: if st.button("Save Changes", key=f"save_{file_path}"): content = st.session_state.files_content[file_path] if fm.save_file(file_path, content): st.success("File saved successfully!") with cols[1]: if st.button("Close File", key=f"close_{file_path}"): st.session_state.open_files.remove(file_path) del st.session_state.files_content[file_path] st.success("File closed successfully!") if st.session_state.active_file == file_path: st.session_state.active_file = ( st.session_state.open_files[0] if st.session_state.open_files else None ) st.rerun() # Refresh the page to update the UI with cols[2]: if st.button("Rename File", key=f"rename_{file_path}"): new_name = st.text_input("New File Name", key=f"new_name_{file_path}") if "/" in new_name or "\\" in new_name: st.warning("Do not include slashes in names!") elif new_name: try: fm.rename_file(file_path, new_name) st.success(f"File renamed to '{new_name}' successfully!") st.rerun() except Exception as e: st.error(f"Error renaming file: {e}") with cols[3]: if st.button("Delete File", key=f"delete_{file_path}"): try: fm.delete_file(file_path) st.success(f"File '{Path(file_path).name}' deleted successfully!") st.rerun() except Exception as e: st.error(f"Error deleting file: {e}") if st.button("▶ Run Code", key="run_code"): result = run_active_file() if not result: st.stop() st.subheader("Execution Output") if result["return_code"] == 0: st.success(f"Exit code: {result['return_code']}") else: st.error(f"Exit code: {result['return_code']}") if result["stdout"]: st.text_area( "Standard Output", value=result["stdout"], height=200, disabled=True, key="run_stdout") if result["stderr"]: st.text_area( "Standard Error", value=result["stderr"], height=200, disabled=True, key="run_stderr") if not result["stdout"] and not result["stderr"]: st.info("No output produced by the code execution.") if __name__ == "__main__": render_editor()