Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix tab completion for filename contains literal wildcard character #7407

Closed
wants to merge 10 commits into from

Conversation

kwkam
Copy link
Contributor

@kwkam kwkam commented Jul 30, 2018

PR Summary

*System.Management.Automation/engine/CommandCompletion/CompletionCompleters:
Use WildcardPattern::Escape to escape completion text of filename.

*System.Management.Automation/engine/regex:
WildcardPattern::Escape should also escape "`" since
WildcardPattern::Unescape would unescape it,
and the matcher parse it as escape character.

*System.Management.Automation/namespaces/LocationGlobber:
Do not pass regex escaped string to WildcardPattern::Get. This fails
tab completion when doing "./path/to/`[f"<TAB>.

PR Checklist

*System.Management.Automation/engine/CommandCompletion/CompletionCompleters:
Use WildcardPattern::Escape to escape completion text of filename.

*System.Management.Automation/engine/regex:
WildcardPattern::Escape should also escape "`" since
WildcardPattern::Unescape would unescape it,
and the matcher parse it as escape character.

*System.Management.Automation/namespaces/LocationGlobber:
Do not pass regex escaped string to WildcardPattern::Get. This fails
tab completion when doing "./path/to/`[f"<TAB>.
@iSazonov
Copy link
Collaborator

iSazonov commented Jul 31, 2018

@kwkam Please remove "[Feature]" from title in your PRs. We need this prefix only in commit header to force run feature tests.

@kwkam kwkam changed the title [Feature] Fix file completion with literal wildcard char Fix file completion with literal wildcard char Jul 31, 2018
@stale
Copy link

stale bot commented Aug 30, 2018

This PR has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed if no further activity occurs within 10 days.
Thank you for your contributions.
Community members are welcome to grab these works.

