Skip to content

Commit 4e144a1

Browse files
authored
tweak terminal suggest sorting for files/folders (microsoft#239145)
1 parent a0a4332 commit 4e144a1

File tree

4 files changed

+49
-95
lines changed

4 files changed

+49
-95
lines changed

src/vs/workbench/contrib/terminalContrib/suggest/test/browser/recordings/windows11_pwsh_single_char.ts

Lines changed: 0 additions & 88 deletions
This file was deleted.

src/vs/workbench/contrib/terminalContrib/suggest/test/browser/terminalSuggestAddon.integrationTest.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import { events as windows11_pwsh_filename_same_case_change_forward_slash } from
3535
import { events as windows11_pwsh_getcontent_delete_ghost } from './recordings/windows11_pwsh_getcontent_delete_ghost.js';
3636
import { events as windows11_pwsh_input_ls_complete_ls } from './recordings/windows11_pwsh_input_ls_complete_ls.js';
3737
import { events as windows11_pwsh_namespace_same_prefix } from './recordings/windows11_pwsh_namespace_same_prefix.js';
38-
import { events as windows11_pwsh_single_char } from './recordings/windows11_pwsh_single_char.js';
3938
import { events as windows11_pwsh_type_before_prompt } from './recordings/windows11_pwsh_type_before_prompt.js';
4039
import { events as windows11_pwsh_writehost_multiline } from './recordings/windows11_pwsh_writehost_multiline.js';
4140
import { events as windows11_pwsh_writehost_multiline_nav_up } from './recordings/windows11_pwsh_writehost_multiline_nav_up.js';
@@ -60,7 +59,6 @@ const recordedTestCases: { name: string; events: RecordedSessionEvent[] }[] = [
6059
{ name: 'windows11_pwsh_getcontent_delete_ghost', events: windows11_pwsh_getcontent_delete_ghost as any as RecordedSessionEvent[] },
6160
{ name: 'windows11_pwsh_input_ls_complete_ls', events: windows11_pwsh_input_ls_complete_ls as any as RecordedSessionEvent[] },
6261
{ name: 'windows11_pwsh_namespace_same_prefix', events: windows11_pwsh_namespace_same_prefix as any as RecordedSessionEvent[] },
63-
{ name: 'windows11_pwsh_single_char', events: windows11_pwsh_single_char as any as RecordedSessionEvent[] },
6462
{ name: 'windows11_pwsh_type_before_prompt', events: windows11_pwsh_type_before_prompt as any as RecordedSessionEvent[] },
6563
{ name: 'windows11_pwsh_writehost_multiline_nav_up', events: windows11_pwsh_writehost_multiline_nav_up as any as RecordedSessionEvent[] },
6664
{ name: 'windows11_pwsh_writehost_multiline', events: windows11_pwsh_writehost_multiline as any as RecordedSessionEvent[] },

src/vs/workbench/services/suggest/browser/simpleCompletionItem.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,25 @@ export interface ISimpleCompletion {
5757
}
5858

5959
export class SimpleCompletionItem {
60-
// perf
60+
/**
61+
* The lowercase label, normalized to `\` path separators on Windows.
62+
*/
6163
readonly labelLow: string;
64+
65+
/**
66+
* {@link labelLow} without the file extension.
67+
*/
6268
readonly labelLowExcludeFileExt: string;
69+
70+
/**
71+
* The lowercase label, when the completion is a file or directory this has normalized path
72+
* separators (/) on Windows and no trailing separator for directories.
73+
*/
74+
readonly labelLowNormalizedPath: string;
75+
76+
/**
77+
* The file extension part from {@link labelLow}.
78+
*/
6379
readonly fileExtLow: string = '';
6480

6581
// sorting, filtering
@@ -73,6 +89,8 @@ export class SimpleCompletionItem {
7389
// ensure lower-variants (perf)
7490
this.labelLow = this.completion.label.toLowerCase();
7591
this.labelLowExcludeFileExt = this.labelLow;
92+
this.labelLowNormalizedPath = this.labelLow;
93+
7694
if (completion.isFile) {
7795
if (isWindows) {
7896
this.labelLow = this.labelLow.replaceAll('/', '\\');
@@ -83,5 +101,14 @@ export class SimpleCompletionItem {
83101
this.fileExtLow = this.labelLow.substring(extIndex + 1);
84102
}
85103
}
104+
105+
if (completion.isFile || completion.isDirectory) {
106+
if (isWindows) {
107+
this.labelLowNormalizedPath = this.labelLow.replaceAll('\\', '/');
108+
}
109+
if (completion.isDirectory) {
110+
this.labelLowNormalizedPath = this.labelLowNormalizedPath.replace(/\/$/, '');
111+
}
112+
}
86113
}
87114
}

src/vs/workbench/services/suggest/browser/simpleCompletionModel.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { quickSelect } from '../../../../base/common/arrays.js';
88
import { CharCode } from '../../../../base/common/charCode.js';
99
import { FuzzyScore, fuzzyScore, fuzzyScoreGracefulAggressive, FuzzyScoreOptions, FuzzyScorer } from '../../../../base/common/filters.js';
1010
import { isWindows } from '../../../../base/common/platform.js';
11+
import { count } from '../../../../base/common/strings.js';
1112

1213
export interface ISimpleCompletionStats {
1314
pLabelLen: number;
@@ -207,12 +208,28 @@ export class SimpleCompletionModel {
207208
}
208209
// Then by file extension length ascending
209210
score = a.fileExtLow.length - b.fileExtLow.length;
211+
if (score !== 0) {
212+
return score;
213+
}
210214
}
211-
if (score === 0 || fileExtScore(a.fileExtLow) === 0 && fileExtScore(b.fileExtLow) === 0) {
212-
// both files or directories, sort alphabetically
213-
score = a.completion.label.localeCompare(b.completion.label);
215+
if (a.labelLowNormalizedPath && b.labelLowNormalizedPath) {
216+
// Directories
217+
// Count depth of path (number of / or \ occurrences)
218+
score = count(a.labelLowNormalizedPath, '/') - count(b.labelLowNormalizedPath, '/');
219+
if (score !== 0) {
220+
return score;
221+
}
222+
223+
// Ensure shorter prefixes appear first
224+
if (b.labelLowNormalizedPath.startsWith(a.labelLowNormalizedPath)) {
225+
return -1; // `a` is a prefix of `b`, so `a` should come first
226+
}
227+
if (a.labelLowNormalizedPath.startsWith(b.labelLowNormalizedPath)) {
228+
return 1; // `b` is a prefix of `a`, so `b` should come first
229+
}
214230
}
215-
return score;
231+
// Sort alphabetically
232+
return a.labelLow.localeCompare(b.labelLow);
216233
});
217234
this._refilterKind = Refilter.Nothing;
218235

0 commit comments

Comments
 (0)