-
Notifications
You must be signed in to change notification settings - Fork 29.3k
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
add terminal completions for other shell types #233776
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: Daniel Imms <[email protected]>
src/vs/workbench/contrib/terminalContrib/suggest/browser/pwshCompletionProviderAddon.ts
Outdated
Show resolved
Hide resolved
…ompletionProviderAddon.ts
Think I finally figured out the bundling issue It did not like this
But changing the |
looks like some tests are failing / leaking disposables now... looking into it |
You might need to hard code all the imports for now? I'm not sure how dynamic imports work with extensions. |
# Node npm | ||
|
||
**Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled. | ||
|
||
## Features | ||
|
||
### Terminal suggest | ||
|
||
Provides terminal suggestions for zsh and bash |
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.
"@fig/autocomplete-generators": "^2.4.0", | ||
"find-up": "^5.0.0", | ||
"find-yarn-workspace-root": "^2.0.0", | ||
"jsonc-parser": "^3.2.0", | ||
"minimatch": "^5.1.6", | ||
"request-light": "^0.7.0", | ||
"vscode-uri": "^3.0.8", | ||
"which": "^4.0.0", | ||
"which-pm": "^2.1.1" |
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.
Do we need all these?
const enableExtensionCompletions = this._configurationService.getValue<ITerminalSuggestConfiguration>(terminalSuggestConfigSection).enableExtensionCompletions; | ||
if (enableExtensionCompletions && !this._hasActivatedExtensions) { | ||
await this._extensionService.activateByEvent('onTerminalCompletionsRequested'); | ||
this._hasActivatedExtensions = true; | ||
} |
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.
Do we need to always activate this event? If the user requests completions, then installs an extension, it will remain deactivated currently I think?
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 see a bunch of listeners in _registerExtensionListeners now, but can we just fire the activation event and do away with that?
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.
no because if you restart the extension host for example, it won't get reset so it won't get activated without the listeners?
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.
Even if you just call activate every time? I thought that's how it's done everywhere else, as opposed to trying to cover all the cases like you're doing here?
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 other places just activate every time
} | ||
|
||
export const terminalSuggestConfiguration: IStringDictionary<IConfigurationPropertySchema> = { | ||
[TerminalSuggestSettingId.Enabled]: { | ||
restricted: true, | ||
markdownDescription: localize('suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells ({0}) when {1} is set to {2}.\n\nIf shell integration is installed manually, {3} needs to be set to {4} before calling the shell integration script.", 'PowerShell v7+', `\`#${TerminalSettingId.ShellIntegrationEnabled}#\``, '`true`', '`VSCODE_SUGGEST`', '`1`'), | ||
markdownDescription: localize('suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells ({0}) when {1} is set to {2}.\n\nIf shell integration is installed manually, {3} needs to be set to {4} before calling the shell integration script. \n\nFor zsh and bash completions, {5} will also need to be set.", 'PowerShell v7+, zsh, bash', `\`#${TerminalSettingId.ShellIntegrationEnabled}#\``, '`true`', '`VSCODE_SUGGEST`', '`1`', `\`#${TerminalSuggestSettingId.EnableExtensionCompletions}#\``), | ||
type: 'boolean', | ||
default: false, |
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 should add experimental to this too
// scored. If word is undefined, then match against the empty string. | ||
item.word = word || ''; |
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.
If word could be undefined wouldn't it throw above when word.length
is called?
// TODO: Use Promise.all so all providers are called in parallel | ||
for (const providerMap of this._providers.values()) { | ||
for (const [extensionId, provider] of providerMap) { | ||
const collectCompletions = async (providers: ITerminalCompletionProvider[]) => { |
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.
Pull into private member function?
@@ -57,31 +63,46 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo | |||
}); | |||
} | |||
|
|||
async provideCompletions(promptValue: string, cursorPosition: number, shellType: TerminalShellType): Promise<ISimpleCompletion[] | undefined> { | |||
async provideCompletions(promptValue: string, cursorPosition: number, shellType: TerminalShellType, token: CancellationToken, triggeredProviders?: ITerminalCompletionProvider[]): Promise<ISimpleCompletion[] | undefined> { |
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.
Passing in triggeredProviders here is a little confusing. Could we not allow the terminal completion service complete control over what providers are used?
} | ||
|
||
export interface ITerminalCompletionService { | ||
_serviceBrand: undefined; | ||
providers: ITerminalCompletionProvider[]; |
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.
providers: ITerminalCompletionProvider[]; | |
readonly providers: ITerminalCompletionProvider[]; |
export class TerminalCompletionService extends Disposable implements ITerminalCompletionService { | ||
declare _serviceBrand: undefined; | ||
private readonly _providers: Map</*ext id*/string, Map</*provider id*/string, ITerminalCompletionProvider>> = new Map(); | ||
get providers() { return [...this._providers.values()].flatMap(providerMap => [...providerMap.values()]); } |
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.
A generator would be preferable here
@@ -165,13 +164,13 @@ export class SimpleCompletionModel { | |||
} else { | |||
// by default match `word` against the `label` | |||
const match = scoreFn(word, wordLow, wordPos, item.completion.label, item.labelLow, 0, this._fuzzyScoreOptions); | |||
if (!match) { | |||
if (!match && word !== '') { |
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 sure why this was needed?
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.
match is undefined if the prompt is empty. this is part of the fix for #233805
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.
This worked before in pwsh fine though 🤔
I reverted the tsconfig change for now so you can test in oss |
fixes #233805
fixes #226562
Done:
npm i
to reduce size ofpackage-lock.json
TODOs
with issues