@stale stale bot added the Stale label Aug 30, 2018
@@ -739,6 +739,9 @@ dir -Recurse `
@{ inputStr = "Get-Process >'.\My ``[Path``]\'"; expected = "'.${separator}My ``[Path``]${separator}test.ps1'" }
@{ inputStr = "Get-Process >${tempDir}\My"; expected = "'${tempDir}${separator}My ``[Path``]'" }
@{ inputStr = "Get-Process > '${tempDir}\My ``[Path``]\'"; expected = "'${tempDir}${separator}My ``[Path``]${separator}test.ps1'" }
@{ inputStr = "cd 'My ``["; expected = "'.${separator}My ``[Path``]'" }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. We should replace the alias with cmdlet and above too.
  2. I'd expect that users will type the path without escape - it doesn't work.
  3. I'd expect that it will work for literal path too - it doesn't work. It could be out of the PR but I'd prefer to remove the fix from the PR and get a full fix in another PR for all scenarios. We should do full review how we process all special chars in Path and in LiteralPath. I do not see the point in partial fixes because they can break something without having a full set of tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Updated test.
  2. I disagree. User should type escape for -Path (which support globbing), just like we do in bash (eg. touch \[test\]). But if you typed escape and auto completion still did not work, that is because by default, powershell treats "unquoted string without space" like "double-quoted string", that "double-quoted string" will consume escape character. For file name [test], either Get-Content -Path ```[ or Get-Content -Path '`[ will work.
  3. Would you please let me know what did not work for -LiteraPath?
    I tried Get-Item -LiteralPath [(TAB) for a file named [test] and it did auto complete.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Consider interactive UX. User do dir and then type directory or file name as one see on screen - without escapes. In the scenario both the user and PowerShell know right name. And more, we can have both names - with escape char too.
  2. Get-Item '.\My `[

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. The problem is, -Path support wildcard. When a path can be an expression, the special characters should always be escaped otherwise it will become too complicated. For example, in a directory there are A.txt, B.txt and [AB].txt, what should Get-Item -Path [AB].txt return?
  2. I tested both -Path and -LiteralPath and both will complete the file name. eg.
    New-Item -Name 'My [test]'
    Get-Item '.\My `[ will be completed to Get-Item '.\My `[test`]', and
    Get-Item -LiteralPath '.\My [ will be completed to Get-Item -LiteralPath '.\My [test]'
    Did you use the build here? https://ci.appveyor.com/project/PowerShell/powershell/build/v6.1.0-rc.10960/job/3i76g2ar1wqlvw7x/artifacts

//
if (IsWildcardChar(ch) && !charsNotToEscape.Contains(ch))
if ((IsWildcardChar(ch) || ch == escapeChar) &&
!charsNotToEscape.Contains(ch))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we always should escape the escape char? What scenario don't work without fix?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. When we accidentally created a file named `[test`]2 due to the incorrect handling of wildcard character, we cannot remove it using the -Path parameter with the tab completed name.
  2. When I escaped string A and get B, and try to unescape B, I would expected that A will be returned, but it is not when A contains escape character.
  3. The wildcard pattern parser always treat escape character as escape character.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that we should test if a file/directory/path exists before trying escape. If exist then return the path. Then continue with escaping wildcard chars. Then continue with expansion wildcards if -Path.
Also what if there is some special symbols in the path? Seems we should process them in cycle.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I know what is wrong here. This part is to fix the WildcardPattern::Escape function itself, which is not necessary related to the file system.
When WildcardPattern::Get parse a pattern string, it always treats the escape character as escape character of an escape character. That means, `` will be parsed to `.
And so is the WildcardPattern::Unescape method, [WildcardPattern]::Unescape('``') will return ` instead of ``.
But, [WildcardPattern]::Escape('`') does not escape the escape character, which conflicts with the others.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kwkam I see your point.
We have the public API

public static string Escape(string pattern)

So the change is a breaking change and it is not desirable to change this behavior until it is established that this is a significant bug.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iSazonov Yes, we should be careful with changes in public API, but I doubt if this is not a significant bug. For example, there is a list of text:

`[HIGH] patch 1`
`[MED] update 1`
`[LOW] patch 1`
`[MED] patch 2`
`[HIGH] hotfix 3`
`[LOW] patch 2`
`[LOW] hotfix 3`

Now, I want to search for `[LOW] patch 1` and `[LOW] patch 2`, and I am using WildcardPattern:

$prefix = '`[LOW] patch '
$pattern = '[1-2]'
$suffix = '`'
$sarg = [WildcardPattern]::Escape($prefix) + $pattern + [WildcardPattern]::Escape($suffix)
$opts = [Management.Automation.WildcardOptions]::Compiled
$matcher = [WildcardPattern]::Get($sarg, $opts)
$ListOfText | ? {$matcher.IsMatch($_)}

No result will be return because of the inconsistency between the Escape method and the WildcardPattern parser. (And this is also the cause of the issue in auto-completed filename which contains escape character)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for good example!

We need PowerShell Committee conclusion.
/cc @SteveL-MSFT

@stale stale bot removed the Stale label Aug 30, 2018
@iSazonov
Copy link
Collaborator

@kwkam Sorry for delay - it is very sensetive aria and we should very careful.

@kwkam
Copy link
Contributor Author

kwkam commented Aug 31, 2018

@iSazonov Yes, that's why this PR was placed behind the cmdlet ones. Please let me know if something is not correct/not working.

@iSazonov iSazonov added Review - Committee The PR/Issue needs a review from the PowerShell Committee Breaking-Change breaking change that may affect users labels Sep 4, 2018
@SteveL-MSFT
Copy link
Member

cc @BrucePay to follow-up

@stale
Copy link

stale bot commented Oct 24, 2018

This PR has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed if no further activity occurs within 10 days.
Thank you for your contributions.
Community members are welcome to grab these works.

@stale stale bot added the Stale label Oct 24, 2018
@iSazonov
Copy link
Collaborator

@SteveL-MSFT We have too many frozen PRs. How we can resolve the problem?

@stale stale bot removed the Stale label Oct 25, 2018
@SteveL-MSFT
Copy link
Member

@BrucePay will follow-up on this specific PR

@stale
Copy link

stale bot commented Nov 25, 2018

This PR has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed if no further activity occurs within 10 days.
Thank you for your contributions.
Community members are welcome to grab these works.

@stale stale bot added the Stale label Nov 25, 2018
@kwkam kwkam changed the title Fix file completion with literal wildcard char Fix tab completion for filename contains literal wildcard character Dec 4, 2018
@ghost ghost removed the Waiting on Author The PR was reviewed and requires changes or comments from the author before being accept label Jun 22, 2019
Co-Authored-By: Ilya <darpa@yandex.ru>
@@ -4383,6 +4383,12 @@ internal static IEnumerable<CompletionResult> CompleteFilename(CompletionContext
if (CompletionRequiresQuotes(completionText, !useLiteralPath))
{
var quoteInUse = quote == string.Empty ? "'" : quote;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should all changes be behind the experimental feature?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a condition of the committee

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except filename completion will now also escape * and ? in non-literal path, the behaviour should be identical unless the experimental feature (the breaking part) is enabled.

@msftrncs
Copy link
Contributor

msftrncs commented Jul 28, 2019

I tested a variation of this PR, while testing the PR I am preparing to fix all argument completion patterns along with variable and member completions, #10226.

Previously, I could not use Get-Content to read the content of a file named `[hello`].txt, the file would NOT be read, but there would also be no error.

I did not modify the WildCardPattern.Escape() method, but instead added .Replace("`", "``") to the passed value of every single instance in the PowerShell code base of the Escape() method.

Now Get-Content reads the content of that file.

Even if changes to WildCardPattern.Escape() are considered too breaking, at least manually escape the backticks, in each call.

Unfortunately this doesn't fix the issue with redirection, which accepts a wildcard path, but then sends it to out-file as a literal.

@kwkam
Copy link
Contributor Author

kwkam commented Dec 7, 2019

Unfortunately this doesn't fix the issue with redirection, which accepts a wildcard path, but then sends it to out-file as a literal.

@msftrncs It was in another PR #9258

@ghost ghost added the Review - Needed The PR is being reviewed label May 27, 2020
@ghost
Copy link

ghost commented May 27, 2020

This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days.
Mainainer, Please provide feedback and/or mark it as Waiting on Author

@TravisEz13 TravisEz13 added Waiting on Author The PR was reviewed and requires changes or comments from the author before being accept and removed Review - Needed The PR is being reviewed labels May 27, 2020
@iSazonov
Copy link
Collaborator

@kwkam Please resolve merge conflicts and address comments.

@ghost ghost removed the Waiting on Author The PR was reviewed and requires changes or comments from the author before being accept label Jun 4, 2020
@TravisEz13 TravisEz13 closed this Jun 5, 2020
@TravisEz13 TravisEz13 reopened this Jun 5, 2020
@ghost ghost added the Review - Needed The PR is being reviewed label Jun 13, 2020
@ghost
Copy link

ghost commented Jun 13, 2020

This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days.
Mainainer, Please provide feedback and/or mark it as Waiting on Author

@@ -0,0 +1,68 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Copyright (c) Microsoft Corporation. All rights reserved.
# Copyright (c) Microsoft Corporation.

@ghost ghost added Waiting on Author The PR was reviewed and requires changes or comments from the author before being accept and removed Review - Needed The PR is being reviewed labels Oct 27, 2020
@TravisEz13
Copy link
Member

@daxian-dbw Can you review this?

@ghost ghost added the Stale label Nov 11, 2020
@ghost
Copy link

ghost commented Nov 11, 2020

This pull request has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 15 days. It will be closed if no further activity occurs within 10 days of this comment.

@ghost ghost closed this Nov 22, 2020
@floh96
Copy link
Contributor

floh96 commented Jun 10, 2021

@iSazonov could this pr be reopened?
If I'm seeing this correctly, it was closed because of a copyright header change....

@ghost ghost removed the Stale label Jun 10, 2021
@iSazonov
Copy link
Collaborator

@floh96 It makes no sense to reopen. The work could be continue if anybody grabbed the work and MSFT team agreed to review. Now you could open new issue to discuss and vote.

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Breaking-Change breaking change that may affect users Committee-Reviewed PS-Committee has reviewed this and made a decision Waiting on Author The PR was reviewed and requires changes or comments from the author before being accept
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants