-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Make TabCompletion case-insensitive for file names on Unix #4699
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4061,10 +4061,8 @@ internal static IEnumerable<CompletionResult> CompleteFilename(CompletionContext | |
| var relativePaths = context.GetOption("RelativePaths", @default: defaultRelative); | ||
| var useLiteralPath = context.GetOption("LiteralPaths", @default: false); | ||
|
|
||
| if (useLiteralPath && LocationGlobber.StringContainsGlobCharacters(wordToComplete)) | ||
| { | ||
| wordToComplete = WildcardPattern.Escape(wordToComplete, Utils.Separators.StarOrQuestion); | ||
| } | ||
| // We should always escape '[' and ']' if present. | ||
| wordToComplete = WildcardPattern.Escape(wordToComplete, Utils.Separators.StarOrQuestion); | ||
|
|
||
| if (!defaultRelative && wordToComplete.Length >= 2 && wordToComplete[1] == ':' && char.IsLetter(wordToComplete[0]) && executionContext != null) | ||
| { | ||
|
|
@@ -4073,6 +4071,43 @@ internal static IEnumerable<CompletionResult> CompleteFilename(CompletionContext | |
| executionContext.SessionState.Drive.GetAtScope(wordToComplete.Substring(0, 1), "global"); | ||
| } | ||
|
|
||
| #if UNIX | ||
| // We use globbing to get completions. | ||
| // Globbing is based on system functions which is case-sensitive on Unix. | ||
| // To make globbing on Unix case-insensitive we transform every char from the input string: | ||
| // "alias:dir" -> "alias:[dD][iI][rR]" | ||
| if (context.GetOption("UnixCaseInsensitiveGlobbing", @default: true) == true) | ||
| { | ||
| StringBuilder sb = new StringBuilder(wordToComplete.Length * 4); | ||
|
|
||
| //wordToComplete = WildcardPattern.Escape(wordToComplete, Utils.Separators.Brackets); | ||
|
|
||
|
||
| // Copy a provider name "as is" without transformation. | ||
| var providerPrefixIndex = wordToComplete.IndexOf(':') + 1; | ||
| int i; | ||
| for (i=0; i < providerPrefixIndex; i++) | ||
| { | ||
| sb.Append(wordToComplete[i]); | ||
| } | ||
|
|
||
| // Transform rest of input string after a provider prefix. | ||
| for (var j=i; j < wordToComplete.Length; j++) | ||
| { | ||
| var lch = Char.ToLower(wordToComplete[j]); | ||
| var uch = Char.ToUpper(wordToComplete[j]); | ||
| if (lch != uch) | ||
| { | ||
| sb.Append('[').Append(lch).Append(uch).Append(']'); | ||
| } | ||
| else | ||
| { | ||
| sb.Append(wordToComplete[j]); | ||
| } | ||
| } | ||
|
|
||
| wordToComplete = sb.ToString(); | ||
| } | ||
| #endif | ||
| var powerShellExecutionHelper = context.Helper; | ||
| powerShellExecutionHelper | ||
| .AddCommandWithPreferenceSetting("Microsoft.PowerShell.Management\\Resolve-Path") | ||
|
|
@@ -4215,7 +4250,7 @@ internal static IEnumerable<CompletionResult> CompleteFilename(CompletionContext | |
| } | ||
|
|
||
| // Sorting the results by the path | ||
| var sortedPsobjs = psobjs.OrderBy(a => a, new ItemPathComparer()); | ||
| var sortedPsobjs = psobjs.OrderBy(a => a, new ItemPathComparer(wordToComplete)); | ||
|
|
||
| foreach (PSObject psobj in sortedPsobjs) | ||
| { | ||
|
|
@@ -6637,6 +6672,13 @@ internal static bool IsAmpersandNeeded(CompletionContext context, bool defaultCh | |
|
|
||
| private class ItemPathComparer : IComparer<PSObject> | ||
| { | ||
| private String _baseWord; | ||
|
|
||
| public ItemPathComparer(String baseWord) | ||
| { | ||
| _baseWord = baseWord + ".*"; | ||
| } | ||
|
|
||
| public int Compare(PSObject x, PSObject y) | ||
| { | ||
| var xPathInfo = PSObject.Base(x) as PathInfo; | ||
|
|
@@ -6666,7 +6708,21 @@ public int Compare(PSObject x, PSObject y) | |
| if (string.IsNullOrEmpty(xPath) || string.IsNullOrEmpty(yPath)) | ||
| Diagnostics.Assert(false, "Base object of item PSObject should be either PathInfo or FileSystemInfo"); | ||
|
|
||
| return String.Compare(xPath, yPath, StringComparison.CurrentCultureIgnoreCase); | ||
| var result = String.Compare(xPath, yPath, StringComparison.CurrentCultureIgnoreCase); | ||
| #if UNIX | ||
| if (result == 0) | ||
| { | ||
| if (Regex.IsMatch(xPath, _baseWord)) | ||
| { | ||
| return -1; | ||
| } | ||
| else | ||
| { | ||
| return 1; | ||
| } | ||
| } | ||
| #endif | ||
| return result; | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like the code was correct before - only when we know we have -LiteralPath.