-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinterface.py
More file actions
145 lines (125 loc) · 5.88 KB
/
Copy pathinterface.py
File metadata and controls
145 lines (125 loc) · 5.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import tempfile
import subprocess
import re
from pathlib import Path
import yaml
from mathmongo.paths import get_latex_runtime_dir, get_projects_dir, validate_mutable_path
from schemas.schemas import (
ConceptoBase, TipoTitulo, TipoReferencia, TipoPresentacion, NivelContexto,
GradoFormalidad, NivelSimbolico, TipoAplicacion
)
def seleccionar_enum(enum_cls):
opciones = list(enum_cls)
for idx, opt in enumerate(opciones, 1):
print(f" [{idx}] {opt.value}")
while True:
try:
sel = int(input("Seleccione (número): "))
if 1 <= sel <= len(opciones):
return opciones[sel - 1]
except ValueError:
pass
print("⚠️ Selección inválida. Intente de nuevo.")
def abrir_editor_vscode(texto_inicial=""):
runtime = validate_mutable_path(get_latex_runtime_dir() / "vscode")
runtime.mkdir(parents=True, exist_ok=True, mode=0o700)
tmp_name = ""
try:
with tempfile.NamedTemporaryFile(
suffix=".tex", mode="w+", delete=False, dir=runtime
) as tmp:
tmp_name = tmp.name
tmp.write(texto_inicial)
tmp.flush()
subprocess.run(["code", "--wait", tmp.name], check=False)
tmp.seek(0)
contenido = tmp.read()
return contenido.strip()
finally:
if tmp_name:
Path(tmp_name).unlink(missing_ok=True)
def capturar_booleano(msg, default=False):
resp = input(f"{msg} [{'Y/n' if default else 'y/N'}]: ").strip().lower()
if not resp:
return default
return resp in ("y", "yes", "s", "si")
def main():
print("✔️ Crear nuevo concepto matemático\n")
data = {}
data["id"] = input("ID (ej. def:grupo_001): ")
print("Tipo:")
tipos = ["definicion", "proposicion", "teorema", "corolario", "ejemplo", "lema", "nota"]
for i, t in enumerate(tipos, 1):
print(f" [{i}] {t}")
data["tipo"] = tipos[int(input("Seleccione: ")) - 1]
data["titulo"] = input("Título (opcional): ") or None
print("Tipo de título:")
data["tipo_titulo"] = seleccionar_enum(TipoTitulo)
data["categorias"] = [c.strip() for c in input("Categorías (separadas por coma): ").split(",") if c.strip()]
if capturar_booleano("¿Abrir VSCode para capturar contenido LaTeX?", True):
contenido = abrir_editor_vscode()
if '---' in contenido:
print("⚠️ Advertencia: Se detectó '---' dentro del contenido, será eliminado.")
contenido = contenido.replace('---', '')
data["contenido_latex"] = contenido
else:
data["contenido_latex"] = input("Contenido LaTeX (línea única): ")
data["es_algoritmo"] = capturar_booleano("¿Es un algoritmo?", False)
if capturar_booleano("¿Agregar referencia?", False):
ref = {
"tipo_referencia": seleccionar_enum(TipoReferencia),
"autor": input("Autor: ") or None,
"fuente": input("Fuente: ") or None,
"anio": int(input("Año: ")) if capturar_booleano("¿Ingresar año?", False) else None,
"tomo": input("Tomo: ") or None,
"edicion": input("Edición: ") or None,
"paginas": input("Páginas: ") or None,
"capitulo": input("Capítulo: ") or None,
"seccion": input("Sección: ") or None,
"editorial": input("Editorial: ") or None,
"doi": input("DOI: ") or None,
"url": input("URL: ") or None,
"issbn": input("ISSBN: ") or None
}
data["referencia"] = ref
if capturar_booleano("¿Agregar contexto docente?", False):
data["contexto_docente"] = {
"nivel_contexto": seleccionar_enum(NivelContexto),
"grado_formalidad": seleccionar_enum(GradoFormalidad)
}
if capturar_booleano("¿Agregar metadatos técnicos?", False):
raw = input("Conceptos previos (coma separada, opcional): ").strip()
previos = [p.strip() for p in raw.split(",") if p.strip()]
meta = {
"usa_notacion_formal": capturar_booleano("¿Usa notación formal?", True),
"incluye_demostracion": capturar_booleano("¿Incluye demostración?", False),
"es_definicion_operativa": capturar_booleano("¿Es definición operativa?", False),
"es_concepto_fundamental": capturar_booleano("¿Es concepto fundamental?", False),
"requiere_conceptos_previos": previos or None,
"incluye_ejemplo": capturar_booleano("¿Incluye ejemplo?", False),
"es_autocontenible": capturar_booleano("¿Es autocontenible?", True),
"tipo_presentacion": seleccionar_enum(TipoPresentacion),
"nivel_simbolico": seleccionar_enum(NivelSimbolico),
"tipo_aplicacion": [seleccionar_enum(TipoAplicacion)] if capturar_booleano("¿Agregar tipo de aplicación?", False) else None
}
data["metadatos_tecnicos"] = meta
data["alias_previos_pendientes"] = previos or None
else:
data["alias_previos_pendientes"] = None
data["source"] = input("Fuente (carpeta): ")
concepto = ConceptoBase(**data)
safe_source = re.sub(r"[^A-Za-z0-9._-]+", "_", concepto.source).strip("._") or "source"
safe_id = re.sub(r"[^A-Za-z0-9._-]+", "_", concepto.id).strip("._") or "concept"
carpeta = validate_mutable_path(get_projects_dir() / "concept_sources" / safe_source)
carpeta.mkdir(parents=True, exist_ok=True, mode=0o700)
ruta = carpeta / f"{safe_id}.md"
# Usar mode="json" para asegurar que enums y fechas se exporten como texto plano
concepto_dict = concepto.model_dump(mode="json", exclude={"contenido_latex"}, exclude_none=True)
with open(ruta, "w", encoding="utf-8") as f:
f.write("---\n")
yaml.dump(concepto_dict, f, sort_keys=False, allow_unicode=True)
f.write("---\n\n")
f.write(concepto.contenido_latex)
print(f"✔️ Guardado en {ruta}")
if __name__ == "__main__":
main()