Skip to content

Commit 6073ae4

Browse files
yotsudaclaude
andcommitted
Add -Skip/-First compatibility to all line-range cmdlets (closes #41)
- Add -Skip and -First parameters to Show-TextFiles, Remove-LinesFromFile, Update-LinesInFile, and Update-MatchInFile - Map to -LineRange internally via shared MapSkipFirstToLineRange() in base class - Fix PlatyPS v2 Update-Help.ps1 API (Update-CommandHelp, Update-MarkdownModuleFile) - Update PlatyPS help for new parameters - Bump version to 1.7.6 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a46fb98 commit 6073ae4

15 files changed

Lines changed: 504 additions & 37 deletions

PowerShell.MCP.Proxy/PowerShell.MCP.Proxy.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<TargetFramework>net9.0</TargetFramework>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
8-
<Version>1.7.5.0</Version>
8+
<Version>1.7.6.0</Version>
99
<NoWarn>$(NoWarn);NETSDK1206</NoWarn>
1010

1111
<!-- Single File デプロイ設定 -->

PowerShell.MCP/Cmdlets/RemoveLinesFromFileCmdlet.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ public class RemoveLinesFromFileCmdlet : TextFileCmdletBase
3131
[Parameter(ParameterSetName = "LiteralPath")]
3232
public string? Pattern { get; set; }
3333

34+
[Parameter]
35+
public int? Skip { get; set; }
36+
37+
[Parameter]
38+
public int? First { get; set; }
39+
3440
[Parameter]
3541
public string? Encoding { get; set; }
3642

@@ -42,6 +48,9 @@ public class RemoveLinesFromFileCmdlet : TextFileCmdletBase
4248

4349
protected override void BeginProcessing()
4450
{
51+
// -Skip/-First compatibility: map to -LineRange
52+
LineRange = MapSkipFirstToLineRange(Skip, First, LineRange);
53+
4554
// Contains and Pattern can be combined (OR condition), same as Show-TextFiles
4655

4756
// Check that at least one of LineRange, Contains, or Pattern is specified

PowerShell.MCP/Cmdlets/ShowTextFilesCmdlet.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ public class ShowTextFilesCmdlet : TextFileCmdletBase
3333
public string? Contains { get; set; }
3434

3535

36+
[Parameter]
37+
public int? Skip { get; set; }
38+
39+
[Parameter]
40+
public int? First { get; set; }
41+
3642
[Parameter]
3743
public SwitchParameter Recurse { get; set; }
3844

@@ -85,6 +91,9 @@ protected override void BeginProcessing()
8591
null));
8692
}
8793

94+
// -Skip/-First compatibility: map to -LineRange
95+
LineRange = MapSkipFirstToLineRange(Skip, First, LineRange);
96+
8897
// Pre-compile regex for performance (used across all files)
8998
// Combine Contains and Pattern with OR if both specified (single-line mode only)
9099
if (!_isMultilineContains && (!string.IsNullOrEmpty(Pattern) || !string.IsNullOrEmpty(Contains)))

PowerShell.MCP/Cmdlets/TextFileCmdletBase.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,51 @@ protected void ValidateLineRange(string[]? lineRange)
131131
}
132132
}
133133

134+
/// <summary>
135+
/// Maps -Skip/-First to -LineRange. Returns the mapped LineRange value.
136+
/// Throws terminating error for invalid combinations.
137+
/// </summary>
138+
protected string[]? MapSkipFirstToLineRange(int? skip, int? first, string[]? lineRange)
139+
{
140+
if (!skip.HasValue && !first.HasValue)
141+
return lineRange;
142+
143+
if (lineRange != null)
144+
{
145+
ThrowTerminatingError(new ErrorRecord(
146+
new ArgumentException(
147+
"Cannot use -Skip/-First together with -LineRange.\n" +
148+
"Use -LineRange alone.\n\n" +
149+
"Examples:\n" +
150+
" -Skip 200 -First 50 -> -LineRange 201-250\n" +
151+
" -First 20 -> -LineRange 1-20"),
152+
"SkipFirstWithLineRange",
153+
ErrorCategory.InvalidArgument,
154+
null));
155+
}
156+
157+
if (first.HasValue && first.Value <= 0)
158+
{
159+
ThrowTerminatingError(new ErrorRecord(
160+
new ArgumentException("-First must be a positive integer."),
161+
"FirstNotPositive",
162+
ErrorCategory.InvalidArgument,
163+
null));
164+
}
165+
166+
int s = skip ?? 0;
167+
int start = s + 1;
168+
169+
if (!first.HasValue)
170+
{
171+
// -Skip only: from start to end of file
172+
return start <= 1 ? lineRange : new[] { $"{start},-1" };
173+
}
174+
175+
int end = s + first.Value;
176+
return new[] { $"{start}-{end}" };
177+
}
178+
134179
/// <summary>
135180
/// Validates that a parameter value does not contain newline characters
136181
/// </summary>

