mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-06-12 08:54:57 +03:00
515 lines
18 KiB
PowerShell
515 lines
18 KiB
PowerShell
# subsystem-info v1.0 — Compact summary of 1C subsystem structure
|
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
|
param(
|
|
[Parameter(Mandatory=$true)][Alias('Path')][string]$SubsystemPath,
|
|
[ValidateSet("overview","content","ci","tree","full")]
|
|
[string]$Mode = "overview",
|
|
[string]$Name,
|
|
[int]$Limit = 150,
|
|
[int]$Offset = 0,
|
|
[string]$OutFile
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
|
|
# --- Output helper ---
|
|
$script:lines = @()
|
|
function Out([string]$text) { $script:lines += $text }
|
|
|
|
# --- Resolve path ---
|
|
if (-not [System.IO.Path]::IsPathRooted($SubsystemPath)) {
|
|
$SubsystemPath = Join-Path (Get-Location).Path $SubsystemPath
|
|
}
|
|
|
|
# --- Helper: get LocalString text ---
|
|
function Get-MLText($node) {
|
|
if (-not $node -or -not $node.HasChildNodes) { return "" }
|
|
foreach ($item in $node.ChildNodes) {
|
|
if ($item.NodeType -ne 'Element') { continue }
|
|
$lang = ""; $content = ""
|
|
foreach ($c in $item.ChildNodes) {
|
|
if ($c.NodeType -ne 'Element') { continue }
|
|
if ($c.LocalName -eq "lang") { $lang = $c.InnerText }
|
|
if ($c.LocalName -eq "content") { $content = $c.InnerText }
|
|
}
|
|
if ($lang -eq "ru" -and $content) { return $content }
|
|
}
|
|
# fallback: first item
|
|
foreach ($item in $node.ChildNodes) {
|
|
if ($item.NodeType -ne 'Element') { continue }
|
|
foreach ($c in $item.ChildNodes) {
|
|
if ($c.NodeType -ne 'Element') { continue }
|
|
if ($c.LocalName -eq "content" -and $c.InnerText) { return $c.InnerText }
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
# --- Helper: load subsystem XML ---
|
|
function Load-SubsystemXml([string]$xmlPath) {
|
|
[xml]$doc = Get-Content -Path $xmlPath -Encoding UTF8
|
|
$ns = New-Object System.Xml.XmlNamespaceManager($doc.NameTable)
|
|
$ns.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
|
$ns.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core")
|
|
$ns.AddNamespace("xr", "http://v8.1c.ru/8.3/xcf/readable")
|
|
$ns.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")
|
|
$sub = $doc.SelectSingleNode("/md:MetaDataObject/md:Subsystem", $ns)
|
|
if (-not $sub) {
|
|
Write-Host "[ERROR] Not a valid subsystem XML: $xmlPath"
|
|
exit 1
|
|
}
|
|
return @{ Doc=$doc; Ns=$ns; Sub=$sub }
|
|
}
|
|
|
|
# --- Helper: get content items ---
|
|
function Get-ContentItems($props, $ns) {
|
|
$items = @()
|
|
$contentNode = $props.SelectSingleNode("md:Content", $ns)
|
|
if (-not $contentNode -or -not $contentNode.HasChildNodes) { return $items }
|
|
foreach ($item in $contentNode.SelectNodes("xr:Item", $ns)) {
|
|
$items += $item.InnerText
|
|
}
|
|
return $items
|
|
}
|
|
|
|
# --- Helper: get child subsystem names ---
|
|
function Get-ChildNames($sub, $ns) {
|
|
$names = @()
|
|
$co = $sub.SelectSingleNode("md:ChildObjects", $ns)
|
|
if (-not $co -or -not $co.HasChildNodes) { return $names }
|
|
foreach ($child in $co.ChildNodes) {
|
|
if ($child.NodeType -eq 'Element' -and $child.LocalName -eq "Subsystem") {
|
|
$names += $child.InnerText
|
|
}
|
|
}
|
|
return $names
|
|
}
|
|
|
|
# --- Helper: group content by type ---
|
|
function Group-ContentByType($items) {
|
|
$groups = [ordered]@{}
|
|
foreach ($item in $items) {
|
|
if ($item -match '^([^.]+)\.(.+)$') {
|
|
$type = $Matches[1]
|
|
$name = $Matches[2]
|
|
} elseif ($item -match '^[0-9a-fA-F]{8}-') {
|
|
$type = "[UUID]"
|
|
$name = $item
|
|
} else {
|
|
$type = "[Other]"
|
|
$name = $item
|
|
}
|
|
if (-not $groups.Contains($type)) { $groups[$type] = @() }
|
|
$groups[$type] += $name
|
|
}
|
|
return $groups
|
|
}
|
|
|
|
# --- Helper: find subsystem dir from XML path ---
|
|
function Get-SubsystemDir([string]$xmlPath) {
|
|
$dir = [System.IO.Path]::GetDirectoryName($xmlPath)
|
|
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($xmlPath)
|
|
return Join-Path $dir $baseName
|
|
}
|
|
|
|
# --- Show functions for full mode ---
|
|
function Show-Overview {
|
|
Out "Подсистема: $subName"
|
|
if ($synonym -and $synonym -ne $subName) { Out "Синоним: $synonym" }
|
|
if ($commentText) { Out "Комментарий: $commentText" }
|
|
Out "ВключатьВКомандныйИнтерфейс: $inclCI"
|
|
Out "ИспользоватьОднуКоманду: $useOneCmd"
|
|
if ($explanation) { Out "Пояснение: $explanation" }
|
|
if ($picText) { Out "Картинка: $picText" }
|
|
if ($contentItems.Count -gt 0) {
|
|
$parts = @()
|
|
foreach ($type in $groups.Keys) {
|
|
$parts += "$type`: $($groups[$type].Count)"
|
|
}
|
|
Out "Состав: $($contentItems.Count) объектов ($($parts -join ', '))"
|
|
} else {
|
|
Out "Состав: пусто"
|
|
}
|
|
if ($childNames.Count -gt 0) {
|
|
Out "Дочерние подсистемы ($($childNames.Count)): $($childNames -join ', ')"
|
|
}
|
|
if ($hasCI) {
|
|
Out "Командный интерфейс: есть"
|
|
}
|
|
}
|
|
|
|
function Show-Content {
|
|
Out "Состав подсистемы $subName ($($contentItems.Count) объектов):"
|
|
Out ""
|
|
if ($Name) {
|
|
if ($groups.Contains($Name)) {
|
|
$filtered = $groups[$Name]
|
|
Out "$Name ($($filtered.Count)):"
|
|
foreach ($n in $filtered) { Out " $n" }
|
|
} else {
|
|
Out "[INFO] Тип '$Name' не найден в составе."
|
|
Out "Доступные типы: $($groups.Keys -join ', ')"
|
|
}
|
|
} else {
|
|
foreach ($type in $groups.Keys) {
|
|
Out "$type ($($groups[$type].Count)):"
|
|
foreach ($n in $groups[$type]) { Out " $n" }
|
|
Out ""
|
|
}
|
|
}
|
|
}
|
|
|
|
function Show-CI {
|
|
$localSubDir = Get-SubsystemDir $SubsystemPath
|
|
$localCiPath = Join-Path (Join-Path $localSubDir "Ext") "CommandInterface.xml"
|
|
|
|
if (-not (Test-Path $localCiPath)) {
|
|
Out "Командный интерфейс: $subName"
|
|
Out ""
|
|
Out "Файл CommandInterface.xml не найден."
|
|
Out "Путь: $localCiPath"
|
|
} else {
|
|
[xml]$ciDoc = Get-Content -Path $localCiPath -Encoding UTF8
|
|
$ciNs = New-Object System.Xml.XmlNamespaceManager($ciDoc.NameTable)
|
|
$ciNs.AddNamespace("ci", "http://v8.1c.ru/8.3/xcf/extrnprops")
|
|
$ciNs.AddNamespace("xr", "http://v8.1c.ru/8.3/xcf/readable")
|
|
|
|
$ciRoot = $ciDoc.DocumentElement
|
|
|
|
Out "Командный интерфейс: $subName"
|
|
Out ""
|
|
|
|
# --- CommandsVisibility ---
|
|
$visSection = $ciRoot.SelectSingleNode("ci:CommandsVisibility", $ciNs)
|
|
if ($visSection) {
|
|
$hidden = @(); $shown = @()
|
|
foreach ($cmd in $visSection.SelectNodes("ci:Command", $ciNs)) {
|
|
$cmdName = $cmd.GetAttribute("name")
|
|
$vis = $cmd.SelectSingleNode("ci:Visibility/xr:Common", $ciNs)
|
|
if ($vis -and $vis.InnerText -eq "false") { $hidden += $cmdName }
|
|
else { $shown += $cmdName }
|
|
}
|
|
$total = $hidden.Count + $shown.Count
|
|
if (-not $Name -or $Name -eq "visibility") {
|
|
Out "Видимость ($total):"
|
|
if ($hidden.Count -gt 0) {
|
|
Out " СКРЫТО ($($hidden.Count)):"
|
|
foreach ($h in $hidden) { Out " $h" }
|
|
}
|
|
if ($shown.Count -gt 0) {
|
|
Out " ПОКАЗАНО ($($shown.Count)):"
|
|
foreach ($s in $shown) { Out " $s" }
|
|
}
|
|
Out ""
|
|
}
|
|
}
|
|
|
|
# --- CommandsPlacement ---
|
|
$placeSection = $ciRoot.SelectSingleNode("ci:CommandsPlacement", $ciNs)
|
|
if ($placeSection) {
|
|
$placements = @()
|
|
foreach ($cmd in $placeSection.SelectNodes("ci:Command", $ciNs)) {
|
|
$cmdName = $cmd.GetAttribute("name")
|
|
$grp = $cmd.SelectSingleNode("ci:CommandGroup", $ciNs)
|
|
$pl = $cmd.SelectSingleNode("ci:Placement", $ciNs)
|
|
$grpText = if ($grp) { $grp.InnerText } else { "?" }
|
|
$plText = if ($pl) { $pl.InnerText } else { "?" }
|
|
$placements += @{ Name=$cmdName; Group=$grpText; Placement=$plText }
|
|
}
|
|
if ((-not $Name -or $Name -eq "placement") -and $placements.Count -gt 0) {
|
|
Out "Размещение ($($placements.Count)):"
|
|
$arrow = [char]0x2192
|
|
foreach ($p in $placements) {
|
|
Out " $($p.Name) $arrow $($p.Group) ($($p.Placement))"
|
|
}
|
|
Out ""
|
|
}
|
|
}
|
|
|
|
# --- CommandsOrder ---
|
|
$orderSection = $ciRoot.SelectSingleNode("ci:CommandsOrder", $ciNs)
|
|
if ($orderSection) {
|
|
$orderGroups = [ordered]@{}
|
|
foreach ($cmd in $orderSection.SelectNodes("ci:Command", $ciNs)) {
|
|
$cmdName = $cmd.GetAttribute("name")
|
|
$grp = $cmd.SelectSingleNode("ci:CommandGroup", $ciNs)
|
|
$grpText = if ($grp) { $grp.InnerText } else { "?" }
|
|
if (-not $orderGroups.Contains($grpText)) { $orderGroups[$grpText] = @() }
|
|
$orderGroups[$grpText] += $cmdName
|
|
}
|
|
$totalOrder = 0
|
|
foreach ($k in $orderGroups.Keys) { $totalOrder += $orderGroups[$k].Count }
|
|
if ((-not $Name -or $Name -eq "order") -and $totalOrder -gt 0) {
|
|
Out "Порядок команд ($totalOrder):"
|
|
foreach ($grpName in $orderGroups.Keys) {
|
|
Out " [$grpName]:"
|
|
foreach ($c in $orderGroups[$grpName]) { Out " $c" }
|
|
}
|
|
Out ""
|
|
}
|
|
}
|
|
|
|
# --- SubsystemsOrder ---
|
|
$subOrderSection = $ciRoot.SelectSingleNode("ci:SubsystemsOrder", $ciNs)
|
|
if ($subOrderSection) {
|
|
$subOrder = @()
|
|
foreach ($s in $subOrderSection.SelectNodes("ci:Subsystem", $ciNs)) {
|
|
$subOrder += $s.InnerText
|
|
}
|
|
if ((-not $Name -or $Name -eq "subsystems") -and $subOrder.Count -gt 0) {
|
|
Out "Порядок подсистем ($($subOrder.Count)):"
|
|
for ($i = 0; $i -lt $subOrder.Count; $i++) {
|
|
Out " $($i+1). $($subOrder[$i])"
|
|
}
|
|
Out ""
|
|
}
|
|
}
|
|
|
|
# --- GroupsOrder ---
|
|
$grpOrderSection = $ciRoot.SelectSingleNode("ci:GroupsOrder", $ciNs)
|
|
if ($grpOrderSection) {
|
|
$grpOrder = @()
|
|
foreach ($g in $grpOrderSection.SelectNodes("ci:Group", $ciNs)) {
|
|
$grpOrder += $g.InnerText
|
|
}
|
|
if ((-not $Name -or $Name -eq "groups") -and $grpOrder.Count -gt 0) {
|
|
Out "Порядок групп ($($grpOrder.Count)):"
|
|
foreach ($g in $grpOrder) { Out " $g" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# ============================================================
|
|
# Mode: tree
|
|
# ============================================================
|
|
if ($Mode -eq "tree") {
|
|
$isDir = Test-Path $SubsystemPath -PathType Container
|
|
$rootDir = $null
|
|
$rootXml = $null
|
|
|
|
if ($isDir) {
|
|
# Subsystems/ directory — show all top-level subsystems
|
|
$rootDir = $SubsystemPath
|
|
} else {
|
|
# Specific subsystem XML — show tree from this subsystem
|
|
if (-not (Test-Path $SubsystemPath)) {
|
|
Write-Host "[ERROR] File not found: $SubsystemPath"
|
|
exit 1
|
|
}
|
|
$rootXml = $SubsystemPath
|
|
}
|
|
|
|
# Box-drawing chars (PS 5.1 compatible)
|
|
$script:T_BRANCH = [char]0x251C + [char]0x2500 + [char]0x2500 + " " # ├──
|
|
$script:T_LAST = [char]0x2514 + [char]0x2500 + [char]0x2500 + " " # └──
|
|
$script:T_PIPE = [char]0x2502 + " " # │
|
|
$script:T_ARROW = [char]0x2192 # →
|
|
|
|
function Get-TreeLine([string]$xmlPath) {
|
|
$parsed = Load-SubsystemXml $xmlPath
|
|
$sub = $parsed.Sub; $ns = $parsed.Ns
|
|
$props = $sub.SelectSingleNode("md:Properties", $ns)
|
|
$name = $props.SelectSingleNode("md:Name", $ns).InnerText
|
|
|
|
$markers = @()
|
|
$subDir = Get-SubsystemDir $xmlPath
|
|
$ciPath = Join-Path (Join-Path $subDir "Ext") "CommandInterface.xml"
|
|
if (Test-Path $ciPath) { $markers += "CI" }
|
|
$useOne = $props.SelectSingleNode("md:UseOneCommand", $ns)
|
|
if ($useOne -and $useOne.InnerText -eq "true") { $markers += "OneCmd" }
|
|
$inclCI = $props.SelectSingleNode("md:IncludeInCommandInterface", $ns)
|
|
if ($inclCI -and $inclCI.InnerText -eq "false") { $markers += "Скрыт" }
|
|
$markerStr = if ($markers.Count -gt 0) { " [$($markers -join ', ')]" } else { "" }
|
|
|
|
$contentItems = @(Get-ContentItems $props $ns)
|
|
$childNames = @(Get-ChildNames $sub $ns)
|
|
$childStr = if ($childNames.Count -gt 0) { ", $($childNames.Count) дочерних" } else { "" }
|
|
|
|
return @{
|
|
Label = "$name$markerStr ($($contentItems.Count) объектов$childStr)"
|
|
SubDir = $subDir
|
|
ChildNames = $childNames
|
|
}
|
|
}
|
|
|
|
function Build-TreeEntry([string]$xmlPath, [string]$prefix, [bool]$isLast, [bool]$isRoot) {
|
|
$info = Get-TreeLine $xmlPath
|
|
|
|
$connector = if ($isRoot) { "" } elseif ($isLast) { $script:T_LAST } else { $script:T_BRANCH }
|
|
Out "$prefix$connector$($info.Label)"
|
|
|
|
if ($info.ChildNames.Count -gt 0) {
|
|
$childPrefix = if ($isRoot) { "" } elseif ($isLast) { "$prefix " } else { "$prefix$($script:T_PIPE)" }
|
|
$subsDir = Join-Path $info.SubDir "Subsystems"
|
|
for ($i = 0; $i -lt $info.ChildNames.Count; $i++) {
|
|
$childXml = Join-Path $subsDir "$($info.ChildNames[$i]).xml"
|
|
$childIsLast = ($i -eq $info.ChildNames.Count - 1)
|
|
if (Test-Path $childXml) {
|
|
Build-TreeEntry $childXml $childPrefix $childIsLast $false
|
|
} else {
|
|
$conn2 = if ($childIsLast) { $script:T_LAST } else { $script:T_BRANCH }
|
|
Out "$childPrefix$conn2$($info.ChildNames[$i]) [NOT FOUND]"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($rootDir) {
|
|
$label = Split-Path $rootDir -Leaf
|
|
Out "Дерево подсистем от: $label/"
|
|
Out ""
|
|
$xmlFiles = @(Get-ChildItem $rootDir -Filter "*.xml" -File | Sort-Object Name)
|
|
if ($Name) {
|
|
$xmlFiles = @($xmlFiles | Where-Object { $_.BaseName -eq $Name })
|
|
if ($xmlFiles.Count -eq 0) {
|
|
Write-Host "[ERROR] Subsystem '$Name' not found in $rootDir"
|
|
exit 1
|
|
}
|
|
}
|
|
for ($i = 0; $i -lt $xmlFiles.Count; $i++) {
|
|
Build-TreeEntry $xmlFiles[$i].FullName "" ($i -eq $xmlFiles.Count - 1) $true
|
|
}
|
|
} else {
|
|
Build-TreeEntry $rootXml "" $true $true
|
|
}
|
|
|
|
} elseif ($Mode -eq "ci") {
|
|
# ============================================================
|
|
# Mode: ci — CommandInterface.xml
|
|
# ============================================================
|
|
if (Test-Path $SubsystemPath -PathType Container) {
|
|
Write-Host "[ERROR] ci mode requires a subsystem .xml file, not a directory"
|
|
exit 1
|
|
}
|
|
# File not found — check Dir/Name/Name.xml → Dir/Name.xml
|
|
if (-not (Test-Path $SubsystemPath)) {
|
|
$fn = [System.IO.Path]::GetFileNameWithoutExtension($SubsystemPath)
|
|
$pd = Split-Path $SubsystemPath
|
|
if ($fn -eq (Split-Path $pd -Leaf)) {
|
|
$c = Join-Path (Split-Path $pd) "$fn.xml"
|
|
if (Test-Path $c) { $SubsystemPath = $c }
|
|
}
|
|
}
|
|
if (-not (Test-Path $SubsystemPath)) {
|
|
Write-Host "[ERROR] File not found: $SubsystemPath"
|
|
exit 1
|
|
}
|
|
|
|
$parsed = Load-SubsystemXml $SubsystemPath
|
|
$sub = $parsed.Sub; $ns = $parsed.Ns
|
|
$props = $sub.SelectSingleNode("md:Properties", $ns)
|
|
$subName = $props.SelectSingleNode("md:Name", $ns).InnerText
|
|
|
|
Show-CI
|
|
|
|
} else {
|
|
# ============================================================
|
|
# Mode: overview / content — requires a subsystem XML file
|
|
# ============================================================
|
|
if (Test-Path $SubsystemPath -PathType Container) {
|
|
$dirName = Split-Path $SubsystemPath -Leaf
|
|
$candidate = Join-Path $SubsystemPath "$dirName.xml"
|
|
$sibling = Join-Path (Split-Path $SubsystemPath) "$dirName.xml"
|
|
if (Test-Path $candidate) {
|
|
$SubsystemPath = $candidate
|
|
} elseif (Test-Path $sibling) {
|
|
$SubsystemPath = $sibling
|
|
} else {
|
|
Write-Host "[ERROR] No $dirName.xml found in directory. Use -Mode tree for directory listing."
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
# File not found — check Dir/Name/Name.xml → Dir/Name.xml
|
|
if (-not (Test-Path $SubsystemPath)) {
|
|
$fn = [System.IO.Path]::GetFileNameWithoutExtension($SubsystemPath)
|
|
$pd = Split-Path $SubsystemPath
|
|
if ($fn -eq (Split-Path $pd -Leaf)) {
|
|
$c = Join-Path (Split-Path $pd) "$fn.xml"
|
|
if (Test-Path $c) { $SubsystemPath = $c }
|
|
}
|
|
}
|
|
if (-not (Test-Path $SubsystemPath)) {
|
|
Write-Host "[ERROR] File not found: $SubsystemPath"
|
|
exit 1
|
|
}
|
|
|
|
$parsed = Load-SubsystemXml $SubsystemPath
|
|
$sub = $parsed.Sub; $ns = $parsed.Ns
|
|
$props = $sub.SelectSingleNode("md:Properties", $ns)
|
|
|
|
$subName = $props.SelectSingleNode("md:Name", $ns).InnerText
|
|
$synonym = Get-MLText $props.SelectSingleNode("md:Synonym", $ns)
|
|
$comment = $props.SelectSingleNode("md:Comment", $ns)
|
|
$commentText = if ($comment -and $comment.InnerText) { $comment.InnerText } else { "" }
|
|
$inclHelp = $props.SelectSingleNode("md:IncludeHelpInContents", $ns).InnerText
|
|
$inclCI = $props.SelectSingleNode("md:IncludeInCommandInterface", $ns).InnerText
|
|
$useOneCmd = $props.SelectSingleNode("md:UseOneCommand", $ns).InnerText
|
|
$explanation = Get-MLText $props.SelectSingleNode("md:Explanation", $ns)
|
|
|
|
# Picture
|
|
$picNode = $props.SelectSingleNode("md:Picture", $ns)
|
|
$picText = ""
|
|
if ($picNode -and $picNode.HasChildNodes) {
|
|
$picRef = $picNode.SelectSingleNode("xr:Ref", $ns)
|
|
if ($picRef -and $picRef.InnerText) { $picText = $picRef.InnerText }
|
|
}
|
|
|
|
# Content
|
|
$contentItems = @(Get-ContentItems $props $ns)
|
|
$groups = Group-ContentByType $contentItems
|
|
|
|
# Children
|
|
$childNames = @(Get-ChildNames $sub $ns)
|
|
|
|
# CI presence
|
|
$subDir = Get-SubsystemDir $SubsystemPath
|
|
$ciPath = Join-Path (Join-Path $subDir "Ext") "CommandInterface.xml"
|
|
$hasCI = Test-Path $ciPath
|
|
|
|
if ($Mode -eq "overview") {
|
|
Show-Overview
|
|
} elseif ($Mode -eq "content") {
|
|
Show-Content
|
|
} elseif ($Mode -eq "full") {
|
|
Show-Overview
|
|
Out ""; Out "--- content ---"; Out ""
|
|
Show-Content
|
|
Out ""; Out "--- ci ---"; Out ""
|
|
Show-CI
|
|
}
|
|
}
|
|
|
|
# --- Pagination and output ---
|
|
$totalLines = $script:lines.Count
|
|
$outLines = $script:lines
|
|
|
|
if ($Offset -gt 0) {
|
|
if ($Offset -ge $totalLines) {
|
|
Write-Host "[INFO] Offset $Offset exceeds total lines ($totalLines). Nothing to show."
|
|
exit 0
|
|
}
|
|
$outLines = $outLines[$Offset..($totalLines - 1)]
|
|
}
|
|
|
|
if ($Limit -gt 0 -and $outLines.Count -gt $Limit) {
|
|
$shown = $outLines[0..($Limit - 1)]
|
|
$remaining = $totalLines - $Offset - $Limit
|
|
$shown += ""
|
|
$shown += "[ОБРЕЗАНО] Показано $Limit из $totalLines строк. Используйте -Offset $($Offset + $Limit) для продолжения."
|
|
$outLines = $shown
|
|
}
|
|
|
|
if ($OutFile) {
|
|
if (-not [System.IO.Path]::IsPathRooted($OutFile)) {
|
|
$OutFile = Join-Path (Get-Location).Path $OutFile
|
|
}
|
|
$utf8 = New-Object System.Text.UTF8Encoding($true)
|
|
[System.IO.File]::WriteAllLines($OutFile, $outLines, $utf8)
|
|
Write-Host "Output written to $OutFile"
|
|
} else {
|
|
foreach ($l in $outLines) { Write-Host $l }
|
|
}
|