Calc/sympy_helper.py

60 lines
3.1 KiB
Python

import re
class SympyTools:
"""
Utilidades para la integración con SymPy, incluyendo ayuda contextual
y listas de funciones para autocompletado.
"""
_sympy_func_details = {
"diff": "Derivada: diff(expr, var). Ej: diff(sin(x), x)",
"integrate": "Integral: integrate(expr, var). Ej: integrate(x**2, x)",
"solve": "Resolver ecuaciones: solve(expr, var). Ej: solve(x**2-1, x)",
"limit": "Límite: limit(expr, var, valor). Ej: limit(sin(x)/x, x, 0)",
"series": "Serie de Taylor: series(expr, var, punto, n). Ej: series(exp(x), x, 0, 5)",
"Matrix": "Matrices: Matrix([[a, b], [c, d]]). Ej: Matrix([[1,2],[3,4]])",
"plot": "Gráfica: plot(expr, (var, a, b)). Ej: plot(sin(x), (x, -2*pi, 2*pi))", # Corregido ejemplo de plot
"plot3d": "Gráfica 3D: plot3d(expr, (x, a, b), (y, c, d))",
"simplify": "Simplificar: simplify(expr). Ej: simplify((x**2 + 2*x + 1))",
"expand": "Expandir: expand(expr). Ej: expand((x+1)**2)",
"factor": "Factorizar: factor(expr). Ej: factor(x**2 + 2*x + 1)",
"collect": "Agrupar: collect(expr, var). Ej: collect(x*y + x, x)",
"cancel": "Cancelar: cancel(expr). Ej: cancel((x**2 + 2*x + 1)/(x+1))",
"apart": "Fracciones parciales: apart(expr). Ej: apart(1/(x*(x+1)))", # Var opcional en apart
"together": "Unir fracciones: together(expr). Ej: together(1/x + 1/y)",
"latex": "Convertir a LaTeX: latex(expr). Ej: latex(x**2 + 1) → x^{2} + 1",
}
@staticmethod
def Helper(input_str: str) -> str | None:
"""
Ayuda contextual para funciones SymPy comunes.
Se activa si alguna palabra en input_str es un prefijo de un nombre de función conocido.
"""
cleaned_input = input_str.strip()
if not cleaned_input:
return None
# Extraer palabras (posibles identificadores de función) de la entrada
words_in_input = re.findall(r'[a-zA-Z_][a-zA-Z0-9_]*', cleaned_input)
if not words_in_input:
return None
# Iterar sobre las funciones de SymPy definidas
for func_name, help_text in SympyTools._sympy_func_details.items():
# Comprobar si alguna palabra de la entrada es un prefijo del nombre de la función
for word in words_in_input:
# len(word) > 0 para cumplir "no hay minimo" (una palabra no vacía)
if func_name.startswith(word) and len(word) > 0:
# Ej: func_name="solve", word="solv" -> True. Devuelve ayuda para "solve".
# Ej: func_name="solve", word="s" -> True. Devuelve ayuda para "solve"
# (o la primera función en el diccionario que empiece con "s").
return help_text
return None
@staticmethod
def PopupFunctionList():
"""Lista de métodos y sus descripciones breves para el popup de autocompletado."""
return [
(name, desc.split(". Ej:")[0] if ". Ej:" in desc else desc)
for name, desc in SympyTools._sympy_func_details.items()
]