PowerShell.MCP/Cmdlets/UpdateLinesInFileCmdlet.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ protected override object[]? ContentProperty
3434
set => Content = value;
3535
}
3636

37+
[Parameter]
38+
public int? Skip { get; set; }
39+
40+
[Parameter]
41+
public int? First { get; set; }
42+
3743
[Parameter]
3844
public string? Encoding { get; set; }
3945

@@ -42,6 +48,9 @@ protected override object[]? ContentProperty
4248

4349
protected override void BeginProcessing()
4450
{
51+
// -Skip/-First compatibility: map to -LineRange
52+
LineRange = MapSkipFirstToLineRange(Skip, First, LineRange);
53+
4554
InitializeContentAccumulation();
4655
}
4756

PowerShell.MCP/Cmdlets/UpdateMatchInFileCmdlet.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ public class UpdateMatchInFileCmdlet : TextFileCmdletBase
3232
[ValidateLineRange]
3333
public string[]? LineRange { get; set; }
3434

35+
[Parameter]
36+
public int? Skip { get; set; }
37+
38+
[Parameter]
39+
public int? First { get; set; }
40+
3541
[Parameter]
3642
public string? Encoding { get; set; }
3743

@@ -40,6 +46,8 @@ public class UpdateMatchInFileCmdlet : TextFileCmdletBase
4046

