Files
BakNRet/BakNRet/Public/Get-BakNRetCatalogField.ps1
T
Shuery 8c018533c9 feat(tui): 名录字段的读改核心(第三轮第一块)
先侦察事实(232 行、71 个 Slot 级字段):**可编辑面比预想的还窄,边界落在一条可判定的规则上** —— Encrypt 19 个全是单行(可编辑),Description 24 个单行 + 1 个跨行(Edge 那条多行说明,只读),Path / Exclude 一律只读(Scoop 三条带 $(if ($env:SCOOP_GLOBAL){...}) 表达式、Edge 的 Exclude 是跨行拼接)。

规则:**只有单行的 Encrypt / Description 可编辑** —— 与 ADR-0013 的"按能不能安全往返来定"一致:"改一行"对动态表达式与跨行拼接没有明确含义。

扫描时跳过块注释:文件头部模板里有 SoftWareName = @{ ... } 示例,纯文本扫描会把它当成一个软件(实测踩到)。定位靠 (软件名, Slot, 字段名) 三元组且要求唯一命中,命中 0 个或多个都抛错。

实测五个事实:认出 70 个字段、可编辑 43 个(19+24)、往返**逐字节相同 = True**、真改一个只动一行、Edge 的跨行 Description 正确地只读。

过程里两处自己的坑都被门禁逮住:插入的测试代码带过一行手滑垃圾(Parse 层当场报),以及函数文档注释里写了块注释的闭合符号 —— 它提前结束了那段注释,后半句变成代码,而它是**合法语法**所以解析层抓不到、跑到才炸(与"左边空的赋值"同族)。

验收:test.ps1 9/9 全绿(5.1 与 7)。
2026-09-27 21:25:36 +08:00

61 lines
2.8 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
function Get-BakNRetCatalogField {
<#
.SYNOPSIS
把名录文本拆成"Slot 级字段"的表:行号、软件名、Slot 名、字段名、原文值、是否可编辑。
.DESCRIPTION
可编辑面按**能不能安全往返**来定(ADR-0013):
* `Encrypt` / `Description`,且值在**一行之内** → 可编辑(真实名录里是 19 + 24 个);
* `Path` / `Exclude` / `Include` → 一律只读:它们常带 `$( )` 动态表达式(Scoop 那三条
的 `$(if ($env:SCOOP_GLOBAL) { ... })`)与**跨行字符串拼接**(Edge 的 Exclude),
"改一行"对它们没有明确含义;
* `Description` 也可能是跨行的(Edge 那条多行说明)→ 那种同样只读。
文件头部的注释模板里有 `SoftWareName = @{ ... }` 这样的**示例**:纯文本扫描会把它当成一个
软件,所以扫描时显式跳过块注释里的内容。注意本文档里**不能**写那对块注释符号的闭合形式:
它会提前结束上面这段注释(实测踩到:后半句变成了代码,而它是合法语法 —— 等于调用一个
同名命令,所以解析层抓不到,只有跑到那一步才炸)。
#>
param([Parameter(Mandatory = $true)][AllowEmptyString()][string]$Text)
$lines = $Text -split "`r?`n"
$inComment = $false
$app = ''
$slot = ''
$rows = @()
for ($index = 0; $index -lt $lines.Count; $index++) {
$line = $lines[$index]
$trimmed = $line.Trim()
# 块注释:整段跳过(否则模板里的示例会被当成真条目)
if ($trimmed.StartsWith('<#')) { $inComment = $true; continue }
if ($trimmed.StartsWith('#>')) { $inComment = $false; continue }
if ($inComment) { continue }
if ($trimmed -eq '' -or $trimmed.StartsWith('#')) { continue }
if ($line -match '^ ([\w''\-]+)\s*=\s*@\{\s*$') { $app = $Matches[1]; $slot = ''; continue }
if ($line -match '^ ([\w''\-]+)\s*=\s*@\{\s*$') { $slot = $Matches[1]; continue }
if ($line -match '^\s{8}\}') { $slot = ''; continue }
if ($line -match '^\s{4}\}') { $app = ''; continue }
if ($slot -and $line -match '^\s{12}([\w]+)\s*=\s*(.+)$') {
$key = $Matches[1]
$value = $Matches[2]
$singleLine = $value -match "^('.*'|(\`$true|\`$false))\s*$"
$rows += [pscustomobject]@{
Line = $index + 1
App = $app
Slot = $slot
Key = $key
Value = $value
Editable = (($key -eq 'Encrypt' -or $key -eq 'Description') -and $singleLine)
Raw = $line
}
}
}
return @($rows)
}