Skip to content

Commit af8814e

Browse files
authored
Merge pull request microsoft#250694 from microsoft/copilot/fix-248415
Terminal suggest: Boost `main` and `master` in branch results
2 parents ac8b3ac + 3415492 commit af8814e

File tree

2 files changed

+98
-1
lines changed

2 files changed

+98
-1
lines changed

src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalCompletionModel.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,23 @@ const compareCompletionsFn = (leadingLineContent: string, a: TerminalCompletionI
8181
}
8282
}
8383

84+
// Boost main and master branches for git commands
85+
// HACK: Currently this just matches leading line content, it should eventually check the
86+
// completion type is a branch
87+
if (a.completion.kind === TerminalCompletionItemKind.Argument && b.completion.kind === TerminalCompletionItemKind.Argument && /^\s*git\b/.test(leadingLineContent)) {
88+
const aLabel = typeof a.completion.label === 'string' ? a.completion.label : a.completion.label.label;
89+
const bLabel = typeof b.completion.label === 'string' ? b.completion.label : b.completion.label.label;
90+
const aIsMainOrMaster = aLabel === 'main' || aLabel === 'master';
91+
const bIsMainOrMaster = bLabel === 'main' || bLabel === 'master';
92+
93+
if (aIsMainOrMaster && !bIsMainOrMaster) {
94+
return -1;
95+
}
96+
if (bIsMainOrMaster && !aIsMainOrMaster) {
97+
return 1;
98+
}
99+
}
100+
84101
// Sort by more detailed completions
85102
if (a.completion.kind === TerminalCompletionItemKind.Method && b.completion.kind === TerminalCompletionItemKind.Method) {
86103
if (typeof a.completion.label !== 'string' && a.completion.label.description && typeof b.completion.label !== 'string' && b.completion.label.description) {

src/vs/workbench/contrib/terminalContrib/suggest/test/browser/terminalCompletionModel.test.ts

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../../base/
77
import { TerminalCompletionModel } from '../../browser/terminalCompletionModel.js';
88
import { LineContext } from '../../../../../services/suggest/browser/simpleCompletionModel.js';
99
import { TerminalCompletionItem, TerminalCompletionItemKind, type ITerminalCompletion } from '../../browser/terminalCompletionItem.js';
10+
import type { CompletionItemLabel } from '../../../../../services/suggest/browser/simpleCompletionItem.js';
1011

1112
function createItem(options: Partial<ITerminalCompletion>): TerminalCompletionItem {
1213
return new TerminalCompletionItem({
@@ -41,7 +42,7 @@ function createFolderItemsModel(...labels: string[]): TerminalCompletionModel {
4142
);
4243
}
4344

44-
function assertItems(model: TerminalCompletionModel, labels: string[]): void {
45+
function assertItems(model: TerminalCompletionModel, labels: (string | CompletionItemLabel)[]): void {
4546
assert.deepStrictEqual(model.items.map(i => i.completion.label), labels);
4647
assert.strictEqual(model.items.length, labels.length); // sanity check
4748
}
@@ -296,4 +297,83 @@ suite('TerminalCompletionModel', function () {
296297

297298

298299
});
300+
301+
suite('git branch priority sorting', () => {
302+
test('should prioritize main and master branches for git commands', () => {
303+
const items = [
304+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'feature-branch' }),
305+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'master' }),
306+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'development' }),
307+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'main' })
308+
];
309+
const model = new TerminalCompletionModel(items, new LineContext('git checkout ', 0));
310+
assertItems(model, ['main', 'master', 'development', 'feature-branch']);
311+
});
312+
313+
test('should prioritize main and master branches for git switch command', () => {
314+
const items = [
315+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'feature-branch' }),
316+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'main' }),
317+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'another-feature' }),
318+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'master' })
319+
];
320+
const model = new TerminalCompletionModel(items, new LineContext('git switch ', 0));
321+
assertItems(model, ['main', 'master', 'another-feature', 'feature-branch']);
322+
});
323+
324+
test('should not prioritize main and master for non-git commands', () => {
325+
const items = [
326+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'feature-branch' }),
327+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'master' }),
328+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'main' })
329+
];
330+
const model = new TerminalCompletionModel(items, new LineContext('ls ', 0));
331+
assertItems(model, ['feature-branch', 'main', 'master']);
332+
});
333+
334+
test('should handle git commands with leading whitespace', () => {
335+
const items = [
336+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'feature-branch' }),
337+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'master' }),
338+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'main' })
339+
];
340+
const model = new TerminalCompletionModel(items, new LineContext(' git checkout ', 0));
341+
assertItems(model, ['main', 'master', 'feature-branch']);
342+
});
343+
344+
test('should work with complex label objects', () => {
345+
const items = [
346+
createItem({ kind: TerminalCompletionItemKind.Argument, label: { label: 'feature-branch', description: 'Feature branch' } }),
347+
createItem({ kind: TerminalCompletionItemKind.Argument, label: { label: 'master', description: 'Master branch' } }),
348+
createItem({ kind: TerminalCompletionItemKind.Argument, label: { label: 'main', description: 'Main branch' } })
349+
];
350+
const model = new TerminalCompletionModel(items, new LineContext('git checkout ', 0));
351+
assertItems(model, [
352+
{ label: "main", description: "Main branch" },
353+
{ label: "master", description: "Master branch" },
354+
{ label: "feature-branch", description: "Feature branch" },
355+
]);
356+
});
357+
358+
test('should not prioritize branches with similar names', () => {
359+
const items = [
360+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'mainline' }),
361+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'masterpiece' }),
362+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'main' }),
363+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'master' })
364+
];
365+
const model = new TerminalCompletionModel(items, new LineContext('git checkout ', 0));
366+
assertItems(model, ['main', 'master', 'mainline', 'masterpiece']);
367+
});
368+
369+
test('should prioritize for git branch -d', () => {
370+
const items = [
371+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'main' }),
372+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'master' }),
373+
createItem({ kind: TerminalCompletionItemKind.Argument, label: 'dev' })
374+
];
375+
const model = new TerminalCompletionModel(items, new LineContext('git branch -d ', 0));
376+
assertItems(model, ['main', 'master', 'dev']);
377+
});
378+
});
299379
});

0 commit comments

Comments
 (0)