Yasu777 commited on
Commit
cafc4a3
·
verified ·
1 Parent(s): 7f508ac

Create editor.py

Browse files
Files changed (1) hide show
  1. editor.py +207 -0
editor.py ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import tempfile
3
+ import subprocess
4
+ import os
5
+ from streamlit_ace import st_ace
6
+ from chat import request_ai_edit
7
+
8
+ def setup_editor(api_key, mobile=False):
9
+ """コードエディタとその関連機能をセットアップする"""
10
+ # ヘッダー
11
+ st.header("コードエディタ" if not mobile else "エディタ")
12
+
13
+ if st.session_state.current_file:
14
+ # ファイルの拡張子に基づいて言語を設定
15
+ file_ext = os.path.splitext(st.session_state.current_file)[1].lower()
16
+ lang_map = {
17
+ ".py": "python",
18
+ ".js": "javascript",
19
+ ".html": "html",
20
+ ".css": "css",
21
+ ".json": "json",
22
+ ".txt": "text"
23
+ }
24
+ language = lang_map.get(file_ext, "python")
25
+
26
+ # エディタの表示
27
+ st.subheader(f"編集中: {st.session_state.current_file}")
28
+
29
+ # モバイル向けの調整
30
+ editor_height = 300 if mobile else 500
31
+
32
+ # AIに編集を任せるモード
33
+ if st.session_state.ai_edit_mode and st.button("AIに編集を依頼", key="ai_edit_btn"):
34
+ current_code = st.session_state.files[st.session_state.current_file]
35
+ instructions = st.session_state.edit_instructions or "コードを改善してください"
36
+
37
+ with st.spinner("AIによるコード編集中..."):
38
+ edited_code = request_ai_edit(
39
+ api_key,
40
+ current_code,
41
+ instructions,
42
+ language
43
+ )
44
+
45
+ if edited_code:
46
+ st.session_state.files[st.session_state.current_file] = edited_code
47
+ st.success("AIによるコード編集が完了しました")
48
+ st.session_state.active_tab = "エディタ" # モバイルの場合はエディタタブに戻る
49
+ st.rerun()
50
+
51
+ # エディタを表示
52
+ code = st_ace(
53
+ value=st.session_state.files[st.session_state.current_file],
54
+ language=language,
55
+ theme="monokai",
56
+ keybinding="vscode",
57
+ font_size=14 if not mobile else 16, # モバイルでは少し大きく
58
+ min_lines=10,
59
+ max_lines=50,
60
+ height=editor_height,
61
+ key=f"ace_editor_{st.session_state.current_file}"
62
+ )
63
+
64
+ # コードを保存
65
+ st.session_state.files[st.session_state.current_file] = code
66
+
67
+ # アクション関連のボタン
68
+ col1, col2 = st.columns(2)
69
+
70
+ # Python codeの場合、実行ボタンを表示
71
+ if language == "python":
72
+ with col1:
73
+ if st.button("コードを実行", key="run_code_btn", use_container_width=True):
74
+ run_python_code(code)
75
+
76
+ # ファイルダウンロード機能
77
+ with col2:
78
+ st.download_button(
79
+ label="ファイルをダウンロード",
80
+ data=code,
81
+ file_name=st.session_state.current_file,
82
+ key="download_file",
83
+ use_container_width=True
84
+ )
85
+
86
+ # モバイルの場合は追加のナビゲーション
87
+ if mobile:
88
+ if st.button("AIチャットモードへ", key="goto_chat", use_container_width=True):
89
+ st.session_state.active_tab = "チャット"
90
+ st.rerun()
91
+
92
+ else:
93
+ st.info("サイドバーから既存のファイルを選択するか、新しいファイルを作成してください。")
94
+
95
+ # 簡易ファイル作成ボタン(特にモバイル向け)
96
+ if st.button("新しいPythonファイルを作成", key="quick_file_create", use_container_width=True):
97
+ import time
98
+ filename = f"script_{int(time.time())}.py"
99
+ st.session_state.files[filename] = "# 新しいPythonスクリプト\n\n# コードを入力してください\n"
100
+ st.session_state.current_file = filename
101
+ st.rerun()
102
+
103
+ def run_python_code(code):
104
+ """Pythonコードを実行して結果を表示する"""
105
+ with st.spinner("コードを実行中..."):
106
+ # 一時ファイルを作成してコードを実行
107
+ with tempfile.NamedTemporaryFile(suffix='.py', delete=False) as tmp:
108
+ tmp.write(code.encode())
109
+ tmp_name = tmp.name
110
+
111
+ try:
112
+ # サブプロセスでPythonコードを実行
113
+ result = subprocess.run(
114
+ ["python", tmp_name],
115
+ capture_output=True,
116
+ text=True,
117
+ timeout=10 # 10秒のタイムアウト
118
+ )
119
+
120
+ # 実行結果を表示
121
+ if result.stdout:
122
+ st.code(result.stdout, language="text")
123
+
124
+ if result.stderr:
125
+ st.error(result.stderr)
126
+
127
+ # エラーが発生した場合、自動的にエラー修正モードに切り替える
128
+ if st.button("エラー修正AIに相談", key="ask_error_fix"):
129
+ st.session_state.current_mode = "エラー修正モード"
130
+ error_query = f"次のPythonコードにエラーがあります。修正方法を教えてください。\n\n```python\n{code}\n```\n\nエラーメッセージ:\n```\n{result.stderr}\n```"
131
+
132
+ # チャットにエラー修正用のメッセージを追加
133
+ if "messages" not in st.session_state:
134
+ st.session_state.messages = []
135
+
136
+ st.session_state.messages.append({"role": "user", "content": error_query})
137
+ st.session_state.active_tab = "チャット" # モバイルモードではチャットタブに切り替え
138
+ st.rerun()
139
+
140
+ except subprocess.TimeoutExpired:
141
+ st.error("実行がタイムアウトしました(10秒以上かかりました)")
142
+
143
+ except Exception as e:
144
+ st.error(f"実行中にエラーが発生しました: {str(e)}")
145
+
146
+ finally:
147
+ # 一時ファイルを削除
148
+ if os.path.exists(tmp_name):
149
+ os.unlink(tmp_name)
150
+
151
+ def save_generated_code_to_new_file(code_text, suggested_name=None):
152
+ """AIが生成したコードを新しいファイルに保存する"""
153
+ import re
154
+
155
+ # コードブロックのマークアップを削除
156
+ code_pattern = r"```(?:\w+)?\n([\s\S]*?)\n```"
157
+ match = re.search(code_pattern, code_text)
158
+ clean_code = match.group(1) if match else code_text
159
+
160
+ # 言語の推測
161
+ language = "py" # デフォルトはPython
162
+ lang_pattern = r"```(\w+)\n"
163
+ lang_match = re.search(lang_pattern, code_text)
164
+ if lang_match:
165
+ detected_lang = lang_match.group(1).lower()
166
+ lang_mapping = {
167
+ "python": "py",
168
+ "javascript": "js",
169
+ "html": "html",
170
+ "css": "css",
171
+ "json": "json",
172
+ "java": "java",
173
+ "cpp": "cpp",
174
+ "c++": "cpp",
175
+ "c": "c",
176
+ "go": "go",
177
+ "rust": "rs",
178
+ "typescript": "ts"
179
+ }
180
+ language = lang_mapping.get(detected_lang, detected_lang)
181
+
182
+ # ファイル名の生成
183
+ if not suggested_name:
184
+ import hashlib
185
+ import time
186
+ # タイムスタンプとコードの一部からハッシュを生成
187
+ timestamp = str(int(time.time()))
188
+ code_hash = hashlib.md5(clean_code[:100].encode()).hexdigest()[:6]
189
+ suggested_name = f"generated_{timestamp}_{code_hash}"
190
+
191
+ # 拡張子が含まれていなければ追加
192
+ if "." not in suggested_name:
193
+ suggested_name = f"{suggested_name}.{language}"
194
+
195
+ # 同名ファイルが存在する場合は連番を付ける
196
+ base_name, ext = os.path.splitext(suggested_name)
197
+ counter = 1
198
+ file_name = suggested_name
199
+ while file_name in st.session_state.files:
200
+ file_name = f"{base_name}_{counter}{ext}"
201
+ counter += 1
202
+
203
+ # ファイルを保存
204
+ st.session_state.files[file_name] = clean_code
205
+ st.session_state.current_file = file_name
206
+
207
+ return file_name