feat(tui): 改方向(第一轮第五块·编辑动作)
清单上最常改的就是方向,而它**能在文本层精确完成**:加/去一个行首标记即可,不需要把整行拆成字段再拼回去。后者要在 Overrides / Flags / 引号 / 转义之间做逆向,任何一处不精确都会把用户的清单改花 —— 外科式改写的底线是"只动我要动的那一处"(ADR-0013)。 **保留用户的写法风格**:仓库的真实清单里同时存在贴着写(+WindowsTerminal)与留空格(+ WindowsTerminal)两种,统一成一种意味着顺带改动了本不该碰的行。这就是"改一个字段却多出几十行 diff"的来源。断言里两种风格都钉住了。 注释行没有方向可改,直接抛错:静默返回原样会制造"改了但没变"。 判据 12 条,其中往返那条最强:**把一行设成它当前的方向,必须原样返回**(含带注释与修饰符的行)。 验收:test.ps1 9/9 全绿(5.1 与 7)。
This commit is contained in:
1 parent
59ec5a21d4
commit
e1fe99671b
4 files changed
+74
No files matched your search
@@ -19,6 +19,7 @@
|
|||||||
CompatiblePSEditions = @('Desktop', 'Core')
|
CompatiblePSEditions = @('Desktop', 'Core')
|
||||||
|
|
||||||
FunctionsToExport = @(
|
FunctionsToExport = @(
|
||||||
|
'Set-BakNRetBackupListDirection',
|
||||||
'Save-BakNRetConfigFile',
|
'Save-BakNRetConfigFile',
|
||||||
'Get-BakNRetBackupListRow',
|
'Get-BakNRetBackupListRow',
|
||||||
'Set-BakNRetBackupListRow',
|
'Set-BakNRetBackupListRow',
|
||||||
|
|||||||
@@ -162,7 +162,10 @@
|
|||||||
|
|
||||||
. (Join-Path $PSScriptRoot 'Public\Save-BakNRetConfigFile.ps1')
|
. (Join-Path $PSScriptRoot 'Public\Save-BakNRetConfigFile.ps1')
|
||||||
|
|
||||||
|
. (Join-Path $PSScriptRoot 'Public\Set-BakNRetBackupListDirection.ps1')
|
||||||
|
|
||||||
Export-ModuleMember -Function @(
|
Export-ModuleMember -Function @(
|
||||||
|
'Set-BakNRetBackupListDirection',
|
||||||
'Save-BakNRetConfigFile',
|
'Save-BakNRetConfigFile',
|
||||||
'Get-BakNRetBackupListRow',
|
'Get-BakNRetBackupListRow',
|
||||||
'Set-BakNRetBackupListRow',
|
'Set-BakNRetBackupListRow',
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
function Set-BakNRetBackupListDirection {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
改一行的方向(both / backup / restore),其余部分逐字节保持。
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
为什么先只做"方向"这一种编辑:它是清单上最常改的东西,而且**能在文本层精确完成** ——
|
||||||
|
加/去一个行首标记就行。要改别的字段就得把整行拆成字段再拼回去,而"拼回去"要在
|
||||||
|
`Overrides` / `Flags` / 引号 / 转义之间做逆向,任何一处不精确都会把用户的清单改花。
|
||||||
|
外科式改写的底线是"只动我要动的那一处"(ADR-0013)。
|
||||||
|
|
||||||
|
**保留用户的写法风格**:仓库的真实清单里同时存在贴着写(`+WindowsTerminal`)与留空格
|
||||||
|
(`+ WindowsTerminal`)两种。原样保留风格比统一成一种更安全 —— 统一意味着顺带改动了
|
||||||
|
那些我本来不该碰的行,而那正是"改一个字段却多出几十行 diff"的来源。
|
||||||
|
|
||||||
|
注释行与空行**没有方向可改**,所以直接抛错:静默返回原样会制造"改了但没变"。
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)][AllowEmptyString()][string]$Raw,
|
||||||
|
[Parameter(Mandatory = $true)][ValidateSet('both', 'backup', 'restore')][string]$Direction
|
||||||
|
)
|
||||||
|
|
||||||
|
$record = ConvertFrom-BackupListLine -Line $Raw
|
||||||
|
if (-not $record) { throw '这一行不是条目(注释或空行),没有方向可改。' }
|
||||||
|
|
||||||
|
# 拆出:行首缩进 + 原有标记的写法风格 + 标记之后的正文
|
||||||
|
$indent = ''
|
||||||
|
$rest = $Raw
|
||||||
|
if ($rest -match '^(\s+)(.+)$') {
|
||||||
|
$indent = $Matches[1]
|
||||||
|
$rest = $Matches[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
$spaced = $false
|
||||||
|
$body = $rest
|
||||||
|
if ($body.Length -gt 0 -and ($body[0] -eq '+' -or $body[0] -eq '-')) {
|
||||||
|
$spaced = ($body.Length -gt 1 -and $body[1] -eq ' ')
|
||||||
|
$body = $body.Substring(1)
|
||||||
|
if ($spaced) { $body = $body.Substring(1) }
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Direction -eq 'both') { return $indent + $body }
|
||||||
|
|
||||||
|
$marker = if ($Direction -eq 'backup') { '+' } else { '-' }
|
||||||
|
if ($spaced) { return $indent + $marker + ' ' + $body }
|
||||||
|
return $indent + $marker + $body
|
||||||
|
}
|
||||||
@@ -1624,6 +1624,29 @@ Test-Case '保存配置:校验不过什么都不动,过了才备份 + 原子
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Test-Case '改方向:只动行首标记,其余逐字节保持,且保留用户写法风格' {
|
||||||
|
Assert-Equal '+Edge' (Set-BakNRetBackupListDirection -Raw 'Edge' -Direction 'backup') '裸行加 +'
|
||||||
|
Assert-Equal 'Edge' (Set-BakNRetBackupListDirection -Raw '+Edge' -Direction 'both') '去掉标记回到 both'
|
||||||
|
Assert-Equal '-Edge' (Set-BakNRetBackupListDirection -Raw '+Edge' -Direction 'restore') '备份改恢复'
|
||||||
|
Assert-Equal '-Edge :encrypt :- logs\' (Set-BakNRetBackupListDirection -Raw '+Edge :encrypt :- logs\' -Direction 'restore') '其余部分逐字节保持'
|
||||||
|
|
||||||
|
# 风格保留:留空格的写法不能被改成贴着写(真实清单里两种都有)
|
||||||
|
Assert-Equal '+ WindowsTerminal' (Set-BakNRetBackupListDirection -Raw '+ WindowsTerminal' -Direction 'backup') '留空格风格保留'
|
||||||
|
Assert-Equal '- WindowsTerminal' (Set-BakNRetBackupListDirection -Raw '+ WindowsTerminal' -Direction 'restore') '改完仍是留空格'
|
||||||
|
Assert-Equal 'WindowsTerminal' (Set-BakNRetBackupListDirection -Raw '+ WindowsTerminal' -Direction 'both') '去掉留空格的标记'
|
||||||
|
|
||||||
|
# 往返:设成当前方向 → 一行都不该变
|
||||||
|
foreach ($line in @('Edge', '+Edge', '-Edge', '+ WindowsTerminal', '+Edge :encrypt # 说明')) {
|
||||||
|
$current = (ConvertFrom-BackupListLine -Line $line).Direction
|
||||||
|
Assert-Equal $line (Set-BakNRetBackupListDirection -Raw $line -Direction $current) ("设成当前方向应当原样返回:" + $line)
|
||||||
|
}
|
||||||
|
|
||||||
|
# 注释行没有方向可改:抛错而不是静默返回原样
|
||||||
|
$threw = $false
|
||||||
|
try { Set-BakNRetBackupListDirection -Raw '# 注释' -Direction 'backup' | Out-Null } catch { $threw = $true }
|
||||||
|
Assert-True $threw '注释行改方向必须抛错'
|
||||||
|
}
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
Remove-Item -LiteralPath $sandbox -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -LiteralPath $sandbox -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
Remove-Item -LiteralPath $itemSandbox -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -LiteralPath $itemSandbox -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
|||||||
Reference in new issue
Block a user