update 0.4.4
Python application / build (push) Has been cancelled

- update документация
- промт для ии полу конфигурируемый
This commit is contained in:
Igor20264
2026-09-06 11:04:01 +03:00
parent 638fd38d7f
commit 818a044aa1
26 changed files with 1987 additions and 457 deletions
+175 -15
View File
@@ -14,13 +14,20 @@ from .diagram_schemes import (
DiagramScheme,
SCHEME_ID_RE,
ensure_user_schemes,
get_schemes,
load_schemes_from_path,
reload_schemes,
save_schemes,
user_schemes_path,
)
from .dnd import enable_file_drop, first_markdown
from .help_content import SCHEMES_HELP, USAGE_HELP, load_prompt_catalog
from .help_content import (
SCHEMES_HELP,
USAGE_HELP,
compose_prompt,
load_docs_catalog,
load_prompt_catalog,
)
from .pipeline import ConvertRequest, convert, default_output_path, timestamped_output_path
from .profiles import (
DEFAULT_HEADING_NUMBERING,
@@ -244,6 +251,7 @@ class Md2GostApp:
self.template_var = tk.StringVar()
self.title_var = tk.StringVar()
self.assignment_var = tk.StringVar()
self.styles_var = tk.StringVar()
self.fallback_var = tk.StringVar()
self.format_var = tk.StringVar()
self.plantuml_var = tk.StringVar()
@@ -266,6 +274,7 @@ class Md2GostApp:
help_menu = tk.Menu(menubar, tearoff=0)
help_menu.add_command(label="Инструкция", command=lambda: self._open_help_window("usage"))
help_menu.add_command(label="Документация", command=lambda: self._open_help_window("docs"))
help_menu.add_command(label="Схемы", command=lambda: self._open_help_window("schemes"))
help_menu.add_command(label="Промпт для ИИ", command=lambda: self._open_help_window("prompts"))
menubar.add_cascade(label="Справка", menu=help_menu)
@@ -313,8 +322,8 @@ class Md2GostApp:
win = tk.Toplevel(self.root)
win.title("Настройки — Файлы")
win.configure(bg=PAPER)
win.minsize(520, 200)
win.geometry("620x240")
win.minsize(520, 240)
win.geometry("620x280")
win.transient(self.root)
frame = ttk.Frame(win, padding=12)
frame.pack(fill=tk.BOTH, expand=True)
@@ -325,13 +334,16 @@ class Md2GostApp:
tip="DOCX титула, вставляется перед телом отчёта")
self._row_path(frame, 2, "Бланк задания", self.assignment_var, self._browse_assignment, clearable=True,
tip="DOCX бланка задания, вставляется перед телом отчёта")
self._row_path(frame, 3, "Стили JSON", self.styles_var, self._browse_styles, clearable=True,
tip="Оверлей md2gost.styles.json поверх пресета типа документа")
hint = ttk.Label(
frame,
text="Пустой шаблон — встроенный Template.docx. Титул и задание вставляются перед телом отчёта.",
text="Пустой шаблон — встроенный Template.docx. Титул и задание вставляются перед телом отчёта.\n"
"Стили JSON — опционально; также подхватывается md2gost.styles.json рядом с .md.",
style="Hint.TLabel",
wraplength=560,
)
hint.grid(row=3, column=0, columnspan=2, sticky="w", pady=(8, 0))
hint.grid(row=4, column=0, columnspan=2, sticky="w", pady=(8, 0))
win.protocol("WM_DELETE_WINDOW", lambda: self._close_toplevel(win, "_win_files"))
return win
@@ -456,6 +468,7 @@ class Md2GostApp:
def _create_help_window(self, kind: str) -> tk.Toplevel:
titles = {
"usage": "Справка — Инструкция",
"docs": "Справка — Документация",
"schemes": "Справка — Схемы",
"prompts": "Справка — Промпт для ИИ",
}
@@ -463,12 +476,17 @@ class Md2GostApp:
win.title(titles.get(kind, "Справка"))
win.configure(bg=PAPER)
win.minsize(560, 400)
win.geometry("700x560")
if kind == "docs":
win.geometry("780x560")
else:
win.geometry("700x560")
win.transient(self.root)
frame = ttk.Frame(win, padding=12)
frame.pack(fill=tk.BOTH, expand=True)
if kind == "usage":
self._build_help(frame)
elif kind == "docs":
self._build_docs_browser(frame)
elif kind == "schemes":
self._build_schemes_help(frame)
else:
@@ -540,6 +558,60 @@ class Md2GostApp:
box = self._readonly_text(parent, USAGE_HELP.strip() + "\n")
box.pack(fill=tk.BOTH, expand=True)
def _build_docs_browser(self, parent) -> None:
ttk.Label(
parent,
text="Страницы слева; ссылки вида (file.md) в тексте открывайте тем же списком. "
"Markdown показывается как есть.",
style="Hint.TLabel",
wraplength=740,
).pack(anchor=tk.W, pady=(0, 8))
catalog = load_docs_catalog()
if not catalog:
ttk.Label(
parent,
text="Документация не найдена (папка docs/ рядом с программой или внутри сборки).",
style="Hint.TLabel",
).pack(anchor=tk.W)
return
self._docs_catalog = catalog
body = ttk.Frame(parent)
body.pack(fill=tk.BOTH, expand=True)
left = ttk.Frame(body)
left.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10))
self._docs_list = tk.Listbox(left, height=22, width=28, exportselection=False)
self._docs_list.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
for _name, title, _text in catalog:
self._docs_list.insert(tk.END, title)
self._docs_list.bind("<<ListboxSelect>>", self._on_docs_select)
_tip(self._docs_list, "Разделы документации (docs/*.md)")
right = ttk.Frame(body)
right.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self._docs_view = self._readonly_text(right, catalog[0][2])
self._docs_view.pack(fill=tk.BOTH, expand=True)
self._docs_list.selection_set(0)
self._docs_list.see(0)
def _on_docs_select(self, _event=None) -> None:
if not hasattr(self, "_docs_list") or not hasattr(self, "_docs_catalog"):
return
sel = self._docs_list.curselection()
if not sel:
return
idx = int(sel[0])
if idx < 0 or idx >= len(self._docs_catalog):
return
text = self._docs_catalog[idx][2]
self._docs_view.configure(state=tk.NORMAL)
self._docs_view.delete("1.0", tk.END)
self._docs_view.insert("1.0", text)
self._docs_view.configure(state=tk.DISABLED)
def _build_schemes_help(self, parent) -> None:
ttk.Label(
parent,
@@ -553,7 +625,9 @@ class Md2GostApp:
catalog = load_prompt_catalog()
ttk.Label(
parent,
text="Скопируйте промпт целиком и вставьте в ChatGPT / Cursor / Copilot. Следующим сообщением — тип, тема, черновик.",
text="Скопируйте промпт и вставьте в ChatGPT / Cursor / Copilot. "
"Кнопки схем дописывают макросы из md2gost.schemes.json — "
"когда ИИ должен знать C4/BPMN/свои шаблоны. Следующим сообщением — тип, тема, черновик.",
style="Hint.TLabel",
wraplength=640,
).pack(anchor=tk.W, pady=(0, 8))
@@ -575,32 +649,113 @@ class Md2GostApp:
ttk.Label(row, text="Промпт").pack(side=tk.LEFT, padx=(0, 8))
box = ttk.Combobox(row, textvariable=self._prompt_choice, values=titles, state="readonly")
box.pack(side=tk.LEFT, fill=tk.X, expand=True)
box.bind("<<ComboboxSelected>>", lambda _e: self._show_selected_prompt())
box.bind("<<ComboboxSelected>>", lambda _e: self._refresh_composed_prompt())
btn = ttk.Button(row, text="Скопировать", command=self._copy_selected_prompt)
btn.pack(side=tk.LEFT, padx=(8, 0))
_tip(btn, "Скопировать выбранный промпт в буфер обмена")
_tip(btn, "Скопировать собранный промпт (база + выбранные схемы) в буфер")
self._prompt_view = self._readonly_text(parent, self._prompt_texts[titles[0]])
schemes_frame = ttk.LabelFrame(parent, text="Дописать схемы в промпт", padding=6)
schemes_frame.pack(fill=tk.X, pady=(0, 6))
ttk.Label(
schemes_frame,
text="UML/Mermaid и так конвертируются в Рисунок; схемы нужны для макросов.",
style="Hint.TLabel",
wraplength=620,
).pack(anchor=tk.W, pady=(0, 4))
try:
ensure_user_schemes()
schemes_map = get_schemes()
except Exception:
schemes_map = {}
self._prompt_scheme_ids = sorted(schemes_map.keys())
self._prompt_scheme_vars: dict[str, tk.BooleanVar] = {}
self._prompt_schemes_by_id = dict(schemes_map)
toggles = ttk.Frame(schemes_frame)
toggles.pack(fill=tk.X)
if not self._prompt_scheme_ids:
ttk.Label(
toggles,
text="Схемы не найдены (md2gost.schemes.json).",
style="Hint.TLabel",
).pack(anchor=tk.W)
else:
for sid in self._prompt_scheme_ids:
var = tk.BooleanVar(value=False)
self._prompt_scheme_vars[sid] = var
title = schemes_map[sid].title or sid
cb = ttk.Checkbutton(
toggles,
text=f"{title} ({sid})",
variable=var,
command=self._refresh_composed_prompt,
)
cb.pack(anchor=tk.W)
_tip(cb, f"Добавить в промпт макросы схемы ```uml-{sid}")
ctrl = ttk.Frame(schemes_frame)
ctrl.pack(fill=tk.X, pady=(4, 0))
btn_all = ttk.Button(ctrl, text="Все", command=self._prompt_schemes_select_all)
btn_all.pack(side=tk.LEFT, padx=(0, 6))
_tip(btn_all, "Включить все схемы")
btn_none = ttk.Button(ctrl, text="Сбросить", command=self._prompt_schemes_clear)
btn_none.pack(side=tk.LEFT)
_tip(btn_none, "Выключить все схемы")
self._prompt_view = self._readonly_text(parent, "")
self._prompt_view.pack(fill=tk.BOTH, expand=True)
self._copy_status = ttk.Label(parent, text="", style="Hint.TLabel")
self._copy_status.pack(anchor=tk.W, pady=(6, 0))
self._refresh_composed_prompt()
def _show_selected_prompt(self) -> None:
text = self._prompt_texts.get(self._prompt_choice.get(), "")
def _selected_prompt_schemes(self) -> list:
out = []
for sid in getattr(self, "_prompt_scheme_ids", []):
var = self._prompt_scheme_vars.get(sid)
if var is not None and var.get():
scheme = self._prompt_schemes_by_id.get(sid)
if scheme is not None:
out.append(scheme)
return out
def _composed_prompt_text(self) -> str:
base = self._prompt_texts.get(self._prompt_choice.get(), "")
return compose_prompt(base, self._selected_prompt_schemes())
def _refresh_composed_prompt(self) -> None:
if not hasattr(self, "_prompt_view"):
return
text = self._composed_prompt_text()
self._prompt_view.configure(state=tk.NORMAL)
self._prompt_view.delete("1.0", tk.END)
self._prompt_view.insert("1.0", text)
self._prompt_view.configure(state=tk.DISABLED)
self._copy_status.configure(text="")
if hasattr(self, "_copy_status"):
self._copy_status.configure(text="")
def _prompt_schemes_select_all(self) -> None:
for var in self._prompt_scheme_vars.values():
var.set(True)
self._refresh_composed_prompt()
def _prompt_schemes_clear(self) -> None:
for var in self._prompt_scheme_vars.values():
var.set(False)
self._refresh_composed_prompt()
def _copy_selected_prompt(self) -> None:
text = self._prompt_texts.get(self._prompt_choice.get(), "")
text = self._composed_prompt_text()
if not text:
return
self.root.clipboard_clear()
self.root.clipboard_append(text)
self.root.update_idletasks()
self._copy_status.configure(text="Скопировано в буфер обмена — можно вставлять в ИИ.")
n = len(self._selected_prompt_schemes())
extra = f" (+{n} схем)" if n else ""
self._copy_status.configure(
text=f"Скопировано в буфер обмена{extra} — можно вставлять в ИИ."
)
def _readonly_text(self, parent, content: str) -> tk.Text:
wrap = ttk.Frame(parent)
@@ -1065,6 +1220,9 @@ class Md2GostApp:
def _browse_assignment(self) -> None:
self._pick_into(self.assignment_var, "Бланк задания", [("Word", "*.docx")])
def _browse_styles(self) -> None:
self._pick_into(self.styles_var, "Стили JSON", [("JSON", "*.json"), ("Все файлы", "*.*")])
def _browse_jar(self) -> None:
self._pick_into(self.plantuml_var, "Свой plantuml.jar", [("JAR", "*.jar"), ("Все файлы", "*.*")])
self._refresh_diagram_status()
@@ -1149,6 +1307,7 @@ class Md2GostApp:
self.template_var.set(req.template or "")
self.title_var.set(req.title or "")
self.assignment_var.set(req.assignment or "")
self.styles_var.set(getattr(req, "styles_path", None) or "")
self.plantuml_var.set(req.plantuml_jar or "")
self.kroki_var.set(req.kroki_url or "")
self._refresh_diagram_status()
@@ -1181,6 +1340,7 @@ class Md2GostApp:
diagram_fallback=_combo_key(self.fallback_var.get(), ("remote", "local", "off"), "remote"),
diagram_format=_combo_key(self.format_var.get(), ("png", "svg"), "png"),
diagram_scale=self._parse_diagram_scale(),
styles_path=self.styles_var.get().strip() or None,
debug=self.debug_var.get(),
open_when_done=self.open_var.get(),
)