Skip to content

Commit 17f6ba2

Browse files
committed
Implement all documented commands, migrate tests to Pester 5, update docs
Add 15 missing commands (Edit-File, Edit-Profile, Edit-Hosts, Use-NppForGit, Set-FileTimestamp, Open-Item, Get-DirectoryListing, New-DirectoryAndEnter, Set-TempLocation, Get-CommandLocation, Invoke-Elevated, Add-Path, Invoke-ProfileReload, Get-IPAddress, Clear-DNSCache) with aliases and tests. Migrate all 32 test files to Pester 5 scoping and syntax. Update CONTRIBUTING.md and README.md to reflect new commands and CI.
1 parent fadd94d commit 17f6ba2

51 files changed

Lines changed: 1667 additions & 309 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CONTRIBUTING.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,17 +126,27 @@ Enhancement suggestions are tracked as GitHub issues. When creating an enhanceme
126126

127127
## Testing
128128

129-
Tests are written with [Pester](https://pester.dev/) in the `tests/` directory. Run the full suite with:
129+
Tests are written with [Pester 5](https://pester.dev/) in the `tests/` directory. Run the full suite with:
130130

131131
```powershell
132-
Invoke-Pester .\tests\
132+
.\Invoke-Tests.ps1
133133
```
134134

135-
When adding new commands, please add corresponding test coverage. Tests import the module with:
135+
This installs Pester 5+ if needed and runs all tests with detailed output. Tests also run automatically via GitHub Actions CI on every push and pull request.
136+
137+
When adding new commands, please add corresponding test coverage. Tests should use the Pester 5 `BeforeAll` pattern:
136138

137139
```powershell
138-
$repoRoot = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
139-
Import-Module (Join-Path $repoRoot "PowerShellDevToolkit") -Force
140+
BeforeAll {
141+
$repoRoot = Split-Path -Parent (Split-Path -Parent $PSCommandPath)
142+
Import-Module (Join-Path $repoRoot "PowerShellDevToolkit") -Force
143+
}
144+
145+
Describe "Your-Command" {
146+
It "Should do something" {
147+
# test code
148+
}
149+
}
140150
```
141151

142152
Also test manually:

PowerShellDevToolkit/PowerShellDevToolkit.psd1

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@{
22
RootModule = 'PowerShellDevToolkit.psm1'
3-
ModuleVersion = '1.1.0'
3+
ModuleVersion = '1.2.0'
44
GUID = '882e07c2-69ad-46e6-aea6-07adb025f6b3'
55
Author = 'PowerShell Dev Toolkit Contributors'
66
CompanyName = 'Community'
@@ -10,6 +10,7 @@
1010
PowerShellVersion = '5.1'
1111

1212
FunctionsToExport = @(
13+
# Original commands
1314
'Connect-SSH'
1415
'Connect-SSHTunnel'
1516
'Copy-ToClipboard'
@@ -27,12 +28,32 @@
2728
'Show-RecentCommands'
2829
'Start-DevServer'
2930
'Watch-LogFile'
31+
# File & editor commands
32+
'Edit-File'
33+
'Edit-Profile'
34+
'Edit-Hosts'
35+
'Use-NppForGit'
36+
'Set-FileTimestamp'
37+
'Open-Item'
38+
# Directory commands
39+
'Get-DirectoryListing'
40+
'New-DirectoryAndEnter'
41+
'Set-TempLocation'
42+
# Utility commands
43+
'Get-CommandLocation'
44+
'Invoke-Elevated'
45+
'Add-Path'
46+
'Invoke-ProfileReload'
47+
# Network commands
48+
'Get-IPAddress'
49+
'Clear-DNSCache'
3050
)
3151

3252
CmdletsToExport = @()
3353
VariablesToExport = @()
3454

3555
AliasesToExport = @(
56+
# Original aliases
3657
'cssh'
3758
'tunnel'
3859
'tssh'
@@ -51,6 +72,23 @@
5172
'ai-rules'
5273
'rc'
5374
'helpme'
75+
# File & editor aliases
76+
'e'
77+
'npp'
78+
'touch'
79+
'open'
80+
# Directory aliases
81+
'll'
82+
'mkcd'
83+
'temp'
84+
# Utility aliases
85+
'which'
86+
'sudo'
87+
'reload'
88+
'grep'
89+
# Network aliases
90+
'ip'
91+
'Flush-DNS'
5492
)
5593

5694
PrivateData = @{

PowerShellDevToolkit/PowerShellDevToolkit.psm1

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ foreach ($file in @($Private + $Public)) {
1111
catch { Write-Error "Failed to import $($file.FullName): $_" }
1212
}
1313

14-
# Aliases
14+
# Aliases — existing commands
1515
New-Alias -Name cssh -Value Connect-SSH -Force -Scope Global
1616
New-Alias -Name tunnel -Value Connect-SSHTunnel -Force -Scope Global
1717
New-Alias -Name tssh -Value Connect-SSHTunnel -Force -Scope Global
@@ -30,3 +30,30 @@ New-Alias -Name clip -Value Copy-ToClipboard -Force -Scope Global
3030
New-Alias -Name ai-rules -Value New-AIRules -Force -Scope Global
3131
New-Alias -Name rc -Value Show-RecentCommands -Force -Scope Global
3232
New-Alias -Name helpme -Value Show-Help -Force -Scope Global
33+
34+
# Aliases — file & editor commands
35+
New-Alias -Name e -Value Edit-File -Force -Scope Global
36+
New-Alias -Name npp -Value Edit-File -Force -Scope Global
37+
New-Alias -Name touch -Value Set-FileTimestamp -Force -Scope Global
38+
New-Alias -Name open -Value Open-Item -Force -Scope Global
39+
40+
# Aliases — directory commands
41+
New-Alias -Name ll -Value Get-DirectoryListing -Force -Scope Global
42+
New-Alias -Name mkcd -Value New-DirectoryAndEnter -Force -Scope Global
43+
New-Alias -Name temp -Value Set-TempLocation -Force -Scope Global
44+
45+
# Aliases — utility commands
46+
New-Alias -Name which -Value Get-CommandLocation -Force -Scope Global
47+
New-Alias -Name sudo -Value Invoke-Elevated -Force -Scope Global
48+
New-Alias -Name reload -Value Invoke-ProfileReload -Force -Scope Global
49+
New-Alias -Name grep -Value Select-String -Force -Scope Global
50+
51+
# Aliases — network commands
52+
New-Alias -Name ip -Value Get-IPAddress -Force -Scope Global
53+
New-Alias -Name Flush-DNS -Value Clear-DNSCache -Force -Scope Global
54+
55+
# la — list all including hidden (wraps Get-DirectoryListing -Force)
56+
function global:la { Get-DirectoryListing -Force @args }
57+
58+
# o. — open current directory in Explorer
59+
function global:o. { Open-Item . }
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
function Add-Path {
2+
<#
3+
.SYNOPSIS
4+
Add a directory to the system or user PATH environment variable.
5+
6+
.DESCRIPTION
7+
Appends the given directory to the PATH for the current session and
8+
persists the change to either the User or Machine environment store.
9+
Skips silently if the directory is already present.
10+
11+
.PARAMETER Path
12+
Directory to add to PATH.
13+
14+
.PARAMETER User
15+
Persist to the current user's PATH instead of the machine PATH.
16+
Machine PATH requires administrator privileges.
17+
18+
.EXAMPLE
19+
Add-Path "C:\tools\bin"
20+
Add-Path "C:\tools\bin" -User
21+
#>
22+
[CmdletBinding()]
23+
param(
24+
[Parameter(Mandatory, Position = 0)]
25+
[string]$Path,
26+
27+
[switch]$User
28+
)
29+
30+
$scope = if ($User) { 'User' } else { 'Machine' }
31+
32+
$current = [System.Environment]::GetEnvironmentVariable('Path', $scope)
33+
$entries = $current -split ';' | Where-Object { $_ -ne '' }
34+
35+
if ($entries -contains $Path) {
36+
Write-Host "Already in $scope PATH: $Path" -ForegroundColor Yellow
37+
return
38+
}
39+
40+
$newValue = ($entries + $Path) -join ';'
41+
42+
try {
43+
[System.Environment]::SetEnvironmentVariable('Path', $newValue, $scope)
44+
$env:Path = "$env:Path;$Path"
45+
Write-Host "Added to $scope PATH: $Path" -ForegroundColor Green
46+
} catch {
47+
Write-Error "Failed to update $scope PATH. $_"
48+
Write-Host "Tip: Run as administrator for Machine-scope changes, or use -User." -ForegroundColor Yellow
49+
}
50+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
function Clear-DNSCache {
2+
<#
3+
.SYNOPSIS
4+
Flush the Windows DNS resolver cache.
5+
6+
.DESCRIPTION
7+
Calls the built-in Clear-DnsClientCache cmdlet and confirms success.
8+
Requires administrator privileges.
9+
10+
.EXAMPLE
11+
Clear-DNSCache
12+
Flush-DNS
13+
#>
14+
[CmdletBinding()]
15+
param()
16+
17+
try {
18+
Clear-DnsClientCache -ErrorAction Stop
19+
Write-Host "DNS cache flushed successfully." -ForegroundColor Green
20+
} catch {
21+
Write-Error "Failed to flush DNS cache: $_"
22+
Write-Host "Tip: Run as administrator (sudo Clear-DNSCache)." -ForegroundColor Yellow
23+
}
24+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
function Edit-File {
2+
<#
3+
.SYNOPSIS
4+
Open a file or folder in the configured editor (defaults to Notepad++).
5+
6+
.DESCRIPTION
7+
Opens the specified path in Notepad++, using the path from config.json
8+
(editor.notepadPlusPlus). Falls back to common install locations, then
9+
to notepad.exe if Notepad++ is not found. When no path is given, opens
10+
the current directory.
11+
12+
.PARAMETER Path
13+
File or folder to open. Defaults to the current directory.
14+
15+
.PARAMETER Line
16+
Jump to this line number (Notepad++ only).
17+
18+
.PARAMETER Column
19+
Jump to this column number (Notepad++ only, requires -Line).
20+
21+
.EXAMPLE
22+
Edit-File .\file.ps1
23+
Edit-File .\file.ps1 -Line 42 -Column 1
24+
Edit-File .
25+
#>
26+
[CmdletBinding()]
27+
param(
28+
[Parameter(Position = 0)]
29+
[string]$Path = '.',
30+
31+
[Parameter()]
32+
[int]$Line,
33+
34+
[Parameter()]
35+
[int]$Column
36+
)
37+
38+
$resolvedPath = Resolve-Path $Path -ErrorAction SilentlyContinue
39+
if (-not $resolvedPath) {
40+
Write-Error "Path not found: $Path"
41+
return
42+
}
43+
44+
$nppExe = $null
45+
46+
$config = Get-ScriptConfig -ErrorAction SilentlyContinue
47+
if ($config -and $config.editor -and $config.editor.notepadPlusPlus) {
48+
if (Test-Path $config.editor.notepadPlusPlus) {
49+
$nppExe = $config.editor.notepadPlusPlus
50+
}
51+
}
52+
53+
if (-not $nppExe) {
54+
$candidates = @(
55+
"${env:ProgramFiles}\Notepad++\notepad++.exe",
56+
"${env:ProgramFiles(x86)}\Notepad++\notepad++.exe",
57+
"${env:LOCALAPPDATA}\Programs\Notepad++\notepad++.exe"
58+
)
59+
foreach ($c in $candidates) {
60+
if (Test-Path $c) { $nppExe = $c; break }
61+
}
62+
}
63+
64+
if (-not $nppExe) {
65+
$cmd = Get-Command 'notepad++' -ErrorAction SilentlyContinue
66+
if ($cmd) { $nppExe = $cmd.Source }
67+
}
68+
69+
if ($nppExe) {
70+
$args = @("`"$resolvedPath`"")
71+
if ($Line -gt 0) { $args += "-n$Line" }
72+
if ($Column -gt 0) { $args += "-c$Column" }
73+
Start-Process -FilePath $nppExe -ArgumentList $args
74+
} else {
75+
Write-Warning "Notepad++ not found. Falling back to notepad.exe."
76+
Start-Process notepad.exe -ArgumentList "`"$resolvedPath`""
77+
}
78+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
function Edit-Hosts {
2+
<#
3+
.SYNOPSIS
4+
Open the Windows hosts file in an elevated editor session.
5+
6+
.DESCRIPTION
7+
Launches Notepad++ (or notepad.exe) with administrator privileges to
8+
edit C:\Windows\System32\drivers\etc\hosts.
9+
10+
.EXAMPLE
11+
Edit-Hosts
12+
#>
13+
[CmdletBinding()]
14+
param()
15+
16+
$hostsPath = "$env:SystemRoot\System32\drivers\etc\hosts"
17+
18+
$nppExe = $null
19+
$config = Get-ScriptConfig -ErrorAction SilentlyContinue
20+
if ($config -and $config.editor -and $config.editor.notepadPlusPlus) {
21+
if (Test-Path $config.editor.notepadPlusPlus) {
22+
$nppExe = $config.editor.notepadPlusPlus
23+
}
24+
}
25+
26+
if (-not $nppExe) {
27+
$candidates = @(
28+
"${env:ProgramFiles}\Notepad++\notepad++.exe",
29+
"${env:ProgramFiles(x86)}\Notepad++\notepad++.exe",
30+
"${env:LOCALAPPDATA}\Programs\Notepad++\notepad++.exe"
31+
)
32+
foreach ($c in $candidates) {
33+
if (Test-Path $c) { $nppExe = $c; break }
34+
}
35+
}
36+
37+
if (-not $nppExe) {
38+
$cmd = Get-Command 'notepad++' -ErrorAction SilentlyContinue
39+
if ($cmd) { $nppExe = $cmd.Source }
40+
}
41+
42+
$editor = if ($nppExe) { $nppExe } else { 'notepad.exe' }
43+
44+
Write-Host "Opening hosts file with elevated privileges..." -ForegroundColor Cyan
45+
Start-Process -FilePath $editor -ArgumentList "`"$hostsPath`"" -Verb RunAs
46+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
function Edit-Profile {
2+
<#
3+
.SYNOPSIS
4+
Open the current user's PowerShell profile in the configured editor.
5+
6+
.DESCRIPTION
7+
Opens $PROFILE in Notepad++ (or the configured editor). Creates the
8+
profile file first if it does not yet exist.
9+
10+
.EXAMPLE
11+
Edit-Profile
12+
#>
13+
[CmdletBinding()]
14+
param()
15+
16+
if (-not (Test-Path $PROFILE)) {
17+
New-Item -Path $PROFILE -ItemType File -Force | Out-Null
18+
Write-Host "Created profile: $PROFILE" -ForegroundColor Green
19+
}
20+
21+
Edit-File $PROFILE
22+
}

0 commit comments

Comments
 (0)