Enable case-insensitive tab completion for files and folders on case-sensitive filesystem (#8128)

This commit is contained in:
Steve Lee 2018-10-27 21:48:49 -07:00 committed by Ilya
parent 81618bc2c1
commit b27380dc51
3 changed files with 61 additions and 3 deletions

View file

@ -4174,7 +4174,7 @@ namespace System.Management.Automation
string[] entries = null;
try
{
entries = Directory.GetFileSystemEntries(parentPath, leaf);
entries = Directory.GetFileSystemEntries(parentPath, leaf, _enumerationOptions);
}
catch (Exception)
{
@ -4404,6 +4404,11 @@ namespace System.Management.Automation
private const int ERROR_MORE_DATA = 234;
private const int STYPE_DISKTREE = 0;
private const int STYPE_MASK = 0x000000FF;
private static System.IO.EnumerationOptions _enumerationOptions = new System.IO.EnumerationOptions
{
MatchCasing = MatchCasing.CaseInsensitive,
AttributesToSkip = 0 // Default is to skip Hidden and System files, so we clear this to retain existing behavior
};
[DllImport("Netapi32.dll", CharSet = CharSet.Unicode)]
private static extern int NetShareEnum(string serverName, int level, out IntPtr bufptr, int prefMaxLen,

View file

@ -81,6 +81,11 @@ namespace Microsoft.PowerShell.Commands
}
private Collection<WildcardPattern> _excludeMatcher = null;
private static System.IO.EnumerationOptions _enumerationOptions = new System.IO.EnumerationOptions
{
MatchCasing = MatchCasing.CaseInsensitive,
AttributesToSkip = 0 // Default is to skip Hidden and System files, so we clear this to retain existing behavior
};
/// <summary>
/// Converts all / in the path to \
@ -1569,7 +1574,7 @@ namespace Microsoft.PowerShell.Commands
else
{
// Filter the directories
target.Add(directory.EnumerateDirectories(Filter));
target.Add(directory.EnumerateDirectories(Filter, _enumerationOptions));
}
// Making sure to obey the StopProcessing.
@ -1580,7 +1585,7 @@ namespace Microsoft.PowerShell.Commands
// Use the specified filter when retrieving the
// children
target.Add(directory.EnumerateFiles(Filter));
target.Add(directory.EnumerateFiles(Filter, _enumerationOptions));
}
else
{

View file

@ -222,6 +222,7 @@ Describe "TabCompletion" -Tags CI {
$oneSubDir = Join-Path -Path $tempDir -ChildPath "oneSubDir"
$oneSubDirPrime = Join-Path -Path $tempDir -ChildPath "prime"
$twoSubDir = Join-Path -Path $oneSubDir -ChildPath "twoSubDir"
$caseTestPath = Join-Path $testdrive "CaseTest"
New-Item -Path $tempDir -ItemType Directory -Force > $null
New-Item -Path $oneSubDir -ItemType Directory -Force > $null
@ -254,12 +255,17 @@ Describe "TabCompletion" -Tags CI {
}
}
BeforeEach {
New-Item -ItemType Directory -Path $caseTestPath > $null
}
AfterAll {
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
}
AfterEach {
Pop-Location
Remove-Item -Path $caseTestPath -Recurse -Force -ErrorAction SilentlyContinue
}
It "Input '<inputStr>' should successfully complete" -TestCases $testCases {
@ -318,6 +324,48 @@ Describe "TabCompletion" -Tags CI {
$res.CompletionMatches | Should -HaveCount 1
$res.CompletionMatches[0].CompletionText | Should -BeExactly $afterTab
}
It "Test case insensitive <type> path" -Skip:(!$IsLinux) -TestCases @(
@{ type = "File" ; beforeTab = "Get-Content f" },
@{ type = "Directory"; beforeTab = "cd f" }
) {
param ($type, $beforeTab)
$testItems = "foo", "Foo", "fOO"
$testItems | ForEach-Object {
$itemPath = Join-Path $caseTestPath $_
New-Item -ItemType $type -Path $itemPath
}
Push-Location $caseTestPath
$res = TabExpansion2 -inputScript $beforeTab -cursorColumn $beforeTab.Length
$res.CompletionMatches | Should -HaveCount $testItems.Count
# order isn't guaranteed so we'll sort them first
$completions = ($res.CompletionMatches | Sort-Object CompletionText -CaseSensitive).CompletionText -join ":"
$expected = ($testItems | Sort-Object -CaseSensitive | ForEach-Object { "./$_" }) -join ":"
$completions | Should -BeExactly $expected
}
It "Test case insensitive file and folder path completing for <type>" -Skip:(!$IsLinux) -TestCases @(
@{ type = "File" ; beforeTab = "Get-Content f"; expected = "foo","Foo" }, # Get-Content passes thru to provider
@{ type = "Directory"; beforeTab = "cd f" ; expected = "Foo" } # Set-Location is aware of Files vs Folders
) {
param ($beforeTab, $expected)
$filePath = Join-Path $caseTestPath "foo"
$folderPath = Join-Path $caseTestPath "Foo"
New-Item -ItemType File -Path $filePath
New-Item -ItemType Directory -Path $folderPath
Push-Location $caseTestPath
$res = TabExpansion2 -inputScript $beforeTab -cursorColumn $beforeTab.Length
$res.CompletionMatches | Should -HaveCount $expected.Count
# order isn't guaranteed so we'll sort them first
$completions = ($res.CompletionMatches | Sort-Object CompletionText -CaseSensitive).CompletionText -join ":"
$expected = ($expected | Sort-Object -CaseSensitive | ForEach-Object { "./$_" }) -join ":"
}
}
Context "Cmdlet name completion" {