feat(skd-edit): значение-список параметра в шортхенде (+skd-compile)

Значение по умолчанию у параметра СКД может быть списком (несколько <value>
подряд при valueListAllowed=true). Раньше задать список можно было только через
объектную модель skd-compile; шортхенд (add/modify-parameter, parameters) парсил
value= как скаляр.

Теперь в шортхенде: value=v1, v2, v3 задаёт список (кавычки '...' для запятой
внутри значения). Если задан список (>=2 элементов), valueListAllowed выводится
автоматически. Авто-вывод только в шортхенде — объектная модель остаётся
буквальной (bit-perfect round-trip сохранён).

skd-edit (ps1+py v1.25):
- Split-QuotedCsv/Parse-ValueList — токенайзер по запятым с учётом кавычек, БЕЗ
  разреза по ':' (важно для дат вида 2024-01-01T12:30:45)
- add-parameter: эмит N <value>
- modify-parameter: пред-выемка value=-списка, удаление ВСЕХ старых <value>,
  авто valueListAllowed; scalar value= теперь тоже схлопывает список в один <value>

skd-compile (ps1+py v1.105): тот же разбор списка в Parse-ParamShorthand;
объектная модель не тронута.

Документация: skd-edit/skd-compile SKILL.md (поведение), docs/1c-dcs-spec.md и
docs/skd-dsl-spec.md (формат).

Тесты: add-list, modify list<->scalar, список дат (двоеточия целы), compile-
шортхенд. Полный регресс 413/413 на ps1 и py.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-04 12:26:57 +03:00
co-authored by Claude Opus 4.8
parent 9877fe403a
commit 6d119eb473
16 changed files with 680 additions and 51 deletions
@@ -1,4 +1,4 @@
# skd-compile v1.104 — Compile 1C DCS from JSON
# skd-compile v1.105 — Compile 1C DCS from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[string]$DefinitionFile,
@@ -475,6 +475,31 @@ function Parse-TotalShorthand {
# --- 7. Parameter shorthand parser ---
function Split-ValueListCsv {
# Split on top-level commas (respecting 'single'/"double" quotes), strip quotes,
# drop empties. No ':' handling — values may contain colons (dateTime).
param([string]$s)
$result = @()
if ($null -eq $s) { return ,$result }
$items = @()
$buf = New-Object System.Text.StringBuilder
$inQuote = $null
for ($i = 0; $i -lt $s.Length; $i++) {
$ch = $s[$i]
if ($inQuote) { [void]$buf.Append($ch); if ($ch -eq $inQuote) { $inQuote = $null } }
elseif ($ch -eq "'" -or $ch -eq '"') { $inQuote = $ch; [void]$buf.Append($ch) }
elseif ($ch -eq ',') { $items += $buf.ToString(); [void]$buf.Clear() }
else { [void]$buf.Append($ch) }
}
if ($buf.Length -gt 0) { $items += $buf.ToString() }
foreach ($raw in $items) {
$t = $raw.Trim()
if ($t.Length -ge 2 -and (($t[0] -eq "'" -and $t[-1] -eq "'") -or ($t[0] -eq '"' -and $t[-1] -eq '"'))) { $t = $t.Substring(1, $t.Length - 2) }
if ($t -ne "") { $result += $t }
}
return ,$result
}
function Parse-ParamShorthand {
param([string]$s)
@@ -509,7 +534,17 @@ function Parse-ParamShorthand {
$result.name = $Matches[1].Trim()
$result.type = Resolve-TypeStr ($Matches[2].Trim())
if ($Matches[4]) {
$result.value = $Matches[4].Trim()
$rhs = $Matches[4].Trim()
$items = Split-ValueListCsv $rhs
if ($items.Count -ge 2) {
# Multi-value default → list; valueListAllowed implied
$result.value = $items
$result.valueListAllowed = $true
} elseif ($items.Count -eq 1) {
$result.value = $items[0]
} else {
$result.value = $rhs
}
}
} else {
$result.name = $s.Trim()
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# skd-compile v1.104 — Compile 1C DCS from JSON
# skd-compile v1.105 — Compile 1C DCS from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import json
@@ -325,6 +325,39 @@ def parse_total_shorthand(s):
# --- Parameter shorthand parser ---
def split_value_list_csv(s):
"""Split on top-level commas (respecting single/double quotes), strip quotes,
drop empties. No ':' handling — values may contain colons (dateTime)."""
result = []
if s is None:
return result
items = []
buf = []
in_quote = None
for ch in s:
if in_quote:
buf.append(ch)
if ch == in_quote:
in_quote = None
elif ch in ("'", '"'):
in_quote = ch
buf.append(ch)
elif ch == ',':
items.append("".join(buf))
buf = []
else:
buf.append(ch)
if buf:
items.append("".join(buf))
for raw in items:
t = raw.strip()
if len(t) >= 2 and ((t[0] == "'" and t[-1] == "'") or (t[0] == '"' and t[-1] == '"')):
t = t[1:-1]
if t != "":
result.append(t)
return result
def parse_param_shorthand(s):
result = {'name': '', 'type': '', 'value': None, 'autoDates': False, 'title': None}
@@ -355,7 +388,16 @@ def parse_param_shorthand(s):
result['name'] = m.group(1).strip()
result['type'] = resolve_type_str(m.group(2).strip())
if m.group(4):
result['value'] = m.group(4).strip()
rhs = m.group(4).strip()
items = split_value_list_csv(rhs)
if len(items) >= 2:
# Multi-value default → list; valueListAllowed implied
result['value'] = items
result['valueListAllowed'] = True
elif len(items) == 1:
result['value'] = items[0]
else:
result['value'] = rhs
else:
result['name'] = s.strip()