164 lines
6.3 KiB
Python
164 lines
6.3 KiB
Python
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
|
|
|
|
st.session_state.active_tab = active_index
|
|
|
|
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 idx == st.session_state.active_tab:
|
|
st.session_state.active_file = file_path
|
|
|
|
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,
|
|
)
|
|
|
|
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.session_state.open_files.remove(file_path)
|
|
del st.session_state.files_content[file_path]
|
|
st.session_state.active_file = (
|
|
st.session_state.open_files[0]
|
|
if st.session_state.open_files
|
|
else None
|
|
)
|
|
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() |