Skip to content

Instantly share code, notes, and snippets.

@skyline75489
Last active December 17, 2020 10:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skyline75489/480d036db8ae9069b7009377e6eebb79 to your computer and use it in GitHub Desktop.
Save skyline75489/480d036db8ae9069b7009377e6eebb79 to your computer and use it in GitHub Desktop.
Windows Terminal OSC 9;9 for PowerShell
function prompt {
$p = $($executionContext.SessionState.Path.CurrentLocation)
$converted_path = Convert-Path $p
$ansi_escape = [char]27
"PS $p$('>' * ($nestedPromptLevel + 1)) ";
Write-Host "$ansi_escape]9;9;$converted_path$ansi_escape\"
}
@TBBle
Copy link

TBBle commented Sep 19, 2020

The default prompt function (per echo $function:prompt) is

"PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) ";

so perhaps

function prompt {
    $p = $($executionContext.SessionState.Path.CurrentLocation)
    $ansi_escape = [char]27
    "PS $p$('>' * ($nestedPromptLevel + 1)) ";
    Write-Host "$ansi_escape]7;file://$env:COMPUTERNAME/$p$ansi_escape\"
}

to maintain the nested-prompt behaviour, and also include the hostname file:// URL.

A quick test suggests this is generating

ESC]7;file://KEITARO/C:\Users\paulhESC\

which Google Chrome seems to be happy to process.

However, going into \\wsl$\Ubuntu generates

ESC]7;file://KEITARO/Microsoft.PowerShell.Core\FileSystem::\\wsl$\UbuntuESC\

so I suspect this needs more work to correctly generate UNC paths. I haven't found a file:// URL format that lets me pass a UNC path to Chrome yet, so I don't have validation for this.

Microsoft.PowerShell.Core\FileSystem:: is coming from PowerShell Core, obviously, perhaps in Microsoft PowerShell, that prefix is not present in Get-Location?

Edit: Eww. Windows defines the file URL as being a UNC path, so the correct format is file://wsl$/Ubuntu. Which conflicts with the OSC 7 spec of using the hostname to recognise (and ignore) remote paths, while a UNC path is a local path to a remote location.

@skyline75489
Copy link
Author

skyline75489 commented Sep 20, 2020

Convert-Path fixes the UNC path issue for me. As for the fact that file://wsl$/Ubuntu conflicts with file://hostname/wsl$/Ubuntu, I'm using the OSC 7 spec to not damage the compatibility with other terminals.

@TBBle
Copy link

TBBle commented Sep 20, 2020

Ah, nice find on Convert-Path.

And now you've got me looking, I discovered the joy of PSProviders, the things that let you cd HKLM:\Software\Microsoft to access the registry.

I assume that for OSC 7 we only want the FileSystem provider, because anything else would be pretty insane. I haven't tested it with in-box Microsoft PowerShell, just PowerShell Core. I'm assuming the PSProvider Name is still FileSystem there.

I also turned the \ into / for general URL sanity, and got rid of the Write-Host, since that made testing it a bit messy.

So this is what I have now:

function prompt {
    $p = $executionContext.SessionState.Path.CurrentLocation
    $osc7 = ""
    if ($p.Provider.Name -eq "FileSystem") {
        $ansi_escape = [char]27
        $provider_path = $p.ProviderPath -Replace "\\", "/"
        $osc7 = "$ansi_escape]7;file://${env:COMPUTERNAME}/${provider_path}${ansi_escape}\"
    }
    "${osc7}PS $p$('>' * ($nestedPromptLevel + 1)) ";
}

That said, I haven't seen how this interoperates with the PR yet.

@j4james
Copy link

j4james commented Sep 20, 2020

I've only just noticed these gists now, and I see you guys have already got this figured out. So you can probably ignore a lot of my comments on the PR. The only thing I think worth mentioning is that we'd ideally be applying URL escaping to the path name. I know that's not going to be possible in the cmd.exe shell, but I'm assuming it might be achievable with PowerShell.

@skyline75489
Copy link
Author

@j4james I get your point. But on Windows, Neither \ nor / is valid character in a path. So perhaps there's no real need for URL escaping? I'm no expert at this. Hope some Win32 dude could help with this.

@TBBle
Copy link

TBBle commented Sep 24, 2020

As noted on the main ticket, we can use [system.uri] in PowerShell to deal with escaping for us. I'm not sure if we can say "Just generate a legacy filesystem path URL" or if we have to feed it something like [system.url](file://${env:COMPUTERNAME}/$p.ProviderPath), but either way escaping is not our problem.

@j4james
Copy link

j4james commented Sep 24, 2020

There are a few characters that are legal in a Windows path but not in a URI path. % is the most obvious one, but there's also #. There may be others, depending on how strict the parser is. I would also have expected non-ascii characters to be escaped to avoid issues with different code pages.

@TBBle
Copy link

TBBle commented Sep 24, 2020

Yup, it supports that fine. Although I didn't create these directories.

PS C:\Users\paulh> [system.uri]("C:\dog%\cat#\mousewords")

AbsolutePath   : C:/dog%25/cat%23/mousewords
AbsoluteUri    : file:///C:/dog%25/cat%23/mousewords
LocalPath      : C:\dog%\cat#\mousewords
Authority      :
HostNameType   : Basic
IsDefaultPort  : True
IsFile         : True
IsLoopback     : True
PathAndQuery   : C:/dog%25/cat%23/mousewords
Segments       : {/, C:/, dog%25/, cat%23/…}
IsUnc          : False
Host           :
Port           : -1
Query          :
Fragment       :
Scheme         : file
OriginalString : C:\dog%\cat#\mousewords
DnsSafeHost    :
IdnHost        :
IsAbsoluteUri  : True
UserEscaped    : False
UserInfo       :

PS C:\Users\paulh> [system.uri]("C:\mẹ\母")

AbsolutePath   : C:/m%E1%BA%B9/%E6%AF%8D
AbsoluteUri    : file:///C:/m%E1%BA%B9/%E6%AF%8D
LocalPath      : C:\mẹ\母
Authority      :
HostNameType   : Basic
IsDefaultPort  : True
IsFile         : True
IsLoopback     : True
PathAndQuery   : C:/m%E1%BA%B9/%E6%AF%8D
Segments       : {/, C:/, m%E1%BA%B9/, %E6%AF%8D}
IsUnc          : False
Host           :
Port           : -1
Query          :
Fragment       :
Scheme         : file
OriginalString : C:\mẹ\母
DnsSafeHost    :
IdnHost        :
IsAbsoluteUri  : True
UserEscaped    : False
UserInfo       :

@j4james
Copy link

j4james commented Sep 24, 2020

Although I didn't create these directories.
AbsolutePath : C:/dog%25/cat%23/mousewords

If it wasn't you, there's a strong indication that your cat may have been responsible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment