Pinescript / app.py
Alikhani099961's picture
Update app.py
cac091d verified
import gradio as gr
import re
import json
from typing import Dict, List, Tuple, Optional
from dataclasses import dataclass
@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
)