File size: 6,804 Bytes
be5d112
 
aba525f
6730e6f
dd04902
7add1f7
0e0ba0f
aba525f
 
be5d112
089452f
 
 
 
 
 
 
 
 
be5d112
dd04902
 
 
 
 
 
 
 
089452f
be5d112
 
 
 
 
 
 
 
 
0e0ba0f
dd04902
1ab7509
0e0ba0f
 
 
7add1f7
1ab7509
7add1f7
 
1ab7509
 
 
be5d112
7add1f7
1ab7509
7add1f7
0e0ba0f
7add1f7
1ab7509
 
 
7add1f7
1ab7509
 
 
7add1f7
1ab7509
 
 
7add1f7
 
be5d112
 
7add1f7
 
6aef7da
 
 
 
 
 
 
 
 
 
6730e6f
 
 
 
 
 
 
 
 
 
 
 
 
aba525f
 
 
 
be5d112
aba525f
9706206
aba525f
 
0e0ba0f
aba525f
 
 
 
 
7add1f7
aba525f
dd04902
 
 
 
aba525f
 
 
 
 
dd04902
 
 
c6c4170
dd04902
aba525f
 
 
0e0ba0f
dd04902
 
6aef7da
 
aba525f
be5d112
dd04902
7add1f7
 
 
76a0fe4
7add1f7
76a0fe4
 
 
 
 
 
6aef7da
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# code_editor.py

import streamlit as st
import streamlit_ace as st_ace
import os
import time, psutil
from pathlib import Path
from utils import execute_code

# Default code snippets
DEFAULT_SNIPPETS = {
    "Python": '''# default code\na = int(input())\nb = int(input())\nprint("Sum:", a + b)''',
    "C": '''// default code\n#include <stdio.h>\nint main() {\n    int a, b;\n    scanf("%d %d", &a, &b);\n    printf("Sum: %d\\n", a + b);\n    return 0;\n}''',
    "C++": '''// default code\n#include <iostream>\nusing namespace std;\nint main() {\n    int a, b;\n    cin >> a >> b;\n    cout << "Sum: " << a + b << endl;\n    return 0;\n}''',
    "Java": '''// default code\nimport java.util.Scanner;\npublic class Program {\n    public static void main(String[] args) {\n        Scanner sc = new Scanner(System.in);\n        int a = sc.nextInt();\n        int b = sc.nextInt();\n        System.out.println("Sum: " + (a + b));\n    }\n}''',
    "JavaScript": '''// default code\nconst readline = require('readline');\nconst rl = readline.createInterface({ input: process.stdin, output: process.stdout });\nlet inputs = [];\nrl.on('line', (line) => {\n  inputs.push(parseInt(line));\n  if (inputs.length === 2) {\n    console.log("Sum:", inputs[0] + inputs[1]);\n    rl.close();\n  }\n});''',
    "C#": '''// default code\nusing System;\npublic class Program {\n    public static void Main(string[] args) {\n        int a = Convert.ToInt32(Console.ReadLine());\n        int b = Convert.ToInt32(Console.ReadLine());\n        Console.WriteLine("Sum: " + (a + b));\n    }\n}'''
}

# Extension-to-language mapping
EXT_LANG_MAP = {
    ".py": "Python",
    ".cpp": "C++",
    ".c": "C",
    ".java": "Java",
    ".js": "JavaScript",
    ".cs": "C#"
}

