feat(interface-edit): normalize command name type prefix (plural/Russian to singular)

All operations (hide, show, place, order) now auto-normalize
the first segment of command names — e.g. Catalogs.X → Catalog.X,
Справочник.X → Catalog.X.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-04-05 16:46:01 +03:00
parent 9620c3846a
commit 91798e3838
3 changed files with 110 additions and 7 deletions
@@ -1,4 +1,4 @@
# interface-edit v1.1 — Edit 1C CommandInterface.xml
# interface-edit v1.2 — Edit 1C CommandInterface.xml
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)][string]$CIPath,
@@ -202,9 +202,59 @@ function Find-CommandByName($section, [string]$cmdName) {
return $null
}
# --- Command name normalization (plural/Russian type prefix → singular English) ---
$script:typeNormMap = @{
"Catalogs"="Catalog"; "Documents"="Document"; "Enums"="Enum"; "Constants"="Constant"
"Reports"="Report"; "DataProcessors"="DataProcessor"
"InformationRegisters"="InformationRegister"; "AccumulationRegisters"="AccumulationRegister"
"AccountingRegisters"="AccountingRegister"; "CalculationRegisters"="CalculationRegister"
"ChartsOfAccounts"="ChartOfAccounts"; "ChartsOfCharacteristicTypes"="ChartOfCharacteristicTypes"
"ChartsOfCalculationTypes"="ChartOfCalculationTypes"
"BusinessProcesses"="BusinessProcess"; "Tasks"="Task"
"ExchangePlans"="ExchangePlan"; "DocumentJournals"="DocumentJournal"
"CommonModules"="CommonModule"; "CommonCommands"="CommonCommand"
"CommonForms"="CommonForm"; "CommonPictures"="CommonPicture"
"CommonTemplates"="CommonTemplate"; "CommonAttributes"="CommonAttribute"
"CommandGroups"="CommandGroup"; "Roles"="Role"
"Subsystems"="Subsystem"; "StyleItems"="StyleItem"
# Russian singular
"Справочник"="Catalog"; "Документ"="Document"; "Перечисление"="Enum"
"Константа"="Constant"; "Отчёт"="Report"; "Отчет"="Report"; "Обработка"="DataProcessor"
"РегистрСведений"="InformationRegister"; "РегистрНакопления"="AccumulationRegister"
"РегистрБухгалтерии"="AccountingRegister"
"ПланСчетов"="ChartOfAccounts"; "ПланВидовХарактеристик"="ChartOfCharacteristicTypes"
"БизнесПроцесс"="BusinessProcess"; "Задача"="Task"
"ПланОбмена"="ExchangePlan"; "ЖурналДокументов"="DocumentJournal"
"ОбщийМодуль"="CommonModule"; "ОбщаяКоманда"="CommonCommand"
"ОбщаяФорма"="CommonForm"; "Подсистема"="Subsystem"
# Russian plural
"Справочники"="Catalog"; "Документы"="Document"; "Перечисления"="Enum"
"Константы"="Constant"; "Отчёты"="Report"; "Отчеты"="Report"; "Обработки"="DataProcessor"
"РегистрыСведений"="InformationRegister"; "РегистрыНакопления"="AccumulationRegister"
"РегистрыБухгалтерии"="AccountingRegister"
"ПланыСчетов"="ChartOfAccounts"; "ПланыВидовХарактеристик"="ChartOfCharacteristicTypes"
"БизнесПроцессы"="BusinessProcess"; "Задачи"="Task"
"ПланыОбмена"="ExchangePlan"; "ЖурналыДокументов"="DocumentJournal"
"Подсистемы"="Subsystem"
}
function Normalize-CmdName([string]$name) {
if (-not $name -or -not $name.Contains('.')) { return $name }
$dotIdx = $name.IndexOf('.')
$first = $name.Substring(0, $dotIdx)
$rest = $name.Substring($dotIdx)
if ($script:typeNormMap.ContainsKey($first)) {
$normalized = "$($script:typeNormMap[$first])$rest"
if ($normalized -ne $name) { Write-Host "[NORM] Command: $name -> $normalized" }
return $normalized
}
return $name
}
# --- Operations ---
function Do-Hide([string[]]$commands) {
$commands = @($commands | ForEach-Object { Normalize-CmdName $_ })
$section = Ensure-Section "CommandsVisibility"
$sectionIndent = Get-ChildIndent $section
@@ -244,6 +294,7 @@ function Do-Hide([string[]]$commands) {
}
function Do-Show([string[]]$commands) {
$commands = @($commands | ForEach-Object { Normalize-CmdName $_ })
$section = $null
foreach ($child in $root.ChildNodes) {
if ($child.NodeType -eq 'Element' -and $child.LocalName -eq "CommandsVisibility") {
@@ -292,7 +343,7 @@ function Do-Show([string[]]$commands) {
function Do-Place([string]$jsonVal) {
$def = $jsonVal | ConvertFrom-Json
$cmdName = "$($def.command)"
$cmdName = Normalize-CmdName "$($def.command)"
$groupName = "$($def.group)"
if (-not $cmdName -or -not $groupName) { Write-Error "place requires {command, group}"; exit 1 }
@@ -326,7 +377,7 @@ function Do-Place([string]$jsonVal) {
function Do-Order([string]$jsonVal) {
$def = $jsonVal | ConvertFrom-Json
$groupName = "$($def.group)"
$commands = @($def.commands | ForEach-Object { "$_" })
$commands = @($def.commands | ForEach-Object { Normalize-CmdName "$_" })
if (-not $groupName -or $commands.Count -eq 0) { Write-Error "order requires {group, commands:[...]}"; exit 1 }
$section = Ensure-Section "CommandsOrder"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# interface-edit v1.1 — Edit 1C CommandInterface.xml
# interface-edit v1.2 — Edit 1C CommandInterface.xml
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -103,6 +103,56 @@ def save_xml_bom(tree, path):
f.write(xml_bytes)
TYPE_NORM_MAP = {
'Catalogs': 'Catalog', 'Documents': 'Document', 'Enums': 'Enum',
'Constants': 'Constant', 'Reports': 'Report', 'DataProcessors': 'DataProcessor',
'InformationRegisters': 'InformationRegister', 'AccumulationRegisters': 'AccumulationRegister',
'AccountingRegisters': 'AccountingRegister', 'CalculationRegisters': 'CalculationRegister',
'ChartsOfAccounts': 'ChartOfAccounts', 'ChartsOfCharacteristicTypes': 'ChartOfCharacteristicTypes',
'ChartsOfCalculationTypes': 'ChartOfCalculationTypes',
'BusinessProcesses': 'BusinessProcess', 'Tasks': 'Task',
'ExchangePlans': 'ExchangePlan', 'DocumentJournals': 'DocumentJournal',
'CommonModules': 'CommonModule', 'CommonCommands': 'CommonCommand',
'CommonForms': 'CommonForm', 'CommonPictures': 'CommonPicture',
'CommonTemplates': 'CommonTemplate', 'CommonAttributes': 'CommonAttribute',
'CommandGroups': 'CommandGroup', 'Roles': 'Role',
'Subsystems': 'Subsystem', 'StyleItems': 'StyleItem',
# Russian singular
'Справочник': 'Catalog', 'Документ': 'Document', 'Перечисление': 'Enum',
'Константа': 'Constant', 'Отчёт': 'Report', 'Отчет': 'Report', 'Обработка': 'DataProcessor',
'РегистрСведений': 'InformationRegister', 'РегистрНакопления': 'AccumulationRegister',
'РегистрБухгалтерии': 'AccountingRegister',
'ПланСчетов': 'ChartOfAccounts', 'ПланВидовХарактеристик': 'ChartOfCharacteristicTypes',
'БизнесПроцесс': 'BusinessProcess', 'Задача': 'Task',
'ПланОбмена': 'ExchangePlan', 'ЖурналДокументов': 'DocumentJournal',
'ОбщийМодуль': 'CommonModule', 'ОбщаяКоманда': 'CommonCommand',
'ОбщаяФорма': 'CommonForm', 'Подсистема': 'Subsystem',
# Russian plural
'Справочники': 'Catalog', 'Документы': 'Document', 'Перечисления': 'Enum',
'Константы': 'Constant', 'Отчёты': 'Report', 'Отчеты': 'Report', 'Обработки': 'DataProcessor',
'РегистрыСведений': 'InformationRegister', 'РегистрыНакопления': 'AccumulationRegister',
'РегистрыБухгалтерии': 'AccountingRegister',
'ПланыСчетов': 'ChartOfAccounts', 'ПланыВидовХарактеристик': 'ChartOfCharacteristicTypes',
'БизнесПроцессы': 'BusinessProcess', 'Задачи': 'Task',
'ПланыОбмена': 'ExchangePlan', 'ЖурналыДокументов': 'DocumentJournal',
'Подсистемы': 'Subsystem',
}
def normalize_cmd_name(name):
if not name or '.' not in name:
return name
dot_idx = name.index('.')
first = name[:dot_idx]
rest = name[dot_idx:]
if first in TYPE_NORM_MAP:
normalized = TYPE_NORM_MAP[first] + rest
if normalized != name:
print(f'[NORM] Command: {name} -> {normalized}')
return normalized
return name
def find_command_by_name(section, cmd_name):
for child in section:
if isinstance(child.tag, str) and localname(child) == "Command":
@@ -207,6 +257,7 @@ def main():
def do_hide(commands):
nonlocal add_count, modify_count
commands = [normalize_cmd_name(c) for c in commands]
section = ensure_section("CommandsVisibility")
section_indent = get_child_indent(section)
@@ -238,6 +289,7 @@ def main():
def do_show(commands):
nonlocal add_count, modify_count
commands = [normalize_cmd_name(c) for c in commands]
section = None
for child in root:
if isinstance(child.tag, str) and localname(child) == "CommandsVisibility":
@@ -277,7 +329,7 @@ def main():
def do_place(json_val):
nonlocal add_count, modify_count
defn = json_val if isinstance(json_val, dict) else json.loads(json_val)
cmd_name = str(defn["command"])
cmd_name = normalize_cmd_name(str(defn["command"]))
group_name = str(defn["group"])
if not cmd_name or not group_name:
print("place requires {command, group}", file=sys.stderr)
@@ -306,7 +358,7 @@ def main():
nonlocal add_count, remove_count
defn = json_val if isinstance(json_val, dict) else json.loads(json_val)
group_name = str(defn["group"])
commands = [str(c) for c in defn["commands"]]
commands = [normalize_cmd_name(str(c)) for c in defn["commands"]]
if not group_name or not commands:
print("order requires {group, commands:[...]}", file=sys.stderr)
sys.exit(1)
@@ -16,7 +16,7 @@
<Explanation/>
<Picture/>
<Content>
<xr:Item xsi:type="xr:MDObjectRef">Catalogs.Товары</xr:Item>
<xr:Item xsi:type="xr:MDObjectRef">Catalog.Товары</xr:Item>
</Content>
</Properties>
<ChildObjects/>