Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| # -*- coding: utf-8 -*- | |
| """ | |
| CodeGPS Pro - 完全实用版 | |
| 真正能用的大模型代码眼睛 - 所有功能都能独立工作 | |
| """ | |
| import gradio as gr | |
| import re | |
| import difflib | |
| from typing import Dict, List, Tuple, Optional | |
| from dataclasses import dataclass | |
| import json | |
| # ==================== 核心引擎 ==================== | |
| class CodeBlock: | |
| start_line: int | |
| end_line: int | |
| type: str | |
| name: str | |
| content: str | |
| parent: Optional[str] = None | |
| class CodeGPSEngine: | |
| """核心代码处理引擎""" | |
| def __init__(self): | |
| self.reset() | |
| def reset(self): | |
| """重置状态""" | |
| self.original_code = "" | |
| self.current_code = "" | |
| self.lines = [] | |
| self.language = "unknown" | |
| self.blocks = [] | |
| self.history = [] | |
| self.is_loaded = False | |
| def auto_load(self, code: str) -> str: | |
| """自动加载代码(无需手动触发)""" | |
| if not code or not code.strip(): | |
| self.reset() | |
| return "⚠️ 代码为空" | |
| self.original_code = code | |
| self.current_code = code | |
| self.lines = code.split('\n') | |
| self.language = self._detect_language(code) | |
| self.blocks = self._parse_blocks() | |
| self.is_loaded = True | |
| return f"✅ 已加载 | 语言:{self.language.upper()} | 行数:{len(self.lines)} | 代码块:{len(self.blocks)}" | |
| def _detect_language(self, code: str) -> str: | |
| """快速检测语言""" | |
| patterns = { | |
| 'python': [r'def\s+\w+', r'class\s+\w+', r'import\s+\w+', r':\s*$'], | |
| 'javascript': [r'function\s+', r'const\s+\w+\s*=', r'=>', r'console\.'], | |
| 'java': [r'public\s+class', r'private\s+\w+', r'System\.'], | |
| 'cpp': [r'#include', r'std::', r'int\s+main'], | |
| 'go': [r'package\s+', r'func\s+', r':='], | |
| 'php': [r'<\?php', r'\$\w+', r'function\s+\w+'], | |
| 'ruby': [r'def\s+\w+', r'end\s*$', r'require\s+'], | |
| 'rust': [r'fn\s+\w+', r'let\s+\w+', r'impl\s+'], | |
| } | |
| for lang, pats in patterns.items(): | |
| matches = sum(1 for p in pats if re.search(p, code, re.MULTILINE)) | |
| if matches >= 2: | |
| return lang | |
| return 'plaintext' | |
| def _parse_blocks(self) -> List[CodeBlock]: | |
| """解析代码块""" | |
| blocks = [] | |
| if self.language == 'python': | |
| blocks = self._parse_python() | |
| elif self.language in ['javascript', 'java', 'cpp', 'go']: | |
| blocks = self._parse_braces() | |
| return blocks | |
| def _parse_python(self) -> List[CodeBlock]: | |
| """解析Python代码""" | |
| blocks = [] | |
| i = 0 | |
| current_class = None | |
| while i < len(self.lines): | |
| line = self.lines[i] | |
| stripped = line.lstrip() | |
| indent = len(line) - len(stripped) | |
| # 类定义 | |
| if re.match(r'class\s+(\w+)', stripped): | |
| name = re.match(r'class\s+(\w+)', stripped).group(1) | |
| start = i + 1 | |
| end = self._find_python_block_end(i, indent) | |
| blocks.append(CodeBlock( | |
| start_line=start, | |
| end_line=end, | |
| type='class', | |
| name=name, | |
| content='\n'.join(self.lines[i:end]) | |
| )) | |
| current_class = name | |
| i = end | |
| continue | |
| # 函数/方法定义 | |
| if re.match(r'def\s+(\w+)', stripped): | |
| name = re.match(r'def\s+(\w+)', stripped).group(1) | |
| start = i + 1 | |
| end = self._find_python_block_end(i, indent) | |
| blocks.append(CodeBlock( | |
| start_line=start, | |
| end_line=end, | |
| type='method' if current_class else 'function', | |
| name=name, | |
| content='\n'.join(self.lines[i:end]), | |
| parent=current_class | |
| )) | |
| i = end | |
| continue | |
| i += 1 | |
| return blocks | |
| def _find_python_block_end(self, start: int, base_indent: int) -> int: | |
| """查找Python代码块结束位置""" | |
| i = start + 1 | |
| while i < len(self.lines): | |
| line = self.lines[i] | |
| if line.strip(): | |
| indent = len(line) - len(line.lstrip()) | |
| if indent <= base_indent: | |
| return i | |
| i += 1 | |
| return len(self.lines) | |
| def _parse_braces(self) -> List[CodeBlock]: | |
| """解析花括号语言""" | |
| blocks = [] | |
| stack = [] | |
| patterns = { | |
| 'function': r'(?:function\s+(\w+)|(\w+)\s*\([^)]*\)\s*\{|fn\s+(\w+)|func\s+(\w+))', | |
| 'class': r'class\s+(\w+)', | |
| } | |
| for i, line in enumerate(self.lines, 1): | |
| # 检测函数 | |
| func_match = re.search(patterns['function'], line) | |
| if func_match: | |
| name = next((g for g in func_match.groups() if g), 'anonymous') | |
| stack.append(('function', name, i, 0)) | |
| # 检测类 | |
| class_match = re.search(patterns['class'], line) | |
| if class_match: | |
| name = class_match.group(1) | |
| stack.append(('class', name, i, 0)) | |
| # 花括号计数 | |
| open_count = line.count('{') | |
| close_count = line.count('}') | |
| if stack: | |
| stack[-1] = (stack[-1][0], stack[-1][1], stack[-1][2], stack[-1][3] + open_count - close_count) | |
| if stack[-1][3] == 0 and (open_count > 0 or close_count > 0): | |
| block_type, name, start, _ = stack.pop() | |
| blocks.append(CodeBlock( | |
| start_line=start, | |
| end_line=i, | |
| type=block_type, | |
| name=name, | |
| content='\n'.join(self.lines[start-1:i]) | |
| )) | |
| return blocks | |
| # ==================== 查询功能 ==================== | |
| def get_line(self, line_num: int) -> Dict: | |
| """获取单行""" | |
| if not self.is_loaded: | |
| return {'success': False, 'error': '❌ 请先输入代码'} | |
| if not 1 <= line_num <= len(self.lines): | |
| return {'success': False, 'error': f'❌ 行号超出范围 (1-{len(self.lines)})'} | |
| return { | |
| 'success': True, | |
| 'content': self.lines[line_num - 1], | |
| 'formatted': f"第{line_num}行: {self.lines[line_num - 1]}" | |
| } | |
| def get_lines(self, start: int, end: int) -> Dict: | |
| """获取多行""" | |
| if not self.is_loaded: | |
| return {'success': False, 'error': '❌ 请先输入代码'} | |
| total = len(self.lines) | |
| if not (1 <= start <= total and 1 <= end <= total): | |
| return {'success': False, 'error': f'❌ 行号超出范围 (1-{total})'} | |
| if start > end: | |
| start, end = end, start | |
| lines_output = [] | |
| for i in range(max(1, start - 2), min(total + 1, end + 3)): | |
| marker = '>>> ' if start <= i <= end else ' ' | |
| lines_output.append(f"{marker}{i:4d} | {self.lines[i-1]}") | |
| return { | |
| 'success': True, | |
| 'content': '\n'.join(self.lines[start-1:end]), | |
| 'formatted': '\n'.join(lines_output) | |
| } | |
| def get_function(self, name: str) -> Dict: | |
| """获取函数""" | |
| if not self.is_loaded: | |
| return {'success': False, 'error': '❌ 请先输入代码'} | |
| for block in self.blocks: | |
| if block.type in ['function', 'method'] and block.name == name: | |
| lines_output = [] | |
| for i in range(block.start_line, block.end_line + 1): | |
| lines_output.append(f"{i:4d} | {self.lines[i-1]}") | |
| return { | |
| 'success': True, | |
| 'content': block.content, | |
| 'formatted': f"📍 函数: {name} [第{block.start_line}-{block.end_line}行]\n" + '\n'.join(lines_output) | |
| } | |
| return {'success': False, 'error': f'❌ 未找到函数: {name}'} | |
| def get_class(self, name: str) -> Dict: | |
| """获取类""" | |
| if not self.is_loaded: | |
| return {'success': False, 'error': '❌ 请先输入代码'} | |
| for block in self.blocks: | |
| if block.type == 'class' and block.name == name: | |
| lines_output = [] | |
| for i in range(block.start_line, block.end_line + 1): | |
| lines_output.append(f"{i:4d} | {self.lines[i-1]}") | |
| return { | |
| 'success': True, | |
| 'content': block.content, | |
| 'formatted': f"📦 类: {name} [第{block.start_line}-{block.end_line}行]\n" + '\n'.join(lines_output) | |
| } | |
| return {'success': False, 'error': f'❌ 未找到类: {name}'} | |
| def search_text(self, keyword: str) -> Dict: | |
| """搜索文本""" | |
| if not self.is_loaded: | |
| return {'success': False, 'error': '❌ 请先输入代码'} | |
| results = [] | |
| for i, line in enumerate(self.lines, 1): | |
| if keyword in line: | |
| results.append(f"{i:4d} | {line}") | |
| if results: | |
| return { | |
| 'success': True, | |
| 'formatted': f"🔍 找到 {len(results)} 处匹配:\n" + '\n'.join(results[:50]) # 最多显示50个 | |
| } | |
| return {'success': False, 'error': f'❌ 未找到: {keyword}'} | |
| def list_all(self) -> str: | |
| """列出所有代码块""" | |
| if not self.is_loaded: | |
| return "❌ 请先输入代码" | |
| output = [f"📋 代码结构 [{self.language.upper()}] 共{len(self.lines)}行\n"] | |
| if not self.blocks: | |
| output.append("⚠️ 未检测到明显的函数/类结构") | |
| return '\n'.join(output) | |
| # 按类型分组 | |
| classes = [b for b in self.blocks if b.type == 'class'] | |
| functions = [b for b in self.blocks if b.type == 'function'] | |
| methods = [b for b in self.blocks if b.type == 'method'] | |
| if classes: | |
| output.append("📦 类定义:") | |
| for b in classes: | |
| output.append(f" ├─ {b.name} (第{b.start_line}-{b.end_line}行)") | |
| if functions: | |
| output.append("\n🔧 函数定义:") | |
| for b in functions: | |
| output.append(f" ├─ {b.name}() (第{b.start_line}-{b.end_line}行)") | |
| if methods: | |
| output.append("\n⚙️ 方法定义:") | |
| for b in methods: | |
| parent = f" [{b.parent}]" if b.parent else "" | |
| output.append(f" ├─ {b.name}(){parent} (第{b.start_line}-{b.end_line}行)") | |
| return '\n'.join(output) | |
| # ==================== 修改功能 ==================== | |
| def replace_line(self, line_num: int, new_content: str) -> Dict: | |
| """替换单行""" | |
| if not self.is_loaded: | |
| return {'success': False, 'error': '❌ 请先输入代码'} | |
| if not 1 <= line_num <= len(self.lines): | |
| return {'success': False, 'error': f'❌ 行号超出范围 (1-{len(self.lines)})'} | |
| old = self.lines[line_num - 1] | |
| self.lines[line_num - 1] = new_content | |
| self.current_code = '\n'.join(self.lines) | |
| self._save_history('replace_line', line_num, old) | |
| return { | |
| 'success': True, | |
| 'message': f'✅ 已替换第{line_num}行', | |
| 'diff': self._make_diff(old, new_content) | |
| } | |
| def replace_lines(self, start: int, end: int, new_content: str) -> Dict: | |
| """替换多行""" | |
| if not self.is_loaded: | |
| return {'success': False, 'error': '❌ 请先输入代码'} | |
| total = len(self.lines) | |
| if not (1 <= start <= total and 1 <= end <= total): | |
| return {'success': False, 'error': f'❌ 行号超出范围 (1-{total})'} | |
| if start > end: | |
| start, end = end, start | |
| old = '\n'.join(self.lines[start-1:end]) | |
| new_lines = new_content.split('\n') | |
| self.lines[start-1:end] = new_lines | |
| self.current_code = '\n'.join(self.lines) | |
| self._save_history('replace_lines', (start, end), old) | |
| return { | |
| 'success': True, | |
| 'message': f'✅ 已替换第{start}-{end}行 ({end-start+1}行 → {len(new_lines)}行)', | |
| 'diff': self._make_diff(old, new_content) | |
| } | |
| def insert_after(self, line_num: int, new_content: str) -> Dict: | |
| """在指定行后插入""" | |
| if not self.is_loaded: | |
| return {'success': False, 'error': '❌ 请先输入代码'} | |
| if not 0 <= line_num <= len(self.lines): | |
| return {'success': False, 'error': f'❌ 行号超出范围 (0-{len(self.lines)})'} | |
| new_lines = new_content.split('\n') | |
| self.lines[line_num:line_num] = new_lines | |
| self.current_code = '\n'.join(self.lines) | |
| self._save_history('insert', line_num, None) | |
| return { | |
| 'success': True, | |
| 'message': f'✅ 已在第{line_num}行后插入{len(new_lines)}行' | |
| } | |
| def delete_lines(self, start: int, end: int) -> Dict: | |
| """删除行""" | |
| if not self.is_loaded: | |
| return {'success': False, 'error': '❌ 请先输入代码'} | |
| total = len(self.lines) | |
| if not (1 <= start <= total and 1 <= end <= total): | |
| return {'success': False, 'error': f'❌ 行号超出范围 (1-{total})'} | |
| if start > end: | |
| start, end = end, start | |
| deleted = '\n'.join(self.lines[start-1:end]) | |
| del self.lines[start-1:end] | |
| self.current_code = '\n'.join(self.lines) | |
| self._save_history('delete', (start, end), deleted) | |
| return { | |
| 'success': True, | |
| 'message': f'✅ 已删除第{start}-{end}行 (共{end-start+1}行)', | |
| 'deleted': deleted | |
| } | |
| def find_replace(self, find_text: str, replace_text: str, max_replace: int = -1) -> Dict: | |
| """查找替换""" | |
| if not self.is_loaded: | |
| return {'success': False, 'error': '❌ 请先输入代码'} | |
| old_code = self.current_code | |
| count = 0 | |
| changes = [] | |
| for i, line in enumerate(self.lines): | |
| if find_text in line: | |
| if max_replace == -1 or count < max_replace: | |
| old_line = line | |
| new_line = line.replace(find_text, replace_text) | |
| self.lines[i] = new_line | |
| count += 1 | |
| changes.append(f"第{i+1}行: {old_line} → {new_line}") | |
| if count > 0: | |
| self.current_code = '\n'.join(self.lines) | |
| self._save_history('find_replace', find_text, old_code) | |
| return { | |
| 'success': True, | |
| 'message': f'✅ 已替换 {count} 处', | |
| 'changes': '\n'.join(changes[:20]) # 最多显示20条 | |
| } | |
| return {'success': False, 'error': f'❌ 未找到: {find_text}'} | |
| def indent_lines(self, start: int, end: int, spaces: int = 4) -> Dict: | |
| """缩进调整""" | |
| if not self.is_loaded: | |
| return {'success': False, 'error': '❌ 请先输入代码'} | |
| total = len(self.lines) | |
| if not (1 <= start <= total and 1 <= end <= total): | |
| return {'success': False, 'error': f'❌ 行号超出范围 (1-{total})'} | |
| indent_str = ' ' * abs(spaces) | |
| for i in range(start-1, end): | |
| if spaces > 0: | |
| self.lines[i] = indent_str + self.lines[i] | |
| else: | |
| # 反向缩进 | |
| self.lines[i] = self.lines[i].lstrip()[:abs(spaces)] + self.lines[i].lstrip()[abs(spaces):] | |
| self.current_code = '\n'.join(self.lines) | |
| self._save_history('indent', (start, end), None) | |
| return { | |
| 'success': True, | |
| 'message': f'✅ 已调整第{start}-{end}行缩进 ({spaces} 空格)' | |
| } | |
| def comment_lines(self, start: int, end: int, uncomment: bool = False) -> Dict: | |
| """注释/取消注释""" | |
| if not self.is_loaded: | |
| return {'success': False, 'error': '❌ 请先输入代码'} | |
| total = len(self.lines) | |
| if not (1 <= start <= total and 1 <= end <= total): | |
| return {'success': False, 'error': f'❌ 行号超出范围 (1-{total})'} | |
| # 根据语言选择注释符 | |
| comment_map = { | |
| 'python': '#', | |
| 'javascript': '//', | |
| 'java': '//', | |
| 'cpp': '//', | |
| 'go': '//', | |
| 'php': '//', | |
| 'ruby': '#', | |
| 'rust': '//', | |
| } | |
| comment_symbol = comment_map.get(self.language, '#') | |
| for i in range(start-1, end): | |
| if uncomment: | |
| self.lines[i] = self.lines[i].lstrip().lstrip(comment_symbol).lstrip() | |
| else: | |
| self.lines[i] = f"{comment_symbol} {self.lines[i]}" | |
| self.current_code = '\n'.join(self.lines) | |
| self._save_history('comment', (start, end), None) | |
| action = '取消注释' if uncomment else '注释' | |
| return { | |
| 'success': True, | |
| 'message': f'✅ 已{action}第{start}-{end}行' | |
| } | |
| def _make_diff(self, old: str, new: str) -> str: | |
| """生成差异对比""" | |
| diff = difflib.unified_diff( | |
| old.split('\n'), | |
| new.split('\n'), | |
| lineterm='', | |
| fromfile='修改前', | |
| tofile='修改后' | |
| ) | |
| return '\n'.join(diff) | |
| def _save_history(self, operation: str, target, old_content): | |
| """保存历史""" | |
| self.history.append({ | |
| 'operation': operation, | |
| 'target': target, | |
| 'old': old_content | |
| }) | |
| def undo(self) -> Dict: | |
| """撤销""" | |
| if not self.history: | |
| return {'success': False, 'error': '❌ 没有可撤销的操作'} | |
| # 简单实现:重新加载原始代码 | |
| self.current_code = self.original_code | |
| self.lines = self.original_code.split('\n') | |
| self.history = [] | |
| return {'success': True, 'message': '✅ 已撤销所有修改'} | |
| def get_current_code(self) -> str: | |
| """获取当前代码""" | |
| return self.current_code | |
| # ==================== UI界面 ==================== | |
| def create_ui(): | |
| engine = CodeGPSEngine() | |
| # 主题色 | |
| theme = gr.themes.Soft( | |
| primary_hue="purple", | |
| secondary_hue="blue", | |
| ) | |
| with gr.Blocks(title="CodeGPS Pro", theme=theme) as app: | |
| gr.HTML(""" | |
| <div style="text-align:center; background:linear-gradient(135deg,#667eea,#764ba2); color:white; padding:40px; border-radius:15px; margin-bottom:30px;"> | |
| <h1 style="font-size:3rem; margin:0;">🎯 CodeGPS Pro</h1> | |
| <p style="font-size:1.3rem; opacity:0.95; margin-top:10px;">大模型的精准代码手术刀 - 立即可用</p> | |
| </div> | |
| """) | |
| # 状态显示 | |
| status_display = gr.Textbox(label="📊 状态", value="等待输入代码...", interactive=False, max_lines=1) | |
| with gr.Tabs(): | |
| # ========== Tab 1: 代码编辑器 ========== | |
| with gr.TabItem("📝 代码编辑器"): | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| code_input = gr.Code( | |
| label="代码输入区", | |
| language="python", | |
| lines=30 | |
| ) | |
| with gr.Row(): | |
| load_example_btn = gr.Button("📥 加载示例代码", variant="secondary") | |
| clear_code_btn = gr.Button("🗑️ 清空", variant="secondary") | |
| with gr.Column(scale=1): | |
| gr.Markdown("### 🗺️ 代码结构") | |
| structure_output = gr.Textbox( | |
| label="", | |
| lines=30, | |
| interactive=False, | |
| show_label=False | |
| ) | |
| # ========== Tab 2: 精准查询 ========== | |
| with gr.TabItem("🔍 查询代码"): | |
| gr.Markdown(""" | |
| ### 使用方法 | |
| - **查询单行**: 输入行号,如 `15` | |
| - **查询范围**: 输入 `10-20` 或分别输入起止行号 | |
| - **查询函数**: 输入函数名,如 `main` | |
| - **查询类**: 输入类名 | |
| - **搜索文本**: 输入关键词搜索 | |
| """) | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("#### 快捷查询") | |
| with gr.Group(): | |
| gr.Markdown("**查询单行**") | |
| query_line_num = gr.Number(label="行号", value=1, precision=0) | |
| query_line_btn = gr.Button("查询单行", variant="primary") | |
| with gr.Group(): | |
| gr.Markdown("**查询范围**") | |
| with gr.Row(): | |
| query_start = gr.Number(label="起始行", value=1, precision=0) | |
| query_end = gr.Number(label="结束行", value=10, precision=0) | |
| query_range_btn = gr.Button("查询范围", variant="primary") | |
| with gr.Group(): | |
| gr.Markdown("**查询函数/类**") | |
| query_name = gr.Textbox(label="名称", placeholder="如: main") | |
| with gr.Row(): | |
| query_func_btn = gr.Button("查询函数") | |
| query_class_btn = gr.Button("查询类") | |
| with gr.Group(): | |
| gr.Markdown("**搜索文本**") | |
| search_keyword = gr.Textbox(label="关键词", placeholder="如: print") | |
| search_btn = gr.Button("搜索", variant="primary") | |
| with gr.Column(): | |
| query_result = gr.Textbox( | |
| label="📍 查询结果", | |
| lines=35, | |
| interactive=False, | |
| elem_classes="code-display" | |
| ) | |
| # ========== Tab 3: 精准修改 ========== | |
| with gr.TabItem("✏️ 修改代码"): | |
| with gr.Row(): | |
| with gr.Column(): | |
| modify_mode = gr.Radio( | |
| label="修改模式", | |
| choices=[ | |
| "替换单行", | |
| "替换多行", | |
| "插入代码", | |
| "删除行", | |
| "查找替换", | |
| "调整缩进", | |
| "添加注释" | |
| ], | |
| value="替换单行" | |
| ) | |
| # 通用参数 | |
| with gr.Group() as single_line_group: | |
| modify_line = gr.Number(label="目标行号", value=1, precision=0) | |
| with gr.Group(visible=False) as range_group: | |
| with gr.Row(): | |
| modify_start = gr.Number(label="起始行", value=1, precision=0) | |
| modify_end = gr.Number(label="结束行", value=1, precision=0) | |
| with gr.Group(visible=False) as find_replace_group: | |
| find_text = gr.Textbox(label="查找文本") | |
| replace_text = gr.Textbox(label="替换为") | |
| with gr.Group(visible=False) as indent_group: | |
| indent_spaces = gr.Slider(-8, 8, value=4, step=4, label="缩进空格数(负数为反向)") | |
| new_code_input = gr.Code( | |
| label="新代码内容", | |
| language="python", | |
| lines=10 | |
| ) | |
| with gr.Row(): | |
| execute_modify_btn = gr.Button("🚀 执行修改", variant="primary", scale=2) | |
| undo_btn = gr.Button("↩️ 撤销全部", variant="secondary", scale=1) | |
| with gr.Column(): | |
| modify_result = gr.Textbox( | |
| label="📊 修改结果", | |
| lines=10, | |
| interactive=False | |
| ) | |
| diff_output = gr.Textbox( | |
| label="🔄 变更对比", | |
| lines=25, | |
| interactive=False, | |
| elem_classes="code-display" | |
| ) | |
| # ========== Tab 4: 导出与预览 ========== | |
| with gr.TabItem("📤 导出代码"): | |
| with gr.Column(): | |
| gr.Markdown("### 当前完整代码") | |
| refresh_btn = gr.Button("🔄 刷新预览", variant="primary") | |
| current_code_output = gr.Code( | |
| label="", | |
| language="python", | |
| lines=40, | |
| show_label=False | |
| ) | |
| with gr.Row(): | |
| download_btn = gr.File(label="下载代码文件") | |
| gr.Markdown("### 📊 修改统计") | |
| stats_output = gr.Textbox( | |
| label="", | |
| lines=5, | |
| interactive=False | |
| ) | |
| # ==================== 事件绑定 ==================== | |
| # 自动加载代码(核心) | |
| def auto_load_handler(code): | |
| status = engine.auto_load(code) | |
| structure = engine.list_all() if engine.is_loaded else "" | |
| return status, structure | |
| code_input.change( | |
| fn=auto_load_handler, | |
| inputs=[code_input], | |
| outputs=[status_display, structure_output] | |
| ) | |
| # 加载示例 | |
| def load_example(): | |
| example = '''def calculate_sum(a, b): | |
| """计算两数之和""" | |
| return a + b | |
| def calculate_average(numbers): | |
| """计算平均值""" | |
| if not numbers: | |
| return 0 | |
| return sum(numbers) / len(numbers) | |
| class Calculator: | |
| def __init__(self): | |
| self.result = 0 | |
| def add(self, value): | |
| """加法""" | |
| self.result += value | |
| return self.result | |
| def subtract(self, value): | |
| """减法""" | |
| self.result -= value | |
| return self.result | |
| def reset(self): | |
| """重置""" | |
| self.result = 0 | |
| if __name__ == "__main__": | |
| calc = Calculator() | |
| calc.add(10) | |
| calc.add(5) | |
| print(f"结果: {calc.result}") | |
| ''' | |
| return example | |
| load_example_btn.click( | |
| fn=load_example, | |
| outputs=[code_input] | |
| ) | |
| clear_code_btn.click( | |
| fn=lambda: "", | |
| outputs=[code_input] | |
| ) | |
| # 查询功能 | |
| def query_line(line_num): | |
| result = engine.get_line(int(line_num)) | |
| if result['success']: | |
| return result['formatted'] | |
| return result['error'] | |
| query_line_btn.click( | |
| fn=query_line, | |
| inputs=[query_line_num], | |
| outputs=[query_result] | |
| ) | |
| def query_range(start, end): | |
| result = engine.get_lines(int(start), int(end)) | |
| if result['success']: | |
| return result['formatted'] | |
| return result['error'] | |
| query_range_btn.click( | |
| fn=query_range, | |
| inputs=[query_start, query_end], | |
| outputs=[query_result] | |
| ) | |
| def query_function(name): | |
| result = engine.get_function(name) | |
| if result['success']: | |
| return result['formatted'] | |
| return result['error'] | |
| query_func_btn.click( | |
| fn=query_function, | |
| inputs=[query_name], | |
| outputs=[query_result] | |
| ) | |
| def query_class(name): | |
| result = engine.get_class(name) | |
| if result['success']: | |
| return result['formatted'] | |
| return result['error'] | |
| query_class_btn.click( | |
| fn=query_class, | |
| inputs=[query_name], | |
| outputs=[query_result] | |
| ) | |
| def search_text_handler(keyword): | |
| result = engine.search_text(keyword) | |
| if result['success']: | |
| return result['formatted'] | |
| return result['error'] | |
| search_btn.click( | |
| fn=search_text_handler, | |
| inputs=[search_keyword], | |
| outputs=[query_result] | |
| ) | |
| # 修改模式切换 | |
| def update_modify_ui(mode): | |
| if mode in ["替换多行", "删除行", "调整缩进", "添加注释"]: | |
| return ( | |
| gr.update(visible=False), # single_line_group | |
| gr.update(visible=True), # range_group | |
| gr.update(visible=False), # find_replace_group | |
| gr.update(visible=mode=="调整缩进"), # indent_group | |
| gr.update(visible=mode not in ["删除行", "调整缩进", "添加注释"]) # new_code_input | |
| ) | |
| elif mode == "查找替换": | |
| return ( | |
| gr.update(visible=False), | |
| gr.update(visible=False), | |
| gr.update(visible=True), | |
| gr.update(visible=False), | |
| gr.update(visible=False) | |
| ) | |
| else: # 替换单行, 插入代码 | |
| return ( | |
| gr.update(visible=True), | |
| gr.update(visible=False), | |
| gr.update(visible=False), | |
| gr.update(visible=False), | |
| gr.update(visible=True) | |
| ) | |
| modify_mode.change( | |
| fn=update_modify_ui, | |
| inputs=[modify_mode], | |
| outputs=[single_line_group, range_group, find_replace_group, indent_group, new_code_input] | |
| ) | |
| # 执行修改 | |
| def execute_modify(mode, line, start, end, new_code, find, replace, indent): | |
| result = None | |
| if mode == "替换单行": | |
| result = engine.replace_line(int(line), new_code) | |
| elif mode == "替换多行": | |
| result = engine.replace_lines(int(start), int(end), new_code) | |
| elif mode == "插入代码": | |
| result = engine.insert_after(int(line), new_code) | |
| elif mode == "删除行": | |
| result = engine.delete_lines(int(start), int(end)) | |
| elif mode == "查找替换": | |
| result = engine.find_replace(find, replace) | |
| elif mode == "调整缩进": | |
| result = engine.indent_lines(int(start), int(end), int(indent)) | |
| elif mode == "添加注释": | |
| result = engine.comment_lines(int(start), int(end)) | |
| if result and result['success']: | |
| # 更新代码编辑器 | |
| new_full_code = engine.get_current_code() | |
| status = engine.auto_load(new_full_code) | |
| diff = result.get('diff', result.get('changes', '')) | |
| return ( | |
| result.get('message', '✅ 操作成功'), | |
| diff, | |
| new_full_code, | |
| status | |
| ) | |
| return ( | |
| result.get('error', '❌ 操作失败') if result else '❌ 未知错误', | |
| '', | |
| code_input.value, | |
| status_display.value | |
| ) | |
| execute_modify_btn.click( | |
| fn=execute_modify, | |
| inputs=[ | |
| modify_mode, | |
| modify_line, | |
| modify_start, | |
| modify_end, | |
| new_code_input, | |
| find_text, | |
| replace_text, | |
| indent_spaces | |
| ], | |
| outputs=[modify_result, diff_output, code_input, status_display] | |
| ) | |
| # 撤销 | |
| def undo_handler(): | |
| result = engine.undo() | |
| if result['success']: | |
| code = engine.get_current_code() | |
| status = engine.auto_load(code) | |
| return result['message'], code, status | |
| return result['error'], code_input.value, status_display.value | |
| undo_btn.click( | |
| fn=undo_handler, | |
| outputs=[modify_result, code_input, status_display] | |
| ) | |
| # 刷新预览 | |
| def refresh_preview(): | |
| code = engine.get_current_code() | |
| stats = f"总行数: {len(engine.lines)}\n修改次数: {len(engine.history)}\n语言: {engine.language}" | |
| return code, stats | |
| refresh_btn.click( | |
| fn=refresh_preview, | |
| outputs=[current_code_output, stats_output] | |
| ) | |
| return app | |
| if __name__ == "__main__": | |
| app = create_ui() | |
| app.launch(server_name="0.0.0.0", server_port=7860, share=True) |