Assets/Format-ProcessArgument.ps1

# SPDX-License-Identifier: AGPL-3.0-or-later
# Copyright (C) 2026 Tyler Vigario

<#
.SYNOPSIS
  One argument, quoted so a Windows program reads it back as exactly one argument.

.DESCRIPTION
  Start-Process -ArgumentList joins an array with spaces and quotes NOTHING, on both
  editions. Measured: a launcher at a path with a space, passed that way through
  Windows Terminal, never ran; quoted, it did. So every argument that could hold a space
  -- the shell's path, the launcher's path under the module directory, which lives under
  Documents and so under a profile name or a OneDrive folder -- goes through this.

  The rules are the ones the C runtime and CommandLineToArgvW read back: an argument with
  no whitespace or quote is left as it is; otherwise it is wrapped in quotes, a quote
  inside it is escaped as \", and backslashes are doubled only where they come before a
  quote -- including the closing one, so "C:\dir\" does not swallow its own terminator.
#>

function Format-ProcessArgument {
    [CmdletBinding()]
    [OutputType([string])]
    param([Parameter(Mandatory, ValueFromPipeline)][AllowEmptyString()][string]$Argument)
    process {
        if ($Argument -and $Argument -notmatch '[\s"]') { return $Argument }
        $sb = [System.Text.StringBuilder]::new('"')
        $slashes = 0
        foreach ($c in $Argument.ToCharArray()) {
            if ($c -eq [char]92) { $slashes++; continue }
            if ($c -eq '"') { [void]$sb.Append([char]92, 2 * $slashes + 1).Append('"') }
            else { [void]$sb.Append([char]92, $slashes).Append($c) }
            $slashes = 0
        }
        [void]$sb.Append([char]92, 2 * $slashes).Append('"')
        $sb.ToString()
    }
}