Spaces:
Running
Running
| import gradio as gr | |
| import re | |
| import json | |
| from typing import Dict, List, Tuple, Optional | |
| from dataclasses import dataclass | |
| class PineError: | |
| line_number: int | |
| error_type: str | |
| description: str | |
| suggestion: str | |
| severity: str | |
| class PineProfessionalFixer: | |
| def __init__(self): | |
| self.version_patterns = { | |
| 'v4': r'//@version\s*=\s*4', | |
| 'v5': r'//@version\s*=\s*5', | |
| 'v6': r'//@version\s*=\s*6' | |
| } | |
| # نقشه تبدیل توابع قدیمی به جدید | |
| self.function_migrations = { | |
| 'v4_to_v5': { | |
| 'study': 'indicator', | |
| 'security': 'request.security', | |
| 'tostring': 'str.tostring', | |
| 'tonumber': 'str.tonumber', | |
| 'input': 'input.int', | |
| 'hline': 'hline', | |
| 'alertcondition': 'alert' | |
| }, | |
| 'v5_to_v6': { | |
| 'syminfo.ticker': 'syminfo.tickerid', | |
| 'security': 'request.security' | |
| } | |
| } | |
| # الگوهای خطاهای رایج | |
| self.error_patterns = { | |
| 'syntax_errors': [ | |
| (r'(\w+)\s*\(\s*([^)]*)\s*\)\s*=>', r'\1(\2) =>'), # Arrow function syntax | |
| (r'(\w+)\s*\(\s*([^)]*)\s*\)\s*->', r'\1(\2) =>'), # Wrong arrow | |
| (r'var\s+(\w+)\s*=\s*([^=]+)(?!=)', r'var \1 = \2'), # var declarations | |
| (r'if\s*\(\s*([^)]+)\s*\)\s*{', r'if \1'), # if statements | |
| (r'for\s+(\w+)\s*=\s*([^;]+);([^;]+);([^{]+){', r'for \1 = \2 to \3'), # for loops | |
| ], | |
| 'indentation_errors': [ | |
| (r'^(\s{2,})(\S)', r' \2'), # Fix indentation to 4 spaces | |
| (r'^(\t+)(\S)', lambda m: ' ' * len(m.group(1)) + m.group(2)), # Convert tabs to spaces | |
| ], | |
| 'variable_errors': [ | |
| (r'(\w+)\s*:=\s*([^=]+)(?!=)', r'\1 := \2'), # Assignment operators | |
| (r'(\w+)\s*==\s*([^=]+)', r'\1 == \2'), # Comparison operators | |
| ] | |
| } | |
| def detect_version(self, code: str) -> str: | |
| """تشخیص ورژن Pine Script""" | |
| for version, pattern in self.version_patterns.items(): | |
| if re.search(pattern, code, re.IGNORECASE): | |
| return version | |
| return 'v5' # Default version | |
| def fix_syntax_errors(self, code: str) -> str: | |
| """تصحیح خطاهای نحوی""" | |
| fixed_code = code | |
| for pattern, replacement in self.error_patterns['syntax_errors']: | |
| fixed_code = re.sub(pattern, replacement, fixed_code, flags=re.MULTILINE) | |
| return fixed_code | |
| def fix_indentation(self, code: str) -> str: | |
| """تصحیح فاصلهگذاری و تورفتگی""" | |
| lines = code.split('\n') | |
| fixed_lines = [] | |
| for line in lines: | |
| # حذف فاصلههای اضافی در انتهای خط | |
| line = line.rstrip() | |
| # تصحیح تورفتگی | |
| if line.strip(): | |
| # محاسبه سطح تورفتگی | |
| indent_level = 0 | |
| for char in line: | |
| if char == ' ': | |
| indent_level += 1 | |
| elif char == '\t': | |
| indent_level += 4 | |
| else: | |
| break | |
| # تصحیح به مضارب 4 | |
| correct_indent = (indent_level // 4) * 4 | |
| fixed_line = ' ' * correct_indent + line.lstrip() | |
| fixed_lines.append(fixed_line) | |
| else: | |
| fixed_lines.append('') | |
| return '\n'.join(fixed_lines) | |
| def fix_variable_declarations(self, code: str) -> str: | |
| """تصحیح تعریف متغیرها""" | |
| fixed_code = code | |
| # تصحیح عملگرهای انتساب | |
| fixed_code = re.sub(r'(\w+)\s*:=\s*([^=\n]+)', r'\1 := \2', fixed_code) | |
| fixed_code = re.sub(r'(\w+)\s*=\s*([^=\n]+)', r'\1 = \2', fixed_code) | |
| return fixed_code | |
| def fix_function_calls(self, code: str, version: str) -> str: | |
| """تصحیح فراخوانی توابع بر اساس ورژن""" | |
| fixed_code = code | |
| if version == 'v4': | |
| # تبدیل از v4 به v5 | |
| for old_func, new_func in self.function_migrations['v4_to_v5'].items(): | |
| pattern = r'\b' + re.escape(old_func) + r'\b' | |
| fixed_code = re.sub(pattern, new_func, fixed_code) | |
| return fixed_code | |
| def fix_parentheses_and_brackets(self, code: str) -> str: | |
| """تصحیح پرانتزها و براکتها""" | |
| fixed_code = code | |
| # تصحیح فاصلههای اضافی در پرانتزها | |
| fixed_code = re.sub(r'\(\s+', '(', fixed_code) | |
| fixed_code = re.sub(r'\s+\)', ')', fixed_code) | |
| fixed_code = re.sub(r'\[\s+', '[', fixed_code) | |
| fixed_code = re.sub(r'\s+\]', ']', fixed_code) | |
| return fixed_code | |
| def fix_line_endings(self, code: str) -> str: | |
| """تصحیح پایان خطوط""" | |
| # تبدیل انواع مختلف line ending به Unix style | |
| fixed_code = code.replace('\r\n', '\n').replace('\r', '\n') | |
| # حذف خطوط خالی اضافی | |
| fixed_code = re.sub(r'\n{3,}', '\n\n', fixed_code) | |
| return fixed_code | |
| def validate_pine_structure(self, code: str, version: str) -> List[PineError]: | |
| """اعتبارسنجی ساختار کلی Pine Script""" | |
| errors = [] | |
| lines = code.split('\n') | |
| # بررسی وجود //@version | |
| if not re.search(r'//@version\s*=\s*[456]', code): | |
| errors.append(PineError( | |
| line_number=1, | |
| error_type="Version Missing", | |
| description="Version declaration is missing", | |
| suggestion="Add //@version=5 at the beginning", | |
| severity="Critical" | |
| )) | |
| # بررسی وجود indicator یا study | |
| has_main_declaration = False | |
| for i, line in enumerate(lines): | |
| if re.search(r'\b(indicator|study)\s*\(', line): | |
| has_main_declaration = True | |
| break | |
| if not has_main_declaration: | |
| errors.append(PineError( | |
| line_number=1, | |
| error_type="Main Declaration Missing", | |
| description="Missing indicator() or study() declaration", | |
| suggestion="Add indicator('Title') declaration", | |
| severity="Critical" | |
| )) | |
| return errors | |
| def fix_all_errors(self, code: str) -> Tuple[str, List[PineError], str]: | |
| """تصحیح همه خطاها""" | |
| if not code.strip(): | |
| return "", [], "❌ لطفاً کد Pine Script خود را وارد کنید" | |
| progress = "🔍 شروع تحلیل و تصحیح کد Pine Script...\n" | |
| # تشخیص ورژن | |
| version = self.detect_version(code) | |
| progress += f"📊 ورژن تشخیص داده شده: {version}\n" | |
| # مراحل تصحیح | |
| fixed_code = code | |
| progress += "🔧 تصحیح خطاهای نحوی...\n" | |
| fixed_code = self.fix_syntax_errors(fixed_code) | |
| progress += "📐 تصحیح فاصلهگذاری و تورفتگی...\n" | |
| fixed_code = self.fix_indentation(fixed_code) | |
| progress += "🔤 تصحیح متغیرها...\n" | |
| fixed_code = self.fix_variable_declarations(fixed_code) | |
| progress += "⚙️ تصحیح فراخوانی توابع...\n" | |
| fixed_code = self.fix_function_calls(fixed_code, version) | |
| progress += "🔗 تصحیح پرانتزها و براکتها...\n" | |
| fixed_code = self.fix_parentheses_and_brackets(fixed_code) | |
| progress += "📝 تصحیح پایان خطوط...\n" | |
| fixed_code = self.fix_line_endings(fixed_code) | |
| # اعتبارسنجی نهایی | |
| progress += "✅ اعتبارسنجی نهایی...\n" | |
| validation_errors = self.validate_pine_structure(fixed_code, version) | |
| progress += "🎯 تصحیح کامل شد!\n" | |
| return fixed_code, validation_errors, progress | |
| # ایجاد شیء فیکسر | |
| fixer = PineProfessionalFixer() | |
| def process_pine_code(input_code): | |
| """پردازش کد Pine Script""" | |
| if not input_code or not input_code.strip(): | |
| return "", "❌ لطفاً کد Pine Script خود را وارد کنید", "" | |
| try: | |
| fixed_code, errors, progress = fixer.fix_all_errors(input_code) | |
| # ایجاد گزارش خطاها | |
| error_report = "" | |
| if errors: | |
| error_report = "⚠️ خطاهای یافت شده:\n" | |
| for i, error in enumerate(errors, 1): | |
| error_report += f"{i}. خط {error.line_number}: {error.description}\n" | |
| error_report += f" پیشنهاد: {error.suggestion}\n" | |
| error_report += f" اهمیت: {error.severity}\n\n" | |
| else: | |
| error_report = "✅ هیچ خطای ساختاری یافت نشد!" | |
| # ایجاد پیام موفقیت | |
| success_message = """ | |
| 🎉 کد شما با موفقیت تصحیح شد! | |
| 📋 راهنمای استفاده: | |
| 1. کد تصحیح شده را از باکس زیر کپی کنید | |
| 2. در Pine Editor در TradingView پیست کنید | |
| 3. دکمه 'Add to Chart' را بزنید | |
| ✨ کد شما آماده استفاده است! | |
| """ | |
| return fixed_code, error_report, success_message | |
| except Exception as e: | |
| error_msg = f"❌ خطا در تصحیح کد: {str(e)}\nلطفاً کد خود را بررسی کنید و دوباره تلاش کنید." | |
| return "", error_msg, "" | |
| # تعریف رابط کاربری Gradio | |
| def create_interface(): | |
| with gr.Blocks(title="Pine Script Professional Fixer", theme=gr.themes.Soft()) as interface: | |
| gr.Markdown(""" | |
| # 🚀 Pine Script Professional Error Fixer | |
| ## ابزار حرفهای تصحیح کدهای Pine Script | |
| **ویژگیها:** | |
| - ✅ سازگار با ورژنهای 4، 5 و 6 | |
| - 🔧 تصحیح خطاهای نحوی و ساختاری | |
| - 📐 بهینهسازی فاصلهگذاری | |
| - ⚙️ تبدیل توابع قدیمی به جدید | |
| - 🎯 آماده برای استفاده در TradingView | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| input_code = gr.Textbox( | |
| label="📝 کد Pine Script خود را اینجا وارد کنید:", | |
| placeholder="// مثال:\n//@version=5\nindicator('My Indicator')\nplot(close)", | |
| lines=15, | |
| max_lines=25 | |
| ) | |
| fix_button = gr.Button("🔧 تصحیح و بهینهسازی کد", variant="primary", size="lg") | |
| with gr.Column(scale=1): | |
| output_code = gr.Textbox( | |
| label="✅ کد تصحیح شده:", | |
| lines=15, | |
| max_lines=25, | |
| interactive=False | |
| ) | |
| with gr.Row(): | |
| error_report = gr.Textbox( | |
| label="📊 گزارش خطاها:", | |
| lines=5, | |
| interactive=False | |
| ) | |
| success_message = gr.Textbox( | |
| label="🎉 وضعیت:", | |
| lines=5, | |
| interactive=False | |
| ) | |
| # مثالهای نمونه | |
| gr.Markdown(""" | |
| ## 📚 مثالهای نمونه: | |
| **مثال ساده:** | |
| ```pine | |
| //@version=5 | |
| indicator("My RSI", shorttitle="RSI") | |
| rsi_value = ta.rsi(close, 14) | |
| plot(rsi_value, color=color.blue) | |
| hline(70, "Overbought", color=color.red) | |
| hline(30, "Oversold", color=color.green) | |
| ``` | |
| **نکات مهم:** | |
| - حتماً ورژن Pine Script را مشخص کنید | |
| - از indicator() یا study() استفاده کنید | |
| - فاصلهگذاری صحیح را رعایت کنید | |
| """) | |
| # اتصال دکمه به تابع | |
| fix_button.click( | |
| fn=process_pine_code, | |
| inputs=[input_code], | |
| outputs=[output_code, error_report, success_message] | |
| ) | |
| return interface | |
| # اجرای برنامه | |
| if __name__ == "__main__": | |
| interface = create_interface() | |
| interface.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=True, | |
| show_error=True | |
| ) |