From 0ee7ad4b6cbce92b50da96e122f9ce2815d6f786 Mon Sep 17 00:00:00 2001
From: James Brundage <+@users.noreply.github.com>
Date: Sun, 9 Aug 2026 12:10:59 -0700
Subject: [PATCH 01/11] feat: Vector commands return type without input ( Fixes
#14 )
---
Commands/Get-Vector2.ps1 | 4 ++++
Commands/Get-Vector3.ps1 | 6 ++++++
Commands/Get-Vector4.ps1 | 6 ++++++
3 files changed, 16 insertions(+)
diff --git a/Commands/Get-Vector2.ps1 b/Commands/Get-Vector2.ps1
index f3d2c6b..bd25c55 100644
--- a/Commands/Get-Vector2.ps1
+++ b/Commands/Get-Vector2.ps1
@@ -32,6 +32,10 @@ function Get-Vector2 {
}
)
+ if (-not $allIn.Length) {
+ return [Numerics.Vector2]
+ }
+
# and expand them
$expandAllIn = @($allIn | Vector)
diff --git a/Commands/Get-Vector3.ps1 b/Commands/Get-Vector3.ps1
index 4dc1a25..a7607cb 100644
--- a/Commands/Get-Vector3.ps1
+++ b/Commands/Get-Vector3.ps1
@@ -36,6 +36,12 @@ function Get-Vector3 {
}
)
+ # If there were no arguments
+ if (-not $allIn.Length) {
+ # return the vector type
+ return [Numerics.Vector3]
+ }
+
# and expand them
$expandAllIn = @($allIn | Vector)
diff --git a/Commands/Get-Vector4.ps1 b/Commands/Get-Vector4.ps1
index b2d0d69..c515be7 100644
--- a/Commands/Get-Vector4.ps1
+++ b/Commands/Get-Vector4.ps1
@@ -32,6 +32,12 @@ function Get-Vector4 {
}
)
+ # If there were no arguments
+ if (-not $allIn.Length) {
+ # return the vector type
+ return [Numerics.Vector4]
+ }
+
# and expand them
$expandAllIn = @($allIn | vector)
For ($n = 0; $n -lt $expandAllIn.Length; $n+=4) {
From 0749f128ed4f0e06e32836216a75149bd8d5f53f Mon Sep 17 00:00:00 2001
From: James Brundage <+@users.noreply.github.com>
Date: Sun, 9 Aug 2026 12:45:50 -0700
Subject: [PATCH 02/11] feat: Vector commands return type without input ( Fixes
#14 )
---
Commands/Get-Vector2.ps1 | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Commands/Get-Vector2.ps1 b/Commands/Get-Vector2.ps1
index bd25c55..8774ea2 100644
--- a/Commands/Get-Vector2.ps1
+++ b/Commands/Get-Vector2.ps1
@@ -32,7 +32,9 @@ function Get-Vector2 {
}
)
+ # If there were no arguments
if (-not $allIn.Length) {
+ # return the vector type
return [Numerics.Vector2]
}
From 8851d48cd7e897ffccefd99f3b928bfbbf538f35 Mon Sep 17 00:00:00 2001
From: James Brundage <+@users.noreply.github.com>
Date: Wed, 12 Aug 2026 12:16:06 -0700
Subject: [PATCH 03/11] feat: `Get-Vector` supports v2-v4 ( Fixes #15 )
---
Commands/Get-Vector.ps1 | 115 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 111 insertions(+), 4 deletions(-)
diff --git a/Commands/Get-Vector.ps1 b/Commands/Get-Vector.ps1
index 8002ada..8419ff2 100644
--- a/Commands/Get-Vector.ps1
+++ b/Commands/Get-Vector.ps1
@@ -24,10 +24,62 @@ function Get-Vector
* `offset.hours`, `offset.minutes`, `offset.seconds`
* `[string]s` will return their bytes in the current `$outputEncoding`
* Anything unknown will be stringified and the bytes will be returned
+ .EXAMPLE
+ # Create a vector out of two numbers
+ Vector2 1 2
+ .EXAMPLE
+ (Vector2 1 2) + (Vector2 2 1)
+ .EXAMPLE
+ (Vector2 1 2) - (Vector2 2 1)
+ .EXAMPLE
+ # Create a thousand vectors
+ $vectors = Vector2 1..2kb
+ .EXAMPLE
+ # Create a thousand vectors in random order, using the pipeline
+ $vectors = 1..2kb | Get-Random -Count 2kb | Vector2
+ .EXAMPLE
+ # Create a vector from a string
+ $vector = Vector2 "hi"
+ .EXAMPLE
+ # Create a vector out of two numbers
+ Vector3 1 2 3
+ .EXAMPLE
+ (Vector3 1 2 3 ) + (Vector3 3 2 1)
+ .EXAMPLE
+ (Vector3 1 2 3 ) - (Vector3 3 2 1)
+ .EXAMPLE
+ # Create a thousand vectors
+ $vectors = Vector3 1..3kb
+ .EXAMPLE
+ # Create a thousand vectors in random order, using the pipeline
+ $vectors = 1..3kb | Get-Random -Count 3kb | Vector3
+ .EXAMPLE
+ # Create a vector from a string
+ $vector = Vector3 "hi"
+ .EXAMPLE
+ # Create a vector out of four numbers
+ Vector4 1 2 3 4
+ .EXAMPLE
+ (Vector4 1 2 3 4 ) + (Vector4 4 3 2 1 )
+ .EXAMPLE
+ (Vector4 1 2 3 4 ) - (Vector4 4 3 2 1)
+ .EXAMPLE
+ # Create a thousand vectors
+ $vectors = Vector4 1..4kb
+ .EXAMPLE
+ # Create a thousand vectors in random order, using the pipeline
+ $vectors = 1..4kb | Get-Random -Count 4kb | Vector4
+ .EXAMPLE
+ # Create vectors from a string
+ Vector4 "hi"
#>
- [Alias('Vector','Vector1','V1')]
+ [Alias('Vector',
+ 'Get-Vector1','Vector1','V1',
+ 'Get-Vector2','Vector2','V2',
+ 'Get-Vector3','Vector3','V3',
+ 'Get-Vector4','Vector4','V4'
+ )]
param()
-
filter toVector {
$arg = $_
# Return primitive types
@@ -36,7 +88,7 @@ function Get-Vector
return ($arg -as [float])
}
# Return vector components
- if ($arg -is [ValueType]) {
+ if ($arg -is [ValueType]) {
if ($arg -is [Numerics.Vector2]) {
return $arg.X,$arg.Y
}
@@ -115,5 +167,60 @@ function Get-Vector
}
)
- return $allIn | toVector
+ $myName = $MyInvocation.InvocationName
+
+ $expandAllIn = @($allIn | toVector)
+
+ if (-not $expandAllIn.Length) {
+ if ($myName -match '2$') {
+ return [Numerics.Vector2]
+ }
+ elseif ($myName -match '3$') {
+ return [Numerics.Vector3]
+ }
+ elseif ($myName -match '4$') {
+ return [Numerics.Vector4]
+ }
+ else {
+ return [Numerics.Vector2],[Numerics.Vector3],[Numerics.Vector4]
+ }
+ }
+ if ($myName -match '[234]$') {
+ $dimension = $matches.0 -as [int]
+ for ($n = 0; $n -lt $expandAllIn.Length; $n+=$dimension) {
+ $nums = $expandAllIn[$n..($n+($dimension-1))] -as [float[]]
+ if ($dimension -eq 2) {
+ if ($nums.Length -eq 1) {
+ [Numerics.Vector2]::new($nums[0])
+ } else {
+ [Numerics.Vector2]::new($nums)
+ }
+ } elseif ($dimension -eq 3) {
+ if ($nums.Length -eq 1) {
+ [Numerics.Vector3]::new($nums[0])
+ }
+ elseif ($nums.Length -eq 2) {
+ [Numerics.Vector3]::new([Numerics.Vector2]::new($nums[0],$nums[1]), 0)
+ }
+ elseif ($nums.Length -eq 3) {
+ [Numerics.Vector3]::new($nums)
+ }
+ } elseif ($dimension -eq 4) {
+ if ($nums.Length -eq 1) {
+ [Numerics.Vector4]::new($nums[0])
+ }
+ elseif ($nums.Length -eq 2) {
+ [Numerics.Vector4]::new([Numerics.Vector2]::new($nums[0],$nums[1]), 0, 0)
+ }
+ elseif ($nums.Length -eq 3) {
+ [Numerics.Vector4]::new([Numerics.Vector3]::new($nums[0],$nums[1],$nums[2]), 0)
+ }
+ elseif ($nums.Length -eq 4) {
+ [Numerics.Vector4]::new($nums)
+ }
+ }
+ }
+ } else {
+ return $allIn | toVector
+ }
}
\ No newline at end of file
From d6229ef99f91b2ec63f53d97fef2a9294b94627c Mon Sep 17 00:00:00 2001
From: James Brundage <+@users.noreply.github.com>
Date: Wed, 12 Aug 2026 12:18:23 -0700
Subject: [PATCH 04/11] feat: `Vector` eponym ( Fixes #15 )
---
Commands/Get-Vector.ps1 | 226 ---------------------------------------
Commands/Get-Vector2.ps1 | 52 ---------
Commands/Get-Vector3.ps1 | 63 -----------
Commands/Get-Vector4.ps1 | 58 ----------
Vector.ps1 | 223 ++++++++++++++++++++++++++++++++++++++
Vector.psm1 | 120 +++++++++++++++------
6 files changed, 313 insertions(+), 429 deletions(-)
delete mode 100644 Commands/Get-Vector.ps1
delete mode 100644 Commands/Get-Vector2.ps1
delete mode 100644 Commands/Get-Vector3.ps1
delete mode 100644 Commands/Get-Vector4.ps1
create mode 100644 Vector.ps1
diff --git a/Commands/Get-Vector.ps1 b/Commands/Get-Vector.ps1
deleted file mode 100644
index 8419ff2..0000000
--- a/Commands/Get-Vector.ps1
+++ /dev/null
@@ -1,226 +0,0 @@
-function Get-Vector
-{
- <#
- .SYNOPSIS
- Gets a one dimensional vector
- .DESCRIPTION
- Gets a one dimensional vector (or, more simply, a list of numbers)
-
- This will convert a variety of types into numbers.
- .NOTES
- This attempts to convert any type into a number.
-
- Some types are special:
-
- * Primitive types will be casted to float
- * `[Numerics.Vector2]`,`[Numerics.Vector3]`,`[Numerics.Vector4]` output each component
- * `[string]`s that match a range (`$start..$end`) will output that range
- * `[Version]`s will output each numeric component
- * `[semver]`s will output each numeric component, followed by the bytes of a release type
- * `[DateTime]` and `[DateTimeOffset]` will become a series of 12 numbers
- * `year`,`month`,`day`
- * `hour`, `minute`, `second`
- * `millisecond`, `microsecond`, `nanosecond`
- * `offset.hours`, `offset.minutes`, `offset.seconds`
- * `[string]s` will return their bytes in the current `$outputEncoding`
- * Anything unknown will be stringified and the bytes will be returned
- .EXAMPLE
- # Create a vector out of two numbers
- Vector2 1 2
- .EXAMPLE
- (Vector2 1 2) + (Vector2 2 1)
- .EXAMPLE
- (Vector2 1 2) - (Vector2 2 1)
- .EXAMPLE
- # Create a thousand vectors
- $vectors = Vector2 1..2kb
- .EXAMPLE
- # Create a thousand vectors in random order, using the pipeline
- $vectors = 1..2kb | Get-Random -Count 2kb | Vector2
- .EXAMPLE
- # Create a vector from a string
- $vector = Vector2 "hi"
- .EXAMPLE
- # Create a vector out of two numbers
- Vector3 1 2 3
- .EXAMPLE
- (Vector3 1 2 3 ) + (Vector3 3 2 1)
- .EXAMPLE
- (Vector3 1 2 3 ) - (Vector3 3 2 1)
- .EXAMPLE
- # Create a thousand vectors
- $vectors = Vector3 1..3kb
- .EXAMPLE
- # Create a thousand vectors in random order, using the pipeline
- $vectors = 1..3kb | Get-Random -Count 3kb | Vector3
- .EXAMPLE
- # Create a vector from a string
- $vector = Vector3 "hi"
- .EXAMPLE
- # Create a vector out of four numbers
- Vector4 1 2 3 4
- .EXAMPLE
- (Vector4 1 2 3 4 ) + (Vector4 4 3 2 1 )
- .EXAMPLE
- (Vector4 1 2 3 4 ) - (Vector4 4 3 2 1)
- .EXAMPLE
- # Create a thousand vectors
- $vectors = Vector4 1..4kb
- .EXAMPLE
- # Create a thousand vectors in random order, using the pipeline
- $vectors = 1..4kb | Get-Random -Count 4kb | Vector4
- .EXAMPLE
- # Create vectors from a string
- Vector4 "hi"
- #>
- [Alias('Vector',
- 'Get-Vector1','Vector1','V1',
- 'Get-Vector2','Vector2','V2',
- 'Get-Vector3','Vector3','V3',
- 'Get-Vector4','Vector4','V4'
- )]
- param()
- filter toVector {
- $arg = $_
- # Return primitive types
- if ($arg.GetType -and $arg.GetType().IsPrimitive) {
- # casted to float
- return ($arg -as [float])
- }
- # Return vector components
- if ($arg -is [ValueType]) {
- if ($arg -is [Numerics.Vector2]) {
- return $arg.X,$arg.Y
- }
- elseif ($arg -is [Numerics.Vector3]) {
- return $arg.X,$arg.Y,$arg.Z
- }
- elseif ($arg -is [Numerics.Vector4]) {
- return $arg.X,$arg.Y,$arg.Z, $arg.W
- }
- }
- # Look for inline ranges.
- if ($arg -is [string]) {
- if ($arg -match '^\d..\d') {
- $start, $end = $arg -split '\..', 2
- $startInt = ($start -as [int])
- $endInt = ($end -as [int])
- if ($null -ne $startInt -and $null -ne $endInt) {
- # If found, return them expanded.
- return ($startInt..$endInt)
- }
- }
- if ($arg -as [float]) {
- return $arg -as [float]
- }
- }
-
-
- # If the arg is a version, get each number of the version
- if ($arg -is [version]) {return $arg.Major,$arg.Minor,$arg.Build,$arg.Revision}
-
- # If we support semver and the arg is semver
- if (('semver' -as [type]) -and $arg -is [semver]) {
- # Return the numeric parts of the semver
- $arg.Major,$arg.Minor,$arg.Patch
- # and turn any string portions to bytes
- if ($arg.PreReleaseLabel) {
- # make sure to include a leading dash for pre-releases
- $OutputEncoding.GetBytes("-$($arg.PreReleaseLabel)")
- }
-
- if ($arg.BuildLabel) {
- # make sure to include a leading plus for build labels
- $OutputEncoding.GetBytes("+$($arg.BuildLabel)")
- }
- return
- }
-
- # If the arg is a datetime or datetimeoffset
- if ($arg -is [DateTime] -or $arg -is [DateTimeOffset]) {
- # make it an offset, and then output 12 values
- $dateArg = $arg -as [DateTimeOffset]
- # * `year` `month` `day`
- $dateArg.Year, $dateArg.Month, $dateArg.Day,
- # * `hour` `minute` `second`
- $dateArg.Hour, $dateArg.Minute, $dateArg.Second,
- # * `millisecond`, `microsecond`, `nanosecond`
- $dateArg.Millisecond, $dateArg.Microsecond, $dateArg.Nanosecond,
- # * `offset hours`, `offset minutes`, `offset seconds`
- $dateArg.Offset.Hours,$dateArg.Offset.Minutes,$dateArg.Offset.Seconds
- return
- }
- # If the arg is a string
- if ($arg -is [string]) {
- # return its bytes
- return $OutputEncoding.GetBytes($arg)
- }
- # any input we have not caught, stringify and turn to bytes
- return $OutputEncoding.GetBytes("$arg")
- }
-
-
- # Collect all of our input and arguments
- $allIn = @($input) + @(
- foreach ($arg in $args) {
- $arg
- }
- )
-
- $myName = $MyInvocation.InvocationName
-
- $expandAllIn = @($allIn | toVector)
-
- if (-not $expandAllIn.Length) {
- if ($myName -match '2$') {
- return [Numerics.Vector2]
- }
- elseif ($myName -match '3$') {
- return [Numerics.Vector3]
- }
- elseif ($myName -match '4$') {
- return [Numerics.Vector4]
- }
- else {
- return [Numerics.Vector2],[Numerics.Vector3],[Numerics.Vector4]
- }
- }
- if ($myName -match '[234]$') {
- $dimension = $matches.0 -as [int]
- for ($n = 0; $n -lt $expandAllIn.Length; $n+=$dimension) {
- $nums = $expandAllIn[$n..($n+($dimension-1))] -as [float[]]
- if ($dimension -eq 2) {
- if ($nums.Length -eq 1) {
- [Numerics.Vector2]::new($nums[0])
- } else {
- [Numerics.Vector2]::new($nums)
- }
- } elseif ($dimension -eq 3) {
- if ($nums.Length -eq 1) {
- [Numerics.Vector3]::new($nums[0])
- }
- elseif ($nums.Length -eq 2) {
- [Numerics.Vector3]::new([Numerics.Vector2]::new($nums[0],$nums[1]), 0)
- }
- elseif ($nums.Length -eq 3) {
- [Numerics.Vector3]::new($nums)
- }
- } elseif ($dimension -eq 4) {
- if ($nums.Length -eq 1) {
- [Numerics.Vector4]::new($nums[0])
- }
- elseif ($nums.Length -eq 2) {
- [Numerics.Vector4]::new([Numerics.Vector2]::new($nums[0],$nums[1]), 0, 0)
- }
- elseif ($nums.Length -eq 3) {
- [Numerics.Vector4]::new([Numerics.Vector3]::new($nums[0],$nums[1],$nums[2]), 0)
- }
- elseif ($nums.Length -eq 4) {
- [Numerics.Vector4]::new($nums)
- }
- }
- }
- } else {
- return $allIn | toVector
- }
-}
\ No newline at end of file
diff --git a/Commands/Get-Vector2.ps1 b/Commands/Get-Vector2.ps1
deleted file mode 100644
index 8774ea2..0000000
--- a/Commands/Get-Vector2.ps1
+++ /dev/null
@@ -1,52 +0,0 @@
-function Get-Vector2 {
- <#
- .SYNOPSIS
- Gets a Vector2
- .DESCRIPTION
- Gets any input and arguments as a Vector2
- .LINK
- https://learn.microsoft.com/en-us/dotnet/api/system.numerics.vector2?wt.mc_id=MVP_321542
- .EXAMPLE
- # Create a vector out of two numbers
- Vector2 1 2
- .EXAMPLE
- (Vector2 1 2) + (Vector2 2 1)
- .EXAMPLE
- (Vector2 1 2) - (Vector2 2 1)
- .EXAMPLE
- # Create a thousand vectors
- $vectors = Vector2 1..2kb
- .EXAMPLE
- # Create a thousand vectors in random order, using the pipeline
- $vectors = 1..2kb | Get-Random -Count 2kb | Vector2
- .EXAMPLE
- # Create a vector from a string
- $vector = Vector2 "hi"
- #>
- [Alias('V2','Vector2')]
- param()
- # Collect all of our input and arguments
- $allIn = @($input) + @(
- foreach ($arg in $args) {
- $arg
- }
- )
-
- # If there were no arguments
- if (-not $allIn.Length) {
- # return the vector type
- return [Numerics.Vector2]
- }
-
- # and expand them
- $expandAllIn = @($allIn | Vector)
-
- For ($n = 0; $n -lt $expandAllIn.Length; $n+=2) {
- $argSet = $expandAllIn[$n..($n+1)] -as [float[]]
- if ($argSet.Length -eq 1) {
- [Numerics.Vector2]::new($argSet[0])
- } else {
- [Numerics.Vector2]::new($argSet)
- }
- }
-}
diff --git a/Commands/Get-Vector3.ps1 b/Commands/Get-Vector3.ps1
deleted file mode 100644
index a7607cb..0000000
--- a/Commands/Get-Vector3.ps1
+++ /dev/null
@@ -1,63 +0,0 @@
-function Get-Vector3 {
- <#
- .SYNOPSIS
- Gets a Vector3
- .DESCRIPTION
- Gets any input and arguments as a Vector3
- .LINK
- https://learn.microsoft.com/en-us/dotnet/api/system.numerics.vector3?wt.mc_id=MVP_321542
- .EXAMPLE
- # Create a vector out of two numbers
- Vector3 1 2 3
- .EXAMPLE
- (Vector3 1 2 3 ) + (Vector3 3 2 1)
- .EXAMPLE
- (Vector3 1 2 3 ) - (Vector3 3 2 1)
- .EXAMPLE
- # Create a thousand vectors
- $vectors = Vector3 1..3kb
- .EXAMPLE
- # Create a thousand vectors in random order, using the pipeline
- $vectors = 1..3kb | Get-Random -Count 3kb | Vector3
- .EXAMPLE
- # Create a vector from a string
- $vector = Vector3 "hi"
- .NOTES
- This script is self contained so that it can be easily dropped into any project
- #>
- [Alias('Vector3','V3')]
- param()
-
-
- # Collect all of our input and arguments
- $allIn = @($input) + @(
- foreach ($arg in $args) {
- $arg
- }
- )
-
- # If there were no arguments
- if (-not $allIn.Length) {
- # return the vector type
- return [Numerics.Vector3]
- }
-
- # and expand them
- $expandAllIn = @($allIn | Vector)
-
- # Go over our arguments three at a time
- For ($n = 0; $n -lt $expandAllIn.Length; $n+=3) {
- $argSet = $expandAllIn[$n..($n+2)] -as [float[]]
- switch ($argSet.Length) {
- 1 {
- [Numerics.Vector3]::new($argSet[0])
- }
- 2 {
- [Numerics.Vector3]::new([Numerics.Vector2]::new($argSet[0],$argSet[1]), 1)
- }
- 3 {
- [Numerics.Vector3]::new($argSet)
- }
- }
- }
-}
diff --git a/Commands/Get-Vector4.ps1 b/Commands/Get-Vector4.ps1
deleted file mode 100644
index c515be7..0000000
--- a/Commands/Get-Vector4.ps1
+++ /dev/null
@@ -1,58 +0,0 @@
-function Get-Vector4 {
- <#
- .SYNOPSIS
- Gets a Vector4
- .DESCRIPTION
- Gets any input and arguments as a Vector4
- .LINK
- https://learn.microsoft.com/en-us/dotnet/api/system.numerics.vector4?wt.mc_id=MVP_321542
- .EXAMPLE
- # Create a vector out of four numbers
- Vector4 1 2 3 4
- .EXAMPLE
- (Vector4 1 2 3 4 ) + (Vector4 4 3 2 1 )
- .EXAMPLE
- (Vector4 1 2 3 4 ) - (Vector4 4 3 2 1)
- .EXAMPLE
- # Create a thousand vectors
- $vectors = Vector4 1..4kb
- .EXAMPLE
- # Create a thousand vectors in random order, using the pipeline
- $vectors = 1..4kb | Get-Random -Count 4kb | Vector4
- .EXAMPLE
- # Create vectors from a string
- Vector4 "hi"
- #>
- [Alias('v4','Vector4')]
- param()
- # Collect all of our input and arguments
- $allIn = @($input) + @(
- foreach ($arg in $args) {
- $arg
- }
- )
-
- # If there were no arguments
- if (-not $allIn.Length) {
- # return the vector type
- return [Numerics.Vector4]
- }
-
- # and expand them
- $expandAllIn = @($allIn | vector)
- For ($n = 0; $n -lt $expandAllIn.Length; $n+=4) {
- $argSet = $expandAllIn[$n..($n+3)] -as [float[]]
- switch ($argSet.Length) {
- 1 {[Numerics.Vector4]::new($argSet[0]) }
- 2 {
- [Numerics.Vector4]::new([Numerics.Vector2]::new($argSet[0],$argSet[1]), 1, 1)
- }
- 3 {
- [Numerics.Vector4]::new([Numerics.Vector3]::new($argSet[0],$argSet[1],$argSet[2]), 1)
- }
- 4 {
- [Numerics.Vector4]::new($argSet)
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Vector.ps1 b/Vector.ps1
new file mode 100644
index 0000000..48d16ac
--- /dev/null
+++ b/Vector.ps1
@@ -0,0 +1,223 @@
+<#
+.SYNOPSIS
+ Gets a one dimensional vector
+.DESCRIPTION
+ Gets a one dimensional vector (or, more simply, a list of numbers)
+
+ This will convert a variety of types into numbers.
+.NOTES
+ This attempts to convert any type into a number.
+
+ Some types are special:
+
+ * Primitive types will be casted to float
+ * `[Numerics.Vector2]`,`[Numerics.Vector3]`,`[Numerics.Vector4]` output each component
+ * `[string]`s that match a range (`$start..$end`) will output that range
+ * `[Version]`s will output each numeric component
+ * `[semver]`s will output each numeric component, followed by the bytes of a release type
+ * `[DateTime]` and `[DateTimeOffset]` will become a series of 12 numbers
+ * `year`,`month`,`day`
+ * `hour`, `minute`, `second`
+ * `millisecond`, `microsecond`, `nanosecond`
+ * `offset.hours`, `offset.minutes`, `offset.seconds`
+ * `[string]s` will return their bytes in the current `$outputEncoding`
+ * Anything unknown will be stringified and the bytes will be returned
+.EXAMPLE
+ # Create a vector out of two numbers
+ Vector2 1 2
+.EXAMPLE
+ (Vector2 1 2) + (Vector2 2 1)
+.EXAMPLE
+ (Vector2 1 2) - (Vector2 2 1)
+.EXAMPLE
+ # Create a thousand vectors
+ $vectors = Vector2 1..2kb
+.EXAMPLE
+ # Create a thousand vectors in random order, using the pipeline
+ $vectors = 1..2kb | Get-Random -Count 2kb | Vector2
+.EXAMPLE
+ # Create a vector from a string
+ $vector = Vector2 "hi"
+.EXAMPLE
+ # Create a vector out of two numbers
+ Vector3 1 2 3
+.EXAMPLE
+ (Vector3 1 2 3 ) + (Vector3 3 2 1)
+.EXAMPLE
+ (Vector3 1 2 3 ) - (Vector3 3 2 1)
+.EXAMPLE
+ # Create a thousand vectors
+ $vectors = Vector3 1..3kb
+.EXAMPLE
+ # Create a thousand vectors in random order, using the pipeline
+ $vectors = 1..3kb | Get-Random -Count 3kb | Vector3
+.EXAMPLE
+ # Create a vector from a string
+ $vector = Vector3 "hi"
+.EXAMPLE
+ # Create a vector out of four numbers
+ Vector4 1 2 3 4
+.EXAMPLE
+ (Vector4 1 2 3 4 ) + (Vector4 4 3 2 1 )
+.EXAMPLE
+ (Vector4 1 2 3 4 ) - (Vector4 4 3 2 1)
+.EXAMPLE
+ # Create a thousand vectors
+ $vectors = Vector4 1..4kb
+.EXAMPLE
+ # Create a thousand vectors in random order, using the pipeline
+ $vectors = 1..4kb | Get-Random -Count 4kb | Vector4
+.EXAMPLE
+ # Create vectors from a string
+ Vector4 "hi"
+#>
+[Alias('Vector',
+ 'Get-Vector1','Vector1','V1',
+ 'Get-Vector2','Vector2','V2',
+ 'Get-Vector3','Vector3','V3',
+ 'Get-Vector4','Vector4','V4'
+)]
+param()
+filter toVector {
+ $arg = $_
+ # Return primitive types
+ if ($arg.GetType -and $arg.GetType().IsPrimitive) {
+ # casted to float
+ return ($arg -as [float])
+ }
+ # Return vector components
+ if ($arg -is [ValueType]) {
+ if ($arg -is [Numerics.Vector2]) {
+ return $arg.X,$arg.Y
+ }
+ elseif ($arg -is [Numerics.Vector3]) {
+ return $arg.X,$arg.Y,$arg.Z
+ }
+ elseif ($arg -is [Numerics.Vector4]) {
+ return $arg.X,$arg.Y,$arg.Z, $arg.W
+ }
+ }
+ # Look for inline ranges.
+ if ($arg -is [string]) {
+ if ($arg -match '^\d..\d') {
+ $start, $end = $arg -split '\..', 2
+ $startInt = ($start -as [int])
+ $endInt = ($end -as [int])
+ if ($null -ne $startInt -and $null -ne $endInt) {
+ # If found, return them expanded.
+ return ($startInt..$endInt)
+ }
+ }
+ if ($arg -as [float]) {
+ return $arg -as [float]
+ }
+ }
+
+
+ # If the arg is a version, get each number of the version
+ if ($arg -is [version]) {return $arg.Major,$arg.Minor,$arg.Build,$arg.Revision}
+
+ # If we support semver and the arg is semver
+ if (('semver' -as [type]) -and $arg -is [semver]) {
+ # Return the numeric parts of the semver
+ $arg.Major,$arg.Minor,$arg.Patch
+ # and turn any string portions to bytes
+ if ($arg.PreReleaseLabel) {
+ # make sure to include a leading dash for pre-releases
+ $OutputEncoding.GetBytes("-$($arg.PreReleaseLabel)")
+ }
+
+ if ($arg.BuildLabel) {
+ # make sure to include a leading plus for build labels
+ $OutputEncoding.GetBytes("+$($arg.BuildLabel)")
+ }
+ return
+ }
+
+ # If the arg is a datetime or datetimeoffset
+ if ($arg -is [DateTime] -or $arg -is [DateTimeOffset]) {
+ # make it an offset, and then output 12 values
+ $dateArg = $arg -as [DateTimeOffset]
+ # * `year` `month` `day`
+ $dateArg.Year, $dateArg.Month, $dateArg.Day,
+ # * `hour` `minute` `second`
+ $dateArg.Hour, $dateArg.Minute, $dateArg.Second,
+ # * `millisecond`, `microsecond`, `nanosecond`
+ $dateArg.Millisecond, $dateArg.Microsecond, $dateArg.Nanosecond,
+ # * `offset hours`, `offset minutes`, `offset seconds`
+ $dateArg.Offset.Hours,$dateArg.Offset.Minutes,$dateArg.Offset.Seconds
+ return
+ }
+ # If the arg is a string
+ if ($arg -is [string]) {
+ # return its bytes
+ return $OutputEncoding.GetBytes($arg)
+ }
+ # any input we have not caught, stringify and turn to bytes
+ return $OutputEncoding.GetBytes("$arg")
+}
+
+
+# Collect all of our input and arguments
+$allIn = @($input) + @(
+ foreach ($arg in $args) {
+ $arg
+ }
+)
+
+$myName = $MyInvocation.InvocationName
+
+$expandAllIn = @($allIn | toVector)
+
+if (-not $expandAllIn.Length) {
+ if ($myName -match '2$') {
+ return [Numerics.Vector2]
+ }
+ elseif ($myName -match '3$') {
+ return [Numerics.Vector3]
+ }
+ elseif ($myName -match '4$') {
+ return [Numerics.Vector4]
+ }
+ else {
+ return [Numerics.Vector2],[Numerics.Vector3],[Numerics.Vector4]
+ }
+}
+if ($myName -match '[234]$') {
+ $dimension = $matches.0 -as [int]
+ for ($n = 0; $n -lt $expandAllIn.Length; $n+=$dimension) {
+ $nums = $expandAllIn[$n..($n+($dimension-1))] -as [float[]]
+ if ($dimension -eq 2) {
+ if ($nums.Length -eq 1) {
+ [Numerics.Vector2]::new($nums[0])
+ } else {
+ [Numerics.Vector2]::new($nums)
+ }
+ } elseif ($dimension -eq 3) {
+ if ($nums.Length -eq 1) {
+ [Numerics.Vector3]::new($nums[0])
+ }
+ elseif ($nums.Length -eq 2) {
+ [Numerics.Vector3]::new([Numerics.Vector2]::new($nums[0],$nums[1]), 0)
+ }
+ elseif ($nums.Length -eq 3) {
+ [Numerics.Vector3]::new($nums)
+ }
+ } elseif ($dimension -eq 4) {
+ if ($nums.Length -eq 1) {
+ [Numerics.Vector4]::new($nums[0])
+ }
+ elseif ($nums.Length -eq 2) {
+ [Numerics.Vector4]::new([Numerics.Vector2]::new($nums[0],$nums[1]), 0, 0)
+ }
+ elseif ($nums.Length -eq 3) {
+ [Numerics.Vector4]::new([Numerics.Vector3]::new($nums[0],$nums[1],$nums[2]), 0)
+ }
+ elseif ($nums.Length -eq 4) {
+ [Numerics.Vector4]::new($nums)
+ }
+ }
+ }
+} else {
+ return $allIn | toVector
+}
diff --git a/Vector.psm1 b/Vector.psm1
index ebecaec..86a7438 100644
--- a/Vector.psm1
+++ b/Vector.psm1
@@ -1,39 +1,99 @@
-$commandsPath = Join-Path $PSScriptRoot Commands
-:ToIncludeFiles foreach ($file in (Get-ChildItem -Path "$commandsPath" -Filter "*-*" -Recurse)) {
- if ($file.Extension -ne '.ps1') { continue } # Skip if the extension is not .ps1
- foreach ($exclusion in '\.[^\.]+\.ps1$') {
- if (-not $exclusion) { continue }
- if ($file.Name -match $exclusion) {
- continue ToIncludeFiles # Skip excluded files
- }
- }
- . $file.FullName
+#region Eponym
+
+# Functions and scripts are interchangeable in PowerShell
+# So we can make a small module using an eponym file.
+# First we need to identify the module name
+$moduleName = $MyInvocation.MyCommand.Name -replace '\.psm1$'
+
+# Once we have done this, we can look for an eponymous script:
+$eponym =
+ $ExecutionContext.SessionState.InvokeCommand.GetCommand((
+ Join-Path $PSScriptRoot "$moduleName.ps1"
+ ), 'ExternalScript')
+
+# If we did not find one,
+if (-not $eponym) {
+ # warn and return.
+ Write-Warning "Missing ./$moduleName.ps1"
+ return
}
-$myModule = $MyInvocation.MyCommand.ScriptBlock.Module
-$ExecutionContext.SessionState.PSVariable.Set($myModule.Name, $myModule)
-$myModule.pstypenames.insert(0, $myModule.Name)
+# We want to define two functions from this script
-New-PSDrive -Name $MyModule.Name -PSProvider FileSystem -Scope Global -Root $PSScriptRoot -ErrorAction Ignore
+# One is the name of the script
+# The other is the "verb" form of the script.
-if ($home) {
- $MyModuleProfileDirectory = Join-Path ([Environment]::GetFolderPath("LocalApplicationData")) $MyModule.Name
- if (-not (Test-Path $MyModuleProfileDirectory)) {
- $null = New-Item -ItemType Directory -Path $MyModuleProfileDirectory -Force
- }
- New-PSDrive -Name "My$($MyModule.Name)" -PSProvider FileSystem -Scope Global -Root $MyModuleProfileDirectory -ErrorAction Ignore
+# Collect our list of verbs
+$verbs = Get-Verb |
+ Sort-Object { $_.Verb.Length }, {$_.Verb } -Descending |
+ Select-Object -ExpandProperty Verb
+
+# and craft a regex to see if we start with the verb.
+$startsWithVerb = "^(?>$(
+ $verbs -join '|'
+))"
+
+# Our Exports are:
+$exports =
+ $moduleName, # * The Eponym
+ $(
+ # The `Verb-Noun` form
+ if ($moduleName -match $startsWithVerb) {
+ "$($matches.0)-$($moduleName -replace "$startsWithVerb\p{P}?")"
+ } else {
+ "Get-$($ModuleName -replace '\p{P}')"
+ }
+ )
+
+# We can use the function provider to create functions in this scope.
+foreach ($functionName in $exports) {
+ # This allows us to dynamically set each export to by the eponym
+ $ExecutionContext.SessionState.PSVariable.Set(
+ "function:$functionName",
+ $eponym.ScriptBlock
+ )
}
-# Set a script variable of this, set to the module
-# (so all scripts in this scope default to the correct `$this`)
-$script:this = $myModule
+# We also want to export any aliases
+# and add support for argument completers.
+$argumentCompleter = $null
+$aliasExports = @(
+ # walk over all of our attributes
+ foreach ($attribute in $eponym.ScriptBlock.Attributes) {
+ # and keep track of any argument completers we find.
+ if ($attribute -is [ArgumentCompleter]) {
+ $argumentCompleter = $attribute
+ }
+ # Then make our aliases
+ foreach ($alias in $attribute.aliasNames) {
+ # (unless the alias is already exported as a function)
+ if ($alias -in $exports) { continue }
+ $ExecutionContext.SessionState.PSVariable.Set(
+ "alias:$alias", $moduleName
+ )
+ $alias
+ }
+ }
+)
+
+# If we had an argument completer
+if ($argumentCompleter.ScriptBlock) {
+ # now is the time to register it.
-#region Custom
-$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
- Remove-TypeData -ErrorAction Ignore -TypeName 'System.Numerics.Vector2'
- Remove-TypeData -ErrorAction Ignore -TypeName 'System.Numerics.Vector3'
- Remove-TypeData -ErrorAction Ignore -TypeName 'System.Numerics.Vector4'
+ # Argument completers need to be registered for each function
+ foreach ($functionExport in $exports) {
+ Register-ArgumentCompleter -CommandName $functionExport -ScriptBlock $argumentCompleter.ScriptBlock
+ }
+
+ # and alias
+ foreach ($aliasExport in $aliasExports) {
+ Register-ArgumentCompleter -CommandName $aliasExport -ScriptBlock $argumentCompleter.ScriptBlock
+ }
}
-#endregion Custom
-Export-ModuleMember -Alias * -Function * -Variable $myModule.Name
+# We will also be exporting our eponym as a variable
+$ExecutionContext.SessionState.PSVariable.Set($moduleName, $eponym)
+
+# All that's left to do is explicitly export just these functions.
+Export-ModuleMember -Function $exports -Alias $aliasExports -Variable $moduleName
+#endregion Eponym
\ No newline at end of file
From 0cc34499adbc8911601d5d41f2fb791b10b90528 Mon Sep 17 00:00:00 2001
From: James Brundage <+@users.noreply.github.com>
Date: Wed, 12 Aug 2026 12:38:27 -0700
Subject: [PATCH 05/11] feat: `Vector` converting matrix input ( Fixes #16 )
---
Vector.ps1 | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/Vector.ps1 b/Vector.ps1
index 48d16ac..8178271 100644
--- a/Vector.ps1
+++ b/Vector.ps1
@@ -70,6 +70,12 @@
.EXAMPLE
# Create vectors from a string
Vector4 "hi"
+.LINK
+ https://learn.microsoft.com/en-us/dotnet/api/system.numerics.vector2?wt.mc_id=MVP_321542
+.LINK
+ https://learn.microsoft.com/en-us/dotnet/api/system.numerics.vector3?wt.mc_id=MVP_321542
+.LINK
+ https://learn.microsoft.com/en-us/dotnet/api/system.numerics.vector4?wt.mc_id=MVP_321542
#>
[Alias('Vector',
'Get-Vector1','Vector1','V1',
@@ -148,6 +154,22 @@ filter toVector {
$dateArg.Offset.Hours,$dateArg.Offset.Minutes,$dateArg.Offset.Seconds
return
}
+
+ if ($arg -is [Numerics.Matrix3x2]) {
+ $arg.M11,$arg.M12,
+ $arg.M21,$arg.M22,
+ $arg.M31,$arg.M32
+ return
+ }
+
+ if ($arg -is [Numerics.Matrix4x4]) {
+ $arg.M11,$arg.M12,$arg.M13,$arg.M14
+ $arg.M21,$arg.M22,$arg.M23,$arg.M24
+ $arg.M31,$arg.M32,$arg.M33,$arg.M34
+ $arg.M41,$arg.M42,$arg.M43,$arg.M44
+ return
+ }
+
# If the arg is a string
if ($arg -is [string]) {
# return its bytes
From 383af093a2f5c29755ba9eb9ec071f65bd50d4be Mon Sep 17 00:00:00 2001
From: James Brundage <+@users.noreply.github.com>
Date: Wed, 12 Aug 2026 12:38:47 -0700
Subject: [PATCH 06/11] feat: `Vector` aliasing ( Fixes #15 )
---
Vector.psd1 | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Vector.psd1 b/Vector.psd1
index 3e83cbf..f4ff3a9 100644
--- a/Vector.psd1
+++ b/Vector.psd1
@@ -25,7 +25,7 @@ Author = 'James Brundage'
CompanyName = 'Start-Automating'
# Copyright statement for this module
-Copyright = '2025 Start-Automating'
+Copyright = '2025-2026 Start-Automating'
# Description of the functionality provided by this module
Description = 'Vectors in PowerShell'
@@ -67,16 +67,16 @@ Description = 'Vectors in PowerShell'
# NestedModules = @()
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
-FunctionsToExport = 'Get-Vector', 'Get-Vector2', 'Get-Vector3', 'Get-Vector4'
+FunctionsToExport = 'Get-Vector'
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
-CmdletsToExport = '*'
+CmdletsToExport = @()
# Variables to export from this module
-VariablesToExport = '*'
+VariablesToExport = @('Vector')
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
-AliasesToExport = 'V1', 'V2', 'V3', 'V4', 'Vector1', 'Vector2', 'Vector3', 'Vector4', 'Vector'
+AliasesToExport = 'Get-Vector2', 'Get-Vector3', 'Get-Vector4', 'V1', 'V2', 'V3', 'V4', 'Vector', 'Vector1', 'Vector2', 'Vector3', 'Vector4'
# DSC resources to export from this module
# DscResourcesToExport = @()
From 40043e32ea1257902d453e6411482881997175b9 Mon Sep 17 00:00:00 2001
From: James Brundage <+@users.noreply.github.com>
Date: Wed, 12 Aug 2026 12:46:10 -0700
Subject: [PATCH 07/11] docs: `Vector` eponym doc corrections ( Fixes #15 )
---
Vector.ps1 | 10 ++-
Vector.psd1 | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 187 insertions(+), 2 deletions(-)
diff --git a/Vector.ps1 b/Vector.ps1
index 8178271..4c88310 100644
--- a/Vector.ps1
+++ b/Vector.ps1
@@ -1,10 +1,15 @@
<#
.SYNOPSIS
- Gets a one dimensional vector
+ Gets vectors
.DESCRIPTION
- Gets a one dimensional vector (or, more simply, a list of numbers)
+ Gets a vector in one, two, three, or four dimensions.
This will convert a variety of types into numbers.
+
+ `Vector1` will return a list of numbers
+ `Vector2` will return a list of `[Numerics.Vector2]`
+ `Vector3` will return a list of `[Numerics.Vector3]`
+ `Vector4` will return a list of `[Numerics.Vector4]`
.NOTES
This attempts to convert any type into a number.
@@ -15,6 +20,7 @@
* `[string]`s that match a range (`$start..$end`) will output that range
* `[Version]`s will output each numeric component
* `[semver]`s will output each numeric component, followed by the bytes of a release type
+ * `[Numerics.Matrix3x2]` and `[Numerics.Matrix4x4]` will return the numbers in the matrix
* `[DateTime]` and `[DateTimeOffset]` will become a series of 12 numbers
* `year`,`month`,`day`
* `hour`, `minute`, `second`
diff --git a/Vector.psd1 b/Vector.psd1
index f4ff3a9..6ec371f 100644
--- a/Vector.psd1
+++ b/Vector.psd1
@@ -123,6 +123,185 @@ PrivateData = @{
* SECURITY (#12)
'@
+ PSIntro = @'
+# Vector
+
+Numbers are great!
+
+When we measure things with one number, it's technically called a scalar.
+
+When we measure things with more than one number, it's called a [vector](https://en.wikipedia.org/wiki/Vector_%28mathematics_and_physics%29)
+
+We can do lots of things with vectors. We can add or substract them, multiply and divide them.
+
+Vectors are very useful.
+
+This module helps you use Vectors in PowerShell
+
+## Vectors in PowerShell
+
+Vectors are actually built into PowerShell.
+
+Because PowerShell is built atop of the .NET Framework,
+and the .NET Framework has had vector support for over a decade,
+PowerShell has had vectors for over a decade.
+
+~~~PowerShell
+# Create a 2D vector
+[Numerics.Vector2]::new(1,2)
+# Create a 3D vector
+[Numerics.Vector3]::new(1,2,3)
+# Create a 4D vector
+[Numerics.Vector4]::new(1,2,3,4)
+~~~
+
+This module exists to make vectors a bit more useful by providing commands to construct them.
+
+### Getting Vectors
+
+There are a few commands in this module:
+
+* `Get-Vector`
+* `Get-Vector2`
+* `Get-Vector3`
+* `Get-Vector4`
+
+Each command constructs a vector of the corresponding dimension.
+
+A Vector with one dimension is just a list.
+
+We can also drop the `Get` and just refer to them by vector number
+
+~~~PowerShell
+Vector2 1 2
+Vector3 1 2 3
+Vector4 1 2 3 4
+~~~
+
+We can be even shorter, and use `V2`, `V3`, and `V4`
+
+~~~PowerShell
+v2 1 2
+v3 1 2 3
+v4 1 2 3 4
+~~~
+
+We can turn anything into a series of vectors.
+
+~~~PowerShell
+v2 1
+v3 1
+v4 1
+~~~
+
+Strings can become vectors, too! (after all, each byte is already a number)
+
+~~~PowerShell
+v2 "hi"
+v3 "hi"
+v4 "hi"
+~~~
+
+### Vector Operators
+
+.NET vectors are _very_ powerful, and overload many operators.
+
+For example, we can add, subtract, multiply, or divide by a scalar.
+
+~~~PowerShell
+# Let's start with addition.
+# We can add a scalar to a vector.
+(v2 1 2) + 1
+(v3 1 2 3) + 1
+(v4 1 2 3 4) + 1
+
+# Let's try substraction:
+(v2 1 2) - 1
+(v3 1 2 3) - 1
+(v4 1 2 3 4) - 1
+
+# How about multiplication?
+(v2 1 2) * 2
+(v3 1 2 3) * 2
+(v4 1 2 3 4) * 2
+
+# What about division?
+(v2 1 2) / 2
+(v3 1 2 3) / 2
+(v4 1 2 3 4) / 2
+~~~
+
+We can also work with other vectors:
+
+~~~PowerShell
+# Adding vectors:
+(v2 1 2) + (v2 1 2)
+(v3 1 2 3) + (v3 1 2 3)
+(v4 1 2 3 4) + (v4 1 2 3 4)
+
+# Subtracting vectors:
+(v2 1 2) - (v2 1 2)
+(v3 1 2 3) - (v3 1 2 3)
+(v4 1 2 3 4) - (v4 1 2 3 4)
+
+# Multiplying vectors:
+(v2 1 2) * (v2 1 2)
+(v3 1 2 3) * (v3 1 2 3)
+(v4 1 2 3 4) * (v4 1 2 3 4)
+
+# Dividing vectors:
+(v2 1 2) / (v2 1 2)
+(v3 1 2 3) / (v3 1 2 3)
+(v4 1 2 3 4) / (v4 1 2 3 4)
+~~~
+
+### Vector Methods
+
+Vectors have a large number of methods to work with.
+
+Let's start simple, by calculating the length of a given vector.
+
+~~~PowerShell
+(v2 1 1).Length()
+(v3 1 1 1).Length()
+(v4 1 1 1 1).Length()
+~~~
+
+Many of the most useful things we can do with a vector are exposed as a static methods:
+
+~~~PowerShell
+(v2 1 1) | Get-Member -Static
+(v3 1 1 1) | Get-Member -Static
+(v4 1 1 1 1) | Get-Member -Static
+~~~
+
+
+We can access static method with `::`
+
+For a small example, let's find the distance between vectors:
+
+~~~PowerShell
+$vector1 = v2 1 2
+$vector2 = v2 2 1
+$vector1::Distance($vector1, $vector2)
+~~~
+
+For another simple example, let's find a few point between two points, using
+[Linear Interpolation `lerp`](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.vector2.lerp?wt.mc_id=MVP_321542)
+
+~~~PowerShell
+$vector1 = v2 1 5
+$vector2 = v2 1 -5
+$vector1::Lerp($vector1, $vector2, 0.25)
+$vector1::Lerp($vector1, $vector2, 0.5)
+$vector1::Lerp($vector1, $vector2, 0.75)
+~~~
+
+All of this would not be possible without the great work of the .NET team to build such incredibly useful data structures.
+
+Hopefully this module helps us all work with vectors!
+'@
+
# Prerelease string of this module
# Prerelease = ''
From 9f1ca66eb77ffc9ee449d005c2ad34da9425c0b0 Mon Sep 17 00:00:00 2001
From: James Brundage <+@users.noreply.github.com>
Date: Wed, 12 Aug 2026 12:47:41 -0700
Subject: [PATCH 08/11] docs: `Vector` `README.md.ps1` ( Fixes #17 )
---
README.md | 237 +++++++++++++++++++++++++++++++++++---
README.md.ps1 | 309 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 528 insertions(+), 18 deletions(-)
create mode 100644 README.md.ps1
diff --git a/README.md b/README.md
index eac6d0d..ed57756 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,7 @@
# Vector
+[](https://www.powershellgallery.com/packages/Vector/)
+## Vectors in PowerShell
+# Vector
Numbers are great!
@@ -31,30 +34,18 @@ PowerShell has had vectors for over a decade.
This module exists to make vectors a bit more useful by providing commands to construct them.
-### Installing and Importing
-
-We can install the Vector module from the gallery:
-
-~~~PowerShell
-# Install the module from the PowerShell gallery
-Install-Module Vector
-~~~
-
-Once installed, we can import the Vector module with Import-Module:
-
-~~~PowerShell
-Import-Module Vector
-~~~
-
### Getting Vectors
There are a few commands in this module:
+* `Get-Vector`
* `Get-Vector2`
* `Get-Vector3`
* `Get-Vector4`
-Each command constructs a vector of the corresponding size.
+Each command constructs a vector of the corresponding dimension.
+
+A Vector with one dimension is just a list.
We can also drop the `Get` and just refer to them by vector number
@@ -172,7 +163,8 @@ $vector2 = v2 2 1
$vector1::Distance($vector1, $vector2)
~~~
-For another simple example, let's find a few point between two points, using [Linear Interpolation `lerp`](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.vector2.lerp?wt.mc_id=MVP_321542)
+For another simple example, let's find a few point between two points, using
+[Linear Interpolation `lerp`](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.vector2.lerp?wt.mc_id=MVP_321542)
~~~PowerShell
$vector1 = v2 1 5
@@ -184,4 +176,213 @@ $vector1::Lerp($vector1, $vector2, 0.75)
All of this would not be possible without the great work of the .NET team to build such incredibly useful data structures.
-Hopefully this module helps us all work with vectors!
\ No newline at end of file
+Hopefully this module helps us all work with vectors!
+
+## Installing and Importing
+
+You can install Vector from the [PowerShell gallery](https://powershellgallery.com/)
+
+~~~PowerShell
+Install-Module Vector -Scope CurrentUser -Force
+~~~
+
+Once installed, you can import the module with:
+
+~~~PowerShell
+Import-Module Vector -PassThru
+~~~
+
+
+You can also clone the repo and import the module locally:
+
+~~~PowerShell
+git clone https://github.com/PowerShellWeb/Vector
+cd ./Vector
+Import-Module ./ -PassThru
+~~~
+
+## Functions
+Vector has 1 function
+### Get-Vector
+#### Gets vectors
+
+Gets a vector in one, two, three, or four dimensions.
+
+This will convert a variety of types into numbers.
+
+`Vector1` will return a list of numbers
+`Vector2` will return a list of `[Numerics.Vector2]`
+`Vector3` will return a list of `[Numerics.Vector3]`
+`Vector4` will return a list of `[Numerics.Vector4]`
+
+
+Notes
+
+This attempts to convert any type into a number.
+
+Some types are special:
+
+* Primitive types will be casted to float
+* `[Numerics.Vector2]`,`[Numerics.Vector3]`,`[Numerics.Vector4]` output each component
+* `[string]`s that match a range (`$start..$end`) will output that range
+* `[Version]`s will output each numeric component
+* `[semver]`s will output each numeric component, followed by the bytes of a release type
+* `[Numerics.Matrix3x2]` and `[Numerics.Matrix4x4]` will return the numbers in the matrix
+* `[DateTime]` and `[DateTimeOffset]` will become a series of 12 numbers
+ * `year`,`month`,`day`
+ * `hour`, `minute`, `second`
+ * `millisecond`, `microsecond`, `nanosecond`
+ * `offset.hours`, `offset.minutes`, `offset.seconds`
+* `[string]s` will return their bytes in the current `$outputEncoding`
+* Anything unknown will be stringified and the bytes will be returned
+
+
+
+Examples
+
+#### Example 1
+
+Create a vector out of two numbers
+~~~PowerShell
+Vector2 1 2
+~~~
+
+
+#### Example 2
+
+~~~PowerShell
+(Vector2 1 2) + (Vector2 2 1)
+~~~
+
+
+#### Example 3
+
+~~~PowerShell
+(Vector2 1 2) - (Vector2 2 1)
+~~~
+
+
+#### Example 4
+
+Create a thousand vectors
+~~~PowerShell
+$vectors = Vector2 1..2kb
+~~~
+
+
+#### Example 5
+
+Create a thousand vectors in random order, using the pipeline
+~~~PowerShell
+$vectors = 1..2kb | Get-Random -Count 2kb | Vector2
+~~~
+
+
+#### Example 6
+
+Create a vector from a string
+~~~PowerShell
+$vector = Vector2 "hi"
+~~~
+
+
+#### Example 7
+
+Create a vector out of two numbers
+~~~PowerShell
+Vector3 1 2 3
+~~~
+
+
+#### Example 8
+
+~~~PowerShell
+(Vector3 1 2 3 ) + (Vector3 3 2 1)
+~~~
+
+
+#### Example 9
+
+~~~PowerShell
+(Vector3 1 2 3 ) - (Vector3 3 2 1)
+~~~
+
+
+#### Example 10
+
+Create a thousand vectors
+~~~PowerShell
+$vectors = Vector3 1..3kb
+~~~
+
+
+#### Example 11
+
+Create a thousand vectors in random order, using the pipeline
+~~~PowerShell
+$vectors = 1..3kb | Get-Random -Count 3kb | Vector3
+~~~
+
+
+#### Example 12
+
+Create a vector from a string
+~~~PowerShell
+$vector = Vector3 "hi"
+~~~
+
+
+#### Example 13
+
+Create a vector out of four numbers
+~~~PowerShell
+Vector4 1 2 3 4
+~~~
+
+
+#### Example 14
+
+~~~PowerShell
+(Vector4 1 2 3 4 ) + (Vector4 4 3 2 1 )
+~~~
+
+
+#### Example 15
+
+~~~PowerShell
+(Vector4 1 2 3 4 ) - (Vector4 4 3 2 1)
+~~~
+
+
+#### Example 16
+
+Create a thousand vectors
+~~~PowerShell
+$vectors = Vector4 1..4kb
+~~~
+
+
+#### Example 17
+
+Create a thousand vectors in random order, using the pipeline
+~~~PowerShell
+$vectors = 1..4kb | Get-Random -Count 4kb | Vector4
+~~~
+
+
+#### Example 18
+
+Create vectors from a string
+~~~PowerShell
+Vector4 "hi"
+~~~
+
+
+
+Links
+
+* [system.numerics.vector2 (Learn DotNet)](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.vector2?wt.mc_id=MVP_321542)
+* [system.numerics.vector3 (Learn DotNet)](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.vector3?wt.mc_id=MVP_321542)
+* [system.numerics.vector4 (Learn DotNet)](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.vector4?wt.mc_id=MVP_321542)
+
+
diff --git a/README.md.ps1 b/README.md.ps1
new file mode 100644
index 0000000..573e240
--- /dev/null
+++ b/README.md.ps1
@@ -0,0 +1,309 @@
+<#
+.SYNOPSIS
+ README.md.ps1
+.DESCRIPTION
+ README.md.ps1 makes README.md
+
+ This is a simple and helpful scripting convention for writing READMEs.
+
+ `./README.md.ps1 > ./README.md`
+
+ Feel free to copy and paste this code.
+
+ Please document your parameters, and add NOTES.
+.NOTES
+ This README.md.ps1 is used to generate help for a module.
+
+ It:
+
+ * Outputs the name and description
+ * Provides installation instructions
+ * Lists commands
+ * Includes aliases
+ * Includes notes
+ * Lists parameters
+ * Lists examples
+ * Lists links
+.EXAMPLE
+ ./README.md.ps1 > ./README.md
+.EXAMPLE
+ Get-Help ./README.md.ps1
+#>
+param(
+# The name of the module
+[string]$ModuleName = $($PSScriptRoot | Split-Path -Leaf),
+
+# The domains that serve git repositories.
+# If the project uri links to this domain,
+# installation instructions will show how to import the module locally.
+[string[]]
+$GitDomains = @(
+ 'github.com', 'tangled.org', 'tangled.sh', 'codeberg.org'
+),
+
+# A list of types the module exposes
+[Alias('ModuleTypeNames','ModuleTypes')]
+[string[]]
+$ModuleTypeName = @(),
+
+# The name of the root directory containing types.
+[string]
+$TypeRoot = 'Types',
+
+# If set, we don't need no badges.
+[switch]
+$NoBadge,
+
+# If set, will not display gallery instructions or badges
+[switch]
+$NotOnGallery
+)
+
+Push-Location $PSScriptRoot
+
+# Import the module
+$module = Import-Module "./$ModuleName.psd1" -PassThru
+
+# And output a header
+"# $module"
+
+if (-not $NoBadge) {
+ # If it is on the gallery, show the downloads badge.
+ if (-not $NotOnGallery) {
+ @(
+ "[!"
+ "[$ModuleName](https://img.shields.io/powershellgallery/dt/$ModuleName)"
+ "](https://www.powershellgallery.com/packages/$ModuleName/)"
+ ) -join ''
+ }
+}
+
+# Show the module description
+"## $($module.Description)"
+
+# Show any intro section defined in the manifest
+$module.PrivateData.PSData.PSIntro
+
+#region Boilerplate installation instructions
+if (-not $NotOnGallery) {
+@"
+
+## Installing and Importing
+
+You can install $ModuleName from the [PowerShell gallery](https://powershellgallery.com/)
+
+~~~PowerShell
+Install-Module $($ModuleName) -Scope CurrentUser -Force
+~~~
+
+Once installed, you can import the module with:
+
+~~~PowerShell
+Import-Module $ModuleName -PassThru
+~~~
+
+"@
+}
+#endregion Gallery installation instructions
+
+#region Git installation instructions
+$projectUri = $module.PrivateData.PSData.ProjectURI -as [uri]
+
+if ($projectUri.DnsSafeHost -in $GitDomains) {
+@"
+
+You can also clone the repo and import the module locally:
+
+~~~PowerShell
+git clone $projectUri
+cd ./$ModuleName
+Import-Module ./ -PassThru
+~~~
+
+"@
+}
+#endregion Git installation instructions
+
+#region Exported Functions
+$exportedFunctions = $module.ExportedFunctions
+
+$uniqueFunctions = @()
+$uniqueNames = @(foreach ($function in $exportedFunctions.GetEnumerator()) {
+ if ($uniqueFunctions -contains $function.Value.ScriptBlock) {
+ continue
+ } else {
+ $uniqueFunctions += $function.Value.ScriptBlock
+ }
+ $function.Key
+})
+
+
+if ($uniqueNames) {
+
+ "## Functions"
+
+ "$($ModuleName) has $($uniqueNames.Count) function$(
+ if ($uniqueNames.Count -gt 1) { "s"}
+ )"
+
+ $duplicate = @()
+ foreach ($export in $uniqueNames) {
+ $exportedFunction = $exportedFunctions[$export]
+ if ($duplicate -contains $exportedFunction.ScriptBlock) {
+ continue
+ } else {
+ $duplicate += $exportedFunction.ScriptBlock
+ }
+ # Get help if it there is help to get
+ $help = Get-Help $export
+ # If the help is a string,
+ if ($help -is [string]) {
+ # make it preformatted text
+ "~~~"
+ "$export"
+ "~~~"
+ } else {
+ # Otherwise, add list the export
+ "### $($export)"
+
+ # And make it's synopsis a header
+ "#### $($help.SYNOPSIS)"
+
+ ""
+ # put the description below that
+ "$($help.Description.text -join [Environment]::NewLine)"
+ ""
+
+ $commandAliases = foreach ($aliasName in $module.ExportedAliases.Keys) {
+ if ($module.ExportedAliases[$aliasName].ResolvedCommand.ScriptBlock -eq
+ $exportedFunction.ScriptBlock) {
+ $aliasName
+ }
+ }
+
+ $notes = $help.alertSet.alert.text
+
+ if ($notes) {
+ ""
+ "Notes
"
+ ""
+ $notes -join [Environment]::NewLine
+ ""
+ " "
+ }
+
+ if ($commandAliases) {
+ ""
+ ""
+ "Aliases
"
+ ""
+ foreach ($commandAlias in $commandAliases) {
+ "- $commandAlias"
+ }
+ " "
+ ""
+ ""
+
+ }
+
+ # Show our examples
+ if ($help.examples.example) {
+ ""
+ "Examples
"
+
+ $exampleNumber = 0
+ foreach ($example in $help.examples.example) {
+ $markdownLines = @()
+ $exampleNumber++
+ $nonCommentLine = $false
+ ""
+ "#### Example $exampleNumber"
+ ""
+
+ # Combine the code and remarks
+ $exampleLines =
+ @(
+ $example.Code
+ foreach ($remark in $example.Remarks.text) {
+ if (-not $remark) { continue }
+ $remark
+ }
+ ) -join ([Environment]::NewLine) -split '(?>\r\n|\n)' # and split into lines
+
+ # Go thru each line in the example as part of a loop
+ $codeBlock = @(foreach ($exampleLine in $exampleLines) {
+ # Any comments until the first uncommentedLine are markdown
+ if ($exampleLine -match '^\#' -and -not $nonCommentLine) {
+ $markdownLines += $exampleLine -replace '^\#\s{0,1}'
+ } else {
+ $nonCommentLine = $true
+ $exampleLine
+ }
+ }) -join [Environment]::NewLine
+
+ $markdownLines
+ "~~~PowerShell"
+ $CodeBlock
+ "~~~"
+ ""
+ }
+ " "
+ }
+
+ # Make a table of parameters
+ if ($help.parameters.parameter) {
+ ""
+
+ "Parameters
"
+
+ ""
+
+ "|Name|Type|Description|"
+ "|-|-|-|"
+ foreach ($parameter in $help.Parameters.Parameter) {
+ "|$($parameter.Name)|$($parameter.type.name)|$(
+ $parameter.description.text -replace '(?>\r\n|\n)', '
'
+ )|"
+ }
+
+ " "
+ ""
+ }
+
+ $relatedUris = foreach ($link in $help.relatedLinks.navigationLink) {
+ if ($link.uri) {
+ $link.uri
+ }
+ }
+ if ($relatedUris) {
+ ""
+ "Links
"
+ ""
+ foreach ($related in $relatedUris) {
+ $relatedUri = $related -as [uri]
+ if ($relatedUri.DnsSafeHost -eq 'learn.microsoft.com' -and
+ $relatedUri.LocalPath -match '/dotnet/api') {
+ "* [$($relatedUri.segments[-1] -replace '/') (Learn DotNet)]($related)"
+ }
+ elseif ($relatedUri.DnsSafeHost -eq 'developer.mozilla.org' -and
+ $relatedUri.LocalPath -match '/(?[[^/]+)/reference') {
+ "* [$($matches.ref) $($relatedUri.segments[-1] -replace '/') (MDN)]($related)"
+ }
+ elseif ($relatedUri.DnsSafeHost -eq 'github.com') {
+ "* [$($relatedUri.Segments -replace '/', ' ') (GitHub)]($related)"
+ }
+ elseif ($relatedUri.DnsSafeHost) {
+ "* [$($relatedUri.DnsSafeHost)$($relatedUri.LocalPath)]($related)"
+ } else {
+ "* [$related]($related)"
+ }
+ }
+ ""
+ "] "
+ }
+ }
+ }
+}
+#endregion Exported Functions
+
+Pop-Location
\ No newline at end of file
From f18a215dce8e3c45da971d337d064928e4a1a847 Mon Sep 17 00:00:00 2001
From: James Brundage <+@users.noreply.github.com>
Date: Wed, 12 Aug 2026 12:49:11 -0700
Subject: [PATCH 09/11] docs: `Vector` `README.md.ps1` ( Fixes #17 )
Using bullet points
---
README.md | 8 ++++----
Vector.ps1 | 8 ++++----
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index ed57756..5a7e519 100644
--- a/README.md
+++ b/README.md
@@ -210,10 +210,10 @@ Gets a vector in one, two, three, or four dimensions.
This will convert a variety of types into numbers.
-`Vector1` will return a list of numbers
-`Vector2` will return a list of `[Numerics.Vector2]`
-`Vector3` will return a list of `[Numerics.Vector3]`
-`Vector4` will return a list of `[Numerics.Vector4]`
+* `Vector1` will return a list of numbers
+* `Vector2` will return a list of `[Numerics.Vector2]`
+* `Vector3` will return a list of `[Numerics.Vector3]`
+* `Vector4` will return a list of `[Numerics.Vector4]`
Notes
diff --git a/Vector.ps1 b/Vector.ps1
index 4c88310..c9af074 100644
--- a/Vector.ps1
+++ b/Vector.ps1
@@ -6,10 +6,10 @@
This will convert a variety of types into numbers.
- `Vector1` will return a list of numbers
- `Vector2` will return a list of `[Numerics.Vector2]`
- `Vector3` will return a list of `[Numerics.Vector3]`
- `Vector4` will return a list of `[Numerics.Vector4]`
+ * `Vector1` will return a list of numbers
+ * `Vector2` will return a list of `[Numerics.Vector2]`
+ * `Vector3` will return a list of `[Numerics.Vector3]`
+ * `Vector4` will return a list of `[Numerics.Vector4]`
.NOTES
This attempts to convert any type into a number.
From d234e467188efced4d9d699142ea8f507882ba36 Mon Sep 17 00:00:00 2001
From: James Brundage <+@users.noreply.github.com>
Date: Wed, 12 Aug 2026 13:08:21 -0700
Subject: [PATCH 10/11] test: `Vector` tests ( Fixes #14 )
Adding tests for types
---
Vector.tests.ps1 | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/Vector.tests.ps1 b/Vector.tests.ps1
index 1422003..24dfdab 100644
--- a/Vector.tests.ps1
+++ b/Vector.tests.ps1
@@ -40,4 +40,25 @@ describe Vector {
$divide.Y | Should -Be 1
}
}
+
+ context 'Vector Types' {
+ it 'Will return the vector type when no parameters are passed' {
+ vector | Should -BeOfType ([Type])
+ }
+ it 'Will return Vector2 if the name ends in 2' {
+ v2 | Should -Be ([Numerics.Vector2])
+ vector2 | Should -Be ([Numerics.Vector2])
+ Get-Vector2 | Should -Be ([Numerics.Vector2])
+ }
+ it 'Will return Vector3 if the name ends in 3' {
+ v3 | Should -Be ([Numerics.Vector3])
+ vector3 | Should -Be ([Numerics.Vector3])
+ Get-Vector3 | Should -Be ([Numerics.Vector3])
+ }
+ it 'Will return Vector4 if the name ends in 4' {
+ v4 | Should -Be ([Numerics.Vector4])
+ vector4 | Should -Be ([Numerics.Vector4])
+ Get-Vector4 | Should -Be ([Numerics.Vector4])
+ }
+ }
}
From 91003bece3079261af3e51e27503e72d9e18c8e0 Mon Sep 17 00:00:00 2001
From: James Brundage <+@users.noreply.github.com>
Date: Thu, 13 Aug 2026 09:52:16 -0700
Subject: [PATCH 11/11] release: `Vector` 0.1.1
Updating Module Version, Release Notes, and CHANGELOG
---
CHANGELOG.md | 14 +++++++++++++-
Vector.psd1 | 37 ++++++++++++++++---------------------
2 files changed, 29 insertions(+), 22 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 803f211..e74d191 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,16 @@
-## Vector 0.1:
+# Vector
+
+## Vector 0.1.1
+
+* `Vector` is an eponoym (#15)
+ * This module exposes one command with many aliases
+* `Vector` converts `Matrix3x2` and `Matrix4x4` into vectors (#16)
+* Vectors return their type when provided no input (#14)
+* Added `README.md.ps1` (#17)
+
+---
+
+## Vector 0.1
* Initial Release of Vector module
* Commands:
diff --git a/Vector.psd1 b/Vector.psd1
index 6ec371f..14d19c9 100644
--- a/Vector.psd1
+++ b/Vector.psd1
@@ -10,7 +10,7 @@
RootModule = 'Vector.psm1'
# Version number of this module.
-ModuleVersion = '0.1'
+ModuleVersion = '0.1.1'
# Supported PSEditions
# CompatiblePSEditions = @()
@@ -93,34 +93,29 @@ PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
- Tags = 'PowerShell', 'Vector', 'Math', 'VectorMath'
+ Tags = 'PowerShell', 'Vector', 'Math'
# A URL to the main website for this project.
- ProjectURI = 'https://github.com/PowerShellWeb/Vector'
+ ProjectURI = 'https://github.com/PoshWeb/Vector'
# A URL to the license for this module.
- LicenseURI = 'https://github.com/PowerShellWeb/Vector/blob/main/LICENSE'
+ LicenseURI = 'https://github.com/PoshWeb/Vector/blob/main/LICENSE'
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
ReleaseNotes = @'
-## Vector 0.1:
-
-* Initial Release of Vector module
-* Commands:
- * Get-Vector (#1)
- * Get-Vector2 (#2)
- * Get-Vector3 (#3)
- * Get-Vector4 (#4)
-* Vector Workflow (#5)
-* Vector Tests (#6)
-* Vector Docs
- * Demo (#7)
- * README (#8)
- * FUNDING (#9)
- * CODE_OF_CONDUCT (#10)
- * CONTRIBUTING (#11)
- * SECURITY (#12)
+## Vector 0.1.1
+
+* `Vector` is an eponoym (#15)
+ * This module exposes one command with many aliases
+* `Vector` converts `Matrix3x2` and `Matrix4x4` into vectors (#16)
+* Vectors return their type when provided no input (#14)
+* Added `README.md.ps1` (#17)
+
+---
+
+Additional History in [CHANGELOG](https://github.com/PoshWeb/Vector/blob/main/CHANGELOG.md)
+
'@
PSIntro = @'