4147
protected override void BeginProcessing()
4248
{
49+
// -Skip/-First compatibility: map to -LineRange
50+
LineRange = MapSkipFirstToLineRange(Skip, First, LineRange);
4351
bool hasLiteral = !string.IsNullOrEmpty(OldText);
4452
bool hasRegex = !string.IsNullOrEmpty(Pattern);
4553

PowerShell.MCP/PlatyPS/Update-Help.ps1

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ foreach ($md in $mdFiles) {
3232
$cmdName = $cmdHelp.Title
3333
$cmdInfo = Get-Command $cmdName -Module PowerShell.MCP -ErrorAction SilentlyContinue
3434
if ($cmdInfo) {
35-
Update-MarkdownCommandHelp -Path $md.FullName -CommandInfo $cmdInfo -Force
35+
Update-CommandHelp -Path $md.FullName
3636
Write-Host " Updated: $($md.Name)" -ForegroundColor Gray
3737
} else {
3838
Write-Warning " Skipped: $($md.Name) (command not found)"
@@ -42,7 +42,8 @@ foreach ($md in $mdFiles) {
4242
# Update module page
4343
$modulePage = Join-Path $markdownPath "PowerShell.MCP.md"
4444
if (Test-Path $modulePage) {
45-
Update-MarkdownModuleFile -Path $modulePage -ModuleInfo (Get-Module PowerShell.MCP) -Force
45+
$commandHelps = $mdFiles | ForEach-Object { Import-MarkdownCommandHelp -Path $_.FullName }
46+
Update-MarkdownModuleFile -Path $modulePage -CommandHelp $commandHelps -Force
4647
Write-Host " Updated: PowerShell.MCP.md" -ForegroundColor Gray
4748
}
4849

PowerShell.MCP/PlatyPS/en-US/PowerShell.MCP.md

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ HelpInfoUri: https://github.com/yotsuda/PowerShell.MCP#readme
55
Locale: ja-JP
66
Module Guid: 313962fa-c90b-424a-9c8a-d4a05f4a1481
77
Module Name: PowerShell.MCP
8-
ms.date: 04/01/2026
8+
ms.date: 04/05/2026
99
PlatyPS schema version: 2024-05-01
1010
title: PowerShell.MCP Module
1111
---
@@ -16,28 +16,12 @@ title: PowerShell.MCP Module
1616

1717
The universal MCP server for Claude Code and other MCP-compatible clients. One installation gives AI access to 10,000+ PowerShell modules and any CLI tool. You and AI collaborate in the same console with full transparency. Supports Windows, Linux, and macOS.
1818

19-
## PowerShell.MCP
19+
## PowerShell.MCP Cmdlets
2020

2121
### [Add-LinesToFile](Add-LinesToFile.md)
2222

2323
Insert lines into a text file at a specific position or at the end
2424

25-
### [Remove-LinesFromFile](Remove-LinesFromFile.md)
26-
27-
Remove lines from a text file by line range or pattern matching
28-
29-
### [Show-TextFiles](Show-TextFiles.md)
30-
31-
Display file contents with line numbers, or search across files with regex or literal patterns
32-
33-
### [Update-LinesInFile](Update-LinesInFile.md)
34-
35-
Replace or delete specific lines in a text file
36-
37-
### [Update-MatchInFile](Update-MatchInFile.md)
38-
39-
Replace text in a file using literal string or regex pattern
40-
4125
### [Get-MCPOwner](Get-MCPOwner.md)
4226

4327
Gets information about the MCP client that owns this console.
@@ -54,7 +38,23 @@ Registers PowerShell.MCP as an MCP server in Claude Code.
5438

5539
Registers PowerShell.MCP as an MCP server in Claude Desktop.
5640

41+
### [Remove-LinesFromFile](Remove-LinesFromFile.md)
42+
43+
Remove lines from a text file by line range or pattern matching
44+
45+
### [Show-TextFiles](Show-TextFiles.md)
46+
47+
Display file contents with line numbers, or search across files with regex or literal patterns
48+
5749
### [Stop-AllPwsh](Stop-AllPwsh.md)
5850

5951
Stops all pwsh processes to release DLL locks.
6052

53+
### [Update-LinesInFile](Update-LinesInFile.md)
54+
55+
Replace or delete specific lines in a text file
56+
57+
### [Update-MatchInFile](Update-MatchInFile.md)
58+
59+
Replace text in a file using literal string or regex pattern
60+

PowerShell.MCP/PlatyPS/en-US/Remove-LinesFromFile.md

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ Remove lines from a text file by line range or pattern matching
2020
### Path
2121

2222
```
23-
Remove-LinesFromFile [-Path] <string[]> [-LineRange <string[]>] [-Contains <string>]
24-
[-Pattern <string>] [-Encoding <string>] [-Backup] [-WhatIf] [-Confirm] [<CommonParameters>]
23+
Remove-LinesFromFile [-Path] <string[]> [-LineRange <string[]>] [-Skip <int>] [-First <int>]
24+
[-Contains <string>] [-Pattern <string>] [-Encoding <string>] [-Backup] [-WhatIf] [-Confirm] [<CommonParameters>]
2525
```
2626

2727
### LiteralPath
2828

2929
```
30-
Remove-LinesFromFile -LiteralPath <string[]> [-LineRange <string[]>] [-Contains <string>]
31-
[-Pattern <string>] [-Encoding <string>] [-Backup] [-WhatIf] [-Confirm] [<CommonParameters>]
30+
Remove-LinesFromFile -LiteralPath <string[]> [-LineRange <string[]>] [-Skip <int>] [-First <int>]
31+
[-Contains <string>] [-Pattern <string>] [-Encoding <string>] [-Backup] [-WhatIf] [-Confirm] [<CommonParameters>]
3232
```
3333

3434
## ALIASES
@@ -137,6 +137,52 @@ AcceptedValues: []
137137
HelpMessage: ''
138138
```
139139

140+
### -First
141+
142+
Number of lines to process.
143+
Use with `-Skip` to define a range, or alone to process from the beginning.
144+
Mapped to `-LineRange` internally (e.g., `-First 20` becomes `-LineRange 1-20`).
145+
146+
```yaml
147+
Type: System.Nullable`1[System.Int32]
148+
DefaultValue: None
149+
SupportsWildcards: false
150+
Aliases: []
151+
ParameterSets:
152+
- Name: (All)
153+
Position: Named
154+
IsRequired: false
155+
ValueFromPipeline: false
156+
ValueFromPipelineByPropertyName: false
157+
ValueFromRemainingArguments: false
158+
DontShow: false
159+
AcceptedValues: []
160+
HelpMessage: ''
161+
```
162+
163+
### -Skip
164+
165+
Number of lines to skip from the beginning.
166+
Use with `-First` to define a window (e.g., `-Skip 200 -First 50` becomes `-LineRange 201-250`).
167+
Use alone to skip lines and process to end of file (e.g., `-Skip 100` becomes `-LineRange 101,-1`).
168+
169+
```yaml
170+
Type: System.Nullable`1[System.Int32]
171+
DefaultValue: None
172+
SupportsWildcards: false
173+
Aliases: []
174+
ParameterSets:
175+
- Name: (All)
176+
Position: Named
177+
IsRequired: false
178+
ValueFromPipeline: false
179+
ValueFromPipelineByPropertyName: false
180+
ValueFromRemainingArguments: false
181+
DontShow: false
182+
AcceptedValues: []
183+
HelpMessage: ''
184+
```
185+
140186
### -Encoding
141187
142188
Character encoding.

PowerShell.MCP/PlatyPS/en-US/Show-TextFiles.md

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ Display file contents with line numbers, or search across files with regex or li
2020
### Path
2121

2222
```
23-
Show-TextFiles [-Path] <string[]> [-LineRange <string[]>] [-Pattern <string>] [-Contains <string>]
24-
[-Recurse] [-Encoding <string>] [<CommonParameters>]
23+
Show-TextFiles [-Path] <string[]> [-LineRange <string[]>] [-Skip <int>] [-First <int>]
24+
[-Pattern <string>] [-Contains <string>] [-Recurse] [-Encoding <string>] [<CommonParameters>]
2525
```
2626

2727
### LiteralPath
2828

2929
```
30-
Show-TextFiles -LiteralPath <string[]> [-LineRange <string[]>] [-Pattern <string>]
31-
[-Contains <string>] [-Recurse] [-Encoding <string>] [<CommonParameters>]
30+
Show-TextFiles -LiteralPath <string[]> [-LineRange <string[]>] [-Skip <int>] [-First <int>]
31+
[-Pattern <string>] [-Contains <string>] [-Recurse] [-Encoding <string>] [<CommonParameters>]
3232
```
3333

3434
## ALIASES
@@ -96,6 +96,52 @@ AcceptedValues: []
9696
HelpMessage: ''
9797
```
9898
99+
### -First
100+
101+
Number of lines to process.
102+
Use with `-Skip` to define a range, or alone to process from the beginning.
103+
Mapped to `-LineRange` internally (e.g., `-First 20` becomes `-LineRange 1-20`).
104+
105+
```yaml
106+
Type: System.Nullable`1[System.Int32]
107+
DefaultValue: None
108+
SupportsWildcards: false
109+
Aliases: []
110+
ParameterSets:
111+
- Name: (All)
112+
Position: Named
113+
IsRequired: false
114+
ValueFromPipeline: false
115+
ValueFromPipelineByPropertyName: false
116+
ValueFromRemainingArguments: false
117+
DontShow: false
118+
AcceptedValues: []
119+
HelpMessage: ''
120+
```
121+
122+
### -Skip
123+
124+
Number of lines to skip from the beginning.
125+
Use with `-First` to define a window (e.g., `-Skip 200 -First 50` becomes `-LineRange 201-250`).
126+
Use alone to skip lines and process to end of file (e.g., `-Skip 100` becomes `-LineRange 101,-1`).
127+
128+
```yaml
129+
Type: System.Nullable`1[System.Int32]
130+
DefaultValue: None
131+
SupportsWildcards: false
132+
Aliases: []
133+
ParameterSets:
134+
- Name: (All)
135+
Position: Named
136+
IsRequired: false
137+
ValueFromPipeline: false
138+
ValueFromPipelineByPropertyName: false
139+
ValueFromRemainingArguments: false
140+
DontShow: false
141+
AcceptedValues: []
142+
HelpMessage: ''
143+
```
144+
99145
### -Encoding
100146
101147
Character encoding.

0 commit comments

Comments
 (0)