SetLocationWSLOverride.psm1

# Public Function:
Function Set-LocationWSLOverride {
    [CmdletBinding(DefaultParameterSetName = 'Path', HelpUri = 'https://go.microsoft.com/fwlink/?LinkID=2097049')]
    param(
        [Parameter(
            ParameterSetName = 'Path',
            Position = 0,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [string]${Path},

        [Parameter(
            ParameterSetName = 'LiteralPath',
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [Alias('PSPath', 'LP')]
        [string]${LiteralPath},

        [switch]${PassThru},

        [Parameter(
            ParameterSetName = 'Stack',
            ValueFromPipelineByPropertyName = $true
        )]
        [string]${StackName}
    )

    dynamicparam {
        try {
            $targetCmd = $ExecutionContext.InvokeCommand.GetCommand(
                'Microsoft.PowerShell.Management\Set-Location',
                [System.Management.Automation.CommandTypes]::Cmdlet,
                $PSBoundParameters
            )
            $dynamicParams = @(
                $targetCmd.Parameters.GetEnumerator() | Microsoft.PowerShell.Core\Where-Object { $_.Value.IsDynamic }
            )
            if ($dynamicParams.Length -gt 0) {
                $paramDictionary = [Management.Automation.RuntimeDefinedParameterDictionary]::new()
                foreach ($param in $dynamicParams) {
                    $param = $param.Value

                    if (-not $MyInvocation.MyCommand.Parameters.ContainsKey($param.Name)) {
                        $dynParam = [Management.Automation.RuntimeDefinedParameter]::new(
                            $param.Name,
                            $param.ParameterType,
                            $param.Attributes
                        )
                        $paramDictionary.Add($param.Name, $dynParam)
                    }
                }

                return $paramDictionary
            }
        } catch {
            throw
        }
    }

    begin {
        try {
            $outBuffer = $null
            if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) {
                $PSBoundParameters['OutBuffer'] = 1
            }

            if ($IsLinux) {
                foreach ($Drive in $script:WindowsDrives) {
                    if ([string]::IsNullOrWhiteSpace($Path) -eq $false) {
                        $PSBoundParameters['Path'] = $Path -Replace "^$($Drive.escapedDrive)", "/mnt/$($Drive.nakedDrive)/"
                    }
                    if ([string]::IsNullOrWhiteSpace($LiteralPath) -eq $false) {
                        $PSBoundParameters['LiteralPath'] = $LiteralPath -Replace "^$($Drive.escapedDrive)", "/mnt/$($Drive.nakedDrive)/"
                    }
                }
            }

            $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand(
                'Microsoft.PowerShell.Management\Set-Location',
                [System.Management.Automation.CommandTypes]::Cmdlet
            )
            $scriptCmd = { & $wrappedCmd @PSBoundParameters }

            $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
            $steppablePipeline.Begin($PSCmdlet)
        } catch {
            throw
        }
    }

    process {
        try {
            $steppablePipeline.Process($_)
        } catch {
            throw
        }
    }

    end {
        try {
            $steppablePipeline.End()
        } catch {
            throw
        }
    }
    <#
    .ForwardHelpTargetName Microsoft.PowerShell.Management\Set-Location
    .ForwardHelpCategory Cmdlet
    #>

}

Function Update-WindowsDrivesList {
    # Create/Update WindowsDrives module scope variable
    $script:WindowsDrives = Get-WindowsFileSystemDrives
}

# Private Function:
Function Get-WindowsFileSystemDrives {
    $result = [System.Collections.Generic.List[PSCustomObject]]::New()
    $WindowsPwshPath = '/mnt/c/Program Files/PowerShell/7/pwsh.exe'
    if (Test-Path -Path $WindowsPwshPath -PathType Leaf) {
        $mntPoints = Get-ChildItem '/mnt' -Directory -Exclude 'wsl' | Select-Object -ExpandProperty Name
        $PwshCmd =
            'Get-PSDrive -PSProvider FileSystem | ' +
            'Where-Object {$_.Name -ine ''Temp''} | ' +
            'Select-Object -ExpandProperty Root | ' +
            'ConvertTo-Json -compress'
        $WinPSDrives = & $WindowsPwshPath -c $PwshCmd | ConvertFrom-Json
        Foreach ($Drive in $WinPSDrives) {
            $WinDrive = [PSCustomObject]@{
                nakedDrive   = $Drive.Replace(':\', '').ToLower()
                escapedDrive = $Drive.Replace('\', '\\')
            }
            if ($mntPoints.Contains($WinDrive.nakedDrive)) {
                $result.Add($WinDrive)
            }
        }

    }
    return $result
}


# Module Import Steps:
Update-WindowsDrivesList
New-Alias -Name 'Set-Location' -Value 'Set-LocationWSLOverride'
Export-ModuleMember 'Set-LocationWSLOverride', 'Update-WindowsDrivesList' -Alias '*' # Export the public function