-
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
Make TabCompletion case-insensitive for file names on Unix #4699
Conversation
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.
I'd also love to see tests for the order of the completed options. The first one should be the one with a correct casing, if accessible. Otherwise, the UX would be pretty bad in the multiple casing cases.
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.
We use alphabetical sort with ignoring casing. I don't know how put an object with correct casing on first place. It looks you request creating very complex sorting.
Do anybody really create multiple files/directories with different casing on Unix?
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 is very common to have both Makefile and makefile.
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 is only one extra press.
I have no idea how to make this weighted sort by simple way 😕
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.
Not exactly simple, but sort insensitive, then compare each element to it's successor in a case sensitive manner, swapping to get case correct first.
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.
Sample 1:
wordToComplete = "aB"
Input:
abcd
aBcd
abde
aBde
Result:
aBcd
aBde
abcd
abde
Sample 2:
wordToComplete = "aB*D"
Input:
abcdef
aBCDef
abcdgh
aBcDgh
Result:
aBCDef
aBcDgh
abcdef
abcdgh
-- If we want the results the sort is not simple as seems - we must take into account wildcards.
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.
Maybe:
- Get a case-sensitive array and sort it
- Get a case-insensitive array and sort it
- Remove elements of (1) array remove from (2) array
- Add elements of (2) array after end of (1) array
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.
I would:
- Case-insensitive array sort
- For each element, compare case insensitive with the next element, if they are equal (should be rare), do a case sensitive wildcard match with the original word to complete to determine the ordering of these 2 elements, swapping if the first fails to match and the second does.
This should be O(n) with an upper bound of 2n, so it's cheaper than 2 sorts.
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.
Is my sample 2 right? If so your suggestion don't work for it. We get:
Result:
aBcd
abcd
aBde
abde
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.
I'm not sure there is a right and wrong result here - only a least surprising, and I think my suggestion prefers case insensitive over the wildcard match which is less surprising, but still orders with some case sensitivity.
At any rate, real world experience will guide us best - try and keep it simple and handle the Makefile/makefile case nicely, and we'll see if it's sufficient.
lzybkr
left a comment
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.
I think we'll want this as an option (on by default).
Options are not really documented or formalized, but see uses of
PowerShell/src/System.Management.Automation/engine/CommandCompletion/CompletionAnalysis.cs
Line 38 in dc399a1
| internal bool GetOption(string option, bool @default) |
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.
You don't need to call ToCharArray - that will unnecessarily create an array.
In C#, strings are enumerable, so you would just use foreach (var ch in wordToComplete) ....
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.
First I made a prototype on PowerShell. :-)
Fixed.
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.
You can reasonably assume all characters are letters and pass wordToComplete.Length * 4 when constructing the string builder to avoid growing and copying the buffer.
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.
Thanks! Fixed.
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.
I'm no expert in Unicode - but I can imagine there are letters that have no upper/lowercase variants, so I would avoid the wildcard if ToUpper == ToLower.
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.
German ß for example doesn't have upper in dotnet. (The correct capitalization is probably SS, but dotnet doesn't seem to do it, same as python 2.)
Also the Turkish I is a classical example: if default locale is used, then lower-cased I will be different. We probably can skip these details as a first implementation.
Note that [aa] is a valid regex.
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.
Thanks! Fixed.
526ef53 to
bfa1b17
Compare
|
Options was added. |
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.
Remove, but it might be worth a comment saying we assume wordToComplete is already a wildcard pattern and do not want to escape anything.
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.
Removed.
Comment added above in line 4114.
Previous I removed there if useLiteralPath - Please clarify the if - it seems we should
(1) always escape '[' and ']'
(2) escape StarOrQuestion for useLiteralPath but we did not this previous and don't now.
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.
The word to complete is usually a wildcard pattern (unless the filename specifies -LiteralPath, but I don't think we do that today).
So I think it's probably best to not escape anything. It is probably uncommon to use tab completion and square brackets together, but I'm sure I've done it before, so it might feel broken.
This does mean you need to detect letters inside square brackets and ignore those.
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.
So we leave as is now and add escape StarOrQuestion for useLiteralPath when we'll need?
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.
Yeah, except I missed the code above that already does that, except you changed it.
In reply to: 136893930 [](ancestors = 136893930)
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.
Not used now, right?
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.
Removed.
|
One MacOs test failed - I have no opportunity to debug 😕 @vors could you help? Update: MacOs have |
c1b300c to
352f380
Compare
7012631 to
6f3b842
Compare
vors
left a comment
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.
- prefer exact case match in the completion order.
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.
0465ccb to
10abc8f
Compare
|
@vors Could you please build and check that we have case match. |
3c69681 to
801af60
Compare
|
@iSazonov order doesn't prefer the original casing from my experiments on macOS |
985e11c to
3e60212
Compare
3e60212 to
801af60
Compare
|
@vors @lzybkr |
|
couple thoughts: order really matters only for a common case (no wildcards). If that is still hard, we can merge it without reordering and improve it later, if this behavior is guarded by an option flag. |
801af60 to
fb1eb1b
Compare
|
I wonder can we use |
|
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. |
|
This PR has be automatically close because it is stale. If you wish to continue working on the PR, please first update the PR, then reopen it. |
PR Summary
Attempt to fix #1273
PR Checklist
.h,.cpp,.cs,.ps1and.psm1files have the correct copyright headerWIP:to the beginning of the title and remove the prefix when the PR is ready.[feature]if the change is significant or affects feature tests