def render_code_editor(ace_theme):
    # ── Language Selector ──────────────────────────────
    lang_list = list(DEFAULT_SNIPPETS.keys())
    default_lang = st.session_state.get("language", "Python")
    selected_lang = st.selectbox("Language", lang_list, index=lang_list.index(default_lang))
    st.session_state.language = selected_lang
    editor_key = f"editor_{selected_lang}"

    # ── File Upload ──────────────────────────────
    uploaded_file = st.file_uploader("πŸ“€ Upload file", type=["py", "cpp", "c", "java", "js", "cs", "txt"])

    if uploaded_file:
        if uploaded_file.size > 10 * 1024 * 1024:
            st.error("🚫 File too large. Max allowed is 10MB.")
        else:
            content = uploaded_file.read().decode("utf-8", errors="ignore")
            filename = uploaded_file.name
            ext = Path(filename).suffix.lower()

            prev_name = st.session_state.get("uploaded_file_name")
            prev_content = st.session_state.get("uploaded_file_content")

            # Only react to new uploads
            if content != prev_content or filename != prev_name:
                st.session_state.uploaded_file_name = filename
                st.session_state.uploaded_file_content = content

                detected_lang = EXT_LANG_MAP.get(ext)
                if detected_lang:
                    st.session_state.language = detected_lang
                    st.session_state.prev_language = detected_lang
                    st.session_state.code = content
                    st.toast(f"βœ… Auto-switched to {detected_lang}", icon="πŸ”„")
                    st.rerun()
                elif ext == ".txt":
                    st.session_state.code = content
                    st.toast("πŸ“„ Loaded text file", icon="πŸ“„")
                else:
                    st.error("❌ Unsupported file format.")
                    return

    # ── Fallback Default Code ──────────────────────────────
    prev_lang = st.session_state.get("prev_language")
    default_code = DEFAULT_SNIPPETS[selected_lang]

    if (
        st.session_state.get("code") is None
        or st.session_state.code.strip() == ""
        or selected_lang != prev_lang
        or st.session_state.code.strip() == DEFAULT_SNIPPETS.get(prev_lang, "")
    ):
        st.session_state.code = default_code
        st.session_state.prev_language = selected_lang

    # ── ACE Code Editor ──────────────────────────────
    code = st_ace.st_ace(
        value=st.session_state.code,
        placeholder=f"Start typing your {selected_lang} code…",
        language=selected_lang.lower() if selected_lang != "C++" else "c_cpp",
        theme=ace_theme,
        keybinding="vscode",
        font_size=14,
        min_lines=20,
        show_gutter=True,
        wrap=True,
        auto_update=True,
        key=editor_key
    )

    if code != st.session_state.code:
        st.session_state.code = code

    # ── Stdin Input ──────────────────────────────
    user_input = st.text_area(
        "πŸ“₯ Input (stdin)",
        value=st.session_state.stdin,
        height=100,
        placeholder="Enter input values, one per line",
        key="stdin_input"
    )
    if user_input != st.session_state.stdin:
        st.session_state.stdin = user_input

    # ── Run Button ──────────────────────────────
    if st.button("▢️ Run"):
        start_time = time.perf_counter()
        process = psutil.Process()
        mem_before = process.memory_info().rss

        out, err, exc = execute_code(
            code=st.session_state.code,
            stdin=st.session_state.stdin,
            language=selected_lang
        )

        exec_time = time.perf_counter() - start_time
        mem_after = process.memory_info().rss
        mem_used = (mem_after - mem_before) / 1024

        st.session_state.code_output = out
        st.session_state.error_output = err or exc

        st.text_area("πŸ“€ Output", out or "(no output)", height=120)
        if err or exc:
            st.error(err or exc)
        st.markdown(f"⏱️ **Execution Time:** {exec_time:.4f}s")
        st.markdown(f"πŸ’Ύ **Memory Used:** {mem_used:.2f} KB")

    # ── Download Code ──────────────────────────────
    if st.session_state.code:
        lang_ext = {
            "Python": "py", "C": "c", "C++": "cpp", "Java": "java",
            "JavaScript": "js", "C#": "cs"
        }
        ext = lang_ext.get(selected_lang, "txt")

        st.download_button(
            label="πŸ’Ύ Download Code",
            data=st.session_state.code,
            file_name=f"code.{ext}",
            mime="text/plain"
        )