Repository navigation
Description
Prerequisites
- Write a descriptive title.
- Make sure you are able to repro it on the latest released version
- Search the existing issues.
- Refer to the FAQ.
- Refer to Differences between Windows PowerShell 5.1 and PowerShell.
Steps to reproduce
With versions prior to 7.4.0, pressing Tab to get completion on a path with ~ converted that path into the full path for my home folder.
Type dir ~\down and press Tab:
- In 7.3.9, it will be completed as
dir C:\Users\bradwilson\Downloads\ - In 7.4.0, it will be completed as
dir ~\Downloads\
For built-in commands (like dir), this is fine. For executables, this passes a path with ~ in it, which makes using such paths impossible unless the executable has its own support for mapping ~ to the home folder. For example, if I try to run notepad ~\.config\git\config, it will tell me the path isn't found; if I run notepad C:\Users\bradwilson\.config\git\config, it will open the file appropriately.
This breaks more than a decade of muscle memory expecting ~ to be translated into the correct path, as I've been using PowerShell as my shell since it was called Monad.
This appears to have been purposefully introduced in #19489. I cannot find any way to restore the old behavior short of sticking w/ version 7.3.9.
Expected behavior
PS> TabExpansion2 '~\Downloads' | select -ExpandProperty CompletionMatches
CompletionText ListItemText ResultType ToolTip
-------------- ------------ ---------- -------
C:\Users\bradwilson\Downloads Downloads ProviderContainer C:\Users\bradwilson\DownloadsActual behavior
PS> TabExpansion2 '~\Downloads' | select -ExpandProperty CompletionMatches
CompletionText ListItemText ResultType ToolTip
-------------- ------------ ---------- -------
~\Downloads Downloads ProviderContainer C:\Users\bradwilson\DownloadsError details
No response
Environment data
Name Value
---- -----
PSVersion 7.3.9
PSEdition Core
GitCommitId 7.3.9
OS Microsoft Windows 10.0.22631
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Name Value
---- -----
PSVersion 7.4.0
PSEdition Core
GitCommitId 7.4.0
OS Microsoft Windows 10.0.22631
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0Visuals
No response
Activity
237dmitry commentedon Nov 22, 2023
In fact, when this behavior finally appeared in 7.4.0-rc.1, I was glad about it. But perhaps this is not as relevant in Windows as it is in Linux.
bradwilson commentedon Nov 22, 2023
It's very counterproductive in Windows.
You could argue it's somewhat counterproductive in Linux as well unless every single application you use from the command line already maps~. Many of the built-in utilities probably already have to do this, so it's less obvious when failures will materialize.PowerShell follows POSIX (partially) and translates ~ before calling executables on Linux/macOS.
237dmitry commentedon Nov 22, 2023
On Linux, all native applications interpret the tilde as a synonym for the user's home directory. It’s just that the command line is shorter due to the fact that it does not expand the path to the full one. The same cannot be said about Windows; most utilities probably simply will not understand what this path is.
bradwilson commentedon Nov 22, 2023
It's worth pointing out that the Unix-y apps on Windows (for example, all the tools that ship with Git) do map
~but will only do it if you pass Unix-y separators.Using less version
563(shipped with Git2.29.2.windows.2), these work:7.3.9:
less C:\Users\bradwilson\.config\git\configAnd crafted by hand:
less ~/.config/git/configBut this doesn't:
7.4.0:
less ~\.config\git\configresults in~.configgitconfig: No such file or directorySince PowerShell uses the backslash when tab completing, it's creating command lines that will be broken with these Unix-y tools.
bradwilson commentedon Nov 22, 2023
To be clear, I don't think the use of the backslash is wrong for PowerShell Core on Windows, as the Unix-y tools do work as expected with backslashes but only with fully qualified paths (which Tab completion no longer generates in 7.4.0).
237dmitry commentedon Nov 22, 2023
I was talking specifically about Linux as the actual installed OS. Not WSL, not ported utilities, but about my main OS, which is the only one on the computer (Windows on the older notebook).
Therefore, I would like everything to remain as it is, at least on Linux.
bradwilson commentedon Nov 22, 2023
I'm fine with the new behavior being the default, as long as I have a trivial way to opt out.
MartinGC94 commentedon Nov 22, 2023
Yes, as you've discovered this was an intentional change and there's currently no way to change the behavior. A quick workaround you can implement on your own machine is to update the tabexpansion2 function to replace the
~character in the completion results with your home path.Assuming this is something that people want fixed, I can think of the following solutions:
~before passing it in as an argument to native commands.Quick and dirty tabexpansion2 workaround:
Details
mklement0 commentedon Nov 22, 2023
Let me provide some context:
On Unix-like platforms it is the (POSIX-compatible) shell (such as
bash) that performs tilde (~) expansion, not the standard utilities (such as asls) themselves; the same applies to globbing (wildcard expansion in filenames), among other such so-called shell expansions. You can verify this with/bin/ls --% ~from PowerShell.On Unix-like platforms only, PowerShell emulates this behavior (as well as globbing) when calling external programs:
~- either in isolation of if followed by/(but not\) - to the value of$HOME.`to escape~-/bin/echo `~- should work like/bin/echo '~'and/bin/echo "~", i.e. should suppress expansion, but currently doesn't; the inverse is true for/bin/echo ~/'foo bar', which should expand -d due to the~itself being unquoted, but doesn't (if you remove the space, it works): Unix: Emulation of ~ (tilde) expansion for native utilities is syntactically incomplete #20754~user1works in POSIX-compatible shells to refer to the home directory ofuser1(verify from PowerShell withsh -c "echo ~$env:USER"), but not in PowerShell: Implement ~username expansion on Windows and Linux #12387On Windows, where the native shell (
cmd.exe) has no such expansion features, PowerShell does not perform them.Given the above, I propose the following variation of MartinGC94's proposal 1:
~expand to the value of$HOMEonly there - conceivably, it could even expand to verbatim$HOME, so as to preserve the intent to express the path abstractly.While making PowerShell emulate literal
~expansion on argument-passing to external programs on Windows also may seem appealing, there's a greater risk of breaking existing Windows-only code that never anticipated~as having special meaning and therefore requiring quoting.Also, emulating globbing too is definitely not an option, as a program expecting, say,
file*.txtverbatim, then receiving multiple arguments (file1.txt file2.txt ...) could break.mklement0 commentedon Nov 22, 2023
Taking a step back, re proposal 3 (unquoted
~expansion on external-program argument-passing also on Windows):It may be an option IF:
~(either in isolation or if followed by\or/) to the current user's home directory falls into bucket 3, i.e. is unlikely to break existing code.Jaykul commentedon Nov 23, 2023
For what it's worth, the problem I have is that I don't think you went far enough. I really don't want TabCompletion to replace generic values like
~with the specific value on my computer. The same goes for or$homeand$pwdand any other variable that I might have a partial path in.How about instead of reverting a good feature, we replace the literal
~at the front of the path with$HOMEand then ... leave all the variables as variables in the path?Since PowerShell expands variables when passing arguments to native apps, this gets us the best of all worlds:
~/Doc{Tab}still tab completesNOTE: the catch to this is that it doesn't work if they're single-quoting the path they are tab-completing, in which case we might want to resort to the old behavior...
MartinGC94 commentedon Nov 23, 2023
I am planning on creating a PR to stop it from replacing variables with their resolved values but that's a separate issue from this.
I don't like the idea of replacing
~with$homewhen tab completing because it would feel weird and confusing for anyone outside of this discussion. It also wouldn't be accurate because the home location that~refers to is set in the provider, while$homejust points to the same static location always. See:rhubarb-geek-nz commentedon Nov 23, 2023
Not exactly true. The tilde is expanded by the shell (bash, sh, zsh etc). The applications don't need to map the tilde in command line arguments. Just like on UNIX the shell expands file wildcards, so the application does not need to enumerate directories, the shell did it for them.
No interpretation by the native app.
The shell does not expand if quoted
and
Now that is a gotcha, because shell does expand environment variables within double quotes but not within single quotes. So shell is doing special treatment for tilde, it is not treating it simply as $HOME.
Bash Manual - Tilde-Expansion
mklement0 commentedon Nov 23, 2023
Thanks, rhubarb-geek-nz - this has all been covered by my previous comment.
MartinGC94: good point about the provider-specific nature of
~.However, tab-completion was previously already provider-aware and would not expand
~while the current location was, say, theEnv:drive (for which a home location isn't defined) - that shouldn't change (or, rather: categorically leave~alone for all other providers).(On a side note: On Unix-like system, when tilde expansion happens in the context of argument-passing to external programs, the current location's provider does not matter; it is always the value of
$HOMEthat is used - which makes sense, given that the outside world only knows the file-system, and nothing about PowerShell's other providers.)Given that among the built-in providers only the
FileSystemone has a home location predefined, the slight loss of level of abstraction that comes from translating~to$HOME- if theFileSystemprovider underlies the current location (which, however, is almost always the case, if I were to guess) - is still preferable to expanding to the full, literal home directory path.To me, translating
~to verbatim$HOMEwould be no more confusing than the old behavior of expanding to, say,C:\Users\jdoe.That said, we could avoid this problem if we went with proposal 3, which is the cleanest solution.
Personally, that is my preference, but the question is whether the concerns raised previously prevent it.
114 remaining items
mklement0 commentedon Apr 23, 2024
Paul Moore (@pfmoore): MartinGC94 has posted a temporary fix in the form of a modified
TabExpansion2function, which you can add to your$PROFILE: expand the Details section in the following comment: #20750 (comment)bradwilson commentedon Apr 24, 2024
Sorry, everybody, but I'm closing this issue. I've been nearly half a year with tons of discussion (and way too many heated words), and never once has anybody from the PowerShell team come to say anything about this.
It's done and over, and we're not getting it back.
microsoft-github-policy-service commentedon Apr 24, 2024
📣 Hey Brad Wilson (@bradwilson), how did we do? We would love to hear your feedback with the link below! 🗣️
🔗 https://aka.ms/PSRepoFeedback
mklement0 commentedon Apr 24, 2024
Brad Wilson (@bradwilson), as much as I can relate to the I'm-gonna-take-my-ball-and-go-home sentiment, the community is better served by keeping this issue open.
The fact that the issue is labeled WG-NeedsReview presumably:
In short: I encourage you to reopen this issue, if only to - for now - increase its visibility to future users.
bradwilson commentedon Apr 24, 2024
You're welcome to open a new issue and even link back here for "history". I have zero confidence that this one will yield any attention. 5 months is long enough to wait for even a simple acknowledgement.
Gonkers commentedon Apr 24, 2024
Thanks for sticking with it as long as you did. I've been affected by other hot-button issues that the pwsh team have refused to acknowledge. This is nothing new for this team.
fwiw, I just downgraded to https://github.com/PowerShell/PowerShell/releases/tag/v7.3.12
jhoneill commentedon Apr 24, 2024
Sadly that's the way the PowerShell team has gone. Not engaging, and indulging in "Developer Driven Development".
microsoft-github-policy-service commentedon Apr 24, 2024
📣 Hey Brad Wilson (@bradwilson), how did we do? We would love to hear your feedback with the link below! 🗣️
🔗 https://aka.ms/PSRepoFeedback
bradwilson commentedon Apr 24, 2024
Thank you, thank you, thank you Steve Lee (@SteveL-MSFT) for the fix! And thanks to Jared Parsons (@jaredpar) for getting it attention.
jaredpar commentedon Apr 24, 2024
That gif is amazing.
jhoneill commentedon Apr 25, 2024
And just when you give up, someone engages and does the right thing :-) Tip-of-the-hat to you Steve.