mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-02 17:57:45 +03:00
feat(form-decompile,form-compile): CommandInterface — командный интерфейс формы из ring-3
Снят fast-fail на CommandInterface (4388 форм, 13.5% корпуса — крупнейший
оставшийся триггер ring-3).
Форменный ключ commandInterface = панели commandBar + navigationPanel, списки
переопределений авто-расстановки (платформа эмитит только отклонения). Элемент:
command (verbatim; "0"=пустой), type (Auto опускаем/Added), defaultVisible,
visible (тот же xr-flag, что userVisible/use — bool или {common,roles}),
group (CommandGroup verbatim), index, attribute. Порядок тегов Item:
Command,Type,Attribute,CommandGroup,Index,DefaultVisible,Visible.
Две формы записи панели: плоский массив (декомпилятор эмитит её) + древовидная
{группа:[команды]} как входной сахар (алиасы important/goTo/seeAlso→
FormNavigationPanel*, important/createBasedOn→FormCommandBar*; иной ключ verbatim;
group из ключа, элементы не дублируют). Голый элемент → строка-shorthand.
Переиспользует Decompile-XrFlag/Emit-XrFlag.
Выборка 2.17: ring3 37→7, match 181→197; сам CommandInterface роундтрипится
бит-в-бит (0 CI-diff, остаток TOTAL — несвязанный хвост раскрытых форм). Зеркало
py байт-в-байт, кейс commands (+commandInterface tree-форма) сертифицирован
загрузкой в 1С. Регресс 40/40 (ps1+py).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ef036c7cf1
commit
d7dedd4843
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# form-compile v1.97 — Compile 1C managed form from JSON or object metadata
|
||||
# form-compile v1.98 — Compile 1C managed form from JSON or object metadata
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import copy
|
||||
@@ -4655,6 +4655,86 @@ def emit_commands(lines, cmds, indent):
|
||||
lines.append(f'{indent}</Commands>')
|
||||
|
||||
|
||||
# Командный интерфейс формы (<CommandInterface>): панели CommandBar + NavigationPanel.
|
||||
# Элемент: строка (голый command, Type=Auto) или dict. Порядок тегов:
|
||||
# Command, Type(деф. Auto), Attribute, CommandGroup, Index, DefaultVisible, Visible(xr-flag).
|
||||
def _resolve_command_group_key(key, panel_tag):
|
||||
"""Ключ-группа древовидной формы → CommandGroup (зависит от панели); иначе verbatim."""
|
||||
k = re.sub(r'\s', '', str(key)).lower()
|
||||
if panel_tag == 'NavigationPanel':
|
||||
m = {'important': 'FormNavigationPanelImportant', 'важное': 'FormNavigationPanelImportant',
|
||||
'goto': 'FormNavigationPanelGoTo', 'перейти': 'FormNavigationPanelGoTo',
|
||||
'seealso': 'FormNavigationPanelSeeAlso', 'смтакже': 'FormNavigationPanelSeeAlso'}
|
||||
else:
|
||||
m = {'important': 'FormCommandBarImportant', 'важное': 'FormCommandBarImportant',
|
||||
'createbasedon': 'FormCommandBarCreateBasedOn', 'создатьнаосновании': 'FormCommandBarCreateBasedOn'}
|
||||
return m.get(k, key)
|
||||
|
||||
|
||||
def emit_command_interface(lines, ci, indent):
|
||||
if not ci:
|
||||
return
|
||||
inner = f'{indent}\t'
|
||||
panels = [
|
||||
('CommandBar', ('commandBar', 'команднаяПанель', 'КоманднаяПанель')),
|
||||
('NavigationPanel', ('navigationPanel', 'панельНавигации', 'ПанельНавигации')),
|
||||
]
|
||||
present = []
|
||||
for tag, syns in panels:
|
||||
items = None
|
||||
for syn in syns:
|
||||
if isinstance(ci, dict) and syn in ci:
|
||||
items = ci[syn]
|
||||
break
|
||||
if items is not None:
|
||||
present.append((tag, items))
|
||||
if not present:
|
||||
return
|
||||
lines.append(f'{indent}<CommandInterface>')
|
||||
for tag, items in present:
|
||||
lines.append(f'{inner}<{tag}>')
|
||||
# Нормализация: плоский список пар (элемент, group-из-дерева). dict → древовидная форма.
|
||||
flat = []
|
||||
if isinstance(items, dict):
|
||||
for gkey, gitems in items.items():
|
||||
grp_tree = _resolve_command_group_key(gkey, tag)
|
||||
for it in gitems:
|
||||
flat.append((it, grp_tree))
|
||||
else:
|
||||
for it in items:
|
||||
flat.append((it, None))
|
||||
for item, tree_group in flat:
|
||||
if isinstance(item, str):
|
||||
cmd, typ, attr, grp, idx, dv, vis = item, 'Auto', None, None, None, None, None
|
||||
else:
|
||||
cmd = get_el_prop(item, ('command', 'команда'))
|
||||
typ = get_el_prop(item, ('type', 'тип')) or 'Auto'
|
||||
attr = get_el_prop(item, ('attribute', 'реквизит'))
|
||||
grp = get_el_prop(item, ('group', 'группа', 'группаКоманд'))
|
||||
idx = get_el_prop(item, ('index', 'индекс'))
|
||||
dv = get_el_prop(item, ('defaultVisible', 'видимость', 'видимостьПоУмолчанию'))
|
||||
vis = get_el_prop(item, ('visible', 'видимостьПоРолям', 'настройкаВидимости'))
|
||||
# group из дерева побеждает (если задан и непустой); явный group элемента — фолбэк
|
||||
if tree_group:
|
||||
grp = tree_group
|
||||
lines.append(f'{inner}\t<Item>')
|
||||
lines.append(f'{inner}\t\t<Command>{esc_xml(str(cmd))}</Command>')
|
||||
lines.append(f'{inner}\t\t<Type>{typ}</Type>')
|
||||
if attr:
|
||||
lines.append(f'{inner}\t\t<Attribute>{esc_xml(str(attr))}</Attribute>')
|
||||
if grp:
|
||||
lines.append(f'{inner}\t\t<CommandGroup>{esc_xml(str(grp))}</CommandGroup>')
|
||||
if idx is not None:
|
||||
lines.append(f'{inner}\t\t<Index>{idx}</Index>')
|
||||
if dv is not None:
|
||||
lines.append(f'{inner}\t\t<DefaultVisible>{"true" if dv else "false"}</DefaultVisible>')
|
||||
if vis is not None:
|
||||
emit_xr_flag(lines, 'Visible', vis, f'{inner}\t\t')
|
||||
lines.append(f'{inner}\t</Item>')
|
||||
lines.append(f'{inner}</{tag}>')
|
||||
lines.append(f'{indent}</CommandInterface>')
|
||||
|
||||
|
||||
# --- Properties emitter ---
|
||||
|
||||
PROP_MAP = {
|
||||
@@ -5204,6 +5284,9 @@ def main():
|
||||
# Commands
|
||||
emit_commands(lines, defn.get('commands'), '\t')
|
||||
|
||||
# CommandInterface (командный интерфейс формы — последний дочерний Form)
|
||||
emit_command_interface(lines, defn.get('commandInterface'), '\t')
|
||||
|
||||
# Close
|
||||
lines.append('</Form>')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user