Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -1,204 +1,320 @@
|
|
1 |
import gradio as gr
|
2 |
-
import json
|
3 |
import time
|
4 |
|
5 |
-
# Simulated file storage (in-memory dictionary
|
6 |
-
files = {"untitled.py": ""}
|
|
|
7 |
|
8 |
# Load file content into editor
|
9 |
-
def load_file(file, current_file):
|
10 |
global files
|
11 |
if file is not None:
|
12 |
with open(file.name, "r") as f:
|
13 |
code = f.read()
|
14 |
filename = file.name.split("/")[-1]
|
15 |
files[filename] = code
|
16 |
-
|
17 |
-
|
|
|
|
|
18 |
|
19 |
# Save current file content
|
20 |
def save_file(code, current_file):
|
21 |
global files
|
22 |
files[current_file] = code
|
23 |
-
return
|
24 |
|
25 |
-
# Simulate running code
|
26 |
def run_code(code, terminal_history):
|
27 |
timestamp = time.strftime("%H:%M:%S")
|
28 |
output = f"[{timestamp}] Ran:\n{code}\nOutput: Simulated execution successful"
|
29 |
return f"{terminal_history}\n{output}".strip()
|
30 |
|
31 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
def get_suggestions(code):
|
33 |
-
|
|
|
34 |
return ["def function_name():", "def main():", "def __init__(self):"]
|
35 |
-
elif "print" in code
|
36 |
return ["print('Hello, World!')", "print(variable)", "print(f'String: {var}')"]
|
37 |
-
elif "import" in code
|
38 |
return ["import os", "import sys", "import numpy as np"]
|
39 |
return ["# Start typing for suggestions"]
|
40 |
|
41 |
-
# Insert suggestion
|
42 |
def insert_suggestion(code, suggestion):
|
43 |
if suggestion:
|
44 |
lines = code.split("\n")
|
45 |
last_line = lines[-1]
|
46 |
-
if last_line.strip()
|
47 |
-
return code + "\n" + suggestion
|
48 |
-
return code + suggestion
|
49 |
return code
|
50 |
|
51 |
-
# Switch tabs
|
52 |
-
def switch_tab(
|
53 |
-
|
54 |
-
return files.get(selected_file, ""), selected_file, list(files.keys())
|
55 |
|
56 |
# Add new file
|
57 |
-
def add_new_file():
|
58 |
-
global files
|
59 |
new_file = f"untitled_{len(files)}.py"
|
60 |
files[new_file] = ""
|
61 |
-
|
|
|
62 |
|
63 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
def download_code(code, current_file):
|
65 |
return code, current_file
|
66 |
|
67 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
with gr.Blocks(
|
69 |
title="VS Code Clone",
|
70 |
css="""
|
71 |
-
.gradio-container { background-color: #1e1e1e; color: #d4d4d4; font-family: 'Consolas', monospace; height: 100vh; }
|
72 |
-
.
|
73 |
-
.sidebar { background-color: #252526; padding: 10px;
|
74 |
-
.editor { background-color: #
|
75 |
.terminal { background-color: #0e0e0e; color: #b5cea8; font-size: 12px; }
|
76 |
-
.
|
77 |
-
button { background-color: #007acc; color: white; border: none; padding: 5px 10px; margin: 2px; }
|
78 |
-
button:hover { background-color: #005f99; }
|
79 |
.tabs { display: flex; gap: 5px; background-color: #1e1e1e; padding: 5px; border-bottom: 1px solid #3c3c3c; }
|
80 |
.tab { background-color: #2d2d2d; padding: 5px 10px; cursor: pointer; }
|
81 |
.tab.active { background-color: #007acc; }
|
82 |
-
|
83 |
-
|
84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
) as app:
|
86 |
# States
|
87 |
current_file = gr.State(value="untitled.py")
|
88 |
terminal_history = gr.State(value="")
|
|
|
|
|
89 |
|
90 |
-
#
|
91 |
-
with gr.Row(elem_classes="topbar"):
|
92 |
-
run_button = gr.Button("▶ Run")
|
93 |
-
save_button = gr.Button("💾 Save")
|
94 |
-
new_file_button = gr.Button("➕ New File")
|
95 |
-
gr.Markdown(f"### VS Code Clone - {time.strftime('%Y-%m-%d')}", elem_classes="topbar")
|
96 |
-
|
97 |
-
# Tabbed editor
|
98 |
-
with gr.Row(elem_classes="tabs"):
|
99 |
-
file_tabs = gr.Dropdown(label="Open Files", choices=list(files.keys()), value="untitled.py", interactive=True)
|
100 |
-
|
101 |
-
# Main layout
|
102 |
with gr.Row():
|
|
|
|
|
|
|
|
|
|
|
103 |
# Sidebar (File Explorer)
|
104 |
-
with gr.Column(scale=1, elem_classes="sidebar"):
|
105 |
gr.Markdown("### Explorer")
|
106 |
file_upload = gr.File(label="Upload File")
|
107 |
file_list = gr.Listbox(label="Files", choices=list(files.keys()), interactive=True, elem_classes="file-list")
|
108 |
-
status_display = gr.Textbox(label="Status", interactive=False)
|
109 |
|
110 |
-
# Editor
|
111 |
with gr.Column(scale=4):
|
112 |
-
|
113 |
-
label="
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
)
|
118 |
with gr.Row():
|
119 |
-
|
120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
|
122 |
-
# Hidden
|
123 |
download_output = gr.File(label="Download", visible=False)
|
124 |
|
125 |
-
# JavaScript for
|
126 |
app.load(_js="""
|
127 |
() => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
document.addEventListener('keydown', (e) => {
|
|
|
|
|
|
|
|
|
|
|
129 |
if (e.ctrlKey && e.key === 's') {
|
130 |
e.preventDefault();
|
131 |
-
document.
|
132 |
}
|
133 |
if (e.ctrlKey && e.key === 'r') {
|
134 |
e.preventDefault();
|
135 |
-
document.
|
136 |
}
|
137 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
}
|
139 |
-
""")
|
|
|
|
|
|
|
|
|
140 |
|
141 |
-
# Event handlers
|
142 |
-
# File upload
|
143 |
file_upload.change(
|
144 |
-
|
145 |
-
inputs=[file_upload, current_file],
|
146 |
-
outputs=[code_editor, current_file, file_list, code_editor]
|
147 |
)
|
148 |
|
149 |
-
|
150 |
-
|
151 |
-
fn=save_file,
|
152 |
inputs=[code_editor, current_file],
|
153 |
-
outputs=[
|
154 |
).then(
|
155 |
-
|
156 |
inputs=[code_editor, current_file],
|
157 |
outputs=[download_output]
|
158 |
)
|
159 |
|
160 |
-
|
161 |
-
|
162 |
-
fn=run_code,
|
163 |
inputs=[code_editor, terminal_history],
|
164 |
outputs=[terminal_output]
|
165 |
).then(
|
166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
inputs=[terminal_output],
|
168 |
outputs=[terminal_history]
|
169 |
)
|
170 |
|
171 |
-
# Suggestions
|
172 |
code_editor.change(
|
173 |
-
|
174 |
inputs=[code_editor],
|
175 |
outputs=[suggestions_list]
|
176 |
)
|
|
|
177 |
suggestions_list.select(
|
178 |
-
|
179 |
inputs=[code_editor, suggestions_list],
|
180 |
outputs=[code_editor]
|
181 |
)
|
182 |
|
183 |
-
# Tab switching
|
184 |
file_tabs.change(
|
185 |
-
|
186 |
-
inputs=[file_tabs],
|
187 |
-
outputs=[code_editor, current_file
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
)
|
189 |
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
outputs=[
|
|
|
|
|
|
|
|
|
194 |
)
|
195 |
|
196 |
-
# File list selection
|
197 |
file_list.select(
|
198 |
-
|
199 |
-
inputs=[file_list],
|
200 |
-
outputs=[code_editor, current_file,
|
|
|
|
|
|
|
|
|
201 |
)
|
202 |
|
203 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
app.launch()
|
|
|
1 |
import gradio as gr
|
|
|
2 |
import time
|
3 |
|
4 |
+
# Simulated file storage (in-memory dictionary)
|
5 |
+
files = {"untitled.py": ""} # file_name: content
|
6 |
+
open_files = ["untitled.py"] # List of open files
|
7 |
|
8 |
# Load file content into editor
|
9 |
+
def load_file(file, current_file, open_files):
|
10 |
global files
|
11 |
if file is not None:
|
12 |
with open(file.name, "r") as f:
|
13 |
code = f.read()
|
14 |
filename = file.name.split("/")[-1]
|
15 |
files[filename] = code
|
16 |
+
if filename not in open_files:
|
17 |
+
open_files.append(filename)
|
18 |
+
return code, filename, list(files.keys()), open_files, code
|
19 |
+
return files.get(current_file, ""), current_file, list(files.keys()), open_files, files.get(current_file, "")
|
20 |
|
21 |
# Save current file content
|
22 |
def save_file(code, current_file):
|
23 |
global files
|
24 |
files[current_file] = code
|
25 |
+
return f"Saved {current_file}"
|
26 |
|
27 |
+
# Simulate running code
|
28 |
def run_code(code, terminal_history):
|
29 |
timestamp = time.strftime("%H:%M:%S")
|
30 |
output = f"[{timestamp}] Ran:\n{code}\nOutput: Simulated execution successful"
|
31 |
return f"{terminal_history}\n{output}".strip()
|
32 |
|
33 |
+
# Process terminal commands
|
34 |
+
def process_command(cmd, files, history):
|
35 |
+
if cmd.strip() == "ls":
|
36 |
+
output = "\n".join(files.keys())
|
37 |
+
elif cmd.startswith("echo "):
|
38 |
+
output = cmd[5:]
|
39 |
+
else:
|
40 |
+
output = f"Command not recognized: {cmd}"
|
41 |
+
return f"{history}\n$ {cmd}\n{output}"
|
42 |
+
|
43 |
+
# AI-powered suggestions
|
44 |
def get_suggestions(code):
|
45 |
+
code = code.lower()
|
46 |
+
if "def" in code:
|
47 |
return ["def function_name():", "def main():", "def __init__(self):"]
|
48 |
+
elif "print" in code:
|
49 |
return ["print('Hello, World!')", "print(variable)", "print(f'String: {var}')"]
|
50 |
+
elif "import" in code:
|
51 |
return ["import os", "import sys", "import numpy as np"]
|
52 |
return ["# Start typing for suggestions"]
|
53 |
|
54 |
+
# Insert suggestion
|
55 |
def insert_suggestion(code, suggestion):
|
56 |
if suggestion:
|
57 |
lines = code.split("\n")
|
58 |
last_line = lines[-1]
|
59 |
+
return code + ("\n" + suggestion if last_line.strip() else suggestion)
|
|
|
|
|
60 |
return code
|
61 |
|
62 |
+
# Switch tabs
|
63 |
+
def switch_tab(selected, files):
|
64 |
+
return files.get(selected, ""), selected
|
|
|
65 |
|
66 |
# Add new file
|
67 |
+
def add_new_file(open_files, files):
|
|
|
68 |
new_file = f"untitled_{len(files)}.py"
|
69 |
files[new_file] = ""
|
70 |
+
open_files.append(new_file)
|
71 |
+
return "", new_file, list(files.keys()), open_files, files[new_file]
|
72 |
|
73 |
+
# Close tab
|
74 |
+
def close_tab(open_files, current_file, files):
|
75 |
+
if len(open_files) > 1:
|
76 |
+
new_open_files = [f for f in open_files if f != current_file]
|
77 |
+
new_current = new_open_files[0]
|
78 |
+
return new_open_files, new_current, files[new_current]
|
79 |
+
return open_files, current_file, files[current_file]
|
80 |
+
|
81 |
+
# Download file
|
82 |
def download_code(code, current_file):
|
83 |
return code, current_file
|
84 |
|
85 |
+
# Process command palette
|
86 |
+
def process_palette(cmd, theme, files, current_file):
|
87 |
+
if cmd == "theme dark":
|
88 |
+
return "dark", "Theme set to dark"
|
89 |
+
elif cmd == "theme light":
|
90 |
+
return "light", "Theme set to light"
|
91 |
+
elif cmd == "save":
|
92 |
+
files[current_file] = code_editor.value
|
93 |
+
return theme, f"Saved {current_file}"
|
94 |
+
return theme, f"Command not found: {cmd}"
|
95 |
+
|
96 |
+
# Gradio interface
|
97 |
with gr.Blocks(
|
98 |
title="VS Code Clone",
|
99 |
css="""
|
100 |
+
.gradio-container { background-color: #1e1e1e; color: #d4d4d4; font-family: 'Consolas', monospace; height: 100vh; margin: 0; }
|
101 |
+
.activity-bar { background-color: #333; padding: 10px; width: 50px; min-width: 50px; }
|
102 |
+
.sidebar { background-color: #252526; padding: 10px; width: 200px; min-width: 200px; }
|
103 |
+
.editor { background-color: #1e1e1e; border: none; }
|
104 |
.terminal { background-color: #0e0e0e; color: #b5cea8; font-size: 12px; }
|
105 |
+
.status-bar { background-color: #007acc; color: white; padding: 5px; }
|
|
|
|
|
106 |
.tabs { display: flex; gap: 5px; background-color: #1e1e1e; padding: 5px; border-bottom: 1px solid #3c3c3c; }
|
107 |
.tab { background-color: #2d2d2d; padding: 5px 10px; cursor: pointer; }
|
108 |
.tab.active { background-color: #007acc; }
|
109 |
+
button { background-color: #007acc; color: white; border: none; padding: 5px; margin: 2px; }
|
110 |
+
button:hover { background-color: #005f99; }
|
111 |
+
.file-list { max-height: 300px; overflow-y: auto; }
|
112 |
+
.command-palette { position: absolute; top: 20%; left: 30%; width: 40%; background: #252526; z-index: 1000; padding: 10px; }
|
113 |
+
.light .gradio-container { background-color: #ffffff; color: #000000; }
|
114 |
+
.light .editor { background-color: #ffffff; color: #000000; }
|
115 |
+
.light .sidebar { background-color: #f3f3f3; }
|
116 |
+
.light .terminal { background-color: #f0f0f0; color: #000000; }
|
117 |
+
.light .status-bar { background-color: #0066cc; }
|
118 |
+
.light .tabs { background-color: #ffffff; }
|
119 |
+
.light .tab { background-color: #e0e0e0; }
|
120 |
+
.light .tab.active { background-color: #0066cc; }
|
121 |
+
"""
|
122 |
) as app:
|
123 |
# States
|
124 |
current_file = gr.State(value="untitled.py")
|
125 |
terminal_history = gr.State(value="")
|
126 |
+
theme_state = gr.State(value="dark")
|
127 |
+
cursor_position = gr.State(value="Ln 1, Col 1")
|
128 |
|
129 |
+
# Layout
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
with gr.Row():
|
131 |
+
# Activity Bar
|
132 |
+
with gr.Column(scale=0, elem_classes="activity-bar"):
|
133 |
+
explorer_btn = gr.Button("📁")
|
134 |
+
terminal_btn = gr.Button("🖥️")
|
135 |
+
|
136 |
# Sidebar (File Explorer)
|
137 |
+
with gr.Column(scale=1, visible=False, elem_classes="sidebar") as sidebar:
|
138 |
gr.Markdown("### Explorer")
|
139 |
file_upload = gr.File(label="Upload File")
|
140 |
file_list = gr.Listbox(label="Files", choices=list(files.keys()), interactive=True, elem_classes="file-list")
|
|
|
141 |
|
142 |
+
# Editor Pane
|
143 |
with gr.Column(scale=4):
|
144 |
+
with gr.Row(elem_classes="tabs"):
|
145 |
+
file_tabs = gr.Dropdown(label="Open Files", choices=open_files, value="untitled.py", interactive=True)
|
146 |
+
new_file_btn = gr.Button("➕")
|
147 |
+
close_tab_btn = gr.Button("❌")
|
148 |
+
code_editor = gr.Code(label="Editor", language="python", lines=20, elem_classes="editor")
|
|
|
149 |
with gr.Row():
|
150 |
+
with gr.Column(scale=3):
|
151 |
+
terminal_panel = gr.Column(visible=False, elem_classes="terminal")
|
152 |
+
with terminal_panel:
|
153 |
+
terminal_output = gr.Textbox(label="Terminal", lines=10, interactive=False)
|
154 |
+
terminal_input = gr.Textbox(label=">", placeholder="Type command and press Enter")
|
155 |
+
with gr.Column(scale=1):
|
156 |
+
suggestions_list = gr.Listbox(label="Suggestions", choices=[], interactive=True)
|
157 |
+
|
158 |
+
# Status Bar
|
159 |
+
with gr.Row(elem_classes="status-bar"):
|
160 |
+
run_btn = gr.Button("▶ Run")
|
161 |
+
save_btn = gr.Button("💾 Save")
|
162 |
+
status_info = gr.Textbox(value="Python • Ln 1, Col 1", interactive=False)
|
163 |
+
|
164 |
+
# Command Palette
|
165 |
+
command_palette = gr.Textbox(label="> Command Palette", visible=False, elem_classes="command-palette")
|
166 |
|
167 |
+
# Hidden Download Output
|
168 |
download_output = gr.File(label="Download", visible=False)
|
169 |
|
170 |
+
# JavaScript for shortcuts and cursor tracking
|
171 |
app.load(_js="""
|
172 |
() => {
|
173 |
+
const editor = document.querySelector('#code_editor textarea');
|
174 |
+
const status = document.querySelector('#status_info input');
|
175 |
+
const palette = document.querySelector('#command_palette');
|
176 |
+
const themeInput = document.querySelector('#theme_state input');
|
177 |
+
const container = document.querySelector('.gradio-container');
|
178 |
+
|
179 |
+
// Cursor position
|
180 |
+
function getCursorPosition(textarea) {
|
181 |
+
const text = textarea.value;
|
182 |
+
const pos = textarea.selectionStart;
|
183 |
+
const lines = text.substr(0, pos).split('\\n');
|
184 |
+
return `Python • Ln ${lines.length}, Col ${lines[lines.length - 1].length + 1}`;
|
185 |
+
}
|
186 |
+
editor.addEventListener('keyup', () => {
|
187 |
+
status.value = getCursorPosition(editor);
|
188 |
+
status.dispatchEvent(new Event('input'));
|
189 |
+
});
|
190 |
+
editor.addEventListener('click', () => {
|
191 |
+
status.value = getCursorPosition(editor);
|
192 |
+
status.dispatchEvent(new Event('input'));
|
193 |
+
});
|
194 |
+
|
195 |
+
// Shortcuts
|
196 |
document.addEventListener('keydown', (e) => {
|
197 |
+
if (e.ctrlKey && e.shiftKey && e.key === 'P') {
|
198 |
+
e.preventDefault();
|
199 |
+
palette.style.display = 'block';
|
200 |
+
palette.querySelector('input').focus();
|
201 |
+
}
|
202 |
if (e.ctrlKey && e.key === 's') {
|
203 |
e.preventDefault();
|
204 |
+
document.querySelector('#save_btn').click();
|
205 |
}
|
206 |
if (e.ctrlKey && e.key === 'r') {
|
207 |
e.preventDefault();
|
208 |
+
document.querySelector('#run_btn').click();
|
209 |
}
|
210 |
});
|
211 |
+
|
212 |
+
// Hide palette on Escape
|
213 |
+
palette.querySelector('input').addEventListener('keydown', (e) => {
|
214 |
+
if (e.key === 'Escape') {
|
215 |
+
palette.style.display = 'none';
|
216 |
+
}
|
217 |
+
});
|
218 |
+
|
219 |
+
// Theme switching
|
220 |
+
container.classList.add(themeInput.value);
|
221 |
+
const observer = new MutationObserver(() => {
|
222 |
+
container.classList.remove('light', 'dark');
|
223 |
+
container.classList.add(themeInput.value);
|
224 |
+
});
|
225 |
+
observer.observe(themeInput, {attributes: true});
|
226 |
}
|
227 |
+
""", outputs=[status_info])
|
228 |
+
|
229 |
+
# Event Handlers
|
230 |
+
explorer_btn.click(lambda v: gr.update(visible=not v), inputs=[sidebar.visible], outputs=[sidebar])
|
231 |
+
terminal_btn.click(lambda v: gr.update(visible=not v), inputs=[terminal_panel.visible], outputs=[terminal_panel])
|
232 |
|
|
|
|
|
233 |
file_upload.change(
|
234 |
+
load_file,
|
235 |
+
inputs=[file_upload, current_file, file_tabs.choices],
|
236 |
+
outputs=[code_editor, current_file, file_list, file_tabs, code_editor]
|
237 |
)
|
238 |
|
239 |
+
save_btn.click(
|
240 |
+
save_file,
|
|
|
241 |
inputs=[code_editor, current_file],
|
242 |
+
outputs=[status_info]
|
243 |
).then(
|
244 |
+
download_code,
|
245 |
inputs=[code_editor, current_file],
|
246 |
outputs=[download_output]
|
247 |
)
|
248 |
|
249 |
+
run_btn.click(
|
250 |
+
run_code,
|
|
|
251 |
inputs=[code_editor, terminal_history],
|
252 |
outputs=[terminal_output]
|
253 |
).then(
|
254 |
+
lambda x: x,
|
255 |
+
inputs=[terminal_output],
|
256 |
+
outputs=[terminal_history]
|
257 |
+
)
|
258 |
+
|
259 |
+
terminal_input.submit(
|
260 |
+
process_command,
|
261 |
+
inputs=[terminal_input, files, terminal_history],
|
262 |
+
outputs=[terminal_output]
|
263 |
+
).then(lambda: "", outputs=[terminal_input]).then(
|
264 |
+
lambda x: x,
|
265 |
inputs=[terminal_output],
|
266 |
outputs=[terminal_history]
|
267 |
)
|
268 |
|
|
|
269 |
code_editor.change(
|
270 |
+
get_suggestions,
|
271 |
inputs=[code_editor],
|
272 |
outputs=[suggestions_list]
|
273 |
)
|
274 |
+
|
275 |
suggestions_list.select(
|
276 |
+
insert_suggestion,
|
277 |
inputs=[code_editor, suggestions_list],
|
278 |
outputs=[code_editor]
|
279 |
)
|
280 |
|
|
|
281 |
file_tabs.change(
|
282 |
+
switch_tab,
|
283 |
+
inputs=[file_tabs, files],
|
284 |
+
outputs=[code_editor, current_file]
|
285 |
+
)
|
286 |
+
|
287 |
+
new_file_btn.click(
|
288 |
+
add_new_file,
|
289 |
+
inputs=[file_tabs.choices, files],
|
290 |
+
outputs=[code_editor, current_file, file_list, file_tabs, code_editor]
|
291 |
)
|
292 |
|
293 |
+
close_tab_btn.click(
|
294 |
+
close_tab,
|
295 |
+
inputs=[file_tabs.choices, current_file, files],
|
296 |
+
outputs=[file_tabs.choices, current_file, code_editor]
|
297 |
+
).then(
|
298 |
+
lambda open_files, current_file: gr.update(choices=open_files, value=current_file),
|
299 |
+
inputs=[file_tabs.choices, current_file],
|
300 |
+
outputs=[file_tabs]
|
301 |
)
|
302 |
|
|
|
303 |
file_list.select(
|
304 |
+
lambda selected, open_files, files: (files[selected], selected, open_files + [selected] if selected not in open_files else open_files),
|
305 |
+
inputs=[file_list, file_tabs.choices, files],
|
306 |
+
outputs=[code_editor, current_file, file_tabs.choices]
|
307 |
+
).then(
|
308 |
+
lambda open_files, current_file: gr.update(choices=open_files, value=current_file),
|
309 |
+
inputs=[file_tabs.choices, current_file],
|
310 |
+
outputs=[file_tabs]
|
311 |
)
|
312 |
|
313 |
+
command_palette.submit(
|
314 |
+
process_palette,
|
315 |
+
inputs=[command_palette, theme_state, files, current_file],
|
316 |
+
outputs=[theme_state, status_info]
|
317 |
+
).then(lambda: gr.update(visible=False), outputs=[command_palette])
|
318 |
+
|
319 |
+
# Launch
|
320 |
app.launch()
|