From a51801b4654c5b38472d6142a494a56fb6640225 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 1 Apr 2022 11:02:02 +0530 Subject: align extension scanning - Extract extension scanning, validating and nls replacement into `INativeExtensionsScannerService` - Use `INativeExtensionsScannerService` for scanning in Desktop and Remote extension managements and extension hosts - Represent invalid extensions in Extensions UI - Remove prompting for invalid extensions while scanning in Desktop Extension Host in Dev mode --- src/vs/workbench/contrib/extensions/browser/extensionsActions.ts | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 2de5c8e1411..31f4499b9de 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -2348,6 +2348,11 @@ export class ExtensionStatusAction extends ExtensionAction { } } + if (isEnabled && !isRunning && !this.extension.local.isValid) { + const errors = this.extension.local.validations.filter(v => v.severity === Severity.Error).map(v => v.message); + this.updateStatus({ icon: errorIcon, message: new MarkdownString(errors.join(' ').trim()) }, true); + } + } private updateStatus(status: ExtensionStatus | undefined, updateClass: boolean): void { -- cgit v1.2.3 From 424cc864b537c39c57de68c8a2564595a16ab8ea Mon Sep 17 00:00:00 2001 From: Leonardo Montini Date: Fri, 1 Apr 2022 15:06:08 +0200 Subject: 143543 replaced true and false with on and off in debug.inlineValues --- src/vs/workbench/contrib/debug/browser/debug.contribution.ts | 2 +- src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts | 2 +- src/vs/workbench/contrib/debug/common/debug.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 11f4ef0ce63..8330e2aab7c 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -419,7 +419,7 @@ configurationRegistry.registerConfiguration({ }, 'debug.inlineValues': { type: ['boolean', 'string'], - 'enum': [true, false, 'auto'], + 'enum': ['on', 'off', 'auto'], description: nls.localize({ comment: ['This is the description for a setting'], key: 'inlineValues' }, "Show variable values inline in editor while debugging."), 'enumDescriptions': [ nls.localize('inlineValues.on', 'Always show variable values inline in editor while debugging.'), diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts index 81133f8fade..a0fbf2da5a1 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts @@ -627,7 +627,7 @@ export class DebugEditorContribution implements IDebugEditorContribution { const model = this.editor.getModel(); const inlineValuesSetting = this.configurationService.getValue('debug').inlineValues; - const inlineValuesTurnedOn = inlineValuesSetting === true || (inlineValuesSetting === 'auto' && model && this.languageFeaturesService.inlineValuesProvider.has(model)); + const inlineValuesTurnedOn = inlineValuesSetting === true || inlineValuesSetting === 'on' || (inlineValuesSetting === 'auto' && model && this.languageFeaturesService.inlineValuesProvider.has(model)); if (!inlineValuesTurnedOn || !model || !stackFrame || model.uri.toString() !== stackFrame.source.uri.toString()) { if (!this.removeInlineValuesScheduler.isScheduled()) { this.removeInlineValuesScheduler.schedule(); diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 7fd322d2d11..be21bf957ef 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -611,7 +611,7 @@ export interface IDebugConfiguration { allowBreakpointsEverywhere: boolean; openDebug: 'neverOpen' | 'openOnSessionStart' | 'openOnFirstSessionStart' | 'openOnDebugBreak'; openExplorerOnEnd: boolean; - inlineValues: boolean | 'auto'; + inlineValues: boolean | 'auto' | 'on' | 'off'; toolBarLocation: 'floating' | 'docked' | 'hidden'; showInStatusBar: 'never' | 'always' | 'onFirstSessionStart'; internalConsoleOptions: 'neverOpen' | 'openOnSessionStart' | 'openOnFirstSessionStart'; -- cgit v1.2.3 From 6e1e0b1d899b2d262265e8faeadee98c562cfe7b Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Fri, 1 Apr 2022 17:35:06 +0200 Subject: Moves tokenization logic from text model to its own text model part. --- src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditTree.ts | 4 ++-- src/vs/workbench/contrib/debug/browser/debugEditorActions.ts | 2 +- src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts | 4 ++-- src/vs/workbench/contrib/debug/browser/repl.ts | 2 +- src/vs/workbench/contrib/emmet/browser/emmetActions.ts | 2 +- .../contrib/extensions/browser/extensionsCompletionItemsProvider.ts | 2 +- .../contrib/notebook/browser/view/cellParts/cellDragRenderer.ts | 2 +- src/vs/workbench/contrib/search/browser/searchView.ts | 2 +- src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts | 2 +- src/vs/workbench/contrib/snippets/browser/insertSnippet.ts | 2 +- .../workbench/contrib/snippets/browser/snippetCompletionProvider.ts | 4 ++-- src/vs/workbench/contrib/snippets/browser/surroundWithSnippet.ts | 2 +- src/vs/workbench/contrib/snippets/browser/tabCompletion.ts | 2 +- 13 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditTree.ts b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditTree.ts index c796f5e0ce4..ca1856c6312 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditTree.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditTree.ts @@ -227,14 +227,14 @@ export class BulkEditDataSource implements IAsyncDataSource= 0; idx--) { prefixLen = range.startColumn - startTokens.getStartOffset(idx); } //suffix-math - let endTokens = textModel.getLineTokens(range.endLineNumber); + let endTokens = textModel.tokenization.getLineTokens(range.endLineNumber); let suffixLen = 0; for (let idx = endTokens.findTokenIndexAtOffset(range.endColumn); suffixLen < 50 && idx < endTokens.getCount(); idx++) { suffixLen += endTokens.getEndOffset(idx) - endTokens.getStartOffset(idx); diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts index bcb3748c6a1..04dd1f1b1fe 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts @@ -313,7 +313,7 @@ class ShowDebugHoverAction extends EditorAction { if (!position || !editor.hasModel()) { return; } - const word = editor.getModel().getWordAtPosition(position); + const word = editor.getModel().tokenization.getWordAtPosition(position); if (!word) { return; } diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts index 81133f8fade..ee581fd735b 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts @@ -179,8 +179,8 @@ function getWordToLineNumbersMap(model: ITextModel | null): Map => { const getWordRangeAtPosition = (model: ITextModel, position: Position): Range | null => { - const wordAtPosition = model.getWordAtPosition(position); + const wordAtPosition = model.tokenization.getWordAtPosition(position); return wordAtPosition ? new Range(position.lineNumber, wordAtPosition.startColumn, position.lineNumber, wordAtPosition.endColumn) : null; }; diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDragRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDragRenderer.ts index 46388b581b4..43c5852753e 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDragRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDragRenderer.ts @@ -65,7 +65,7 @@ class EditorTextRenderer { let result = ''; for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) { - const lineTokens = model.getLineTokens(lineNumber); + const lineTokens = model.tokenization.getLineTokens(lineNumber); const lineContent = lineTokens.getLineContent(); const startOffset = (lineNumber === startLineNumber ? startColumn - 1 : 0); const endOffset = (lineNumber === endLineNumber ? endColumn - 1 : lineContent.length); diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 90411d0caec..eddb57e8663 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -1160,7 +1160,7 @@ export class SearchView extends ViewPane { } if (range.isEmpty() && this.searchConfig.seedWithNearestWord && allowUnselectedWord) { - const wordAtPosition = editor.getModel().getWordAtPosition(range.getStartPosition()); + const wordAtPosition = editor.getModel().tokenization.getWordAtPosition(range.getStartPosition()); if (wordAtPosition) { return wordAtPosition.word; } diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts index 28e8b4fd1e5..76fa794a03a 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts @@ -127,7 +127,7 @@ export const openNewSearchEditor = selected = (selection && activeModel?.getModel()?.getValueInRange(selection)) ?? ''; if (selection?.isEmpty() && configurationService.getValue('search').seedWithNearestWord) { - const wordAtPosition = activeModel.getModel()?.getWordAtPosition(selection.getStartPosition()); + const wordAtPosition = activeModel.getModel()?.tokenization.getWordAtPosition(selection.getStartPosition()); if (wordAtPosition) { selected = wordAtPosition.word; } diff --git a/src/vs/workbench/contrib/snippets/browser/insertSnippet.ts b/src/vs/workbench/contrib/snippets/browser/insertSnippet.ts index 782cb1493fd..3a0088a1f48 100644 --- a/src/vs/workbench/contrib/snippets/browser/insertSnippet.ts +++ b/src/vs/workbench/contrib/snippets/browser/insertSnippet.ts @@ -112,7 +112,7 @@ class InsertSnippetAction extends EditorAction { } languageId = langId; } else { - editor.getModel().tokenizeIfCheap(lineNumber); + editor.getModel().tokenization.tokenizeIfCheap(lineNumber); languageId = editor.getModel().getLanguageIdAtPosition(lineNumber, column); // validate the `languageId` to ensure this is a user diff --git a/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts b/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts index aa6e96d9afe..b2b27cc1db9 100644 --- a/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts +++ b/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts @@ -73,7 +73,7 @@ export class SnippetCompletionProvider implements CompletionItemProvider { const snippets = new Set(await this._snippets.getSnippets(languageId)); const lineContentLow = model.getLineContent(position.lineNumber).toLowerCase(); - const wordUntil = model.getWordUntilPosition(position).word.toLowerCase(); + const wordUntil = model.tokenization.getWordUntilPosition(position).word.toLowerCase(); const suggestions: SnippetCompletion[] = []; const columnOffset = position.column - 1; @@ -182,7 +182,7 @@ export class SnippetCompletionProvider implements CompletionItemProvider { // validate the `languageId` to ensure this is a user // facing language with a name and the chance to have // snippets, else fall back to the outer language - model.tokenizeIfCheap(position.lineNumber); + model.tokenization.tokenizeIfCheap(position.lineNumber); let languageId = model.getLanguageIdAtPosition(position.lineNumber, position.column); if (!this._languageService.getLanguageName(languageId)) { languageId = model.getLanguageId(); diff --git a/src/vs/workbench/contrib/snippets/browser/surroundWithSnippet.ts b/src/vs/workbench/contrib/snippets/browser/surroundWithSnippet.ts index 96c1ecfc5a7..80d25b05968 100644 --- a/src/vs/workbench/contrib/snippets/browser/surroundWithSnippet.ts +++ b/src/vs/workbench/contrib/snippets/browser/surroundWithSnippet.ts @@ -38,7 +38,7 @@ registerAction2(class SurroundWithAction extends EditorAction2 { } const { lineNumber, column } = editor.getPosition(); - editor.getModel().tokenizeIfCheap(lineNumber); + editor.getModel().tokenization.tokenizeIfCheap(lineNumber); const languageId = editor.getModel().getLanguageIdAtPosition(lineNumber, column); const allSnippets = await snippetService.getSnippets(languageId, { includeNoPrefixSnippets: true, includeDisabledSnippets: true }); diff --git a/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts b/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts index 504da91fa71..0ed0cc9470b 100644 --- a/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts +++ b/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts @@ -91,7 +91,7 @@ export class TabCompletionController implements IEditorContribution { // lots of dance for getting the const selection = this._editor.getSelection(); const model = this._editor.getModel(); - model.tokenizeIfCheap(selection.positionLineNumber); + model.tokenization.tokenizeIfCheap(selection.positionLineNumber); const id = model.getLanguageIdAtPosition(selection.positionLineNumber, selection.positionColumn); const snippets = this._snippetService.getSnippetsSync(id); -- cgit v1.2.3 From 811917d3e416a907849fe71995d3be4deab229ca Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 1 Apr 2022 23:26:24 +0530 Subject: change validations to tuple array --- src/vs/workbench/contrib/extensions/browser/extensionsActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 31f4499b9de..ad81be89e2b 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -2349,7 +2349,7 @@ export class ExtensionStatusAction extends ExtensionAction { } if (isEnabled && !isRunning && !this.extension.local.isValid) { - const errors = this.extension.local.validations.filter(v => v.severity === Severity.Error).map(v => v.message); + const errors = this.extension.local.validations.filter(([severity]) => severity === Severity.Error).map(([, message]) => message); this.updateStatus({ icon: errorIcon, message: new MarkdownString(errors.join(' ').trim()) }, true); } -- cgit v1.2.3 From 56e31e29960681b728b783557a000a9881b0c204 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 4 Apr 2022 15:03:46 +0200 Subject: Fix typo --- .../workbench/contrib/comments/browser/commentThreadZoneWidget.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts index 151a49ffbb6..14ad6544915 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts @@ -85,7 +85,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget private readonly _globalToDispose = new DisposableStore(); private _commentThreadDisposables: IDisposable[] = []; private _contextKeyService: IContextKeyService; - private _scopedInstatiationService: IInstantiationService; + private _scopedInstantiationService: IInstantiationService; public get owner(): string { return this._owner; @@ -109,7 +109,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget super(editor, { keepEditorSelection: true }); this._contextKeyService = contextKeyService.createScoped(this.domNode); - this._scopedInstatiationService = instantiationService.createChild(new ServiceCollection( + this._scopedInstantiationService = instantiationService.createChild(new ServiceCollection( [IContextKeyService, this._contextKeyService] )); @@ -184,13 +184,13 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget protected _fillContainer(container: HTMLElement): void { this.setCssClass('review-widget'); - this._commentThreadWidget = this._scopedInstatiationService.createInstance( + this._commentThreadWidget = this._scopedInstantiationService.createInstance( CommentThreadWidget, container, this._owner, this.editor.getModel()!.uri, this._contextKeyService, - this._scopedInstatiationService, + this._scopedInstantiationService, this._commentThread as unknown as languages.CommentThread, this._pendingComment, { editor: this.editor }, -- cgit v1.2.3 From ac39fefe78edff4dccc4375ed29abb240dc71336 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Mon, 4 Apr 2022 09:17:37 -0700 Subject: use builtin so as to not break aliases in shell integration script (#146562) --- .../browser/media/shellIntegration-bash.sh | 30 +++++++++++----------- .../terminal/browser/media/shellIntegration.zsh | 30 +++++++++++----------- 2 files changed, 30 insertions(+), 30 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh index 5b7471bb284..f50ca67b01d 100755 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh @@ -21,48 +21,48 @@ else fi if [[ "$PROMPT_COMMAND" =~ .*(' '.*\;)|(\;.*' ').* ]]; then - echo -e "\033[1;33mShell integration cannot be activated due to complex PROMPT_COMMAND: $PROMPT_COMMAND\033[0m" + builtin echo -e "\033[1;33mShell integration cannot be activated due to complex PROMPT_COMMAND: $PROMPT_COMMAND\033[0m" VSCODE_SHELL_HIDE_WELCOME="" - return; + builtin return fi if [ -z "$VSCODE_SHELL_INTEGRATION" ]; then - return + builtin return fi __vsc_in_command_execution="1" __vsc_last_history_id=$(history 1 | awk '{print $1;}') __vsc_prompt_start() { - printf "\033]633;A\007" + builtin printf "\033]633;A\007" } __vsc_prompt_end() { - printf "\033]633;B\007" + builtin printf "\033]633;B\007" } __vsc_update_cwd() { - printf "\033]633;P;Cwd=%s\007" "$PWD" + builtin printf "\033]633;P;Cwd=%s\007" "$PWD" } __vsc_command_output_start() { - printf "\033]633;C\007" + builtin printf "\033]633;C\007" } __vsc_continuation_start() { - printf "\033]633;F\007" + builtin printf "\033]633;F\007" } __vsc_continuation_end() { - printf "\033]633;G\007" + builtin printf "\033]633;G\007" } __vsc_command_complete() { - local __vsc_history_id=$(history 1 | awk '{print $1;}') + local __vsc_history_id=$(builtin history 1 | awk '{print $1;}') if [[ "$__vsc_history_id" == "$__vsc_last_history_id" ]]; then - printf "\033]633;D\007" + builtin printf "\033]633;D\007" else - printf "\033]633;D;%s\007" "$__vsc_status" + builtin printf "\033]633;D;%s\007" "$__vsc_status" __vsc_last_history_id=$__vsc_history_id fi __vsc_update_cwd @@ -101,9 +101,9 @@ __vsc_prompt_cmd_original() { else IFS=' ' fi - read -ra ADDR <<<"$__vsc_original_prompt_command" + builtin read -ra ADDR <<<"$__vsc_original_prompt_command" for ((i = 0; i < ${#ADDR[@]}; i++)); do - eval ${ADDR[i]} + builtin eval ${ADDR[i]} done IFS='' __vsc_precmd @@ -130,7 +130,7 @@ fi trap '__vsc_preexec' DEBUG if [ -z "$VSCODE_SHELL_HIDE_WELCOME" ]; then - echo -e "\033[1;32mShell integration activated\033[0m" + builtin echo -e "\033[1;32mShell integration activated\033[0m" else VSCODE_SHELL_HIDE_WELCOME="" fi diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.zsh b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.zsh index be84dc9674f..cfba2786a3e 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.zsh +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.zsh @@ -2,11 +2,11 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. # --------------------------------------------------------------------------------------------- -autoload -Uz add-zsh-hook +builtin autoload -Uz add-zsh-hook # Now that the init script is running, unset ZDOTDIR to ensure ~/.zlogout runs as expected as well # as prevent problems that may occur if the user's init scripts depend on ZDOTDIR not being set. -unset ZDOTDIR +builtin unset ZDOTDIR # This variable allows the shell to both detect that VS Code's shell integration is enabled as well # as disable it by unsetting the variable. @@ -25,50 +25,50 @@ fi # Shell integration was disabled by the shell, exit without warning assuming either the shell has # explicitly disabled shell integration as it's incompatible or it implements the protocol. if [ -z "$VSCODE_SHELL_INTEGRATION" ]; then - return + builtin return fi __vsc_in_command_execution="1" __vsc_last_history_id=0 __vsc_prompt_start() { - printf "\033]633;A\007" + builtin printf "\033]633;A\007" } __vsc_prompt_end() { - printf "\033]633;B\007" + builtin printf "\033]633;B\007" } __vsc_update_cwd() { - printf "\033]633;P;Cwd=%s\007" "$PWD" + builtin printf "\033]633;P;Cwd=%s\007" "$PWD" } __vsc_command_output_start() { - printf "\033]633;C\007" + builtin printf "\033]633;C\007" } __vsc_continuation_start() { - printf "\033]633;F\007" + builtin printf "\033]633;F\007" } __vsc_continuation_end() { - printf "\033]633;G\007" + builtin printf "\033]633;G\007" } __vsc_right_prompt_start() { - printf "\033]633;H\007" + builtin printf "\033]633;H\007" } __vsc_right_prompt_end() { - printf "\033]633;I\007" + builtin printf "\033]633;I\007" } __vsc_command_complete() { - local __vsc_history_id=$(history | tail -n1 | awk '{print $1;}') + builtin local __vsc_history_id=$(builtin history | tail -n1 | awk '{print $1;}') if [[ "$__vsc_history_id" == "$__vsc_last_history_id" ]]; then - printf "\033]633;D\007" + builtin printf "\033]633;D\007" else - printf "\033]633;D;%s\007" "$__vsc_status" + builtin printf "\033]633;D;%s\007" "$__vsc_status" __vsc_last_history_id=$__vsc_history_id fi __vsc_update_cwd @@ -114,7 +114,7 @@ add-zsh-hook preexec __vsc_preexec # Show the welcome message if [ -z "${VSCODE_SHELL_HIDE_WELCOME-}" ]; then - echo "\033[1;32mShell integration activated\033[0m" + builtin echo "\033[1;32mShell integration activated\033[0m" else VSCODE_SHELL_HIDE_WELCOME="" fi -- cgit v1.2.3 From 151d616221db103dbf7902145abddc4b62bd7599 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 4 Apr 2022 11:56:41 -0700 Subject: Add comment --- src/vs/workbench/contrib/debug/common/debug.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index be21bf957ef..a811d3c40e8 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -611,7 +611,7 @@ export interface IDebugConfiguration { allowBreakpointsEverywhere: boolean; openDebug: 'neverOpen' | 'openOnSessionStart' | 'openOnFirstSessionStart' | 'openOnDebugBreak'; openExplorerOnEnd: boolean; - inlineValues: boolean | 'auto' | 'on' | 'off'; + inlineValues: boolean | 'auto' | 'on' | 'off'; // boolean for back-compat toolBarLocation: 'floating' | 'docked' | 'hidden'; showInStatusBar: 'never' | 'always' | 'onFirstSessionStart'; internalConsoleOptions: 'neverOpen' | 'openOnSessionStart' | 'openOnFirstSessionStart'; -- cgit v1.2.3 From ca0ac1aeb22d3db363c18aa84834fa1150de41d1 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 4 Apr 2022 12:17:48 -0700 Subject: fix #145917 --- .../workbench/contrib/terminal/browser/xterm/commandNavigationAddon.ts | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/commandNavigationAddon.ts b/src/vs/workbench/contrib/terminal/browser/xterm/commandNavigationAddon.ts index c7b911c633d..60d82f8436d 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/commandNavigationAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/commandNavigationAddon.ts @@ -34,6 +34,9 @@ export class CommandNavigationAddon extends Disposable implements ICommandTracke activate(terminal: Terminal): void { this._terminal = terminal; + this._terminal.onData(() => { + this._currentMarker = Boundary.Bottom; + }); } constructor( -- cgit v1.2.3 From 12f64a68ba92805f9f316eb57d64aa92203adad9 Mon Sep 17 00:00:00 2001 From: rebornix Date: Sun, 3 Apr 2022 11:02:07 -0700 Subject: faster CellFolding ctor. --- .../workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 02beef093cf..39026ca2aca 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -168,7 +168,7 @@ export class MarkupCellRenderer extends AbstractCellRenderer implements IListRen templateDisposables.add(scopedInstaService.createInstance(BetweenCellToolbar, this.notebookEditor, titleToolbarContainer, bottomCellContainer)), templateDisposables.add(scopedInstaService.createInstance(CellEditorStatusBar, this.notebookEditor, container, editorPart, undefined)), templateDisposables.add(new CellFocusIndicator(this.notebookEditor, titleToolbar, focusIndicatorTop, focusIndicatorLeft, focusIndicatorRight, focusIndicatorBottom)), - templateDisposables.add(scopedInstaService.createInstance(FoldedCellHint, this.notebookEditor, DOM.append(container, $('.notebook-folded-hint')))), + templateDisposables.add(new FoldedCellHint(this.notebookEditor, DOM.append(container, $('.notebook-folded-hint')))), templateDisposables.add(new CellDecorations(rootContainer, decorationContainer)), templateDisposables.add(scopedInstaService.createInstance(CellComments, this.notebookEditor, cellCommentPartContainer)), templateDisposables.add(new CollapsedCellInput(this.notebookEditor, cellInputCollapsedContainer)), -- cgit v1.2.3 From 23c7781b9f79f774387844fc75602bdac346dbdd Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Apr 2022 11:15:07 -0700 Subject: Create drop into editor contribition Will use this to add a default implementation and other features for drop into editor --- .../browser/dropIntoEditor.contibution.ts | 92 ++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/vs/workbench/contrib/dropIntoEditor/browser/dropIntoEditor.contibution.ts (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/dropIntoEditor/browser/dropIntoEditor.contibution.ts b/src/vs/workbench/contrib/dropIntoEditor/browser/dropIntoEditor.contibution.ts new file mode 100644 index 00000000000..281d2523b99 --- /dev/null +++ b/src/vs/workbench/contrib/dropIntoEditor/browser/dropIntoEditor.contibution.ts @@ -0,0 +1,92 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { distinct } from 'vs/base/common/arrays'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { Mimes } from 'vs/base/common/mime'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; +import { IPosition } from 'vs/editor/common/core/position'; +import { IEditorContribution } from 'vs/editor/common/editorCommon'; +import { IDataTransferItem } from 'vs/editor/common/languages'; +import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; +import { performSnippetEdit } from 'vs/editor/contrib/snippet/browser/snippetController2'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { extractEditorsDropData } from 'vs/workbench/browser/dnd'; +import { IDataTransfer } from 'vs/workbench/common/dnd'; + + +export class DropIntoEditorController extends Disposable implements IEditorContribution { + + public static readonly ID = 'editor.contrib.dropIntoEditorController'; + + constructor( + editor: ICodeEditor, + @IInstantiationService private readonly _instantiationService: IInstantiationService, + @ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService, + ) { + super(); + + editor.onDropIntoEditor(e => this.onDropIntoEditor(editor, e.position, e.event)); + } + + private async onDropIntoEditor(editor: ICodeEditor, position: IPosition, dragEvent: DragEvent) { + if (!dragEvent.dataTransfer || !editor.hasModel()) { + return; + } + + const model = editor.getModel(); + const modelVersionNow = model.getVersionId(); + + const textEditorDataTransfer: IDataTransfer = new Map(); + for (const item of dragEvent.dataTransfer.items) { + if (item.kind === 'string') { + const type = item.type; + const asStringValue = new Promise(resolve => item.getAsString(resolve)); + textEditorDataTransfer.set(type, { + asString: () => asStringValue, + value: undefined + }); + } + } + + if (!textEditorDataTransfer.has(Mimes.uriList.toLowerCase())) { + const editorData = (await this._instantiationService.invokeFunction(extractEditorsDropData, dragEvent)) + .filter(input => input.resource) + .map(input => input.resource!.toString()); + + if (editorData.length) { + const str = distinct(editorData).join('\n'); + textEditorDataTransfer.set(Mimes.uriList.toLowerCase(), { + asString: () => Promise.resolve(str), + value: undefined + }); + } + } + + if (textEditorDataTransfer.size === 0) { + return; + } + + const ordered = this._languageFeaturesService.documentOnDropEditProvider.ordered(model); + for (const provider of ordered) { + const edit = await provider.provideDocumentOnDropEdits(model, position, textEditorDataTransfer, CancellationToken.None); + if (editor.getModel().getVersionId() !== modelVersionNow) { + return; + } + + if (edit) { + performSnippetEdit(editor, edit); + return; + } + } + + // TODO: default drop behavior + } +} + + +registerEditorContribution(DropIntoEditorController.ID, DropIntoEditorController); -- cgit v1.2.3 From 8c7b28ca7404f87ff7271ed10f4e0a6bbaff35e1 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Apr 2022 11:18:08 -0700 Subject: Add some basic cancelation --- .../dropIntoEditor/browser/dropIntoEditor.contibution.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/dropIntoEditor/browser/dropIntoEditor.contibution.ts b/src/vs/workbench/contrib/dropIntoEditor/browser/dropIntoEditor.contibution.ts index 281d2523b99..e882d9fa58a 100644 --- a/src/vs/workbench/contrib/dropIntoEditor/browser/dropIntoEditor.contibution.ts +++ b/src/vs/workbench/contrib/dropIntoEditor/browser/dropIntoEditor.contibution.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { distinct } from 'vs/base/common/arrays'; -import { CancellationToken } from 'vs/base/common/cancellation'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { Disposable } from 'vs/base/common/lifecycle'; import { Mimes } from 'vs/base/common/mime'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -71,10 +71,18 @@ export class DropIntoEditorController extends Disposable implements IEditorContr return; } + if (editor.getModel().getVersionId() !== modelVersionNow) { + return; + } + + const cts = new CancellationTokenSource(); + editor.onDidDispose(() => cts.cancel()); + model.onDidChangeContent(() => cts.cancel()); + const ordered = this._languageFeaturesService.documentOnDropEditProvider.ordered(model); for (const provider of ordered) { - const edit = await provider.provideDocumentOnDropEdits(model, position, textEditorDataTransfer, CancellationToken.None); - if (editor.getModel().getVersionId() !== modelVersionNow) { + const edit = await provider.provideDocumentOnDropEdits(model, position, textEditorDataTransfer, cts.token); + if (cts.token.isCancellationRequested || editor.getModel().getVersionId() !== modelVersionNow) { return; } -- cgit v1.2.3 From f7d3a81b587ec2f7a01928806119e204fead758b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Apr 2022 13:52:47 -0700 Subject: Add default drop into editor implementation For #142990 --- .../browser/dropIntoEditor.contibution.ts | 55 +++++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/dropIntoEditor/browser/dropIntoEditor.contibution.ts b/src/vs/workbench/contrib/dropIntoEditor/browser/dropIntoEditor.contibution.ts index e882d9fa58a..7e1380f1d1f 100644 --- a/src/vs/workbench/contrib/dropIntoEditor/browser/dropIntoEditor.contibution.ts +++ b/src/vs/workbench/contrib/dropIntoEditor/browser/dropIntoEditor.contibution.ts @@ -4,17 +4,21 @@ *--------------------------------------------------------------------------------------------*/ import { distinct } from 'vs/base/common/arrays'; -import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { Disposable } from 'vs/base/common/lifecycle'; import { Mimes } from 'vs/base/common/mime'; +import { relativePath } from 'vs/base/common/resources'; +import { URI } from 'vs/base/common/uri'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { IPosition } from 'vs/editor/common/core/position'; +import { Range } from 'vs/editor/common/core/range'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { IDataTransferItem } from 'vs/editor/common/languages'; import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; import { performSnippetEdit } from 'vs/editor/contrib/snippet/browser/snippetController2'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { extractEditorsDropData } from 'vs/workbench/browser/dnd'; import { IDataTransfer } from 'vs/workbench/common/dnd'; @@ -27,6 +31,7 @@ export class DropIntoEditorController extends Disposable implements IEditorContr editor: ICodeEditor, @IInstantiationService private readonly _instantiationService: IInstantiationService, @ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService, + @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService, ) { super(); @@ -92,7 +97,53 @@ export class DropIntoEditorController extends Disposable implements IEditorContr } } - // TODO: default drop behavior + return this.doDefaultDrop(editor, position, textEditorDataTransfer, cts.token); + } + + private async doDefaultDrop(editor: ICodeEditor, position: IPosition, textEditorDataTransfer: IDataTransfer, token: CancellationToken): Promise { + const range = new Range(position.lineNumber, position.column, position.lineNumber, position.column); + + const urlListEntry = textEditorDataTransfer.get('text/uri-list'); + if (urlListEntry) { + const urlList = await urlListEntry.asString(); + return this.doUriListDrop(editor, range, urlList, token); + } + + const textEntry = textEditorDataTransfer.get('text') ?? textEditorDataTransfer.get(Mimes.text); + if (textEntry) { + const text = await textEntry.asString(); + performSnippetEdit(editor, { range, snippet: text }); + } + } + + private async doUriListDrop(editor: ICodeEditor, range: Range, urlList: string, token: CancellationToken): Promise { + const uris: URI[] = []; + for (const resource of urlList.split('\n')) { + try { + uris.push(URI.parse(resource)); + } catch { + // noop + } + } + + if (!uris.length) { + return; + } + + const snippet = uris + .map(uri => { + const root = this._workspaceContextService.getWorkspaceFolder(uri); + if (root) { + const rel = relativePath(root.uri, uri); + if (rel) { + return rel; + } + } + return uri.fsPath; + }) + .join(' '); + + performSnippetEdit(editor, { range, snippet }); } } -- cgit v1.2.3 From 8cc0a4f68f113a82df89fda1c5581cc53b497a76 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 4 Apr 2022 16:59:12 -0700 Subject: Better instrument walkthrough interactions --- .../welcomeGettingStarted/browser/gettingStarted.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts index 9784e9f9fd2..6f8b332a0d0 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts @@ -100,11 +100,13 @@ const parsedStartEntries: IWelcomePageStartEntry[] = startEntries.map((e, i) => type GettingStartedActionClassification = { command: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; owner: 'JacksonKearl'; comment: 'Help understand what actions are most commonly taken on the getting started page' }; + walkthroughId: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; owner: 'JacksonKearl'; comment: 'As above' }; argument: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; owner: 'JacksonKearl'; comment: 'As above' }; }; type GettingStartedActionEvent = { command: string; + walkthroughId: string | undefined; argument: string | undefined; }; @@ -343,7 +345,7 @@ export class GettingStartedPage extends EditorPane { private async runDispatchCommand(command: string, argument: string) { this.commandService.executeCommand('workbench.action.keepEditor'); - this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command, argument }); + this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command, argument, walkthroughId: this.currentWalkthrough?.id }); switch (command) { case 'scrollPrev': { this.scrollPrev(); @@ -511,7 +513,7 @@ export class GettingStartedPage extends EditorPane { if (hrefs.length === 1) { const href = hrefs[0]; if (href.startsWith('http')) { - this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command: 'runStepAction', argument: href }); + this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command: 'runStepAction', argument: href, walkthroughId: this.currentWalkthrough?.id }); this.openerService.open(href); } } @@ -546,7 +548,7 @@ export class GettingStartedPage extends EditorPane { if (hrefs.length === 1) { const href = hrefs[0]; if (href.startsWith('http')) { - this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command: 'runStepAction', argument: href }); + this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command: 'runStepAction', argument: href, walkthroughId: this.currentWalkthrough?.id }); this.openerService.open(href); } } @@ -723,10 +725,10 @@ export class GettingStartedPage extends EditorPane { const showOnStartupLabel = $('label.caption', { for: 'showOnStartup' }, localize('welcomePage.showOnStartup', "Show welcome page on startup")); const onShowOnStartupChanged = () => { if (showOnStartupCheckbox.checked) { - this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command: 'showOnStartupChecked', argument: undefined }); + this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command: 'showOnStartupChecked', argument: undefined, walkthroughId: this.currentWalkthrough?.id }); this.configurationService.updateValue(configurationKey, 'welcomePage'); } else { - this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command: 'showOnStartupUnchecked', argument: undefined }); + this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command: 'showOnStartupUnchecked', argument: undefined, walkthroughId: this.currentWalkthrough?.id }); this.configurationService.updateValue(configurationKey, 'none'); } }; @@ -852,7 +854,7 @@ export class GettingStartedPage extends EditorPane { link.title = fullPath; link.setAttribute('aria-label', localize('welcomePage.openFolderWithPath', "Open folder {0} with path {1}", name, parentPath)); link.addEventListener('click', e => { - this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command: 'openRecent', argument: undefined }); + this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command: 'openRecent', argument: undefined, walkthroughId: this.currentWalkthrough?.id }); this.hostService.openWindow([windowOpenable], { forceNewWindow: e.ctrlKey || e.metaKey, remoteAuthority: recent.remoteAuthority || null // local window if remoteAuthority is not set or can not be deducted from the openable @@ -1092,7 +1094,7 @@ export class GettingStartedPage extends EditorPane { const toSide = href.startsWith('command:toSide:'); const command = href.replace(/command:(toSide:)?/, 'command:'); - this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command: 'runStepAction', argument: href }); + this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command: 'runStepAction', argument: href, walkthroughId: this.currentWalkthrough?.id }); const fullSize = this.groupsService.contentDimension; -- cgit v1.2.3 From 21480b1a1877831d416aff9ec187527efac876c5 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 4 Apr 2022 16:59:19 -0700 Subject: Remove leftover 'boolean' type See PR #146543 --- src/vs/workbench/contrib/debug/browser/debug.contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 8330e2aab7c..c9e21957b98 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -418,7 +418,7 @@ configurationRegistry.registerConfiguration({ default: false }, 'debug.inlineValues': { - type: ['boolean', 'string'], + type: 'string', 'enum': ['on', 'off', 'auto'], description: nls.localize({ comment: ['This is the description for a setting'], key: 'inlineValues' }, "Show variable values inline in editor while debugging."), 'enumDescriptions': [ -- cgit v1.2.3 From ccbe4d40e96ab0186a511053597abc6a078a69bd Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 5 Apr 2022 14:10:08 +0200 Subject: Avoid using `ModesRegistry.registerLanguage` in tests --- .../snippets/test/browser/snippetsService.test.ts | 94 ++++++++++------------ 1 file changed, 44 insertions(+), 50 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/snippets/test/browser/snippetsService.test.ts b/src/vs/workbench/contrib/snippets/test/browser/snippetsService.test.ts index 540e3fce155..9a602558814 100644 --- a/src/vs/workbench/contrib/snippets/test/browser/snippetsService.test.ts +++ b/src/vs/workbench/contrib/snippets/test/browser/snippetsService.test.ts @@ -6,15 +6,15 @@ import * as assert from 'assert'; import { SnippetCompletion, SnippetCompletionProvider } from 'vs/workbench/contrib/snippets/browser/snippetCompletionProvider'; import { Position } from 'vs/editor/common/core/position'; -import { ModesRegistry } from 'vs/editor/common/languages/modesRegistry'; -import { LanguageService } from 'vs/editor/common/services/languageService'; -import { createTextModel } from 'vs/editor/test/common/testTextModel'; +import { createModelServices, instantiateTextModel } from 'vs/editor/test/common/testTextModel'; import { ISnippetsService } from 'vs/workbench/contrib/snippets/browser/snippets.contribution'; import { Snippet, SnippetSource } from 'vs/workbench/contrib/snippets/browser/snippetsFile'; import { CompletionContext, CompletionItemLabel, CompletionItemRanges, CompletionTriggerKind } from 'vs/editor/common/languages'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/testLanguageConfigurationService'; import { EditOperation } from 'vs/editor/common/core/editOperation'; +import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; +import { ILanguageService } from 'vs/editor/common/languages/language'; class SimpleSnippetService implements ISnippetsService { declare readonly _serviceBrand: undefined; @@ -37,27 +37,21 @@ class SimpleSnippetService implements ISnippetsService { } suite('SnippetsService', function () { - const disposableStore: DisposableStore = new DisposableStore(); const context: CompletionContext = { triggerKind: CompletionTriggerKind.Invoke }; - suiteSetup(function () { - disposableStore.add(ModesRegistry.registerLanguage({ - id: 'fooLang', - extensions: ['.fooLang',] - })); - }); - - suiteTeardown(function () { - disposableStore.dispose(); - }); - let disposables: DisposableStore; - let languageService: LanguageService; + let instantiationService: TestInstantiationService; + let languageService: ILanguageService; let snippetService: ISnippetsService; setup(function () { disposables = new DisposableStore(); - languageService = disposables.add(new LanguageService()); + instantiationService = createModelServices(disposables); + languageService = instantiationService.get(ILanguageService); + disposables.add(languageService.registerLanguage({ + id: 'fooLang', + extensions: ['.fooLang',] + })); snippetService = new SimpleSnippetService([new Snippet( ['fooLang'], 'barTest', @@ -84,7 +78,7 @@ suite('SnippetsService', function () { test('snippet completions - simple', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - const model = disposables.add(createTextModel('', 'fooLang')); + const model = disposables.add(instantiateTextModel(instantiationService, '', 'fooLang')); return provider.provideCompletionItems(model, new Position(1, 1), context)!.then(result => { assert.strictEqual(result.incomplete, undefined); @@ -95,7 +89,7 @@ suite('SnippetsService', function () { test('snippet completions - simple 2', async function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - const model = disposables.add(createTextModel('hello ', 'fooLang')); + const model = disposables.add(instantiateTextModel(instantiationService, 'hello ', 'fooLang')); await provider.provideCompletionItems(model, new Position(1, 6) /* hello| */, context)!.then(result => { assert.strictEqual(result.incomplete, undefined); @@ -111,7 +105,7 @@ suite('SnippetsService', function () { test('snippet completions - with prefix', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - const model = disposables.add(createTextModel('bar', 'fooLang')); + const model = disposables.add(instantiateTextModel(instantiationService, 'bar', 'fooLang')); return provider.provideCompletionItems(model, new Position(1, 4), context)!.then(result => { assert.strictEqual(result.incomplete, undefined); @@ -146,7 +140,7 @@ suite('SnippetsService', function () { )]); const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - const model = disposables.add(createTextModel('bar-bar', 'fooLang')); + const model = disposables.add(instantiateTextModel(instantiationService, 'bar-bar', 'fooLang')); await provider.provideCompletionItems(model, new Position(1, 3), context)!.then(result => { assert.strictEqual(result.incomplete, undefined); @@ -217,19 +211,19 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = createTextModel('\t { assert.strictEqual(result.suggestions.length, 1); model.dispose(); - model = createTextModel('\t { assert.strictEqual(result.suggestions.length, 1); assert.strictEqual((result.suggestions[0].range as any).insert.startColumn, 2); model.dispose(); - model = createTextModel('a { assert.strictEqual(result.suggestions.length, 1); @@ -252,7 +246,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = disposables.add(createTextModel('\n\t\n>/head>', 'fooLang')); + let model = disposables.add(instantiateTextModel(instantiationService, '\n\t\n>/head>', 'fooLang')); return provider.provideCompletionItems(model, new Position(1, 1), context)!.then(result => { assert.strictEqual(result.suggestions.length, 1); return provider.provideCompletionItems(model, new Position(2, 2), context)!; @@ -282,7 +276,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = disposables.add(createTextModel('', 'fooLang')); + let model = disposables.add(instantiateTextModel(instantiationService, '', 'fooLang')); return provider.provideCompletionItems(model, new Position(1, 1), context)!.then(result => { assert.strictEqual(result.suggestions.length, 2); let [first, second] = result.suggestions; @@ -309,7 +303,7 @@ suite('SnippetsService', function () { )]); const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = disposables.add(createTextModel('p-', 'fooLang')); + let model = disposables.add(instantiateTextModel(instantiationService, 'p-', 'fooLang')); let result = await provider.provideCompletionItems(model, new Position(1, 2), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -334,7 +328,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = disposables.add(createTextModel('Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea b', 'fooLang')); + let model = disposables.add(instantiateTextModel(instantiationService, 'Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea b', 'fooLang')); let result = await provider.provideCompletionItems(model, new Position(1, 158), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -353,7 +347,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = disposables.add(createTextModel(':', 'fooLang')); + let model = disposables.add(instantiateTextModel(instantiationService, ':', 'fooLang')); let result = await provider.provideCompletionItems(model, new Position(1, 2), context)!; assert.strictEqual(result.suggestions.length, 0); @@ -372,7 +366,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = disposables.add(createTextModel('template', 'fooLang')); + let model = disposables.add(instantiateTextModel(instantiationService, 'template', 'fooLang')); let result = await provider.provideCompletionItems(model, new Position(1, 9), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -395,7 +389,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = disposables.add(createTextModel('Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea b text_after_b', 'fooLang')); + let model = disposables.add(instantiateTextModel(instantiationService, 'Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea b text_after_b', 'fooLang')); let result = await provider.provideCompletionItems(model, new Position(1, 158), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -403,7 +397,7 @@ suite('SnippetsService', function () { test('issue #61296: VS code freezes when editing CSS file with emoji', async function () { const languageConfigurationService = new TestLanguageConfigurationService(); - disposableStore.add(languageConfigurationService.register('fooLang', { + disposables.add(languageConfigurationService.register('fooLang', { wordPattern: /(#?-?\d*\.\d\w*%?)|(::?[\w-]*(?=[^,{;]*[,{]))|(([@#.!])?[\w-?]+%?|[@#!.])/g })); @@ -419,7 +413,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, languageConfigurationService); - let model = disposables.add(createTextModel('.🐷-a-b', 'fooLang')); + let model = disposables.add(instantiateTextModel(instantiationService, '.🐷-a-b', 'fooLang')); let result = await provider.provideCompletionItems(model, new Position(1, 8), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -438,7 +432,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = disposables.add(createTextModel('a ', 'fooLang')); + let model = disposables.add(instantiateTextModel(instantiationService, 'a ', 'fooLang')); let result = await provider.provideCompletionItems(model, new Position(1, 3), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -465,7 +459,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = createTextModel(' <', 'fooLang'); + let model = instantiateTextModel(instantiationService, ' <', 'fooLang'); let result = await provider.provideCompletionItems(model, new Position(1, 3), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -473,7 +467,7 @@ suite('SnippetsService', function () { assert.strictEqual((first.range as any).insert.startColumn, 2); model.dispose(); - model = createTextModel('1', 'fooLang'); + model = instantiateTextModel(instantiationService, '1', 'fooLang'); result = await provider.provideCompletionItems(model, new Position(1, 2), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -495,7 +489,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = createTextModel('not wordFoo bar', 'fooLang'); + let model = instantiateTextModel(instantiationService, 'not wordFoo bar', 'fooLang'); let result = await provider.provideCompletionItems(model, new Position(1, 3), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -504,7 +498,7 @@ suite('SnippetsService', function () { assert.strictEqual((first.range as any).replace.endColumn, 9); model.dispose(); - model = createTextModel('not woFoo bar', 'fooLang'); + model = instantiateTextModel(instantiationService, 'not woFoo bar', 'fooLang'); result = await provider.provideCompletionItems(model, new Position(1, 3), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -513,7 +507,7 @@ suite('SnippetsService', function () { assert.strictEqual((first.range as any).replace.endColumn, 3); model.dispose(); - model = createTextModel('not word', 'fooLang'); + model = instantiateTextModel(instantiationService, 'not word', 'fooLang'); result = await provider.provideCompletionItems(model, new Position(1, 1), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -537,7 +531,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = createTextModel('filler e KEEP ng filler', 'fooLang'); + let model = instantiateTextModel(instantiationService, 'filler e KEEP ng filler', 'fooLang'); let result = await provider.provideCompletionItems(model, new Position(1, 9), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -549,7 +543,7 @@ suite('SnippetsService', function () { test('Snippet will replace auto-closing pair if specified in prefix', async function () { const languageConfigurationService = new TestLanguageConfigurationService(); - disposableStore.add(languageConfigurationService.register('fooLang', { + disposables.add(languageConfigurationService.register('fooLang', { brackets: [ ['{', '}'], ['[', ']'], @@ -569,7 +563,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, languageConfigurationService); - let model = createTextModel('[psc]', 'fooLang'); + let model = instantiateTextModel(instantiationService, '[psc]', 'fooLang'); let result = await provider.provideCompletionItems(model, new Position(1, 5), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -594,7 +588,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = createTextModel(' ci', 'fooLang'); + let model = instantiateTextModel(instantiationService, ' ci', 'fooLang'); let result = await provider.provideCompletionItems(model, new Position(1, 4), context)!; assert.strictEqual(result.suggestions.length, 1); @@ -615,7 +609,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = createTextModel('\'\'', 'fooLang'); + let model = instantiateTextModel(instantiationService, '\'\'', 'fooLang'); let result = await provider.provideCompletionItems( model, new Position(1, 2), @@ -637,7 +631,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = createTextModel('\'\'', 'fooLang'); + let model = instantiateTextModel(instantiationService, '\'\'', 'fooLang'); let result = await provider.provideCompletionItems( model, @@ -657,7 +651,7 @@ suite('SnippetsService', function () { ]); const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = createTextModel('\'hellot\'', 'fooLang'); + let model = instantiateTextModel(instantiationService, '\'hellot\'', 'fooLang'); let result = await provider.provideCompletionItems( model, @@ -678,7 +672,7 @@ suite('SnippetsService', function () { ]); const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = createTextModel(')*&^', 'fooLang'); + let model = instantiateTextModel(instantiationService, ')*&^', 'fooLang'); let result = await provider.provideCompletionItems( model, @@ -698,7 +692,7 @@ suite('SnippetsService', function () { ]); const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = createTextModel('foobar', 'fooLang'); + let model = instantiateTextModel(instantiationService, 'foobar', 'fooLang'); let result = await provider.provideCompletionItems( model, @@ -718,7 +712,7 @@ suite('SnippetsService', function () { const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = createTextModel('function abc(w)', 'fooLang'); + let model = instantiateTextModel(instantiationService, 'function abc(w)', 'fooLang'); let result = await provider.provideCompletionItems( model, new Position(1, 15), @@ -737,7 +731,7 @@ suite('SnippetsService', function () { ]); const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); - let model = createTextModel('di', 'fooLang'); + let model = instantiateTextModel(instantiationService, 'di', 'fooLang'); let result = await provider.provideCompletionItems( model, new Position(1, 3), -- cgit v1.2.3 From 4cbb57235f6b1e9ee9b0d1d8e7eaeb335c4fa9b8 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 5 Apr 2022 14:57:23 +0200 Subject: Respond to UX feedback on resolved/unresolved comments (#146733) Part of #127473 --- .../contrib/comments/browser/commentColors.ts | 15 +++++++++------ .../contrib/comments/browser/commentThreadWidget.ts | 3 ++- .../comments/browser/commentThreadZoneWidget.ts | 9 +++++---- .../contrib/comments/browser/commentsTreeViewer.ts | 19 ++++++++++++++++--- .../workbench/contrib/comments/common/commentModel.ts | 8 +++++--- 5 files changed, 37 insertions(+), 17 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentColors.ts b/src/vs/workbench/contrib/comments/browser/commentColors.ts index 3fc12217f70..0ae19209c29 100644 --- a/src/vs/workbench/contrib/comments/browser/commentColors.ts +++ b/src/vs/workbench/contrib/comments/browser/commentColors.ts @@ -5,12 +5,13 @@ import { Color } from 'vs/base/common/color'; import * as languages from 'vs/editor/common/languages'; +import { peekViewBorder } from 'vs/editor/contrib/peekView/browser/peekView'; import * as nls from 'vs/nls'; -import { contrastBorder, editorWarningForeground, editorWidgetForeground, registerColor } from 'vs/platform/theme/common/colorRegistry'; +import { contrastBorder, disabledForeground, registerColor } from 'vs/platform/theme/common/colorRegistry'; import { IColorTheme } from 'vs/platform/theme/common/themeService'; -export const resolvedCommentBorder = registerColor('comments.resolved.border', { dark: editorWidgetForeground, light: editorWidgetForeground, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('resolvedCommentBorder', 'Color of borders and arrow for resolved comments.')); -export const unresolvedCommentBorder = registerColor('comments.unresolved.border', { dark: editorWarningForeground, light: editorWarningForeground, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('unresolvedCommentBorder', 'Color of borders and arrow for unresolved comments.')); +const resolvedCommentBorder = registerColor('comments.resolved.border', { dark: disabledForeground, light: disabledForeground, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('resolvedCommentBorder', 'Color of borders and arrow for resolved comments.')); +const unresolvedCommentBorder = registerColor('comments.unresolved.border', { dark: peekViewBorder, light: peekViewBorder, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('unresolvedCommentBorder', 'Color of borders and arrow for unresolved comments.')); const commentThreadStateColors = new Map([ [languages.CommentThreadState.Unresolved, unresolvedCommentBorder], @@ -18,8 +19,10 @@ const commentThreadStateColors = new Map([ ]); export const commentThreadStateColorVar = '--comment-thread-state-color'; +export const commentViewThreadStateColorVar = '--comment-view-thread-state-color'; +export const commentThreadStateBackgroundColorVar = '--comment-thread-state-background-color'; -export function getCommentThreadStateColor(thread: languages.CommentThread, theme: IColorTheme): Color | undefined { - const colorId = thread.state !== undefined ? commentThreadStateColors.get(thread.state) : undefined; - return colorId !== undefined ? theme.getColor(colorId) : undefined; +export function getCommentThreadStateColor(state: languages.CommentThreadState | undefined, theme: IColorTheme): Color | undefined { + const colorId = (state !== undefined) ? commentThreadStateColors.get(state) : undefined; + return (colorId !== undefined) ? theme.getColor(colorId) : undefined; } diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts index b4989b77691..0f9f5fd1500 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts @@ -24,7 +24,7 @@ import { IColorTheme } from 'vs/platform/theme/common/themeService'; import { contrastBorder, focusBorder, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, textBlockQuoteBackground, textBlockQuoteBorder, textLinkActiveForeground, textLinkForeground } from 'vs/platform/theme/common/colorRegistry'; import { PANEL_BORDER } from 'vs/workbench/common/theme'; import { IRange } from 'vs/editor/common/core/range'; -import { commentThreadStateColorVar } from 'vs/workbench/contrib/comments/browser/commentColors'; +import { commentThreadStateBackgroundColorVar, commentThreadStateColorVar } from 'vs/workbench/contrib/comments/browser/commentColors'; import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; import { FontInfo } from 'vs/editor/common/config/fontInfo'; @@ -248,6 +248,7 @@ export class CommentThreadWidget extends const content: string[] = []; content.push(`.monaco-editor .review-widget > .body { border-top: 1px solid var(${commentThreadStateColorVar}) }`); + content.push(`.monaco-editor .review-widget > .head { background-color: var(${commentThreadStateBackgroundColorVar}) }`); const linkColor = theme.getColor(textLinkForeground); if (linkColor) { diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts index 14ad6544915..d7832f4c718 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts @@ -23,10 +23,10 @@ import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { CommentThreadWidget } from 'vs/workbench/contrib/comments/browser/commentThreadWidget'; import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; -import { commentThreadStateColorVar, getCommentThreadStateColor } from 'vs/workbench/contrib/comments/browser/commentColors'; +import { commentThreadStateBackgroundColorVar, commentThreadStateColorVar, getCommentThreadStateColor } from 'vs/workbench/contrib/comments/browser/commentColors'; import { peekViewBorder } from 'vs/editor/contrib/peekView/browser/peekView'; -export function getCommentThreadWidgetStateColor(thread: languages.CommentThread, theme: IColorTheme): Color | undefined { +export function getCommentThreadWidgetStateColor(thread: languages.CommentThreadState | undefined, theme: IColorTheme): Color | undefined { return getCommentThreadStateColor(thread, theme) ?? theme.getColor(peekViewBorder); } @@ -344,12 +344,13 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget this._commentThreadDisposables.push(this._commentThread.onDidChangeState(() => { const borderColor = - getCommentThreadWidgetStateColor(this._commentThread, this.themeService.getColorTheme()) || Color.transparent; + getCommentThreadWidgetStateColor(this._commentThread.state, this.themeService.getColorTheme()) || Color.transparent; this.style({ frameColor: borderColor, arrowColor: borderColor, }); this.container?.style.setProperty(commentThreadStateColorVar, `${borderColor}`); + this.container?.style.setProperty(commentThreadStateBackgroundColorVar, `${borderColor.transparent(.1)}`); })); } @@ -410,7 +411,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget } private _applyTheme(theme: IColorTheme) { - const borderColor = getCommentThreadWidgetStateColor(this._commentThread, this.themeService.getColorTheme()) || Color.transparent; + const borderColor = getCommentThreadWidgetStateColor(this._commentThread.state, this.themeService.getColorTheme()) || Color.transparent; this.style({ arrowColor: borderColor, frameColor: borderColor diff --git a/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts b/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts index e291c7d32de..ebe8b7b9de2 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts @@ -18,12 +18,15 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { WorkbenchAsyncDataTree, IListService, IWorkbenchAsyncDataTreeOptions } from 'vs/platform/list/browser/listService'; -import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { IColorTheme, IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IColorMapping } from 'vs/platform/theme/common/styler'; import { TimestampWidget } from 'vs/workbench/contrib/comments/browser/timestamp'; import { Codicon } from 'vs/base/common/codicons'; import { IMarkdownString } from 'vs/base/common/htmlContent'; +import { commentViewThreadStateColorVar, getCommentThreadStateColor } from 'vs/workbench/contrib/comments/browser/commentColors'; +import { CommentThreadState } from 'vs/editor/common/languages'; +import { Color } from 'vs/base/common/color'; export const COMMENTS_VIEW_ID = 'workbench.panel.comments'; export const COMMENTS_VIEW_TITLE = 'Comments'; @@ -50,7 +53,7 @@ interface IResourceTemplateData { interface ICommentThreadTemplateData { threadMetadata: { - icon?: HTMLElement; + icon: HTMLElement; userNames: HTMLSpanElement; timestamp: TimestampWidget; separator: HTMLElement; @@ -121,7 +124,8 @@ export class CommentNodeRenderer implements IListRenderer constructor( @IOpenerService private readonly openerService: IOpenerService, - @IConfigurationService private readonly configurationService: IConfigurationService + @IConfigurationService private readonly configurationService: IConfigurationService, + @IThemeService private themeService: IThemeService ) { } renderTemplate(container: HTMLElement) { @@ -185,6 +189,11 @@ export class CommentNodeRenderer implements IListRenderer renderElement(node: ITreeNode, index: number, templateData: ICommentThreadTemplateData, height: number | undefined): void { const commentCount = node.element.replies.length + 1; templateData.threadMetadata.icon?.classList.add(...ThemeIcon.asClassNameArray((commentCount === 1) ? Codicon.comment : Codicon.commentDiscussion)); + if (node.element.threadState !== undefined) { + const color = this.getCommentThreadWidgetStateColor(node.element.threadState, this.themeService.getColorTheme()); + templateData.threadMetadata.icon.style.setProperty(commentViewThreadStateColorVar, `${color}`); + templateData.threadMetadata.icon.style.color = `var(${commentViewThreadStateColorVar}`; + } templateData.threadMetadata.userNames.textContent = node.element.comment.userName; templateData.threadMetadata.timestamp.setTimestamp(node.element.comment.timestamp ? new Date(node.element.comment.timestamp) : undefined); const originalComment = node.element; @@ -213,6 +222,10 @@ export class CommentNodeRenderer implements IListRenderer } + private getCommentThreadWidgetStateColor(state: CommentThreadState | undefined, theme: IColorTheme): Color | undefined { + return (state !== undefined) ? getCommentThreadStateColor(state, theme) : undefined; + } + disposeTemplate(templateData: ICommentThreadTemplateData): void { templateData.disposables.forEach(disposeable => disposeable.dispose()); } diff --git a/src/vs/workbench/contrib/comments/common/commentModel.ts b/src/vs/workbench/contrib/comments/common/commentModel.ts index d8f97430b4b..06ec27f01c3 100644 --- a/src/vs/workbench/contrib/comments/common/commentModel.ts +++ b/src/vs/workbench/contrib/comments/common/commentModel.ts @@ -5,7 +5,7 @@ import { URI } from 'vs/base/common/uri'; import { IRange } from 'vs/editor/common/core/range'; -import { Comment, CommentThread, CommentThreadChangedEvent } from 'vs/editor/common/languages'; +import { Comment, CommentThread, CommentThreadChangedEvent, CommentThreadState } from 'vs/editor/common/languages'; import { groupBy } from 'vs/base/common/arrays'; import { localize } from 'vs/nls'; @@ -21,14 +21,16 @@ export class CommentNode { replies: CommentNode[] = []; resource: URI; isRoot: boolean; + threadState?: CommentThreadState; - constructor(owner: string, threadId: string, resource: URI, comment: Comment, range: IRange) { + constructor(owner: string, threadId: string, resource: URI, comment: Comment, range: IRange, threadState: CommentThreadState | undefined) { this.owner = owner; this.threadId = threadId; this.comment = comment; this.resource = resource; this.range = range; this.isRoot = false; + this.threadState = threadState; } hasReply(): boolean { @@ -51,7 +53,7 @@ export class ResourceWithCommentThreads { public static createCommentNode(owner: string, resource: URI, commentThread: CommentThread): CommentNode { const { threadId, comments, range } = commentThread; - const commentNodes: CommentNode[] = comments!.map(comment => new CommentNode(owner, threadId!, resource, comment, range)); + const commentNodes: CommentNode[] = comments!.map(comment => new CommentNode(owner, threadId!, resource, comment, range, commentThread.state)); if (commentNodes.length > 1) { commentNodes[0].replies = commentNodes.slice(1, commentNodes.length); } -- cgit v1.2.3 From b541c1cc97490dfa1811a925f91f725c39af14d4 Mon Sep 17 00:00:00 2001 From: Anthony Stewart <150152+a-stewart@users.noreply.github.com> Date: Tue, 5 Apr 2022 15:25:33 +0200 Subject: Rename user facinging instances of SCM to Source Control (#146742) Co-authored-by: Anthony Stewart --- .../contrib/preferences/browser/settingsLayout.ts | 2 +- .../workbench/contrib/scm/browser/scm.contribution.ts | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts b/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts index d631ff74b4a..9d2c8958ba0 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts @@ -145,7 +145,7 @@ export const tocData: ITOCEntry = { }, { id: 'features/scm', - label: localize('scm', "SCM"), + label: localize('scm', "Source Control"), settings: ['scm.*'] }, { diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index 27fa26a947d..42c3b990f72 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -83,7 +83,7 @@ viewsRegistry.registerViews([{ containerIcon: sourceControlViewIcon, openCommandActionDescriptor: { id: viewContainer.id, - mnemonicTitle: localize({ key: 'miViewSCM', comment: ['&& denotes a mnemonic'] }, "S&&CM"), + mnemonicTitle: localize({ key: 'miViewSCM', comment: ['&& denotes a mnemonic'] }, "Source &&Control"), keybindings: { primary: 0, win: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyG }, @@ -118,7 +118,7 @@ Registry.as(WorkbenchExtensions.Workbench) Registry.as(ConfigurationExtensions.Configuration).registerConfiguration({ id: 'scm', order: 5, - title: localize('scmConfigurationTitle', "SCM"), + title: localize('scmConfigurationTitle', "Source Control"), type: 'object', scope: ConfigurationScope.RESOURCE, properties: { @@ -215,14 +215,14 @@ Registry.as(ConfigurationExtensions.Configuration).regis enumDescriptions: [ localize('scm.defaultViewSortKey.name', "Sort the repository changes by file name."), localize('scm.defaultViewSortKey.path', "Sort the repository changes by path."), - localize('scm.defaultViewSortKey.status', "Sort the repository changes by SCM status.") + localize('scm.defaultViewSortKey.status', "Sort the repository changes by Source Control status.") ], description: localize('scm.defaultViewSortKey', "Controls the default Source Control repository sort mode."), default: 'path' }, 'scm.autoReveal': { type: 'boolean', - description: localize('autoReveal', "Controls whether the SCM view should automatically reveal and select files when opening them."), + description: localize('autoReveal', "Controls whether the Source Control view should automatically reveal and select files when opening them."), default: true }, 'scm.inputFontFamily': { @@ -237,7 +237,7 @@ Registry.as(ConfigurationExtensions.Configuration).regis }, 'scm.alwaysShowRepositories': { type: 'boolean', - markdownDescription: localize('alwaysShowRepository', "Controls whether repositories should always be visible in the SCM view."), + markdownDescription: localize('alwaysShowRepository', "Controls whether repositories should always be visible in the Source Control view."), default: false }, 'scm.repositories.visible': { @@ -247,7 +247,7 @@ Registry.as(ConfigurationExtensions.Configuration).regis }, 'scm.showActionButton': { type: 'boolean', - markdownDescription: localize('showActionButton', "Controls whether an action button can be shown in the SCM view."), + markdownDescription: localize('showActionButton', "Controls whether an action button can be shown in the Source Control view."), default: true } } @@ -255,7 +255,7 @@ Registry.as(ConfigurationExtensions.Configuration).regis KeybindingsRegistry.registerCommandAndKeybindingRule({ id: 'scm.acceptInput', - description: { description: localize('scm accept', "SCM: Accept Input"), args: [] }, + description: { description: localize('scm accept', "Source Control: Accept Input"), args: [] }, weight: KeybindingWeight.WorkbenchContrib, when: ContextKeyExpr.has('scmRepository'), primary: KeyMod.CtrlCmd | KeyCode.Enter, @@ -276,7 +276,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ }); const viewNextCommitCommand = { - description: { description: localize('scm view next commit', "SCM: View Next Commit"), args: [] }, + description: { description: localize('scm view next commit', "Source Control: View Next Commit"), args: [] }, weight: KeybindingWeight.WorkbenchContrib, handler: (accessor: ServicesAccessor) => { const contextKeyService = accessor.get(IContextKeyService); @@ -287,7 +287,7 @@ const viewNextCommitCommand = { }; const viewPreviousCommitCommand = { - description: { description: localize('scm view previous commit', "SCM: View Previous Commit"), args: [] }, + description: { description: localize('scm view previous commit', "Source Control: View Previous Commit"), args: [] }, weight: KeybindingWeight.WorkbenchContrib, handler: (accessor: ServicesAccessor) => { const contextKeyService = accessor.get(IContextKeyService); -- cgit v1.2.3 From 6c7f263edbc2efec58e1692db6091da7e49ecb2e Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Tue, 5 Apr 2022 08:34:14 -0700 Subject: Remove tag check, fixes #139886 (#146269) --- src/vs/workbench/contrib/preferences/browser/settingsTree.ts | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index f4b4b41ad94..7b551ab1466 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -2234,13 +2234,6 @@ export class SettingsTreeFilter implements ITreeFilter { } } - // @modified or tag - if (element instanceof SettingsTreeSettingElement && this.viewState.tagFilters) { - if (!element.matchesAllTags(this.viewState.tagFilters)) { - return false; - } - } - // Group with no visible children if (element instanceof SettingsTreeGroupElement) { if (typeof element.count === 'number') { -- cgit v1.2.3 From b0990b94a7dfabfbcac25110e7aa0953acb79004 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Tue, 5 Apr 2022 20:53:48 +0200 Subject: SCM - Add settings to toggle diff decorator pattern (#146724) --- .../contrib/scm/browser/dirtydiffDecorator.ts | 102 ++++++++++++++++----- .../contrib/scm/browser/scm.contribution.ts | 19 ++++ 2 files changed, 99 insertions(+), 22 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts index 600b2af4b21..8bae9fbc794 100644 --- a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts +++ b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts @@ -20,7 +20,7 @@ import { URI } from 'vs/base/common/uri'; import { ISCMService, ISCMRepository, ISCMProvider } from 'vs/workbench/contrib/scm/common/scm'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { registerThemingParticipant, IColorTheme, ICssStyleCollector, themeColorFromId, IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { editorBackground, editorErrorForeground, registerColor, transparent } from 'vs/platform/theme/common/colorRegistry'; +import { editorErrorForeground, registerColor, transparent } from 'vs/platform/theme/common/colorRegistry'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction } from 'vs/editor/browser/editorExtensions'; import { PeekViewWidget, getOuterEditor, peekViewBorder, peekViewTitleBackground, peekViewTitleForeground, peekViewTitleInfoForeground } from 'vs/editor/contrib/peekView/browser/peekView'; @@ -52,6 +52,7 @@ import { TextCompareEditorActiveContext } from 'vs/workbench/common/contextkeys' import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; import { IChange } from 'vs/editor/common/diff/diffComputer'; import { Color } from 'vs/base/common/color'; +import { editorGutter } from 'vs/editor/common/core/editorColorRegistry'; class DiffActionRunner extends ActionRunner { @@ -923,8 +924,10 @@ class DirtyDiffDecorator extends Disposable { return ModelDecorationOptions.createDynamic(decorationOptions); } - private modifiedOptions: ModelDecorationOptions; private addedOptions: ModelDecorationOptions; + private addedPatternOptions: ModelDecorationOptions; + private modifiedOptions: ModelDecorationOptions; + private modifiedPatternOptions: ModelDecorationOptions; private deletedOptions: ModelDecorationOptions; private decorations: string[] = []; private editorModel: ITextModel | null; @@ -932,25 +935,38 @@ class DirtyDiffDecorator extends Disposable { constructor( editorModel: ITextModel, private model: DirtyDiffModel, - @IConfigurationService configurationService: IConfigurationService + @IConfigurationService private readonly configurationService: IConfigurationService ) { super(); this.editorModel = editorModel; + const decorations = configurationService.getValue('scm.diffDecorations'); const gutter = decorations === 'all' || decorations === 'gutter'; const overview = decorations === 'all' || decorations === 'overview'; const minimap = decorations === 'all' || decorations === 'minimap'; + this.addedOptions = DirtyDiffDecorator.createDecoration('dirty-diff-added', { + gutter, + overview: { active: overview, color: overviewRulerAddedForeground }, + minimap: { active: minimap, color: minimapGutterAddedBackground }, + isWholeLine: true + }); + this.addedPatternOptions = DirtyDiffDecorator.createDecoration('dirty-diff-added-pattern', { + gutter, + overview: { active: overview, color: overviewRulerAddedForeground }, + minimap: { active: minimap, color: minimapGutterAddedBackground }, + isWholeLine: true + }); this.modifiedOptions = DirtyDiffDecorator.createDecoration('dirty-diff-modified', { gutter, overview: { active: overview, color: overviewRulerModifiedForeground }, minimap: { active: minimap, color: minimapGutterModifiedBackground }, isWholeLine: true }); - this.addedOptions = DirtyDiffDecorator.createDecoration('dirty-diff-added', { + this.modifiedPatternOptions = DirtyDiffDecorator.createDecoration('dirty-diff-modified-pattern', { gutter, - overview: { active: overview, color: overviewRulerAddedForeground }, - minimap: { active: minimap, color: minimapGutterAddedBackground }, + overview: { active: overview, color: overviewRulerModifiedForeground }, + minimap: { active: minimap, color: minimapGutterModifiedBackground }, isWholeLine: true }); this.deletedOptions = DirtyDiffDecorator.createDecoration('dirty-diff-deleted', { @@ -960,6 +976,12 @@ class DirtyDiffDecorator extends Disposable { isWholeLine: false }); + this._register(configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('scm.diffDecorationsGutterPattern')) { + this.onDidChange(); + } + })); + this._register(model.onDidChange(this.onDidChange, this)); } @@ -967,6 +989,8 @@ class DirtyDiffDecorator extends Disposable { if (!this.editorModel) { return; } + + const pattern = this.configurationService.getValue<{ added: boolean; modified: boolean }>('scm.diffDecorationsGutterPattern'); const decorations = this.model.changes.map((change) => { const changeType = getChangeType(change); const startLineNumber = change.modifiedStartLineNumber; @@ -979,7 +1003,7 @@ class DirtyDiffDecorator extends Disposable { startLineNumber: startLineNumber, startColumn: 1, endLineNumber: endLineNumber, endColumn: 1 }, - options: this.addedOptions + options: pattern.added ? this.addedPatternOptions : this.addedOptions }; case ChangeType.Delete: return { @@ -995,7 +1019,7 @@ class DirtyDiffDecorator extends Disposable { startLineNumber: startLineNumber, startColumn: 1, endLineNumber: endLineNumber, endColumn: 1 }, - options: this.modifiedOptions + options: pattern.modified ? this.modifiedPatternOptions : this.modifiedOptions }; } }); @@ -1371,9 +1395,21 @@ export class DirtyDiffWorkbenchController extends Disposable implements ext.IWor private setViewState(state: IViewState): void { this.viewState = state; this.stylesheet.textContent = ` - .monaco-editor .dirty-diff-modified { background-size: ${state.width}px 4.5px; } - .monaco-editor .dirty-diff-modified, .monaco-editor .dirty-diff-added{border-left-width:${state.width}px;} - .monaco-editor .dirty-diff-modified, .monaco-editor .dirty-diff-added, .monaco-editor .dirty-diff-deleted { + .monaco-editor .dirty-diff-added, + .monaco-editor .dirty-diff-modified { + border-left-width:${state.width}px; + } + .monaco-editor .dirty-diff-added-pattern, + .monaco-editor .dirty-diff-added-pattern:before, + .monaco-editor .dirty-diff-modified-pattern, + .monaco-editor .dirty-diff-modified-pattern:before { + background-size: ${state.width}px ${state.width}px; + } + .monaco-editor .dirty-diff-added, + .monaco-editor .dirty-diff-added-pattern, + .monaco-editor .dirty-diff-modified, + .monaco-editor .dirty-diff-modified-pattern, + .monaco-editor .dirty-diff-deleted { opacity: ${state.visibility === 'always' ? 1 : 0}; } `; @@ -1468,39 +1504,61 @@ export class DirtyDiffWorkbenchController extends Disposable implements ext.IWor registerEditorContribution(DirtyDiffController.ID, DirtyDiffController); registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { - const editorBackgroundColor = theme.getColor(editorBackground); + const editorGutterBackgroundColor = theme.getColor(editorGutter); const editorGutterModifiedBackgroundColor = theme.getColor(editorGutterModifiedBackground); - const linearGradient = `-45deg, ${editorGutterModifiedBackgroundColor} 25%, ${editorBackgroundColor} 25%, ${editorBackgroundColor} 50%, ${editorGutterModifiedBackgroundColor} 50%, ${editorGutterModifiedBackgroundColor} 75%, ${editorBackgroundColor} 75%, ${editorBackgroundColor}`; - if (editorGutterModifiedBackgroundColor) { + const getLinearGradient = (color: Color): string => { + return `-45deg, ${color} 25%, ${editorGutterBackgroundColor} 25%, ${editorGutterBackgroundColor} 50%, ${color} 50%, ${color} 75%, ${editorGutterBackgroundColor} 75%, ${editorGutterBackgroundColor}`; + }; + + if (editorGutterBackgroundColor && editorGutterModifiedBackgroundColor) { collector.addRule(` .monaco-editor .dirty-diff-modified { - background-repeat: repeat-y; - background-image: linear-gradient(${linearGradient}); + border-left-color: ${editorGutterModifiedBackgroundColor}; + border-left-style: solid; transition: opacity 0.5s; } .monaco-editor .dirty-diff-modified:before { + background: ${editorGutterModifiedBackgroundColor}; + } + .monaco-editor .dirty-diff-modified-pattern { + background-image: linear-gradient(${getLinearGradient(editorGutterModifiedBackgroundColor)}); + background-repeat: repeat-y; + transition: opacity 0.5s; + } + .monaco-editor .dirty-diff-modified-pattern:before { + background-image: linear-gradient(${getLinearGradient(editorGutterModifiedBackgroundColor)}); transform: translateX(3px); - background-size: 3px 3px; - background-image: linear-gradient(${linearGradient}); } - .monaco-editor .margin:hover .dirty-diff-modified { + .monaco-editor .margin:hover .dirty-diff-modified, + .monaco-editor .margin:hover .dirty-diff-modified-pattern { opacity: 1; } `); } const editorGutterAddedBackgroundColor = theme.getColor(editorGutterAddedBackground); - if (editorGutterAddedBackgroundColor) { + if (editorGutterBackgroundColor && editorGutterAddedBackgroundColor) { collector.addRule(` .monaco-editor .dirty-diff-added { - border-left: 3px solid ${editorGutterAddedBackgroundColor}; + border-left-color: ${editorGutterAddedBackgroundColor}; + border-left-style: solid; transition: opacity 0.5s; } .monaco-editor .dirty-diff-added:before { background: ${editorGutterAddedBackgroundColor}; } - .monaco-editor .margin:hover .dirty-diff-added { + .monaco-editor .dirty-diff-added-pattern { + background-image: linear-gradient(${getLinearGradient(editorGutterAddedBackgroundColor)}); + background-repeat: repeat-y; + transition: opacity 0.5s; + } + .monaco-editor .dirty-diff-added-pattern:before { + background-image: linear-gradient(${getLinearGradient(editorGutterAddedBackgroundColor)}); + transform: translateX(3px); + } + .monaco-editor .margin:hover .dirty-diff-added, + .monaco-editor .margin:hover .dirty-diff-added-pattern { opacity: 1; } `); diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index 42c3b990f72..2b5f202e350 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -161,6 +161,25 @@ Registry.as(ConfigurationExtensions.Configuration).regis description: localize('scm.diffDecorationsGutterAction', "Controls the behavior of Source Control diff gutter decorations."), default: 'diff' }, + 'scm.diffDecorationsGutterPattern': { + type: 'object', + description: localize('diffGutterPattern', "Controls whether a pattern is used for the diff decorations in gutter."), + additionalProperties: false, + properties: { + 'added': { + type: 'boolean', + description: localize('diffGutterPatternAdded', "Use pattern for the diff decorations in gutter for added lines."), + }, + 'modified': { + type: 'boolean', + description: localize('diffGutterPatternModifed', "Use pattern for the diff decorations in gutter for modified lines."), + }, + }, + default: { + 'added': false, + 'modified': true + } + }, 'scm.diffDecorationsIgnoreTrimWhitespace': { type: 'string', enum: ['true', 'false', 'inherit'], -- cgit v1.2.3 From b99fd9959458130caa1703926534b76fb31deba6 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 5 Apr 2022 21:16:20 +0200 Subject: Use word related methods always through `ITextModel` --- src/vs/workbench/contrib/debug/browser/debugEditorActions.ts | 2 +- src/vs/workbench/contrib/debug/browser/repl.ts | 2 +- .../contrib/extensions/browser/extensionsCompletionItemsProvider.ts | 2 +- src/vs/workbench/contrib/search/browser/searchView.ts | 2 +- src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts | 2 +- src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts index 04dd1f1b1fe..bcb3748c6a1 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts @@ -313,7 +313,7 @@ class ShowDebugHoverAction extends EditorAction { if (!position || !editor.hasModel()) { return; } - const word = editor.getModel().tokenization.getWordAtPosition(position); + const word = editor.getModel().getWordAtPosition(position); if (!word) { return; } diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 14dd25cbf6b..cc2a06f698e 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -238,7 +238,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { const model = this.replInput.getModel(); if (model) { - const word = model.tokenization.getWordAtPosition(position); + const word = model.getWordAtPosition(position); const overwriteBefore = word ? word.word.length : 0; const text = model.getValue(); const focusedStackFrame = this.debugService.getViewModel().focusedStackFrame; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsCompletionItemsProvider.ts b/src/vs/workbench/contrib/extensions/browser/extensionsCompletionItemsProvider.ts index 593c8df3dd9..3f8c429d93f 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsCompletionItemsProvider.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsCompletionItemsProvider.ts @@ -26,7 +26,7 @@ export class ExtensionsCompletionItemsProvider extends Disposable implements IWo this._register(languageFeaturesService.completionProvider.register({ language: 'jsonc', pattern: '**/settings.json' }, { provideCompletionItems: async (model: ITextModel, position: Position, _context: CompletionContext, token: CancellationToken): Promise => { const getWordRangeAtPosition = (model: ITextModel, position: Position): Range | null => { - const wordAtPosition = model.tokenization.getWordAtPosition(position); + const wordAtPosition = model.getWordAtPosition(position); return wordAtPosition ? new Range(position.lineNumber, wordAtPosition.startColumn, position.lineNumber, wordAtPosition.endColumn) : null; }; diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index eddb57e8663..90411d0caec 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -1160,7 +1160,7 @@ export class SearchView extends ViewPane { } if (range.isEmpty() && this.searchConfig.seedWithNearestWord && allowUnselectedWord) { - const wordAtPosition = editor.getModel().tokenization.getWordAtPosition(range.getStartPosition()); + const wordAtPosition = editor.getModel().getWordAtPosition(range.getStartPosition()); if (wordAtPosition) { return wordAtPosition.word; } diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts index 76fa794a03a..28e8b4fd1e5 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts @@ -127,7 +127,7 @@ export const openNewSearchEditor = selected = (selection && activeModel?.getModel()?.getValueInRange(selection)) ?? ''; if (selection?.isEmpty() && configurationService.getValue('search').seedWithNearestWord) { - const wordAtPosition = activeModel.getModel()?.tokenization.getWordAtPosition(selection.getStartPosition()); + const wordAtPosition = activeModel.getModel()?.getWordAtPosition(selection.getStartPosition()); if (wordAtPosition) { selected = wordAtPosition.word; } diff --git a/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts b/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts index b2b27cc1db9..af03f2ea749 100644 --- a/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts +++ b/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts @@ -73,7 +73,7 @@ export class SnippetCompletionProvider implements CompletionItemProvider { const snippets = new Set(await this._snippets.getSnippets(languageId)); const lineContentLow = model.getLineContent(position.lineNumber).toLowerCase(); - const wordUntil = model.tokenization.getWordUntilPosition(position).word.toLowerCase(); + const wordUntil = model.getWordUntilPosition(position).word.toLowerCase(); const suggestions: SnippetCompletion[] = []; const columnOffset = position.column - 1; -- cgit v1.2.3 From fd46d7191cdf6acb79cc920323600b290fee5e3a Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 5 Apr 2022 10:09:37 -0700 Subject: Update remote prefs search query format --- src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts b/src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts index fbddbef9008..f5c142d6cca 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts @@ -379,7 +379,7 @@ class RemoteSearchProvider implements ISearchProvider { const hasMoreFilters = filters.length > (filterPage + 1) * RemoteSearchProvider.MAX_REQUEST_FILTERS; const body = JSON.stringify({ - query: encodedQuery, + search: encodedQuery, filters: encodeURIComponent(filterStr), rawQuery: encodeURIComponent(verbatimQuery) }); -- cgit v1.2.3 From c89ef733272b56985661d7d2e56882422a11d5da Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 5 Apr 2022 16:56:32 -0700 Subject: Dont persist match ranges unnecessarily ref #145997 --- .../workbench/contrib/searchEditor/browser/searchEditor.contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts index 4d0742dc00a..ed23a5f2632 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts @@ -121,7 +121,7 @@ class SearchEditorInputSerializer implements IEditorSerializer { const config = input.tryReadConfigSync(); const dirty = input.isDirty(); - const matchRanges = input.getMatchRanges(); + const matchRanges = dirty ? input.getMatchRanges() : []; const backingUri = input.backingUri; return JSON.stringify({ modelUri, dirty, config, name: input.getName(), matchRanges, backingUri: backingUri?.toString() } as SerializedSearchEditor); -- cgit v1.2.3 From 37049cd22f67b46208e2a0de95e2906ddd3fe8c1 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 5 Apr 2022 17:11:18 -0700 Subject: Prioritize Text File in New File list Ref #144667 --- src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts b/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts index b78599440db..f269eb24ea4 100644 --- a/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts +++ b/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts @@ -175,14 +175,13 @@ class NewFileTemplatesManager extends Disposable { qp.show(); } - } Registry.as(WorkbenchExtensions.Workbench) .registerWorkbenchContribution(NewFileTemplatesManager, LifecyclePhase.Restored); MenuRegistry.appendMenuItem(MenuId.NewFile, { - group: 'File', + group: 'file', command: { id: 'workbench.action.files.newUntitledFile', title: localize('miNewFile2', "Text File") -- cgit v1.2.3 From f050b17dacedba13962244b13c70084a473d08f7 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 5 Apr 2022 17:29:01 -0700 Subject: Prioritize New File even more Fix #144667 --- .../welcomeViews/common/newFile.contribution.ts | 35 +++++++++++----------- 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts b/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts index f269eb24ea4..7e54169a228 100644 --- a/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts +++ b/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts @@ -9,7 +9,7 @@ import { assertIsDefined } from 'vs/base/common/types'; import { localize } from 'vs/nls'; import { Action2, IMenuService, MenuId, registerAction2, IMenu, MenuRegistry, MenuItemAction } from 'vs/platform/actions/common/actions'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -18,11 +18,9 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; - +const builtInSource = localize('Built-In', "Built-In"); const category = localize('Create', "Create"); -export const HasMultipleNewFileEntries = new RawContextKey('hasMultipleNewFileEntries', false); - registerAction2(class extends Action2 { constructor() { super({ @@ -36,7 +34,6 @@ registerAction2(class extends Action2 { }, menu: { id: MenuId.MenubarFileMenu, - when: HasMultipleNewFileEntries, group: '1_new', order: 2 } @@ -68,8 +65,6 @@ class NewFileTemplatesManager extends Disposable { this._register({ dispose() { if (NewFileTemplatesManager.Instance === this) { NewFileTemplatesManager.Instance = undefined; } } }); this.menu = menuService.createMenu(MenuId.NewFile, contextKeyService); - this.updateContextKeys(); - this._register(this.menu.onDidChange(() => { this.updateContextKeys(); })); } private allEntries(): NewFileItem[] { @@ -77,17 +72,13 @@ class NewFileTemplatesManager extends Disposable { for (const [groupName, group] of this.menu.getActions({ renderShortTitle: true })) { for (const action of group) { if (action instanceof MenuItemAction) { - items.push({ commandID: action.item.id, from: action.item.source ?? localize('Built-In', "Built-In"), title: action.label, group: groupName }); + items.push({ commandID: action.item.id, from: action.item.source ?? builtInSource, title: action.label, group: groupName }); } } } return items; } - private updateContextKeys() { - HasMultipleNewFileEntries.bindTo(this.contextKeyService).set(this.allEntries().length > 1); - } - run() { const entries = this.allEntries(); if (entries.length === 0) { @@ -108,12 +99,20 @@ class NewFileTemplatesManager extends Disposable { qp.matchOnDetail = true; qp.matchOnDescription = true; - const sortCategories = (a: string, b: string): number => { + const sortCategories = (a: NewFileItem, b: NewFileItem): number => { const categoryPriority: Record = { 'file': 1, 'notebook': 2 }; - if (categoryPriority[a] && categoryPriority[b]) { return categoryPriority[b] - categoryPriority[a]; } - if (categoryPriority[a]) { return 1; } - if (categoryPriority[b]) { return -1; } - return a.localeCompare(b); + if (categoryPriority[a.group] && categoryPriority[b.group]) { + if (categoryPriority[a.group] !== categoryPriority[b.group]) { + return categoryPriority[b.group] - categoryPriority[a.group]; + } + } + else if (categoryPriority[a.group]) { return 1; } + else if (categoryPriority[b.group]) { return -1; } + + if (a.from === builtInSource) { return 1; } + if (b.from === builtInSource) { return -1; } + + return a.from.localeCompare(b.from); }; const displayCategory: Record = { @@ -125,7 +124,7 @@ class NewFileTemplatesManager extends Disposable { const items: (((IQuickPickItem & NewFileItem) | IQuickPickSeparator))[] = []; let lastSeparator: string | undefined; entries - .sort((a, b) => -sortCategories(a.group, b.group)) + .sort((a, b) => -sortCategories(a, b)) .forEach((entry) => { const command = entry.commandID; const keybinding = this.keybindingService.lookupKeybinding(command || '', this.contextKeyService); -- cgit v1.2.3 From 9a2949806a615af89af4ef902ea01c646f7f9015 Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 6 Apr 2022 10:14:35 +0200 Subject: fix leaking observer, https://github.com/microsoft/vscode/issues/146841 --- .../contrib/languageStatus/browser/languageStatus.contribution.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts index d6d4689d90e..867ebed9818 100644 --- a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts +++ b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/languageStatus'; import * as dom from 'vs/base/browser/dom'; import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; -import { DisposableStore, dispose } from 'vs/base/common/lifecycle'; +import { DisposableStore, dispose, toDisposable } from 'vs/base/common/lifecycle'; import Severity from 'vs/base/common/severity'; import { getCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { localize } from 'vs/nls'; @@ -227,6 +227,7 @@ class EditorStatusContribution implements IWorkbenchContribution { } }); observer.observe(document.body, { childList: true, subtree: true }); + this._renderDisposables.add(toDisposable(() => observer.disconnect())); } } } -- cgit v1.2.3 From 14c8d53371fd2ca6fee2ffa0f0df2722410e98ac Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 6 Apr 2022 11:51:40 +0200 Subject: add background color to language status animation, https://github.com/microsoft/vscode/issues/145950 --- .../browser/languageStatus.contribution.ts | 10 +++++--- .../browser/media/languageStatus.css | 30 +++++++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts index 867ebed9818..8154e7d5bb5 100644 --- a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts +++ b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts @@ -202,16 +202,18 @@ class EditorStatusContribution implements IWorkbenchContribution { // animate the status bar icon whenever language status changes, repeat animation // when severity is warning or error, don't show animation when showing progress/busy const userHasInteractedWithStatus = this._interactionCounter.value >= 3; - const node = document.querySelector('.monaco-workbench .statusbar DIV#status\\.languageStatus span.codicon'); + const node = document.querySelector('.monaco-workbench .statusbar DIV#status\\.languageStatus A'); if (node instanceof HTMLElement) { + const _sev = `sev${first.severity}`; const _wiggle = 'wiggle'; const _repeat = 'repeat'; if (!isOneBusy) { node.classList.toggle(_wiggle, showSeverity || !userHasInteractedWithStatus); + node.classList.toggle(_sev, showSeverity || !userHasInteractedWithStatus); node.classList.toggle(_repeat, showSeverity); - this._renderDisposables.add(dom.addDisposableListener(node, 'animationend', _e => node.classList.remove(_wiggle, _repeat))); + this._renderDisposables.add(dom.addDisposableListener(node, 'animationend', _e => node.classList.remove(_wiggle, _repeat, _sev))); } else { - node.classList.remove(_wiggle, _repeat); + node.classList.remove(_wiggle, _repeat, _sev); } } @@ -226,7 +228,7 @@ class EditorStatusContribution implements IWorkbenchContribution { observer.disconnect(); } }); - observer.observe(document.body, { childList: true, subtree: true }); + observer.observe(hoverTarget, { childList: true, subtree: true }); this._renderDisposables.add(toDisposable(() => observer.disconnect())); } } diff --git a/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css b/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css index 131695f460a..247d28fe894 100644 --- a/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css +++ b/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css @@ -6,31 +6,49 @@ @keyframes wiggle { 0% { - transform: rotate(0) scale(1) + transform: rotate(0) scale(1); + opacity: 0; + } + + 30% { + opacity: .75; } 15%, 45% { - transform: rotate(.04turn) scale(1.1) + transform: rotate(.04turn) scale(1.1); } 30%, 60% { - transform: rotate(-.04turn) scale(1.2) + transform: rotate(-.04turn) scale(1.2); } 100% { - transform: rotate(0) scale(1) + transform: rotate(0) scale(1); + opacity: 0; } } -.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus span.codicon.wiggle { +.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus A.wiggle { animation-duration: .8s; animation-iteration-count: 1; animation-name: wiggle; } -.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus span.codicon.wiggle.repeat { +.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus A.wiggle.sev1 { + background-color: var(--vscode-statusBarItem-prominentBackground); +} + +.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus A.wiggle.sev2 { + background-color: var(--vscode-statusBarItem-warningBackground); +} + +.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus A.wiggle.sev3 { + background-color: var(--vscode-statusBarItem-errorBackground); +} + +.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus A.wiggle.repeat { animation-iteration-count: 3; } -- cgit v1.2.3 From 7e86d63f29392acc8c3710773ddf0549cf9833bc Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 6 Apr 2022 14:08:00 +0200 Subject: tests - disable experiments in tests --- src/vs/workbench/contrib/experiments/common/experimentService.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/experiments/common/experimentService.ts b/src/vs/workbench/contrib/experiments/common/experimentService.ts index a0d52ac4b52..0770dbb143e 100644 --- a/src/vs/workbench/contrib/experiments/common/experimentService.ts +++ b/src/vs/workbench/contrib/experiments/common/experimentService.ts @@ -21,6 +21,7 @@ import { asJson, IRequestService } from 'vs/platform/request/common/request'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService, lastSessionDateStorageKey } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspaceTagsService } from 'vs/workbench/contrib/tags/common/workspaceTags'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { ITextFileEditorModel, ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; @@ -182,7 +183,8 @@ export class ExperimentService extends Disposable implements IExperimentService @IConfigurationService private readonly configurationService: IConfigurationService, @IProductService private readonly productService: IProductService, @IWorkspaceTagsService private readonly workspaceTagsService: IWorkspaceTagsService, - @IExtensionService private readonly extensionService: IExtensionService + @IExtensionService private readonly extensionService: IExtensionService, + @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService ) { super(); @@ -227,6 +229,10 @@ export class ExperimentService extends Disposable implements IExperimentService } protected async getExperiments(): Promise { + if (this.environmentService.enableSmokeTestDriver || this.environmentService.extensionTestsLocationURI) { + return []; // TODO@sbatten add CLI argument (https://github.com/microsoft/vscode-internalbacklog/issues/2855) + } + const experimentsUrl = this.configurationService.getValue('_workbench.experimentsUrl') || this.productService.experimentsUrl; if (!experimentsUrl || this.configurationService.getValue('workbench.enableExperiments') === false) { return []; -- cgit v1.2.3 From 1a36fbf049631e6e5ebb3988d8337e936e928ec1 Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 6 Apr 2022 14:16:31 +0200 Subject: add command to reset interaction counter, https://github.com/microsoft/vscode/issues/145950 --- .../browser/languageStatus.contribution.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts index 8154e7d5bb5..16337d7781d 100644 --- a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts +++ b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts @@ -28,6 +28,8 @@ import { Codicon } from 'vs/base/common/codicons'; import { IStorageService, IStorageValueChangeEvent, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { equals } from 'vs/base/common/arrays'; import { URI } from 'vs/base/common/uri'; +import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; class LanguageStatusViewModel { @@ -387,3 +389,19 @@ class EditorStatusContribution implements IWorkbenchContribution { } Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(EditorStatusContribution, LifecyclePhase.Restored); + +registerAction2(class extends Action2 { + + constructor() { + super({ + id: 'editor.inlayHints.Reset', + title: localize('reset', 'Reset Language Status Interaction Counter'), + category: localize('cat', 'View'), + f1: true + }); + } + + run(accessor: ServicesAccessor): void { + accessor.get(IStorageService).remove('languageStatus.interactCount', StorageScope.GLOBAL); + } +}); -- cgit v1.2.3 From 1df2d85c184ece806678751d3f30e185fd2cde39 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 6 Apr 2022 18:08:50 +0200 Subject: Make comments color names consistent Fixes #146813 --- src/vs/workbench/contrib/comments/browser/commentColors.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentColors.ts b/src/vs/workbench/contrib/comments/browser/commentColors.ts index 0ae19209c29..9fd3ade031c 100644 --- a/src/vs/workbench/contrib/comments/browser/commentColors.ts +++ b/src/vs/workbench/contrib/comments/browser/commentColors.ts @@ -10,8 +10,8 @@ import * as nls from 'vs/nls'; import { contrastBorder, disabledForeground, registerColor } from 'vs/platform/theme/common/colorRegistry'; import { IColorTheme } from 'vs/platform/theme/common/themeService'; -const resolvedCommentBorder = registerColor('comments.resolved.border', { dark: disabledForeground, light: disabledForeground, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('resolvedCommentBorder', 'Color of borders and arrow for resolved comments.')); -const unresolvedCommentBorder = registerColor('comments.unresolved.border', { dark: peekViewBorder, light: peekViewBorder, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('unresolvedCommentBorder', 'Color of borders and arrow for unresolved comments.')); +const resolvedCommentBorder = registerColor('editorCommentsWidget.resolvedBorder', { dark: disabledForeground, light: disabledForeground, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('resolvedCommentBorder', 'Color of borders and arrow for resolved comments.')); +const unresolvedCommentBorder = registerColor('editorCommentsWidget.unresolvedBorder', { dark: peekViewBorder, light: peekViewBorder, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('unresolvedCommentBorder', 'Color of borders and arrow for unresolved comments.')); const commentThreadStateColors = new Map([ [languages.CommentThreadState.Unresolved, unresolvedCommentBorder], -- cgit v1.2.3 From 368c39cd7a884f22fa21948e941babddafe186cb Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 6 Apr 2022 17:55:02 +0200 Subject: make fuzzyScore full match boost configurable and don't it for inline completions, https://github.com/microsoft/vscode/issues/146523 --- .../contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts index 703b333927a..0680340ed33 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts @@ -201,7 +201,7 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess item.highlights = undefined; return true; } - const score = fuzzyScore(picker.value, picker.value.toLowerCase(), 1 /*@-character*/, item.label, item.label.toLowerCase(), 0, true); + const score = fuzzyScore(picker.value, picker.value.toLowerCase(), 1 /*@-character*/, item.label, item.label.toLowerCase(), 0, { firstMatchCanBeWeak: true, boostFullMatch: true }); if (!score) { return false; } -- cgit v1.2.3 From 807596b4a21f2815fc36207b002c3ad3469f035f Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 6 Apr 2022 18:28:25 +0200 Subject: flash background with prominent color only and only for warning and error, https://github.com/microsoft/vscode/issues/145950 --- .../browser/languageStatus.contribution.ts | 19 +++++++----- .../browser/media/languageStatus.css | 35 +++++++++++----------- 2 files changed, 29 insertions(+), 25 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts index 16337d7781d..1068901ce24 100644 --- a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts +++ b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts @@ -204,18 +204,21 @@ class EditorStatusContribution implements IWorkbenchContribution { // animate the status bar icon whenever language status changes, repeat animation // when severity is warning or error, don't show animation when showing progress/busy const userHasInteractedWithStatus = this._interactionCounter.value >= 3; - const node = document.querySelector('.monaco-workbench .statusbar DIV#status\\.languageStatus A'); - if (node instanceof HTMLElement) { - const _sev = `sev${first.severity}`; + const node = document.querySelector('.monaco-workbench.enable-motion .statusbar DIV#status\\.languageStatus A>SPAN.codicon'); + const container = document.querySelector('.monaco-workbench.enable-motion .statusbar DIV#status\\.languageStatus'); + if (node instanceof HTMLElement && container) { const _wiggle = 'wiggle'; - const _repeat = 'repeat'; + const _flash = 'flash'; if (!isOneBusy) { + // wiggle icon when severe or "new" node.classList.toggle(_wiggle, showSeverity || !userHasInteractedWithStatus); - node.classList.toggle(_sev, showSeverity || !userHasInteractedWithStatus); - node.classList.toggle(_repeat, showSeverity); - this._renderDisposables.add(dom.addDisposableListener(node, 'animationend', _e => node.classList.remove(_wiggle, _repeat, _sev))); + this._renderDisposables.add(dom.addDisposableListener(node, 'animationend', _e => node.classList.remove(_wiggle))); + // flash background when severe + container.classList.toggle(_flash, showSeverity); + this._renderDisposables.add(dom.addDisposableListener(container, 'animationend', _e => container.classList.remove(_flash))); } else { - node.classList.remove(_wiggle, _repeat, _sev); + node.classList.remove(_wiggle); + container.classList.remove(_flash); } } diff --git a/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css b/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css index 247d28fe894..55ef5b103df 100644 --- a/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css +++ b/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css @@ -3,15 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +/* status bar animation */ @keyframes wiggle { 0% { transform: rotate(0) scale(1); - opacity: 0; - } - - 30% { - opacity: .75; } 15%, @@ -26,32 +22,37 @@ 100% { transform: rotate(0) scale(1); - opacity: 0; } } -.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus A.wiggle { +.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus A>SPAN.codicon.wiggle { animation-duration: .8s; animation-iteration-count: 1; animation-name: wiggle; } -.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus A.wiggle.sev1 { - background-color: var(--vscode-statusBarItem-prominentBackground); -} +@keyframes flash { + 0% { + background-color: initial; + } -.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus A.wiggle.sev2 { - background-color: var(--vscode-statusBarItem-warningBackground); -} + 50% { + background-color: var(--vscode-statusBarItem-prominentBackground); + } -.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus A.wiggle.sev3 { - background-color: var(--vscode-statusBarItem-errorBackground); + 100% { + background-color: initial; + } } -.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus A.wiggle.repeat { - animation-iteration-count: 3; +.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus.flash { + animation-duration: .8s; + animation-iteration-count: 1; + animation-name: flash; } +/* --- hover */ + .monaco-workbench .hover-language-status { display: flex; padding: 4px 8px; -- cgit v1.2.3 From 9405808b23f254e1ce619a6cdc75635a94cb8d45 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 6 Apr 2022 10:39:47 -0700 Subject: Use SELECT_KERNEL_ID other than string literal --- .../notebook/browser/contrib/editorStatusBar/editorStatusBar.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts index cb7ab0f8586..83b35ce916d 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts @@ -38,7 +38,7 @@ import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeat registerAction2(class extends Action2 { constructor() { super({ - id: '_notebook.selectKernel', + id: SELECT_KERNEL_ID, category: NOTEBOOK_ACTIONS_CATEGORY, title: { value: nls.localize('notebookActions.selectKernel', "Select Notebook Kernel"), original: 'Select Notebook Kernel' }, // precondition: NOTEBOOK_IS_ACTIVE_EDITOR, @@ -381,7 +381,7 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution { tooltip: isSuggested ? nls.localize('tooltop', "{0} (suggestion)", tooltip) : tooltip, command: SELECT_KERNEL_ID, }, - '_notebook.selectKernel', + SELECT_KERNEL_ID, StatusbarAlignment.RIGHT, 10 )); @@ -399,7 +399,7 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution { command: SELECT_KERNEL_ID, backgroundColor: { id: 'statusBarItem.prominentBackground' } }, - '_notebook.selectKernel', + SELECT_KERNEL_ID, StatusbarAlignment.RIGHT, 10 )); -- cgit v1.2.3 From d675c045f8f633c096abf4386417318885af913d Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 6 Apr 2022 11:19:09 -0700 Subject: Add additionalScrollHeight to search tree, fix #146935 --- src/vs/workbench/contrib/search/browser/searchResultsView.ts | 4 +++- src/vs/workbench/contrib/search/browser/searchView.ts | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/search/browser/searchResultsView.ts b/src/vs/workbench/contrib/search/browser/searchResultsView.ts index eebc83d22a0..976f351c60e 100644 --- a/src/vs/workbench/contrib/search/browser/searchResultsView.ts +++ b/src/vs/workbench/contrib/search/browser/searchResultsView.ts @@ -54,8 +54,10 @@ interface IMatchTemplate { export class SearchDelegate implements IListVirtualDelegate { + public static ITEM_HEIGHT = 22; + getHeight(element: RenderableMatch): number { - return 22; + return SearchDelegate.ITEM_HEIGHT; } getTemplateId(element: RenderableMatch): string { diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 90411d0caec..2984e51c32f 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -739,7 +739,8 @@ export class SearchView extends ViewPane { selectionNavigation: true, overrideStyles: { listBackground: this.getBackgroundColor() - } + }, + additionalScrollHeight: SearchDelegate.ITEM_HEIGHT })); this._register(this.tree.onContextMenu(e => this.onContextMenu(e))); const updateHasSomeCollapsible = () => this.toggleCollapseStateDelayer.trigger(() => this.hasSomeCollapsibleResultKey.set(this.hasSomeCollapsible())); -- cgit v1.2.3 From 4aa15bc4e10cff58d83befdc84e66ae84ab17528 Mon Sep 17 00:00:00 2001 From: John Murray Date: Wed, 6 Apr 2022 19:20:55 +0100 Subject: Add 'Evaluate in Debug Console' and 'Add to Watch' to palette (#146775) * Add 'Evaluate in Debug Console' and 'Add to Watch' to palette, and make 'Run to Cursor' work from there * revert unnecessary changes --- .../contrib/debug/browser/debug.contribution.ts | 5 ++++- .../contrib/debug/browser/debugEditorActions.ts | 22 ++++++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index c9e21957b98..70b236b3fbd 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -30,7 +30,7 @@ import { DebugStatusContribution } from 'vs/workbench/contrib/debug/browser/debu import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration'; import { LoadedScriptsView } from 'vs/workbench/contrib/debug/browser/loadedScriptsView'; -import { RunToCursorAction } from 'vs/workbench/contrib/debug/browser/debugEditorActions'; +import { RunToCursorAction, SelectionToReplAction, SelectionToWatchExpressionsAction } from 'vs/workbench/contrib/debug/browser/debugEditorActions'; import { WatchExpressionsView, ADD_WATCH_LABEL, REMOVE_WATCH_EXPRESSIONS_COMMAND_ID, REMOVE_WATCH_EXPRESSIONS_LABEL, ADD_WATCH_ID } from 'vs/workbench/contrib/debug/browser/watchExpressionsView'; import { VariablesView, SET_VARIABLE_ID, COPY_VALUE_ID, BREAK_WHEN_VALUE_CHANGES_ID, COPY_EVALUATE_PATH_ID, ADD_TO_WATCH_ID, BREAK_WHEN_VALUE_IS_ACCESSED_ID, BREAK_WHEN_VALUE_IS_READ_ID, VIEW_MEMORY_ID } from 'vs/workbench/contrib/debug/browser/variablesView'; import { Repl } from 'vs/workbench/contrib/debug/browser/repl'; @@ -56,6 +56,7 @@ import { EditorPaneDescriptor, IEditorPaneRegistry } from 'vs/workbench/browser/ import { DisassemblyViewInput } from 'vs/workbench/contrib/debug/common/disassemblyViewInput'; import { DebugLifecycle } from 'vs/workbench/contrib/debug/common/debugLifecycle'; import { Icon } from 'vs/platform/action/common/action'; +import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; const debugCategory = nls.localize('debugCategory', "Debug"); registerColors(); @@ -112,6 +113,8 @@ registerDebugCommandPaletteItem(FOCUS_REPL_ID, nls.localize({ comment: ['Debug i registerDebugCommandPaletteItem(JUMP_TO_CURSOR_ID, nls.localize('jumpToCursor', "Jump to Cursor"), CONTEXT_JUMP_TO_CURSOR_SUPPORTED); registerDebugCommandPaletteItem(JUMP_TO_CURSOR_ID, nls.localize('SetNextStatement', "Set Next Statement"), CONTEXT_JUMP_TO_CURSOR_SUPPORTED); registerDebugCommandPaletteItem(RunToCursorAction.ID, RunToCursorAction.LABEL, ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'))); +registerDebugCommandPaletteItem(SelectionToReplAction.ID, SelectionToReplAction.LABEL, ContextKeyExpr.and(EditorContextKeys.hasNonEmptySelection, CONTEXT_IN_DEBUG_MODE)); +registerDebugCommandPaletteItem(SelectionToWatchExpressionsAction.ID, SelectionToWatchExpressionsAction.LABEL, ContextKeyExpr.and(EditorContextKeys.hasNonEmptySelection, CONTEXT_IN_DEBUG_MODE)); registerDebugCommandPaletteItem(TOGGLE_INLINE_BREAKPOINT_ID, nls.localize('inlineBreakpoint', "Inline Breakpoint")); registerDebugCommandPaletteItem(DEBUG_START_COMMAND_ID, DEBUG_START_LABEL, ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUG_STATE.notEqualsTo(getStateLabel(State.Initializing)))); registerDebugCommandPaletteItem(DEBUG_RUN_COMMAND_ID, DEBUG_RUN_LABEL, ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUG_STATE.notEqualsTo(getStateLabel(State.Initializing)))); diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts index bcb3748c6a1..4264520e56a 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts @@ -234,13 +234,16 @@ export class RunToCursorAction extends EditorAction { } } -class SelectionToReplAction extends EditorAction { +export class SelectionToReplAction extends EditorAction { + + public static readonly ID = 'editor.debug.action.selectionToRepl'; + public static readonly LABEL = nls.localize('evaluateInDebugConsole', "Evaluate in Debug Console"); constructor() { super({ - id: 'editor.debug.action.selectionToRepl', - label: nls.localize('evaluateInDebugConsole', "Evaluate in Debug Console"), - alias: 'Evaluate', + id: SelectionToReplAction.ID, + label: SelectionToReplAction.LABEL, + alias: 'Debug: Evaluate in Console', precondition: ContextKeyExpr.and(EditorContextKeys.hasNonEmptySelection, CONTEXT_IN_DEBUG_MODE, EditorContextKeys.editorTextFocus), contextMenuOpts: { group: 'debug', @@ -264,13 +267,16 @@ class SelectionToReplAction extends EditorAction { } } -class SelectionToWatchExpressionsAction extends EditorAction { +export class SelectionToWatchExpressionsAction extends EditorAction { + + public static readonly ID = 'editor.debug.action.selectionToWatch'; + public static readonly LABEL = nls.localize('addToWatch', "Add to Watch"); constructor() { super({ - id: 'editor.debug.action.selectionToWatch', - label: nls.localize('addToWatch', "Add to Watch"), - alias: 'Add to Watch', + id: SelectionToWatchExpressionsAction.ID, + label: SelectionToWatchExpressionsAction.LABEL, + alias: 'Debug: Add to Watch', precondition: ContextKeyExpr.and(EditorContextKeys.hasNonEmptySelection, CONTEXT_IN_DEBUG_MODE, EditorContextKeys.editorTextFocus), contextMenuOpts: { group: 'debug', -- cgit v1.2.3 From 78a20cf4dbc52699aa1b55a0fd7920e59dfb041b Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Wed, 6 Apr 2022 16:20:41 -0400 Subject: update strings and editor --- .../codeEditor/browser/untitledTextEditorHint.ts | 23 ++++++++++++++++++++++ .../files/browser/fileActions.contribution.ts | 6 +++--- .../workbench/contrib/files/browser/fileActions.ts | 2 +- .../contrib/files/browser/views/explorerView.ts | 2 +- .../common/gettingStartedContent.ts | 4 ++-- .../welcomeViews/common/newFile.contribution.ts | 2 +- 6 files changed, 31 insertions(+), 8 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts index 306f9b93ce7..4f2918ddd94 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts @@ -112,6 +112,21 @@ class UntitledTextEditorHintContentWidget implements IContentWidget { language.title = localize('keyboardBindingTooltip', "{0}", languageKeybindingLabel); } this.domNode.appendChild(language); + + const or = $('span'); + or.innerText = localize('or', " or ",); + this.domNode.appendChild(or); + + const chooseEditor = $('a.choose-editor'); + chooseEditor.style.cursor = 'pointer'; + chooseEditor.innerText = localize('chooseEditor', "select a different editor"); + const chooseEditorKeyBinding = this.keybindingService.lookupKeybinding('welcome.showNewFileEntries'); + const chooseEditorKeybindingLabel = chooseEditorKeyBinding?.getLabel(); + if (chooseEditorKeybindingLabel) { + chooseEditor.title = localize('chooseEditorBindingTooltip', "{0}", chooseEditorKeybindingLabel); + } + this.domNode.appendChild(chooseEditor); + const toGetStarted = $('span'); toGetStarted.innerText = localize('toGetStarted', " to get started. Start typing to dismiss, or ",); this.domNode.appendChild(toGetStarted); @@ -136,6 +151,14 @@ class UntitledTextEditorHintContentWidget implements IContentWidget { this.toDispose.push(dom.addDisposableListener(language, GestureEventType.Tap, languageOnClickOrTap)); this.toDispose.push(Gesture.addTarget(language)); + const chooseEditorOnClickOrTap = async (e: MouseEvent) => { + e.stopPropagation(); + await this.commandService.executeCommand('welcome.showNewFileEntries', { from: 'hint' }); + }; + this.toDispose.push(dom.addDisposableListener(chooseEditor, 'click', chooseEditorOnClickOrTap)); + this.toDispose.push(dom.addDisposableListener(chooseEditor, GestureEventType.Tap, chooseEditorOnClickOrTap)); + this.toDispose.push(Gesture.addTarget(chooseEditor)); + const dontShowOnClickOrTap = () => { this.configurationService.updateValue(untitledTextEditorHintSetting, 'hidden'); this.dispose(); diff --git a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts index d88bd1c2d2b..3825aad9830 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts @@ -206,7 +206,7 @@ appendToCommandPalette(SAVE_FILES_COMMAND_ID, { value: nls.localize('saveFiles', appendToCommandPalette(REVERT_FILE_COMMAND_ID, { value: nls.localize('revert', "Revert File"), original: 'Revert File' }, category); appendToCommandPalette(COMPARE_WITH_SAVED_COMMAND_ID, { value: nls.localize('compareActiveWithSaved', "Compare Active File with Saved"), original: 'Compare Active File with Saved' }, category); appendToCommandPalette(SAVE_FILE_AS_COMMAND_ID, { value: SAVE_FILE_AS_LABEL, original: 'Save As...' }, category); -appendToCommandPalette(NEW_FILE_COMMAND_ID, { value: NEW_FILE_LABEL, original: 'New File' }, category, WorkspaceFolderCountContext.notEqualsTo('0')); +appendToCommandPalette(NEW_FILE_COMMAND_ID, { value: NEW_FILE_LABEL, original: 'New Text File' }, category, WorkspaceFolderCountContext.notEqualsTo('0')); appendToCommandPalette(NEW_FOLDER_COMMAND_ID, { value: NEW_FOLDER_LABEL, original: 'New Folder' }, category, WorkspaceFolderCountContext.notEqualsTo('0')); appendToCommandPalette(NEW_UNTITLED_FILE_COMMAND_ID, { value: NEW_UNTITLED_FILE_LABEL, original: 'New Untitled File' }, category); @@ -576,7 +576,7 @@ MenuRegistry.appendMenuItem(MenuId.ExplorerContext, { }); // Empty Editor Group Context Menu -MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroupContext, { command: { id: NEW_UNTITLED_FILE_COMMAND_ID, title: nls.localize('newFile', "New File") }, group: '1_file', order: 10 }); +MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroupContext, { command: { id: NEW_UNTITLED_FILE_COMMAND_ID, title: nls.localize('newFile', "New Text File") }, group: '1_file', order: 10 }); MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroupContext, { command: { id: 'workbench.action.quickOpen', title: nls.localize('openFile', "Open File...") }, group: '1_file', order: 20 }); // File menu @@ -585,7 +585,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, { group: '1_new', command: { id: NEW_UNTITLED_FILE_COMMAND_ID, - title: nls.localize({ key: 'miNewFile', comment: ['&& denotes a mnemonic'] }, "&&New File") + title: nls.localize({ key: 'miNewFile', comment: ['&& denotes a mnemonic'] }, "&&New Text File") }, order: 1 }); diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index d3100d24946..e482338009e 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -53,7 +53,7 @@ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteA import { IPathService } from 'vs/workbench/services/path/common/pathService'; export const NEW_FILE_COMMAND_ID = 'explorer.newFile'; -export const NEW_FILE_LABEL = nls.localize('newFile', "New File"); +export const NEW_FILE_LABEL = nls.localize('newFile', "New Text File"); export const NEW_FOLDER_COMMAND_ID = 'explorer.newFolder'; export const NEW_FOLDER_LABEL = nls.localize('newFolder', "New Folder"); export const TRIGGER_RENAME_LABEL = nls.localize('rename', "Rename"); diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index c82cc35150a..a7885058f6a 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -891,7 +891,7 @@ registerAction2(class extends Action2 { constructor() { super({ id: 'workbench.files.action.createFileFromExplorer', - title: nls.localize('createNewFile', "New File"), + title: nls.localize('createNewEditor', "New Editor"), f1: false, icon: Codicon.newFile, precondition: ExplorerResourceNotReadonlyContext, diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/common/gettingStartedContent.ts b/src/vs/workbench/contrib/welcomeGettingStarted/common/gettingStartedContent.ts index a091be87b19..ac4305b3e3d 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/common/gettingStartedContent.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/common/gettingStartedContent.ts @@ -57,8 +57,8 @@ type GettingStartedStartEntryContent = BuiltinGettingStartedStartEntry[]; export const startEntries: GettingStartedStartEntryContent = [ { id: 'welcome.showNewFileEntries', - title: localize('gettingStarted.newFile.title', "New File..."), - description: localize('gettingStarted.newFile.description', "Open a new untitled file, notebook, or custom editor."), + title: localize('gettingStarted.newEditor.title', "New Editor..."), + description: localize('gettingStarted.newEditor.description', "Open a new untitled file, notebook, or custom editor."), icon: Codicon.newFile, content: { type: 'startEntry', diff --git a/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts b/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts index 7e54169a228..1fe5734dd99 100644 --- a/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts +++ b/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts @@ -25,7 +25,7 @@ registerAction2(class extends Action2 { constructor() { super({ id: 'welcome.showNewFileEntries', - title: { value: localize('welcome.newFile', "New File..."), original: 'New File...' }, + title: { value: localize('welcome.newEditor', "New Editor..."), original: 'New Editor...' }, category, f1: true, keybinding: { -- cgit v1.2.3 From a3d53f76790d8c88f835afe85225ff6442703409 Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Wed, 6 Apr 2022 16:05:53 -0700 Subject: Add language-specific scope widget indicators (#146343) Fixes #145716 --- .../preferences/browser/preferencesWidgets.ts | 42 ++++++++++++++++------ .../contrib/preferences/browser/settingsEditor2.ts | 2 ++ 2 files changed, 34 insertions(+), 10 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts index 9ec6a0b1083..4c942330f52 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts @@ -36,6 +36,7 @@ import { PANEL_ACTIVE_TITLE_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIV import { settingsEditIcon, settingsScopeDropDownIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; +import { ILanguageService } from 'vs/editor/common/languages/language'; export class FolderSettingsActionViewItem extends BaseActionViewItem { @@ -216,6 +217,7 @@ export class SettingsTargetsWidget extends Widget { private userLocalSettings!: Action; private userRemoteSettings!: Action; private workspaceSettings!: Action; + private folderSettingsAction!: Action; private folderSettings!: FolderSettingsActionViewItem; private options: ISettingsTargetsWidgetOptions; @@ -232,6 +234,7 @@ export class SettingsTargetsWidget extends Widget { @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, @ILabelService private readonly labelService: ILabelService, @IPreferencesService private readonly preferencesService: IPreferencesService, + @ILanguageService private readonly languageService: ILanguageService, ) { super(); this.options = options || {}; @@ -240,6 +243,15 @@ export class SettingsTargetsWidget extends Widget { this._register(this.contextService.onDidChangeWorkspaceFolders(() => this.update())); } + private resetLabels() { + const remoteAuthority = this.environmentService.remoteAuthority; + const hostLabel = remoteAuthority && this.labelService.getHostLabel(Schemas.vscodeRemote, remoteAuthority); + this.userLocalSettings.label = localize('userSettings', "User"); + this.userRemoteSettings.label = localize('userSettingsRemote', "Remote") + (hostLabel ? ` [${hostLabel}]` : ''); + this.workspaceSettings.label = localize('workspaceSettings', "Workspace"); + this.folderSettingsAction.label = localize('folderSettings', "Folder"); + } + private create(parent: HTMLElement): void { const settingsTabsWidget = DOM.append(parent, DOM.$('.settings-tabs-widget')); this.settingsSwitcherBar = this._register(new ActionBar(settingsTabsWidget, { @@ -250,31 +262,28 @@ export class SettingsTargetsWidget extends Widget { actionViewItemProvider: (action: IAction) => action.id === 'folderSettings' ? this.folderSettings : undefined })); - this.userLocalSettings = new Action('userSettings', localize('userSettings', "User"), '.settings-tab', true, () => this.updateTarget(ConfigurationTarget.USER_LOCAL)); + this.userLocalSettings = new Action('userSettings', '', '.settings-tab', true, () => this.updateTarget(ConfigurationTarget.USER_LOCAL)); this.preferencesService.getEditableSettingsURI(ConfigurationTarget.USER_LOCAL).then(uri => { // Don't wait to create UI on resolving remote this.userLocalSettings.tooltip = uri?.fsPath || ''; }); - const remoteAuthority = this.environmentService.remoteAuthority; - const hostLabel = remoteAuthority && this.labelService.getHostLabel(Schemas.vscodeRemote, remoteAuthority); - const remoteSettingsLabel = localize('userSettingsRemote', "Remote") + - (hostLabel ? ` [${hostLabel}]` : ''); - this.userRemoteSettings = new Action('userSettingsRemote', remoteSettingsLabel, '.settings-tab', true, () => this.updateTarget(ConfigurationTarget.USER_REMOTE)); + this.userRemoteSettings = new Action('userSettingsRemote', '', '.settings-tab', true, () => this.updateTarget(ConfigurationTarget.USER_REMOTE)); this.preferencesService.getEditableSettingsURI(ConfigurationTarget.USER_REMOTE).then(uri => { this.userRemoteSettings.tooltip = uri?.fsPath || ''; }); - this.workspaceSettings = new Action('workspaceSettings', localize('workspaceSettings', "Workspace"), '.settings-tab', false, () => this.updateTarget(ConfigurationTarget.WORKSPACE)); + this.workspaceSettings = new Action('workspaceSettings', '', '.settings-tab', false, () => this.updateTarget(ConfigurationTarget.WORKSPACE)); - const folderSettingsAction = new Action('folderSettings', localize('folderSettings', "Folder"), '.settings-tab', false, async folder => { + this.folderSettingsAction = new Action('folderSettings', '', '.settings-tab', false, async folder => { this.updateTarget(isWorkspaceFolder(folder) ? folder.uri : ConfigurationTarget.USER_LOCAL); }); - this.folderSettings = this.instantiationService.createInstance(FolderSettingsActionViewItem, folderSettingsAction); + this.folderSettings = this.instantiationService.createInstance(FolderSettingsActionViewItem, this.folderSettingsAction); + this.resetLabels(); this.update(); - this.settingsSwitcherBar.push([this.userLocalSettings, this.userRemoteSettings, this.workspaceSettings, folderSettingsAction]); + this.settingsSwitcherBar.push([this.userLocalSettings, this.userRemoteSettings, this.workspaceSettings, this.folderSettingsAction]); } get settingsTarget(): SettingsTarget | null { @@ -314,6 +323,19 @@ export class SettingsTargetsWidget extends Widget { } } + updateLanguageFilterIndicators(filter: string | undefined) { + this.resetLabels(); + if (filter) { + const languageToUse = this.languageService.getLanguageName(filter); + if (languageToUse) { + this.userLocalSettings.label += ` [${languageToUse}]`; + this.userRemoteSettings.label += ` [${languageToUse}]`; + this.workspaceSettings.label += ` [${languageToUse}]`; + this.folderSettingsAction.label += ` [${languageToUse}]`; + } + } + } + private onWorkbenchStateChanged(): void { this.folderSettings.folder = null; this.update(); diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 77942bbbf0a..938d0029a08 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -1304,6 +1304,8 @@ export class SettingsEditor2 extends EditorPane { this.viewState.languageFilter = parsedQuery.languageFilter; } + this.settingsTargetsWidget.updateLanguageFilterIndicators(this.viewState.languageFilter); + if (query && query !== '@') { query = this.parseSettingFromJSON(query) || query; return this.triggerFilterPreferences(query); -- cgit v1.2.3 From d1cb6c96928c2fa314841767ea109dd932ba1d68 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 6 Apr 2022 22:27:45 -0700 Subject: Fix #146761 --- src/vs/workbench/contrib/files/common/explorerModel.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/common/explorerModel.ts b/src/vs/workbench/contrib/files/common/explorerModel.ts index dfc1c9effc5..b0ae19eedba 100644 --- a/src/vs/workbench/contrib/files/common/explorerModel.ts +++ b/src/vs/workbench/contrib/files/common/explorerModel.ts @@ -374,7 +374,10 @@ export class ExplorerItem { .filter(entry => typeof (entry[0]) === 'string' && typeof (entry[1]) === 'string' && entry[0] && entry[1]) .map(([parentPattern, childrenPatterns]) => - [parentPattern.trim(), childrenPatterns.split(',').map(p => this.getPlatformAwareName(p.trim().replace(/\u200b/g, '')))] as [string, string[]]); + [ + this.getPlatformAwareName(parentPattern.trim()), + childrenPatterns.split(',').map(p => this.getPlatformAwareName(p.trim().replace(/\u200b/g, ''))) + ] as [string, string[]]); this.root._fileNester = new ExplorerFileNestingTrie(patterns); } -- cgit v1.2.3 From d2663decf774f5ca5472c25d55e9e47e0c3b9ad3 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 7 Apr 2022 11:09:38 +0200 Subject: Show commment on last line of range and update internals (#146916) Part of #146510 --- .../contrib/comments/browser/commentGlyphWidget.ts | 2 +- .../comments/browser/commentThreadZoneWidget.ts | 14 +++- .../comments/browser/commentsEditorContribution.ts | 79 +++++++++++++--------- 3 files changed, 59 insertions(+), 36 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentGlyphWidget.ts b/src/vs/workbench/contrib/comments/browser/commentGlyphWidget.ts index 71be0f04c36..7be06df3a41 100644 --- a/src/vs/workbench/contrib/comments/browser/commentGlyphWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentGlyphWidget.ts @@ -62,7 +62,7 @@ export class CommentGlyphWidget { return { position: { - lineNumber: range ? range.startLineNumber : this._lineNumber, + lineNumber: range ? range.endLineNumber : this._lineNumber, column: 1 }, preference: [ContentWidgetPositionPreference.EXACT] diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts index d7832f4c718..0e41198ccb2 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts @@ -201,7 +201,17 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget let newPosition = this.getPosition(); if (newPosition) { - this.commentService.updateCommentThreadTemplate(this.owner, this._commentThread.commentThreadHandle, new Range(newPosition.lineNumber, 1, newPosition.lineNumber, 1)); + let range: Range; + const originalRange = this._commentThread.range; + if (newPosition.lineNumber !== originalRange.endLineNumber) { + // The widget could have moved as a result of editor changes. + // We need to try to calculate the new, more correct, range for the comment. + const distance = newPosition.lineNumber - this._commentThread.range.endLineNumber; + range = new Range(originalRange.startLineNumber + distance, originalRange.startColumn, originalRange.endLineNumber + distance, originalRange.endColumn); + } else { + range = new Range(originalRange.startLineNumber, originalRange.startColumn, originalRange.endLineNumber, originalRange.endColumn); + } + this.commentService.updateCommentThreadTemplate(this.owner, this._commentThread.commentThreadHandle, range); } } }, @@ -261,7 +271,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget this._commentThreadWidget.updateCommentThread(commentThread); // Move comment glyph widget and show position if the line has changed. - const lineNumber = this._commentThread.range.startLineNumber; + const lineNumber = this._commentThread.range.endLineNumber; let shouldMoveWidget = false; if (this._commentGlyph) { if (this._commentGlyph.getPosition().position!.lineNumber !== lineNumber) { diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index a172f418ba0..79048b422ce 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -66,6 +66,13 @@ export class ReviewViewZone implements IViewZone { } } +interface CommentRangeAction { + ownerId: string; + extensionId: string | undefined; + label: string | undefined; + commentingRangesInfo: languages.CommentingRanges; +} + class CommentingRangeDecoration implements IModelDeltaDecoration { private _decorationId: string | undefined; private _startLineNumber: number; @@ -91,7 +98,7 @@ class CommentingRangeDecoration implements IModelDeltaDecoration { this._endLineNumber = _range.endLineNumber; } - public getCommentAction(): { ownerId: string; extensionId: string | undefined; label: string | undefined; commentingRangesInfo: languages.CommentingRanges } { + public getCommentAction(): CommentRangeAction { return { extensionId: this._extensionId, label: this._label, @@ -184,28 +191,35 @@ class CommentingRangeDecorator { } } - public getMatchedCommentAction(line: number) { + public getMatchedCommentAction(commentRange: Range): CommentRangeAction[] { // keys is ownerId - const foundHoverActions = new Map(); - let result = []; + const foundHoverActions = new Map(); for (const decoration of this.commentingRangeDecorations) { const range = decoration.getActiveRange(); - if (range && range.startLineNumber <= line && line <= range.endLineNumber) { + if (range && ((range.startLineNumber <= commentRange.startLineNumber) || (commentRange.endLineNumber <= range.endLineNumber))) { // We can have 3 commenting ranges that match from the same owner because of how - // the line hover decoration is done. We only want to use the action from 1 of them. + // the line hover decoration is done. + // The 3 ranges must be merged so that we can see if the new commentRange fits within them. const action = decoration.getCommentAction(); - if (decoration.isHover) { - if (foundHoverActions.get(action.ownerId) === action.commentingRangesInfo) { - continue; - } else { - foundHoverActions.set(action.ownerId, action.commentingRangesInfo); - } + const alreadyFoundInfo = foundHoverActions.get(action.ownerId); + if (alreadyFoundInfo?.action.commentingRangesInfo === action.commentingRangesInfo) { + // Merge ranges. + const newRange = new Range( + range.startLineNumber < alreadyFoundInfo.range.startLineNumber ? range.startLineNumber : alreadyFoundInfo.range.startLineNumber, + range.startColumn < alreadyFoundInfo.range.startColumn ? range.startColumn : alreadyFoundInfo.range.startColumn, + range.endLineNumber > alreadyFoundInfo.range.endLineNumber ? range.endLineNumber : alreadyFoundInfo.range.endLineNumber, + range.endColumn > alreadyFoundInfo.range.endColumn ? range.endColumn : alreadyFoundInfo.range.endColumn + ); + foundHoverActions.set(action.ownerId, { range: newRange, action }); + } else { + foundHoverActions.set(action.ownerId, { range, action }); } - result.push(action); } } - return result; + return Array.from(foundHoverActions.values()).filter(action => { + return (action.range.startLineNumber <= commentRange.startLineNumber) && (commentRange.endLineNumber <= action.range.endLineNumber); + }).map(actions => actions.action); } public dispose(): void { @@ -229,7 +243,7 @@ export class CommentController implements IEditorContribution { private _commentingRangeSpaceReserved = false; private _computePromise: CancelablePromise> | null; private _addInProgress!: boolean; - private _emptyThreadsToAddQueue: [number, IEditorMouseEvent | undefined][] = []; + private _emptyThreadsToAddQueue: [Range, IEditorMouseEvent | undefined][] = []; private _computeCommentingRangePromise!: CancelablePromise | null; private _computeCommentingRangeScheduler!: Delayer> | null; private _pendingCommentCache: { [key: string]: { [key: string]: string } }; @@ -569,26 +583,26 @@ export class CommentController implements IEditorContribution { if (e.target.element.className.indexOf('comment-diff-added') >= 0) { const lineNumber = e.target.position!.lineNumber; - this.addOrToggleCommentAtLine(lineNumber, e); + this.addOrToggleCommentAtLine(new Range(lineNumber, 1, lineNumber, 1), e); } } - public async addOrToggleCommentAtLine(lineNumber: number, e: IEditorMouseEvent | undefined): Promise { + public async addOrToggleCommentAtLine(commentRange: Range, e: IEditorMouseEvent | undefined): Promise { // If an add is already in progress, queue the next add and process it after the current one finishes to // prevent empty comment threads from being added to the same line. if (!this._addInProgress) { this._addInProgress = true; // The widget's position is undefined until the widget has been displayed, so rely on the glyph position instead - const existingCommentsAtLine = this._commentWidgets.filter(widget => widget.getGlyphPosition() === lineNumber); + const existingCommentsAtLine = this._commentWidgets.filter(widget => widget.getGlyphPosition() === commentRange.endLineNumber); if (existingCommentsAtLine.length) { - existingCommentsAtLine.forEach(widget => widget.toggleExpand(lineNumber)); + existingCommentsAtLine.forEach(widget => widget.toggleExpand(commentRange.endLineNumber)); this.processNextThreadToAdd(); return; } else { - this.addCommentAtLine(lineNumber, e); + this.addCommentAtLine(commentRange, e); } } else { - this._emptyThreadsToAddQueue.push([lineNumber, e]); + this._emptyThreadsToAddQueue.push([commentRange, e]); } } @@ -600,8 +614,8 @@ export class CommentController implements IEditorContribution { } } - public addCommentAtLine(lineNumber: number, e: IEditorMouseEvent | undefined): Promise { - const newCommentInfos = this._commentingRangeDecorator.getMatchedCommentAction(lineNumber); + public addCommentAtLine(range: Range, e: IEditorMouseEvent | undefined): Promise { + const newCommentInfos = this._commentingRangeDecorator.getMatchedCommentAction(range); if (!newCommentInfos.length || !this.editor.hasModel()) { return Promise.resolve(); } @@ -612,7 +626,7 @@ export class CommentController implements IEditorContribution { this.contextMenuService.showContextMenu({ getAnchor: () => anchor, - getActions: () => this.getContextMenuActions(newCommentInfos, lineNumber), + getActions: () => this.getContextMenuActions(newCommentInfos, range), getActionsContext: () => newCommentInfos.length ? newCommentInfos[0] : undefined, onHide: () => { this._addInProgress = false; } }); @@ -629,7 +643,7 @@ export class CommentController implements IEditorContribution { if (commentInfos.length) { const { ownerId } = commentInfos[0]; - this.addCommentAtLine2(lineNumber, ownerId); + this.addCommentAtLine2(range, ownerId); } }).then(() => { this._addInProgress = false; @@ -637,7 +651,7 @@ export class CommentController implements IEditorContribution { } } else { const { ownerId } = newCommentInfos[0]!; - this.addCommentAtLine2(lineNumber, ownerId); + this.addCommentAtLine2(range, ownerId); } return Promise.resolve(); @@ -656,7 +670,7 @@ export class CommentController implements IEditorContribution { return picks; } - private getContextMenuActions(commentInfos: { ownerId: string; extensionId: string | undefined; label: string | undefined; commentingRangesInfo: languages.CommentingRanges }[], lineNumber: number): IAction[] { + private getContextMenuActions(commentInfos: { ownerId: string; extensionId: string | undefined; label: string | undefined; commentingRangesInfo: languages.CommentingRanges }[], commentRange: Range): IAction[] { const actions: IAction[] = []; commentInfos.forEach(commentInfo => { @@ -668,7 +682,7 @@ export class CommentController implements IEditorContribution { undefined, true, () => { - this.addCommentAtLine2(lineNumber, ownerId); + this.addCommentAtLine2(commentRange, ownerId); return Promise.resolve(); } )); @@ -676,8 +690,7 @@ export class CommentController implements IEditorContribution { return actions; } - public addCommentAtLine2(lineNumber: number, ownerId: string) { - const range = new Range(lineNumber, 1, lineNumber, 1); + public addCommentAtLine2(range: Range, ownerId: string) { this.commentService.createCommentThreadTemplate(ownerId, this.editor.getModel()!.uri, range); this.processNextThreadToAdd(); return; @@ -848,15 +861,15 @@ CommandsRegistry.registerCommand({ return Promise.resolve(); } - const position = activeEditor.getPosition(); - return controller.addOrToggleCommentAtLine(position.lineNumber, undefined); + const position = activeEditor.getSelection(); + return controller.addOrToggleCommentAtLine(position, undefined); } }); MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: ADD_COMMENT_COMMAND, - title: nls.localize('comments.addCommand', "Add Comment on Current Line"), + title: nls.localize('comments.addCommand', "Add Comment on Current Selection"), category: 'Comments' }, when: ActiveCursorHasCommentingRange -- cgit v1.2.3 From 0de44f9786177c1a3e3f3bbef3440acb4f9b312b Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 7 Apr 2022 08:06:31 -0700 Subject: variables: allow resolving `extensionDir` (#146274) * variables: allow resolving `extensionDir` This allows us to fix https://github.com/microsoft/vscode-remote-release/issues/5516#issuecomment-911597917 It enables a new replacement in the format `${extensionDir:}` which will expand to the filesystem path where the extension is stored. This involved churn, since now resolution is always synchronous (where before the terminal took a synchronous-only path.) Additionally, changes were needed to inject this information in the variable resolver. As part of this I made the extension host resolver (used by debug and tasks) its own extension host service. * fixup! preserve object key order in resolution, add extensionDir support * fixup! address pr comments * fixup! address pr comments * fixup! address pr comments * config: fix config replacement only working for first variable per line * fixup! fix unit tests --- .../terminal/browser/terminalProcessManager.ts | 6 +-- .../browser/terminalProfileResolverService.ts | 12 +++--- .../contrib/terminal/common/environmentVariable.ts | 3 +- .../common/environmentVariableCollection.ts | 13 +++--- .../contrib/terminal/common/terminalEnvironment.ts | 46 ++++++++++----------- .../electron-sandbox/localTerminalBackend.ts | 4 +- .../common/environmentVariableCollection.test.ts | 12 +++--- .../test/common/environmentVariableService.test.ts | 4 +- .../test/common/terminalEnvironment.test.ts | 48 +++++++++++----------- 9 files changed, 74 insertions(+), 74 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index 5e749dcac5b..6c09333437c 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -388,7 +388,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce baseEnv = await this._terminalProfileResolverService.getEnvironment(this.remoteAuthority); } - const env = terminalEnvironment.createTerminalEnvironment(shellLaunchConfig, envFromConfigValue, variableResolver, this._productService.version, this._configHelper.config.detectLocale, baseEnv); + const env = await terminalEnvironment.createTerminalEnvironment(shellLaunchConfig, envFromConfigValue, variableResolver, this._productService.version, this._configHelper.config.detectLocale, baseEnv); if (!this._isDisposed && !shellLaunchConfig.strictEnv && !shellLaunchConfig.hideFromUser) { this._extEnvironmentVariableCollection = this._environmentVariableService.mergedCollection; this._register(this._environmentVariableService.onDidChangeCollections(newCollection => this._onEnvironmentVariableCollectionChange(newCollection))); @@ -398,7 +398,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce // info widget. While technically these could differ due to the slight change of a race // condition, the chance is minimal plus the impact on the user is also not that great // if it happens - it's not worth adding plumbing to sync back the resolved collection. - this._extEnvironmentVariableCollection.applyToProcessEnvironment(env, variableResolver); + await this._extEnvironmentVariableCollection.applyToProcessEnvironment(env, variableResolver); if (this._extEnvironmentVariableCollection.map.size > 0) { this.environmentVariableInfo = new EnvironmentVariableInfoChangesActive(this._extEnvironmentVariableCollection); this._onEnvironmentVariableInfoChange.fire(this.environmentVariableInfo); @@ -423,7 +423,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file); - const initialCwd = terminalEnvironment.getCwd( + const initialCwd = await terminalEnvironment.getCwd( shellLaunchConfig, userHome, variableResolver, diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProfileResolverService.ts b/src/vs/workbench/contrib/terminal/browser/terminalProfileResolverService.ts index 5885b71b3a3..0849f6676b2 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProfileResolverService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProfileResolverService.ts @@ -355,25 +355,23 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro const env = await this._context.getEnvironment(options.remoteAuthority); const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(options.remoteAuthority ? Schemas.vscodeRemote : Schemas.file); const lastActiveWorkspace = activeWorkspaceRootUri ? withNullAsUndefined(this._workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri)) : undefined; - profile.path = this._resolveVariables(profile.path, env, lastActiveWorkspace); + profile.path = await this._resolveVariables(profile.path, env, lastActiveWorkspace); // Resolve args variables if (profile.args) { if (typeof profile.args === 'string') { - profile.args = this._resolveVariables(profile.args, env, lastActiveWorkspace); + profile.args = await this._resolveVariables(profile.args, env, lastActiveWorkspace); } else { - for (let i = 0; i < profile.args.length; i++) { - profile.args[i] = this._resolveVariables(profile.args[i], env, lastActiveWorkspace); - } + profile.args = await Promise.all(profile.args.map(arg => this._resolveVariables(arg, env, lastActiveWorkspace))); } } return profile; } - private _resolveVariables(value: string, env: IProcessEnvironment, lastActiveWorkspace: IWorkspaceFolder | undefined) { + private async _resolveVariables(value: string, env: IProcessEnvironment, lastActiveWorkspace: IWorkspaceFolder | undefined) { try { - value = this._configurationResolverService.resolveWithEnvironment(env, lastActiveWorkspace, value); + value = await this._configurationResolverService.resolveWithEnvironment(env, lastActiveWorkspace, value); } catch (e) { this._logService.error(`Could not resolve shell`, e); } diff --git a/src/vs/workbench/contrib/terminal/common/environmentVariable.ts b/src/vs/workbench/contrib/terminal/common/environmentVariable.ts index c307e138dd4..1f105bfaa94 100644 --- a/src/vs/workbench/contrib/terminal/common/environmentVariable.ts +++ b/src/vs/workbench/contrib/terminal/common/environmentVariable.ts @@ -7,6 +7,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation' import { Event } from 'vs/base/common/event'; import { IProcessEnvironment } from 'vs/base/common/platform'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { VariableResolver } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; export const IEnvironmentVariableService = createDecorator('environmentVariableService'); @@ -51,7 +52,7 @@ export interface IMergedEnvironmentVariableCollection { * @param variableResolver An optional function to use to resolve variables within the * environment values. */ - applyToProcessEnvironment(env: IProcessEnvironment, variableResolver?: (str: string) => string): void; + applyToProcessEnvironment(env: IProcessEnvironment, variableResolver?: VariableResolver): Promise; /** * Generates a diff of this connection against another. Returns undefined if the collections are diff --git a/src/vs/workbench/contrib/terminal/common/environmentVariableCollection.ts b/src/vs/workbench/contrib/terminal/common/environmentVariableCollection.ts index a64ef609d29..e67f607c506 100644 --- a/src/vs/workbench/contrib/terminal/common/environmentVariableCollection.ts +++ b/src/vs/workbench/contrib/terminal/common/environmentVariableCollection.ts @@ -5,6 +5,7 @@ import { IProcessEnvironment, isWindows } from 'vs/base/common/platform'; import { EnvironmentVariableMutatorType, IEnvironmentVariableCollection, IExtensionOwnedEnvironmentVariableMutator, IMergedEnvironmentVariableCollection, IMergedEnvironmentVariableCollectionDiff } from 'vs/workbench/contrib/terminal/common/environmentVariable'; +import { VariableResolver } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; export class MergedEnvironmentVariableCollection implements IMergedEnvironmentVariableCollection { readonly map: Map = new Map(); @@ -41,16 +42,16 @@ export class MergedEnvironmentVariableCollection implements IMergedEnvironmentVa }); } - applyToProcessEnvironment(env: IProcessEnvironment, variableResolver?: (str: string) => string): void { + async applyToProcessEnvironment(env: IProcessEnvironment, variableResolver?: VariableResolver): Promise { let lowerToActualVariableNames: { [lowerKey: string]: string | undefined } | undefined; if (isWindows) { lowerToActualVariableNames = {}; Object.keys(env).forEach(e => lowerToActualVariableNames![e.toLowerCase()] = e); } - this.map.forEach((mutators, variable) => { + for (const [variable, mutators] of this.map) { const actualVariable = isWindows ? lowerToActualVariableNames![variable.toLowerCase()] || variable : variable; - mutators.forEach(mutator => { - const value = variableResolver ? variableResolver(mutator.value) : mutator.value; + for (const mutator of mutators) { + const value = variableResolver ? await variableResolver(mutator.value) : mutator.value; switch (mutator.type) { case EnvironmentVariableMutatorType.Append: env[actualVariable] = (env[actualVariable] || '') + value; @@ -62,8 +63,8 @@ export class MergedEnvironmentVariableCollection implements IMergedEnvironmentVa env[actualVariable] = value; break; } - }); - }); + } + } } diff(other: IMergedEnvironmentVariableCollection): IMergedEnvironmentVariableCollectionDiff | undefined { diff --git a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts index b1922c5cd52..80041aeb869 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts @@ -78,17 +78,17 @@ function mergeNonNullKeys(env: IProcessEnvironment, other: ITerminalEnvironment } } -function resolveConfigurationVariables(variableResolver: VariableResolver, env: ITerminalEnvironment): ITerminalEnvironment { - Object.keys(env).forEach((key) => { - const value = env[key]; +async function resolveConfigurationVariables(variableResolver: VariableResolver, env: ITerminalEnvironment): Promise { + await Promise.all(Object.entries(env).map(async ([key, value]) => { if (typeof value === 'string') { try { - env[key] = variableResolver(value); + env[key] = await variableResolver(value); } catch (e) { env[key] = value; } } - }); + })); + return env; } @@ -179,17 +179,17 @@ export function getLangEnvVariable(locale?: string): string { return parts.join('_') + '.UTF-8'; } -export function getCwd( +export async function getCwd( shell: IShellLaunchConfig, userHome: string | undefined, variableResolver: VariableResolver | undefined, root: Uri | undefined, customCwd: string | undefined, logService?: ILogService -): string { +): Promise { if (shell.cwd) { const unresolved = (typeof shell.cwd === 'object') ? shell.cwd.fsPath : shell.cwd; - const resolved = _resolveCwd(unresolved, variableResolver); + const resolved = await _resolveCwd(unresolved, variableResolver); return _sanitizeCwd(resolved || unresolved); } @@ -197,7 +197,7 @@ export function getCwd( if (!shell.ignoreConfigurationCwd && customCwd) { if (variableResolver) { - customCwd = _resolveCwd(customCwd, variableResolver, logService); + customCwd = await _resolveCwd(customCwd, variableResolver, logService); } if (customCwd) { if (path.isAbsolute(customCwd)) { @@ -216,10 +216,10 @@ export function getCwd( return _sanitizeCwd(cwd); } -function _resolveCwd(cwd: string, variableResolver: VariableResolver | undefined, logService?: ILogService): string | undefined { +async function _resolveCwd(cwd: string, variableResolver: VariableResolver | undefined, logService?: ILogService): Promise { if (variableResolver) { try { - return variableResolver(cwd); + return await variableResolver(cwd); } catch (e) { logService?.error('Could not resolve terminal cwd', e); return undefined; @@ -251,7 +251,7 @@ export type TerminalShellArgsSetting = ( | TerminalSettingId.ShellArgsLinux ); -export type VariableResolver = (str: string) => string; +export type VariableResolver = (str: string) => Promise; export function createVariableResolver(lastActiveWorkspace: IWorkspaceFolder | undefined, env: IProcessEnvironment, configurationResolverService: IConfigurationResolverService | undefined): VariableResolver | undefined { if (!configurationResolverService) { @@ -263,7 +263,7 @@ export function createVariableResolver(lastActiveWorkspace: IWorkspaceFolder | u /** * @deprecated Use ITerminalProfileResolverService */ -export function getDefaultShell( +export async function getDefaultShell( fetchSetting: (key: TerminalShellSetting) => string | undefined, defaultShell: string, isWoW64: boolean, @@ -272,7 +272,7 @@ export function getDefaultShell( logService: ILogService, useAutomationShell: boolean, platformOverride: Platform = platform -): string { +): Promise { let maybeExecutable: string | undefined; if (useAutomationShell) { // If automationShell is specified, this should override the normal setting @@ -300,7 +300,7 @@ export function getDefaultShell( if (variableResolver) { try { - executable = variableResolver(executable); + executable = await variableResolver(executable); } catch (e) { logService.error(`Could not resolve shell`, e); } @@ -312,13 +312,13 @@ export function getDefaultShell( /** * @deprecated Use ITerminalProfileResolverService */ -export function getDefaultShellArgs( +export async function getDefaultShellArgs( fetchSetting: (key: TerminalShellSetting | TerminalShellArgsSetting) => string | string[] | undefined, useAutomationShell: boolean, variableResolver: VariableResolver | undefined, logService: ILogService, platformOverride: Platform = platform, -): string | string[] { +): Promise { if (useAutomationShell) { if (!!getShellSetting(fetchSetting, 'automationShell', platformOverride)) { return []; @@ -331,13 +331,13 @@ export function getDefaultShellArgs( return []; } if (typeof args === 'string' && platformOverride === Platform.Windows) { - return variableResolver ? variableResolver(args) : args; + return variableResolver ? await variableResolver(args) : args; } if (variableResolver) { const resolvedArgs: string[] = []; for (const arg of args) { try { - resolvedArgs.push(variableResolver(arg)); + resolvedArgs.push(await variableResolver(arg)); } catch (e) { logService.error(`Could not resolve ${TerminalSettingPrefix.ShellArgs}${platformKey}`, e); resolvedArgs.push(arg); @@ -357,14 +357,14 @@ function getShellSetting( return fetchSetting(`terminal.integrated.${type}.${platformKey}`); } -export function createTerminalEnvironment( +export async function createTerminalEnvironment( shellLaunchConfig: IShellLaunchConfig, envFromConfig: ITerminalEnvironment | undefined, variableResolver: VariableResolver | undefined, version: string | undefined, detectLocale: 'auto' | 'off' | 'on', baseEnv: IProcessEnvironment -): IProcessEnvironment { +): Promise { // Create a terminal environment based on settings, launch config and permissions const env: IProcessEnvironment = {}; if (shellLaunchConfig.strictEnv) { @@ -379,10 +379,10 @@ export function createTerminalEnvironment( // Resolve env vars from config and shell if (variableResolver) { if (allowedEnvFromConfig) { - resolveConfigurationVariables(variableResolver, allowedEnvFromConfig); + await resolveConfigurationVariables(variableResolver, allowedEnvFromConfig); } if (shellLaunchConfig.env) { - resolveConfigurationVariables(variableResolver, shellLaunchConfig.env); + await resolveConfigurationVariables(variableResolver, shellLaunchConfig.env); } } diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts index c38b20757e8..b2f01c3e853 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts @@ -250,9 +250,9 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke const platformKey = isWindows ? 'windows' : (isMacintosh ? 'osx' : 'linux'); const envFromConfigValue = this._configurationService.getValue(`terminal.integrated.env.${platformKey}`); const baseEnv = await (shellLaunchConfig.useShellEnvironment ? this.getShellEnvironment() : this.getEnvironment()); - const env = terminalEnvironment.createTerminalEnvironment(shellLaunchConfig, envFromConfigValue, variableResolver, this._productService.version, this._configurationService.getValue(TerminalSettingId.DetectLocale), baseEnv); + const env = await terminalEnvironment.createTerminalEnvironment(shellLaunchConfig, envFromConfigValue, variableResolver, this._productService.version, this._configurationService.getValue(TerminalSettingId.DetectLocale), baseEnv); if (!shellLaunchConfig.strictEnv && !shellLaunchConfig.hideFromUser) { - this._environmentVariableService.mergedCollection.applyToProcessEnvironment(env, variableResolver); + await this._environmentVariableService.mergedCollection.applyToProcessEnvironment(env, variableResolver); } return env; } diff --git a/src/vs/workbench/contrib/terminal/test/common/environmentVariableCollection.test.ts b/src/vs/workbench/contrib/terminal/test/common/environmentVariableCollection.test.ts index 7b0b6594d4a..40c086a7dcc 100644 --- a/src/vs/workbench/contrib/terminal/test/common/environmentVariableCollection.test.ts +++ b/src/vs/workbench/contrib/terminal/test/common/environmentVariableCollection.test.ts @@ -78,7 +78,7 @@ suite('EnvironmentVariable - MergedEnvironmentVariableCollection', () => { }); suite('applyToProcessEnvironment', () => { - test('should apply the collection to an environment', () => { + test('should apply the collection to an environment', async () => { const merged = new MergedEnvironmentVariableCollection(new Map([ ['ext', { map: deserializeEnvironmentVariableCollection([ @@ -93,7 +93,7 @@ suite('EnvironmentVariable - MergedEnvironmentVariableCollection', () => { B: 'bar', C: 'baz' }; - merged.applyToProcessEnvironment(env); + await merged.applyToProcessEnvironment(env); deepStrictEqual(env, { A: 'a', B: 'barb', @@ -101,7 +101,7 @@ suite('EnvironmentVariable - MergedEnvironmentVariableCollection', () => { }); }); - test('should apply the collection to environment entries with no values', () => { + test('should apply the collection to environment entries with no values', async () => { const merged = new MergedEnvironmentVariableCollection(new Map([ ['ext', { map: deserializeEnvironmentVariableCollection([ @@ -112,7 +112,7 @@ suite('EnvironmentVariable - MergedEnvironmentVariableCollection', () => { }] ])); const env: IProcessEnvironment = {}; - merged.applyToProcessEnvironment(env); + await merged.applyToProcessEnvironment(env); deepStrictEqual(env, { A: 'a', B: 'b', @@ -120,7 +120,7 @@ suite('EnvironmentVariable - MergedEnvironmentVariableCollection', () => { }); }); - test('should apply to variable case insensitively on Windows only', () => { + test('should apply to variable case insensitively on Windows only', async () => { const merged = new MergedEnvironmentVariableCollection(new Map([ ['ext', { map: deserializeEnvironmentVariableCollection([ @@ -135,7 +135,7 @@ suite('EnvironmentVariable - MergedEnvironmentVariableCollection', () => { B: 'B', C: 'C' }; - merged.applyToProcessEnvironment(env); + await merged.applyToProcessEnvironment(env); if (isWindows) { deepStrictEqual(env, { A: 'a', diff --git a/src/vs/workbench/contrib/terminal/test/common/environmentVariableService.test.ts b/src/vs/workbench/contrib/terminal/test/common/environmentVariableService.test.ts index ed3269a6b83..dd391ea487d 100644 --- a/src/vs/workbench/contrib/terminal/test/common/environmentVariableService.test.ts +++ b/src/vs/workbench/contrib/terminal/test/common/environmentVariableService.test.ts @@ -87,7 +87,7 @@ suite('EnvironmentVariable - EnvironmentVariableService', () => { ]); }); - test('should correctly apply the environment values from multiple extension contributions in the correct order', () => { + test('should correctly apply the environment values from multiple extension contributions in the correct order', async () => { const collection1 = new Map(); const collection2 = new Map(); const collection3 = new Map(); @@ -109,7 +109,7 @@ suite('EnvironmentVariable - EnvironmentVariableService', () => { // Verify the entries get applied to the environment as expected const env: IProcessEnvironment = { A: 'foo' }; - environmentVariableService.mergedCollection.applyToProcessEnvironment(env); + await environmentVariableService.mergedCollection.applyToProcessEnvironment(env); deepStrictEqual(env, { A: 'a2:a3:a1' }); }); }); diff --git a/src/vs/workbench/contrib/terminal/test/common/terminalEnvironment.test.ts b/src/vs/workbench/contrib/terminal/test/common/terminalEnvironment.test.ts index ca148531c12..b3918029cd0 100644 --- a/src/vs/workbench/contrib/terminal/test/common/terminalEnvironment.test.ts +++ b/src/vs/workbench/contrib/terminal/test/common/terminalEnvironment.test.ts @@ -180,66 +180,66 @@ suite('Workbench - TerminalEnvironment', () => { strictEqual(Uri.file(a).fsPath, Uri.file(b).fsPath); } - test('should default to userHome for an empty workspace', () => { - assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, undefined), '/userHome/'); + test('should default to userHome for an empty workspace', async () => { + assertPathsMatch(await getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, undefined), '/userHome/'); }); - test('should use to the workspace if it exists', () => { - assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, Uri.file('/foo'), undefined), '/foo'); + test('should use to the workspace if it exists', async () => { + assertPathsMatch(await getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, Uri.file('/foo'), undefined), '/foo'); }); - test('should use an absolute custom cwd as is', () => { - assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, '/foo'), '/foo'); + test('should use an absolute custom cwd as is', async () => { + assertPathsMatch(await getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, '/foo'), '/foo'); }); - test('should normalize a relative custom cwd against the workspace path', () => { - assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, Uri.file('/bar'), 'foo'), '/bar/foo'); - assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, Uri.file('/bar'), './foo'), '/bar/foo'); - assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, Uri.file('/bar'), '../foo'), '/foo'); + test('should normalize a relative custom cwd against the workspace path', async () => { + assertPathsMatch(await getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, Uri.file('/bar'), 'foo'), '/bar/foo'); + assertPathsMatch(await getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, Uri.file('/bar'), './foo'), '/bar/foo'); + assertPathsMatch(await getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, Uri.file('/bar'), '../foo'), '/foo'); }); - test('should fall back for relative a custom cwd that doesn\'t have a workspace', () => { - assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, 'foo'), '/userHome/'); - assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, './foo'), '/userHome/'); - assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, '../foo'), '/userHome/'); + test('should fall back for relative a custom cwd that doesn\'t have a workspace', async () => { + assertPathsMatch(await getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, 'foo'), '/userHome/'); + assertPathsMatch(await getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, './foo'), '/userHome/'); + assertPathsMatch(await getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, '../foo'), '/userHome/'); }); - test('should ignore custom cwd when told to ignore', () => { - assertPathsMatch(getCwd({ executable: undefined, args: [], ignoreConfigurationCwd: true }, '/userHome/', undefined, Uri.file('/bar'), '/foo'), '/bar'); + test('should ignore custom cwd when told to ignore', async () => { + assertPathsMatch(await getCwd({ executable: undefined, args: [], ignoreConfigurationCwd: true }, '/userHome/', undefined, Uri.file('/bar'), '/foo'), '/bar'); }); }); suite('getDefaultShell', () => { - test('should change Sysnative to System32 in non-WoW64 systems', () => { - const shell = getDefaultShell(key => { + test('should change Sysnative to System32 in non-WoW64 systems', async () => { + const shell = await getDefaultShell(key => { return ({ 'terminal.integrated.shell.windows': 'C:\\Windows\\Sysnative\\cmd.exe' } as any)[key]; }, 'DEFAULT', false, 'C:\\Windows', undefined, {} as any, false, Platform.Windows); strictEqual(shell, 'C:\\Windows\\System32\\cmd.exe'); }); - test('should not change Sysnative to System32 in WoW64 systems', () => { - const shell = getDefaultShell(key => { + test('should not change Sysnative to System32 in WoW64 systems', async () => { + const shell = await getDefaultShell(key => { return ({ 'terminal.integrated.shell.windows': 'C:\\Windows\\Sysnative\\cmd.exe' } as any)[key]; }, 'DEFAULT', true, 'C:\\Windows', undefined, {} as any, false, Platform.Windows); strictEqual(shell, 'C:\\Windows\\Sysnative\\cmd.exe'); }); - test('should use automationShell when specified', () => { - const shell1 = getDefaultShell(key => { + test('should use automationShell when specified', async () => { + const shell1 = await getDefaultShell(key => { return ({ 'terminal.integrated.shell.windows': 'shell', 'terminal.integrated.automationShell.windows': undefined } as any)[key]; }, 'DEFAULT', false, 'C:\\Windows', undefined, {} as any, false, Platform.Windows); strictEqual(shell1, 'shell', 'automationShell was false'); - const shell2 = getDefaultShell(key => { + const shell2 = await getDefaultShell(key => { return ({ 'terminal.integrated.shell.windows': 'shell', 'terminal.integrated.automationShell.windows': undefined } as any)[key]; }, 'DEFAULT', false, 'C:\\Windows', undefined, {} as any, true, Platform.Windows); strictEqual(shell2, 'shell', 'automationShell was true'); - const shell3 = getDefaultShell(key => { + const shell3 = await getDefaultShell(key => { return ({ 'terminal.integrated.shell.windows': 'shell', 'terminal.integrated.automationShell.windows': 'automationShell' -- cgit v1.2.3 From 3a90a6a46d95a523a210d28e42e24e14c28248e2 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 6 Apr 2022 18:51:02 -0700 Subject: Add dropdown to stop/disconnect button for additional actions. Fix #134412 --- .../contrib/debug/browser/callStackView.ts | 92 ++++++++++++---------- .../contrib/debug/browser/debug.contribution.ts | 6 +- .../contrib/debug/browser/debugCommands.ts | 11 ++- .../contrib/debug/browser/debugService.ts | 6 +- .../contrib/debug/browser/debugSession.ts | 7 +- .../contrib/debug/browser/debugToolBar.ts | 89 +++++++++++++++++++-- .../contrib/debug/browser/debugViewlet.ts | 52 +++++++----- .../contrib/debug/browser/rawDebugSession.ts | 15 +++- src/vs/workbench/contrib/debug/common/debug.ts | 5 +- .../contrib/debug/common/debugViewModel.ts | 11 ++- 10 files changed, 208 insertions(+), 86 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/callStackView.ts b/src/vs/workbench/contrib/debug/browser/callStackView.ts index 687732063d7..747b990c3fc 100644 --- a/src/vs/workbench/contrib/debug/browser/callStackView.ts +++ b/src/vs/workbench/contrib/debug/browser/callStackView.ts @@ -3,50 +3,51 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { RunOnceScheduler } from 'vs/base/common/async'; import * as dom from 'vs/base/browser/dom'; -import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; -import { IDebugService, State, IStackFrame, IDebugSession, IThread, CONTEXT_CALLSTACK_ITEM_TYPE, IDebugModel, CALLSTACK_VIEW_ID, CONTEXT_DEBUG_STATE, getStateLabel, CONTEXT_STACK_FRAME_SUPPORTS_RESTART, CONTEXT_CALLSTACK_SESSION_IS_ATTACH, CONTEXT_CALLSTACK_ITEM_STOPPED, CONTEXT_CALLSTACK_SESSION_HAS_ONE_THREAD, IRawStoppedDetails } from 'vs/workbench/contrib/debug/common/debug'; -import { Thread, StackFrame, ThreadAndSessionIds } from 'vs/workbench/contrib/debug/common/debugModel'; +import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; +import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; +import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; +import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; +import { ITreeCompressionDelegate } from 'vs/base/browser/ui/tree/asyncDataTree'; +import { ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; +import { ICompressibleTreeRenderer } from 'vs/base/browser/ui/tree/objectTree'; +import { IAsyncDataSource, ITreeContextMenuEvent, ITreeNode } from 'vs/base/browser/ui/tree/tree'; +import { Action, IAction } from 'vs/base/common/actions'; +import { RunOnceScheduler } from 'vs/base/common/async'; +import { Codicon } from 'vs/base/common/codicons'; +import { Event } from 'vs/base/common/event'; +import { createMatches, FuzzyScore, IMatch } from 'vs/base/common/filters'; +import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { posix } from 'vs/base/common/path'; +import { commonSuffixLength } from 'vs/base/common/strings'; +import { localize } from 'vs/nls'; +import { Icon } from 'vs/platform/action/common/action'; +import { createAndFillInActionBarActions, createAndFillInContextMenuActions, MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { IMenu, IMenuService, MenuId, MenuItemAction, MenuRegistry, registerAction2, SubmenuItemAction } from 'vs/platform/actions/common/actions'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ContextKeyExpr, ContextKeyExpression, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { MenuId, IMenu, IMenuService, MenuItemAction, SubmenuItemAction, registerAction2, MenuRegistry } from 'vs/platform/actions/common/actions'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { renderViewTree } from 'vs/workbench/contrib/debug/browser/baseDebugView'; -import { IAction, Action } from 'vs/base/common/actions'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IContextKey, IContextKeyService, ContextKeyExpr, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; -import { ViewPane, ViewAction } from 'vs/workbench/browser/parts/views/viewPane'; import { ILabelService } from 'vs/platform/label/common/label'; -import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; -import { createAndFillInContextMenuActions, createAndFillInActionBarActions, MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; -import { ITreeNode, ITreeContextMenuEvent, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree'; import { WorkbenchCompressibleAsyncDataTree } from 'vs/platform/list/browser/listService'; -import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; -import { createMatches, FuzzyScore, IMatch } from 'vs/base/common/filters'; -import { Event } from 'vs/base/common/event'; -import { dispose, IDisposable } from 'vs/base/common/lifecycle'; -import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; -import { isSessionAttach } from 'vs/workbench/contrib/debug/common/debugUtils'; -import { STOP_ID, STOP_LABEL, DISCONNECT_ID, DISCONNECT_LABEL, RESTART_SESSION_ID, RESTART_LABEL, STEP_OVER_ID, STEP_OVER_LABEL, STEP_INTO_LABEL, STEP_INTO_ID, STEP_OUT_LABEL, STEP_OUT_ID, PAUSE_ID, PAUSE_LABEL, CONTINUE_ID, CONTINUE_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; -import { IViewDescriptorService } from 'vs/workbench/common/views'; -import { textLinkForeground } from 'vs/platform/theme/common/colorRegistry'; -import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { INotificationService } from 'vs/platform/notification/common/notification'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { textLinkForeground } from 'vs/platform/theme/common/colorRegistry'; import { attachStylerCallback } from 'vs/platform/theme/common/styler'; -import { INotificationService } from 'vs/platform/notification/common/notification'; -import { commonSuffixLength } from 'vs/base/common/strings'; -import { posix } from 'vs/base/common/path'; -import { ITreeCompressionDelegate } from 'vs/base/browser/ui/tree/asyncDataTree'; -import { ICompressibleTreeRenderer } from 'vs/base/browser/ui/tree/objectTree'; -import { ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { ViewAction, ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; +import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; +import { IViewDescriptorService } from 'vs/workbench/common/views'; +import { renderViewTree } from 'vs/workbench/contrib/debug/browser/baseDebugView'; +import { CONTINUE_ID, CONTINUE_LABEL, DISCONNECT_ID, DISCONNECT_LABEL, PAUSE_ID, PAUSE_LABEL, RESTART_LABEL, RESTART_SESSION_ID, STEP_INTO_ID, STEP_INTO_LABEL, STEP_OUT_ID, STEP_OUT_LABEL, STEP_OVER_ID, STEP_OVER_LABEL, STOP_ID, STOP_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; -import { localize } from 'vs/nls'; -import { Codicon } from 'vs/base/common/codicons'; -import { Icon } from 'vs/platform/action/common/action'; +import { createDisconnectMenuItemAction } from 'vs/workbench/contrib/debug/browser/debugToolBar'; +import { CALLSTACK_VIEW_ID, CONTEXT_CALLSTACK_ITEM_STOPPED, CONTEXT_CALLSTACK_ITEM_TYPE, CONTEXT_CALLSTACK_SESSION_HAS_ONE_THREAD, CONTEXT_CALLSTACK_SESSION_IS_ATTACH, CONTEXT_DEBUG_STATE, CONTEXT_STACK_FRAME_SUPPORTS_RESTART, getStateLabel, IDebugModel, IDebugService, IDebugSession, IRawStoppedDetails, IStackFrame, IThread, State } from 'vs/workbench/contrib/debug/common/debug'; +import { StackFrame, Thread, ThreadAndSessionIds } from 'vs/workbench/contrib/debug/common/debugModel'; +import { isSessionAttach } from 'vs/workbench/contrib/debug/common/debugUtils'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; const $ = dom.$; @@ -239,7 +240,7 @@ export class CallStackView extends ViewPane { this.dataSource = new CallStackDataSource(this.debugService); this.tree = >this.instantiationService.createInstance(WorkbenchCompressibleAsyncDataTree, 'CallStackView', treeContainer, new CallStackDelegate(), new CallStackCompressionDelegate(this.debugService), [ - new SessionsRenderer(this.menu, this.callStackItemType, this.callStackSessionIsAttach, this.callStackItemStopped, this.sessionHasOneThread, this.instantiationService), + this.instantiationService.createInstance(SessionsRenderer, this.menu, this.callStackItemType, this.callStackSessionIsAttach, this.callStackItemStopped, this.sessionHasOneThread), new ThreadsRenderer(this.menu, this.callStackItemType, this.callStackItemStopped), this.instantiationService.createInstance(StackFramesRenderer, this.callStackItemType), new ErrorsRenderer(), @@ -497,6 +498,7 @@ interface ISessionTemplateData { label: HighlightedLabel; actionBar: ActionBar; elementDisposable: IDisposable[]; + templateDisposable: IDisposable; } interface IErrorTemplateData { @@ -526,7 +528,7 @@ class SessionsRenderer implements ICompressibleTreeRenderer, private callStackItemStopped: IContextKey, private sessionHasOneThread: IContextKey, - private readonly instantiationService: IInstantiationService + @IInstantiationService private readonly instantiationService: IInstantiationService, ) { } get templateId(): string { @@ -539,8 +541,18 @@ class SessionsRenderer implements ICompressibleTreeRenderer { + if ((action.id === STOP_ID || action.id === DISCONNECT_ID) && action instanceof MenuItemAction) { + stopActionViewItemDisposables.clear(); + const item = this.instantiationService.invokeFunction(accessor => createDisconnectMenuItemAction(action as MenuItemAction, stopActionViewItemDisposables, accessor)); + if (item) { + return item; + } + } + if (action instanceof MenuItemAction) { return this.instantiationService.createInstance(MenuEntryActionViewItem, action, undefined); } else if (action instanceof SubmenuItemAction) { @@ -549,9 +561,9 @@ class SessionsRenderer implements ICompressibleTreeRenderer, _: number, data: ISessionTemplateData): void { @@ -600,7 +612,7 @@ class SessionsRenderer implements ICompressibleTreeRenderer, _: number, templateData: ISessionTemplateData): void { diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 70b236b3fbd..6e0fdd58b40 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -16,11 +16,11 @@ import { CallStackView } from 'vs/workbench/contrib/debug/browser/callStackView' import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; import { IDebugService, VIEWLET_ID, DEBUG_PANEL_ID, CONTEXT_IN_DEBUG_MODE, INTERNAL_CONSOLE_OPTIONS_SCHEMA, - CONTEXT_DEBUG_STATE, VARIABLES_VIEW_ID, CALLSTACK_VIEW_ID, WATCH_VIEW_ID, BREAKPOINTS_VIEW_ID, LOADED_SCRIPTS_VIEW_ID, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_CALLSTACK_ITEM_TYPE, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_DEBUG_UX, BREAKPOINT_EDITOR_CONTRIBUTION_ID, REPL_VIEW_ID, CONTEXT_BREAKPOINTS_EXIST, EDITOR_CONTRIBUTION_ID, CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_SET_VARIABLE_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED, CONTEXT_VARIABLE_EVALUATE_NAME_PRESENT, getStateLabel, State, CONTEXT_WATCH_ITEM_TYPE, CONTEXT_STACK_FRAME_SUPPORTS_RESTART, CONTEXT_BREAK_WHEN_VALUE_IS_READ_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_IS_ACCESSED_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED, DISASSEMBLY_VIEW_ID, CONTEXT_SET_EXPRESSION_SUPPORTED, CONTEXT_VARIABLE_IS_READONLY, CONTEXT_CAN_VIEW_MEMORY, + CONTEXT_DEBUG_STATE, VARIABLES_VIEW_ID, CALLSTACK_VIEW_ID, WATCH_VIEW_ID, BREAKPOINTS_VIEW_ID, LOADED_SCRIPTS_VIEW_ID, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_CALLSTACK_ITEM_TYPE, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_DEBUG_UX, BREAKPOINT_EDITOR_CONTRIBUTION_ID, REPL_VIEW_ID, CONTEXT_BREAKPOINTS_EXIST, EDITOR_CONTRIBUTION_ID, CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_SET_VARIABLE_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED, CONTEXT_VARIABLE_EVALUATE_NAME_PRESENT, getStateLabel, State, CONTEXT_WATCH_ITEM_TYPE, CONTEXT_STACK_FRAME_SUPPORTS_RESTART, CONTEXT_BREAK_WHEN_VALUE_IS_READ_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_IS_ACCESSED_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED, DISASSEMBLY_VIEW_ID, CONTEXT_SET_EXPRESSION_SUPPORTED, CONTEXT_VARIABLE_IS_READONLY, CONTEXT_CAN_VIEW_MEMORY, CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, } from 'vs/workbench/contrib/debug/common/debug'; import { DebugToolBar } from 'vs/workbench/contrib/debug/browser/debugToolBar'; import { DebugService } from 'vs/workbench/contrib/debug/browser/debugService'; -import { ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID, JUMP_TO_CURSOR_ID, RESTART_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, STEP_OUT_LABEL, PAUSE_LABEL, DISCONNECT_LABEL, STOP_LABEL, CONTINUE_LABEL, DEBUG_START_LABEL, DEBUG_START_COMMAND_ID, DEBUG_RUN_LABEL, DEBUG_RUN_COMMAND_ID, EDIT_EXPRESSION_COMMAND_ID, REMOVE_EXPRESSION_COMMAND_ID, SELECT_AND_START_ID, SELECT_AND_START_LABEL, SET_EXPRESSION_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import { ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID, JUMP_TO_CURSOR_ID, RESTART_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, STEP_OUT_LABEL, PAUSE_LABEL, DISCONNECT_LABEL, STOP_LABEL, CONTINUE_LABEL, DEBUG_START_LABEL, DEBUG_START_COMMAND_ID, DEBUG_RUN_LABEL, DEBUG_RUN_COMMAND_ID, EDIT_EXPRESSION_COMMAND_ID, REMOVE_EXPRESSION_COMMAND_ID, SELECT_AND_START_ID, SELECT_AND_START_LABEL, SET_EXPRESSION_COMMAND_ID, DISCONNECT_AND_SUSPEND_ID, DISCONNECT_AND_SUSPEND_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; import { StatusBarColorProvider } from 'vs/workbench/contrib/debug/browser/statusbarColorProvider'; import { IViewsRegistry, Extensions as ViewExtensions, IViewContainersRegistry, ViewContainerLocation, ViewContainer } from 'vs/workbench/common/views'; import { isMacintosh, isWeb } from 'vs/base/common/platform'; @@ -107,6 +107,7 @@ registerDebugCommandPaletteItem(STEP_INTO_ID, STEP_INTO_LABEL, CONTEXT_IN_DEBUG_ registerDebugCommandPaletteItem(STEP_OUT_ID, STEP_OUT_LABEL, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); registerDebugCommandPaletteItem(PAUSE_ID, PAUSE_LABEL, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('running')); registerDebugCommandPaletteItem(DISCONNECT_ID, DISCONNECT_LABEL, CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.or(CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED)); +registerDebugCommandPaletteItem(DISCONNECT_AND_SUSPEND_ID, DISCONNECT_AND_SUSPEND_LABEL, CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.or(CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED)); registerDebugCommandPaletteItem(STOP_ID, STOP_LABEL, CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.or(CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED)); registerDebugCommandPaletteItem(CONTINUE_ID, CONTINUE_LABEL, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); registerDebugCommandPaletteItem(FOCUS_REPL_ID, nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugFocusConsole' }, 'Focus on Debug Console View')); @@ -138,6 +139,7 @@ const registerDebugViewMenuItem = (menuId: MenuId, id: string, title: string, or }; registerDebugViewMenuItem(MenuId.DebugCallStackContext, RESTART_SESSION_ID, RESTART_LABEL, 10, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('session'), undefined, '3_modification'); registerDebugViewMenuItem(MenuId.DebugCallStackContext, DISCONNECT_ID, DISCONNECT_LABEL, 20, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('session'), undefined, '3_modification'); +registerDebugViewMenuItem(MenuId.DebugCallStackContext, DISCONNECT_AND_SUSPEND_ID, DISCONNECT_AND_SUSPEND_LABEL, 21, ContextKeyExpr.and(CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('session'), CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED), undefined, '3_modification'); registerDebugViewMenuItem(MenuId.DebugCallStackContext, STOP_ID, STOP_LABEL, 30, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('session'), undefined, '3_modification'); registerDebugViewMenuItem(MenuId.DebugCallStackContext, PAUSE_ID, PAUSE_LABEL, 10, ContextKeyExpr.and(CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('running'))); registerDebugViewMenuItem(MenuId.DebugCallStackContext, CONTINUE_ID, CONTINUE_LABEL, 10, ContextKeyExpr.and(CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('stopped'))); diff --git a/src/vs/workbench/contrib/debug/browser/debugCommands.ts b/src/vs/workbench/contrib/debug/browser/debugCommands.ts index 4a022554117..5f6e41bf0c6 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCommands.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCommands.ts @@ -44,6 +44,7 @@ export const STEP_INTO_ID = 'workbench.action.debug.stepInto'; export const STEP_OUT_ID = 'workbench.action.debug.stepOut'; export const PAUSE_ID = 'workbench.action.debug.pause'; export const DISCONNECT_ID = 'workbench.action.debug.disconnect'; +export const DISCONNECT_AND_SUSPEND_ID = 'workbench.action.debug.disconnectAndSuspend'; export const STOP_ID = 'workbench.action.debug.stop'; export const RESTART_FRAME_ID = 'workbench.action.debug.restartFrame'; export const CONTINUE_ID = 'workbench.action.debug.continue'; @@ -64,6 +65,7 @@ export const STEP_INTO_LABEL = nls.localize('stepIntoDebug', "Step Into"); export const STEP_OUT_LABEL = nls.localize('stepOutDebug', "Step Out"); export const PAUSE_LABEL = nls.localize('pauseDebug', "Pause"); export const DISCONNECT_LABEL = nls.localize('disconnect', "Disconnect"); +export const DISCONNECT_AND_SUSPEND_LABEL = nls.localize('disconnectSuspend', "Disconnect and Suspend"); export const STOP_LABEL = nls.localize('stop', "Stop"); export const CONTINUE_LABEL = nls.localize('continueDebug', "Continue"); export const FOCUS_SESSION_LABEL = nls.localize('focusSession', "Focus Session"); @@ -313,7 +315,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ } }); -async function stopHandler(accessor: ServicesAccessor, _: string, context: CallStackContext | unknown, disconnect: boolean): Promise { +async function stopHandler(accessor: ServicesAccessor, _: string, context: CallStackContext | unknown, disconnect: boolean, suspend?: boolean): Promise { const debugService = accessor.get(IDebugService); let session: IDebugSession | undefined; if (isSessionContext(context)) { @@ -329,7 +331,7 @@ async function stopHandler(accessor: ServicesAccessor, _: string, context: CallS session = session.parentSession; } - await debugService.stopSession(session, disconnect); + await debugService.stopSession(session, disconnect, suspend); } KeybindingsRegistry.registerCommandAndKeybindingRule({ @@ -340,6 +342,11 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ handler: (accessor, _, context) => stopHandler(accessor, _, context, true) }); +CommandsRegistry.registerCommand({ + id: DISCONNECT_AND_SUSPEND_ID, + handler: (accessor, _, context) => stopHandler(accessor, _, context, true, true) +}); + KeybindingsRegistry.registerCommandAndKeybindingRule({ id: STOP_ID, weight: KeybindingWeight.WorkbenchContrib, diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index 39b73ddbc29..d2665b688bd 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -801,9 +801,9 @@ export class DebugService implements IDebugService { }); } - async stopSession(session: IDebugSession | undefined, disconnect = false): Promise { + async stopSession(session: IDebugSession | undefined, disconnect = false, suspend = false): Promise { if (session) { - return disconnect ? session.disconnect() : session.terminate(); + return disconnect ? session.disconnect(undefined, suspend) : session.terminate(); } const sessions = this.model.getSessions(); @@ -815,7 +815,7 @@ export class DebugService implements IDebugService { this.cancelTokens(undefined); } - return Promise.all(sessions.map(s => disconnect ? s.disconnect() : s.terminate())); + return Promise.all(sessions.map(s => disconnect ? s.disconnect(undefined, suspend) : s.terminate())); } private async substituteVariables(launch: ILaunch | undefined, config: IConfig): Promise { diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index 6d7ec022e42..9109c4f0145 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -350,7 +350,7 @@ export class DebugSession implements IDebugSession { /** * end the current debug adapter session */ - async disconnect(restart = false): Promise { + async disconnect(restart = false, suspend = false): Promise { if (!this.raw) { // Adapter went down but it did not send a 'terminated' event, simulate like the event has been sent this.onDidExitAdapter(); @@ -358,9 +358,10 @@ export class DebugSession implements IDebugSession { this.cancelAllRequests(); if (this._options.lifecycleManagedByParent && this.parentSession) { - await this.parentSession.disconnect(restart); + await this.parentSession.disconnect(restart, suspend); } else if (this.raw) { - await this.raw.disconnect({ restart, terminateDebuggee: false }); + // TODO terminateDebuggee should be undefined by default? + await this.raw.disconnect({ restart, terminateDebuggee: false, suspendDebuggee: suspend }); } if (!restart) { diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index 8bb67ae408f..fdd1c3a61e0 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -10,11 +10,11 @@ import * as dom from 'vs/base/browser/dom'; import * as arrays from 'vs/base/common/arrays'; import { localize } from 'vs/nls'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions'; -import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; +import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, Action } from 'vs/base/common/actions'; +import { ActionBar, ActionsOrientation, IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IDebugConfiguration, IDebugService, State, CONTEXT_DEBUG_STATE, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_MULTI_SESSION_DEBUG, VIEWLET_ID } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugConfiguration, IDebugService, State, CONTEXT_DEBUG_STATE, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_MULTI_SESSION_DEBUG, VIEWLET_ID, CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED } from 'vs/workbench/contrib/debug/common/debug'; import { FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; @@ -25,14 +25,18 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { RunOnceScheduler } from 'vs/base/common/async'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { createActionViewItem, createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { IMenu, IMenuService, MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; +import { IMenu, IMenuService, MenuId, MenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions'; import { IContextKeyService, ContextKeyExpression, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle'; import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; import { debugToolBarBackground, debugToolBarBorder } from 'vs/workbench/contrib/debug/browser/debugColors'; import { URI } from 'vs/base/common/uri'; -import { CONTINUE_LABEL, CONTINUE_ID, PAUSE_ID, STOP_ID, DISCONNECT_ID, STEP_OVER_ID, STEP_INTO_ID, RESTART_SESSION_ID, STEP_OUT_ID, STEP_BACK_ID, REVERSE_CONTINUE_ID, RESTART_LABEL, STEP_OUT_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, DISCONNECT_LABEL, STOP_LABEL, PAUSE_LABEL, FOCUS_SESSION_ID, FOCUS_SESSION_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import { CONTINUE_LABEL, CONTINUE_ID, PAUSE_ID, STOP_ID, DISCONNECT_ID, STEP_OVER_ID, STEP_INTO_ID, RESTART_SESSION_ID, STEP_OUT_ID, STEP_BACK_ID, REVERSE_CONTINUE_ID, RESTART_LABEL, STEP_OUT_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, DISCONNECT_LABEL, STOP_LABEL, PAUSE_LABEL, FOCUS_SESSION_ID, FOCUS_SESSION_LABEL, DISCONNECT_AND_SUSPEND_ID, DISCONNECT_AND_SUSPEND_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; import { ICommandAction } from 'vs/platform/action/common/action'; +import { DropdownWithPrimaryActionViewItem } from 'vs/platform/actions/browser/dropdownWithPrimaryActionViewItem'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; const DEBUG_TOOLBAR_POSITION_KEY = 'debug.actionswidgetposition'; const DEBUG_TOOLBAR_Y_KEY = 'debug.actionswidgety'; @@ -51,6 +55,8 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { private isVisible = false; private isBuilt = false; + private readonly stopActionViewItemDisposables = this._register(new DisposableStore()); + constructor( @INotificationService private readonly notificationService: INotificationService, @ITelemetryService private readonly telemetryService: ITelemetryService, @@ -61,7 +67,7 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { @IThemeService themeService: IThemeService, @IInstantiationService private readonly instantiationService: IInstantiationService, @IMenuService menuService: IMenuService, - @IContextKeyService contextKeyService: IContextKeyService + @IContextKeyService contextKeyService: IContextKeyService, ) { super(themeService); @@ -80,7 +86,14 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { actionViewItemProvider: (action: IAction) => { if (action.id === FOCUS_SESSION_ID) { return this.instantiationService.createInstance(FocusSessionActionViewItem, action, undefined); + } else if (action.id === STOP_ID || action.id === DISCONNECT_ID) { + this.stopActionViewItemDisposables.clear(); + const item = this.instantiationService.invokeFunction(accessor => createDisconnectMenuItemAction(action as MenuItemAction, this.stopActionViewItemDisposables, accessor)); + if (item) { + return item; + } } + return createActionViewItem(this.instantiationService, action); } })); @@ -256,6 +269,35 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { } } +export function createDisconnectMenuItemAction(action: MenuItemAction, disposables: DisposableStore, accessor: ServicesAccessor): IActionViewItem | undefined { + const menuService = accessor.get(IMenuService); + const contextKeyService = accessor.get(IContextKeyService); + const keybindingService = accessor.get(IKeybindingService); + const instantiationService = accessor.get(IInstantiationService); + const contextMenuService = accessor.get(IContextMenuService); + + const menu = menuService.createMenu(MenuId.DebugToolBarStop, contextKeyService); + const secondary: IAction[] = []; + disposables.add(createAndFillInActionBarActions(menu, { shouldForwardArgs: true }, secondary)); + + if (!secondary.length) { + return undefined; + } + + const dropdownAction = disposables.add(new Action('notebook.moreRunActions', localize('notebook.moreRunActionsLabel', "More..."), 'codicon-chevron-down', true)); + const keybindingProvider = (action: IAction) => keybindingService.lookupKeybinding(action.id, contextKeyService); + const item = instantiationService.createInstance(DropdownWithPrimaryActionViewItem, + action as MenuItemAction, + dropdownAction, + secondary, + 'debug-stop-actions', + contextMenuService, + { + getKeyBinding: keybindingProvider + }); + return item; +} + // Debug toolbar const debugViewTitleItems: IDisposable[] = []; @@ -312,3 +354,36 @@ registerDebugToolBarItem(RESTART_SESSION_ID, RESTART_LABEL, 60, icons.debugResta registerDebugToolBarItem(STEP_BACK_ID, localize('stepBackDebug', "Step Back"), 50, icons.debugStepBack, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); registerDebugToolBarItem(REVERSE_CONTINUE_ID, localize('reverseContinue', "Reverse"), 55, icons.debugReverseContinue, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); registerDebugToolBarItem(FOCUS_SESSION_ID, FOCUS_SESSION_LABEL, 100, undefined, CONTEXT_MULTI_SESSION_DEBUG); + +MenuRegistry.appendMenuItem(MenuId.DebugToolBarStop, { + group: 'navigation', + when: ContextKeyExpr.and(CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED), + order: 0, + command: { + id: DISCONNECT_ID, + title: DISCONNECT_LABEL, + icon: icons.debugDisconnect + } +}); + +MenuRegistry.appendMenuItem(MenuId.DebugToolBarStop, { + group: 'navigation', + when: ContextKeyExpr.and(CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED), + order: 0, + command: { + id: STOP_ID, + title: STOP_LABEL, + icon: icons.debugStop + } +}); + +MenuRegistry.appendMenuItem(MenuId.DebugToolBarStop, { + group: 'navigation', + when: ContextKeyExpr.and(CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED), + order: 0, + command: { + id: DISCONNECT_AND_SUSPEND_ID, + title: DISCONNECT_AND_SUSPEND_LABEL, + icon: icons.debugDisconnect + } +}); diff --git a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts index a90416994e1..ae38d059d88 100644 --- a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts @@ -3,34 +3,35 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; +import { IAction } from 'vs/base/common/actions'; +import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle'; import 'vs/css!./media/debugViewlet'; import * as nls from 'vs/nls'; -import { IAction } from 'vs/base/common/actions'; -import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY, REPL_VIEW_ID, CONTEXT_DEBUG_STATE, ILaunch, getStateLabel, CONTEXT_DEBUGGERS_AVAILABLE } from 'vs/workbench/contrib/debug/common/debug'; -import { StartDebugActionViewItem, FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems'; +import { createActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { Action2, MenuId, MenuItemAction, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IProgressService } from 'vs/platform/progress/common/progress'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { IStorageService } from 'vs/platform/storage/common/storage'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ViewPaneContainer, ViewsSubMenu } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; -import { MenuId, registerAction2, Action2, MenuRegistry } from 'vs/platform/actions/common/actions'; -import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { createActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { ViewPaneContainer, ViewsSubMenu } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { WorkbenchStateContext } from 'vs/workbench/common/contextkeys'; import { IViewDescriptorService, IViewsService } from 'vs/workbench/common/views'; -import { WelcomeView } from 'vs/workbench/contrib/debug/browser/welcomeView'; +import { FocusSessionActionViewItem, StartDebugActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems'; +import { DEBUG_CONFIGURE_COMMAND_ID, DEBUG_CONFIGURE_LABEL, DEBUG_START_COMMAND_ID, DEBUG_START_LABEL, DISCONNECT_ID, FOCUS_SESSION_ID, SELECT_AND_START_ID, STOP_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; import { debugConfigure } from 'vs/workbench/contrib/debug/browser/debugIcons'; -import { WorkbenchStateContext } from 'vs/workbench/common/contextkeys'; -import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; -import { FOCUS_SESSION_ID, SELECT_AND_START_ID, DEBUG_CONFIGURE_COMMAND_ID, DEBUG_CONFIGURE_LABEL, DEBUG_START_LABEL, DEBUG_START_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; -import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; +import { createDisconnectMenuItemAction } from 'vs/workbench/contrib/debug/browser/debugToolBar'; +import { WelcomeView } from 'vs/workbench/contrib/debug/browser/welcomeView'; +import { BREAKPOINTS_VIEW_ID, CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUG_STATE, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY, getStateLabel, IDebugService, ILaunch, REPL_VIEW_ID, State, VIEWLET_ID } from 'vs/workbench/contrib/debug/common/debug'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; export class DebugViewPaneContainer extends ViewPaneContainer { @@ -39,6 +40,8 @@ export class DebugViewPaneContainer extends ViewPaneContainer { private breakpointView: ViewPane | undefined; private paneListeners = new Map(); + private readonly stopActionViewItemDisposables = this._register(new DisposableStore()); + constructor( @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, @ITelemetryService telemetryService: ITelemetryService, @@ -53,7 +56,7 @@ export class DebugViewPaneContainer extends ViewPaneContainer { @IConfigurationService configurationService: IConfigurationService, @IContextViewService private readonly contextViewService: IContextViewService, @IContextKeyService private readonly contextKeyService: IContextKeyService, - @IViewDescriptorService viewDescriptorService: IViewDescriptorService + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, ) { super(VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService); @@ -97,6 +100,15 @@ export class DebugViewPaneContainer extends ViewPaneContainer { if (action.id === FOCUS_SESSION_ID) { return new FocusSessionActionViewItem(action, undefined, this.debugService, this.themeService, this.contextViewService, this.configurationService); } + + if (action.id === STOP_ID || action.id === DISCONNECT_ID) { + this.stopActionViewItemDisposables.clear(); + const item = this.instantiationService.invokeFunction(accessor => createDisconnectMenuItemAction(action as MenuItemAction, this.stopActionViewItemDisposables, accessor)); + if (item) { + return item; + } + } + return createActionViewItem(this.instantiationService, action); } diff --git a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts index d1b3b798d9f..ed456ba63af 100644 --- a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts @@ -284,7 +284,8 @@ export class RawDebugSession implements IDisposable { */ disconnect(args: DebugProtocol.DisconnectArguments): Promise { const terminateDebuggee = this.capabilities.supportTerminateDebuggee ? args.terminateDebuggee : undefined; - return this.shutdown(undefined, args.restart, terminateDebuggee); + const suspendDebuggee = this.capabilities.supportSuspendDebuggee ? args.suspendDebuggee : undefined; + return this.shutdown(undefined, args.restart, terminateDebuggee, suspendDebuggee); } //---- DAP requests @@ -553,12 +554,20 @@ export class RawDebugSession implements IDisposable { //---- private - private async shutdown(error?: Error, restart = false, terminateDebuggee: boolean | undefined = undefined): Promise { + private async shutdown(error?: Error, restart = false, terminateDebuggee: boolean | undefined = undefined, suspendDebuggee: boolean | undefined = undefined): Promise { if (!this.inShutdown) { this.inShutdown = true; if (this.debugAdapter) { try { - const args = typeof terminateDebuggee === 'boolean' ? { restart, terminateDebuggee } : { restart }; + const args: DebugProtocol.DisconnectArguments = { restart }; + if (typeof terminateDebuggee === 'boolean') { + args.terminateDebuggee = terminateDebuggee; + } + + if (typeof suspendDebuggee === 'boolean') { + args.suspendDebuggee = suspendDebuggee; + } + this.send('disconnect', args, undefined, 2000); } catch (e) { // Catch the potential 'disconnect' error - no need to show it to the user since the adapter is shutting down diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index a811d3c40e8..b8e653916c5 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -80,6 +80,7 @@ export const CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED = new RawContextKey('breakWhenValueIsAccessedSupported', false, { type: 'boolean', description: nls.localize('breakWhenValueIsAccessedSupported', "True when the focused breakpoint supports to break when value is accessed.") }); export const CONTEXT_BREAK_WHEN_VALUE_IS_READ_SUPPORTED = new RawContextKey('breakWhenValueIsReadSupported', false, { type: 'boolean', description: nls.localize('breakWhenValueIsReadSupported', "True when the focused breakpoint supports to break when value is read.") }); export const CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED = new RawContextKey('terminateDebuggeeSupported', false, { type: 'boolean', description: nls.localize('terminateDebuggeeSupported', "True when the focused session supports the terminate debuggee capability.") }); +export const CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED = new RawContextKey('suspendDebuggeeSupported', false, { type: 'boolean', description: nls.localize('suspendDebuggeeSupported', "True when the focused session supports the suspend debuggee capability.") }); export const CONTEXT_VARIABLE_EVALUATE_NAME_PRESENT = new RawContextKey('variableEvaluateNamePresent', false, { type: 'boolean', description: nls.localize('variableEvaluateNamePresent', "True when the focused variable has an 'evalauteName' field set.") }); export const CONTEXT_VARIABLE_IS_READONLY = new RawContextKey('variableIsReadonly', false, { type: 'boolean', description: nls.localize('variableIsReadonly', "True when the focused variable is readonly.") }); export const CONTEXT_EXCEPTION_WIDGET_VISIBLE = new RawContextKey('exceptionWidgetVisible', false, { type: 'boolean', description: nls.localize('exceptionWidgetVisible', "True when the exception widget is visible.") }); @@ -339,7 +340,7 @@ export interface IDebugSession extends ITreeElement { launchOrAttach(config: IConfig): Promise; restart(): Promise; terminate(restart?: boolean /* false */): Promise; - disconnect(restart?: boolean /* false */): Promise; + disconnect(restart?: boolean /* false */, suspend?: boolean): Promise; sendBreakpoints(modelUri: uri, bpts: IBreakpoint[], sourceModified: boolean): Promise; sendFunctionBreakpoints(fbps: IFunctionBreakpoint[]): Promise; @@ -1073,7 +1074,7 @@ export interface IDebugService { /** * Stops the session. If no session is specified then all sessions are stopped. */ - stopSession(session: IDebugSession | undefined, disconnect?: boolean): Promise; + stopSession(session: IDebugSession | undefined, disconnect?: boolean, suspend?: boolean): Promise; /** * Makes unavailable all sources with the passed uri. Source will appear as grayed out in callstack view. diff --git a/src/vs/workbench/contrib/debug/common/debugViewModel.ts b/src/vs/workbench/contrib/debug/common/debugViewModel.ts index a6444a1f5fa..46468bb81d7 100644 --- a/src/vs/workbench/contrib/debug/common/debugViewModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugViewModel.ts @@ -5,7 +5,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { CONTEXT_DISASSEMBLE_REQUEST_SUPPORTED, CONTEXT_EXPRESSION_SELECTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_FOCUSED_STACK_FRAME_HAS_INSTRUCTION_POINTER_REFERENCE, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_MULTI_SESSION_DEBUG, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_SET_EXPRESSION_SUPPORTED, CONTEXT_SET_VARIABLE_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_STEP_INTO_TARGETS_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED, IDebugSession, IExpression, IExpressionContainer, IStackFrame, IThread, IViewModel } from 'vs/workbench/contrib/debug/common/debug'; +import { CONTEXT_DISASSEMBLE_REQUEST_SUPPORTED, CONTEXT_EXPRESSION_SELECTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_FOCUSED_STACK_FRAME_HAS_INSTRUCTION_POINTER_REFERENCE, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_MULTI_SESSION_DEBUG, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_SET_EXPRESSION_SUPPORTED, CONTEXT_SET_VARIABLE_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_STEP_INTO_TARGETS_SUPPORTED, CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED, IDebugSession, IExpression, IExpressionContainer, IStackFrame, IThread, IViewModel } from 'vs/workbench/contrib/debug/common/debug'; import { isSessionAttach } from 'vs/workbench/contrib/debug/common/debugUtils'; export class ViewModel implements IViewModel { @@ -31,7 +31,8 @@ export class ViewModel implements IViewModel { private setVariableSupported!: IContextKey; private setExpressionSupported!: IContextKey; private multiSessionDebug!: IContextKey; - private terminateDebuggeeSuported!: IContextKey; + private terminateDebuggeeSupported!: IContextKey; + private suspendDebuggeeSupported!: IContextKey; private disassembleRequestSupported!: IContextKey; private focusedStackFrameHasInstructionPointerReference!: IContextKey; @@ -47,7 +48,8 @@ export class ViewModel implements IViewModel { this.setVariableSupported = CONTEXT_SET_VARIABLE_SUPPORTED.bindTo(contextKeyService); this.setExpressionSupported = CONTEXT_SET_EXPRESSION_SUPPORTED.bindTo(contextKeyService); this.multiSessionDebug = CONTEXT_MULTI_SESSION_DEBUG.bindTo(contextKeyService); - this.terminateDebuggeeSuported = CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED.bindTo(contextKeyService); + this.terminateDebuggeeSupported = CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED.bindTo(contextKeyService); + this.suspendDebuggeeSupported = CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED.bindTo(contextKeyService); this.disassembleRequestSupported = CONTEXT_DISASSEMBLE_REQUEST_SUPPORTED.bindTo(contextKeyService); this.focusedStackFrameHasInstructionPointerReference = CONTEXT_FOCUSED_STACK_FRAME_HAS_INSTRUCTION_POINTER_REFERENCE.bindTo(contextKeyService); }); @@ -85,7 +87,8 @@ export class ViewModel implements IViewModel { this.jumpToCursorSupported.set(session ? !!session.capabilities.supportsGotoTargetsRequest : false); this.setVariableSupported.set(session ? !!session.capabilities.supportsSetVariable : false); this.setExpressionSupported.set(session ? !!session.capabilities.supportsSetExpression : false); - this.terminateDebuggeeSuported.set(session ? !!session.capabilities.supportTerminateDebuggee : false); + this.terminateDebuggeeSupported.set(session ? !!session.capabilities.supportTerminateDebuggee : false); + this.suspendDebuggeeSupported.set(session ? !!session.capabilities.supportSuspendDebuggee : false); this.disassembleRequestSupported.set(!!session?.capabilities.supportsDisassembleRequest); this.focusedStackFrameHasInstructionPointerReference.set(!!stackFrame?.instructionPointerReference); const attach = !!session && isSessionAttach(session); -- cgit v1.2.3 From ad78a1cdfec4a96fa550355dbc9b189dd9ea4c65 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 7 Apr 2022 12:18:41 -0800 Subject: Enable drop into editor for notebooks (#146966) Fixes #146961 This makes two changes: - For drag over, make sure the cellDnd sees the event before the editor widget does (using `useCapture`). This lets us avoid showing the drop into indicator when dragging notebook cells - For drag_over and drop events, don't do anything if a cell is not being dragged. This lets us drop other things into code cells --- .../contrib/notebook/browser/view/cellParts/cellDnd.ts | 13 ++++++++++--- .../contrib/notebook/browser/view/cellParts/markdownCell.ts | 1 + .../contrib/notebook/browser/view/renderers/cellRenderer.ts | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts index 8c0b8a99748..86e0a69074a 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts @@ -78,7 +78,7 @@ export class CellDragAndDropController extends Disposable { this._register(DOM.addDisposableListener(document.body, DOM.EventType.DRAG_START, this.onGlobalDragStart.bind(this), true)); this._register(DOM.addDisposableListener(document.body, DOM.EventType.DRAG_END, this.onGlobalDragEnd.bind(this), true)); - const addCellDragListener = (eventType: string, handler: (e: CellDragEvent) => void) => { + const addCellDragListener = (eventType: string, handler: (e: CellDragEvent) => void, useCapture = false) => { this._register(DOM.addDisposableListener( notebookEditor.getDomNode(), eventType, @@ -87,14 +87,21 @@ export class CellDragAndDropController extends Disposable { if (cellDragEvent) { handler(cellDragEvent); } - })); + }, useCapture)); }; addCellDragListener(DOM.EventType.DRAG_OVER, event => { + if (!this.currentDraggedCell) { + return; + } event.browserEvent.preventDefault(); + event.browserEvent.stopImmediatePropagation(); this.onCellDragover(event); - }); + }, true); addCellDragListener(DOM.EventType.DROP, event => { + if (!this.currentDraggedCell) { + return; + } event.browserEvent.preventDefault(); this.onCellDrop(event); }); diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts index bf119feb15c..b7652ba37ca 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts @@ -327,6 +327,7 @@ export class StatefulMarkdownCell extends Disposable { width: width, height: editorHeight }, + enableDropIntoEditor: true, // overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode() }, { contributions: this.notebookEditor.creationOptions.cellEditorContributions diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 39026ca2aca..2bcf55c8531 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -274,6 +274,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende width: 0, height: 0 }, + enableDropIntoEditor: true, }, { contributions: this.notebookEditor.creationOptions.cellEditorContributions }); -- cgit v1.2.3 From 897ab9567cc31477e5955a7f4b34750b6faacbaf Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 8 Apr 2022 09:13:06 +0200 Subject: editors - reload error placeholder when file is coming back --- .../contrib/debug/browser/debugTaskRunner.ts | 3 +- .../contrib/debug/browser/rawDebugSession.ts | 8 ++--- .../extensions/browser/extensionsViewlet.ts | 8 ++--- .../contrib/extensions/browser/extensionsViews.ts | 8 ++--- .../files/browser/editors/textFileEditor.ts | 7 ++--- .../files/electron-sandbox/textFileEditor.ts | 34 ++++++++++------------ .../contrib/notebook/browser/notebookEditor.ts | 7 ++--- 7 files changed, 31 insertions(+), 44 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debugTaskRunner.ts b/src/vs/workbench/contrib/debug/browser/debugTaskRunner.ts index 4c0b2af2ea0..a9a006c2a4b 100644 --- a/src/vs/workbench/contrib/debug/browser/debugTaskRunner.ts +++ b/src/vs/workbench/contrib/debug/browser/debugTaskRunner.ts @@ -15,7 +15,6 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { withUndefinedAsNull } from 'vs/base/common/types'; import { IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/markers'; import { IDebugConfiguration } from 'vs/workbench/contrib/debug/common/debug'; -import { createErrorWithActions } from 'vs/base/common/errorMessage'; import { IViewsService } from 'vs/workbench/common/views'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; @@ -158,7 +157,7 @@ export class DebugTaskRunner { const errorMessage = typeof taskId === 'string' ? nls.localize('DebugTaskNotFoundWithTaskId', "Could not find the task '{0}'.", taskId) : nls.localize('DebugTaskNotFound', "Could not find the specified task."); - return Promise.reject(createErrorWithActions(errorMessage)); + return Promise.reject(new Error(errorMessage)); } // If a task is missing the problem matcher the promise will never complete, so we need to have a workaround #35340 diff --git a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts index ed456ba63af..1f57bf3b7a9 100644 --- a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { Event, Emitter } from 'vs/base/common/event'; import * as objects from 'vs/base/common/objects'; -import { Action } from 'vs/base/common/actions'; +import { toAction } from 'vs/base/common/actions'; import * as errors from 'vs/base/common/errors'; import { createErrorWithActions } from 'vs/base/common/errorMessage'; import { formatPII, isUri } from 'vs/workbench/contrib/debug/common/debugUtils'; @@ -747,11 +747,7 @@ export class RawDebugSession implements IDisposable { const uri = URI.parse(url); // Use a suffixed id if uri invokes a command, so default 'Open launch.json' command is suppressed on dialog const actionId = uri.scheme === Schemas.command ? 'debug.moreInfo.command' : 'debug.moreInfo'; - return createErrorWithActions(userMessage, { - actions: [new Action(actionId, label, undefined, true, async () => { - this.openerService.open(uri, { allowCommands: true }); - })] - }); + return createErrorWithActions(userMessage, [toAction({ id: actionId, label, run: () => this.openerService.open(uri, { allowCommands: true }) })]); } if (showErrors && error && error.format && error.showUser) { this.notificationService.error(userMessage); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts index f51545869aa..cf3f3473212 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts @@ -719,11 +719,9 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE const message = err && err.message || ''; if (/ECONNREFUSED/.test(message)) { - const error = createErrorWithActions(localize('suggestProxyError', "Marketplace returned 'ECONNREFUSED'. Please check the 'http.proxy' setting."), { - actions: [ - new Action('open user settings', localize('open user settings', "Open User Settings"), undefined, true, () => this.preferencesService.openUserSettings()) - ] - }); + const error = createErrorWithActions(localize('suggestProxyError', "Marketplace returned 'ECONNREFUSED'. Please check the 'http.proxy' setting."), [ + new Action('open user settings', localize('open user settings', "Open User Settings"), undefined, true, () => this.preferencesService.openUserSettings()) + ]); this.notificationService.error(error); return; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts index d7455895d9e..de628c54a8d 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts @@ -972,11 +972,9 @@ export class ExtensionsListView extends ViewPane { const message = err && err.message || ''; if (/ECONNREFUSED/.test(message)) { - const error = createErrorWithActions(localize('suggestProxyError', "Marketplace returned 'ECONNREFUSED'. Please check the 'http.proxy' setting."), { - actions: [ - new Action('open user settings', localize('open user settings', "Open User Settings"), undefined, true, () => this.preferencesService.openUserSettings()) - ] - }); + const error = createErrorWithActions(localize('suggestProxyError', "Marketplace returned 'ECONNREFUSED'. Please check the 'http.proxy' setting."), [ + new Action('open user settings', localize('open user settings', "Open User Settings"), undefined, true, () => this.preferencesService.openUserSettings()) + ]); this.notificationService.error(error); return; diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts index f7eca9c59df..dc8fd63c3ae 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts @@ -26,7 +26,7 @@ import { ICodeEditorViewState, ScrollType } from 'vs/editor/common/editorCommon' import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { IErrorWithActions } from 'vs/base/common/errorMessage'; +import { createErrorWithActions } from 'vs/base/common/errorMessage'; import { EditorActivation, ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; @@ -187,8 +187,7 @@ export class TextFileEditor extends BaseTextEditor { // Offer to create a file from the error if we have a file not found and the name is valid if ((error).fileOperationResult === FileOperationResult.FILE_NOT_FOUND && await this.pathService.hasValidBasename(input.preferredResource)) { - const fileNotFoundError: FileOperationError & IErrorWithActions = new FileOperationError(localize('fileNotFoundError', "File not found"), FileOperationResult.FILE_NOT_FOUND); - fileNotFoundError.actions = [ + const fileNotFoundError = createErrorWithActions(new FileOperationError(localize('fileNotFoundError', "File not found"), FileOperationResult.FILE_NOT_FOUND), [ toAction({ id: 'workbench.files.action.createMissingFile', label: localize('createFile', "Create File"), run: async () => { await this.textFileService.create([{ resource: input.preferredResource }]); @@ -201,7 +200,7 @@ export class TextFileEditor extends BaseTextEditor { }); } }) - ]; + ]); throw fileNotFoundError; } diff --git a/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts b/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts index e4d1eee0b33..64978ce1742 100644 --- a/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts @@ -62,24 +62,22 @@ export class NativeTextFileEditor extends TextFileEditor { if ((error).fileOperationResult === FileOperationResult.FILE_EXCEEDS_MEMORY_LIMIT) { const memoryLimit = Math.max(MIN_MAX_MEMORY_SIZE_MB, +this.textResourceConfigurationService.getValue(undefined, 'files.maxMemoryForLargeFilesMB') || FALLBACK_MAX_MEMORY_SIZE_MB); - throw createErrorWithActions(localize('fileTooLargeForHeapError', "To open a file of this size, you need to restart and allow {0} to use more memory", this.productService.nameShort), { - actions: [ - toAction({ - id: 'workbench.window.action.relaunchWithIncreasedMemoryLimit', label: localize('relaunchWithIncreasedMemoryLimit', "Restart with {0} MB", memoryLimit), run: () => { - return this.nativeHostService.relaunch({ - addArgs: [ - `--max-memory=${memoryLimit}` - ] - }); - } - }), - toAction({ - id: 'workbench.window.action.configureMemoryLimit', label: localize('configureMemoryLimit', 'Configure Memory Limit'), run: () => { - return this.preferencesService.openUserSettings({ query: 'files.maxMemoryForLargeFilesMB' }); - } - }), - ] - }); + throw createErrorWithActions(localize('fileTooLargeForHeapError', "To open a file of this size, you need to restart and allow {0} to use more memory", this.productService.nameShort), [ + toAction({ + id: 'workbench.window.action.relaunchWithIncreasedMemoryLimit', label: localize('relaunchWithIncreasedMemoryLimit', "Restart with {0} MB", memoryLimit), run: () => { + return this.nativeHostService.relaunch({ + addArgs: [ + `--max-memory=${memoryLimit}` + ] + }); + } + }), + toAction({ + id: 'workbench.window.action.configureMemoryLimit', label: localize('configureMemoryLimit', 'Configure Memory Limit'), run: () => { + return this.preferencesService.openUserSettings({ query: 'files.maxMemoryForLargeFilesMB' }); + } + }), + ]); } // Fallback to handling in super type diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index 623686523fa..58edfc13e6b 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -7,7 +7,7 @@ import * as DOM from 'vs/base/browser/dom'; import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { IAction, toAction } from 'vs/base/common/actions'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { IErrorWithActions } from 'vs/base/common/errorMessage'; +import { createErrorWithActions } from 'vs/base/common/errorMessage'; import { Emitter, Event } from 'vs/base/common/event'; import { DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { extname, isEqual } from 'vs/base/common/resources'; @@ -289,8 +289,7 @@ export class NotebookEditor extends EditorPane implements IEditorPaneWithSelecti } } } catch (e) { - const error: Error & IErrorWithActions = e instanceof Error ? e : new Error(e.message); - error.actions = [ + const error = createErrorWithActions(e instanceof Error ? e : new Error(e.message), [ toAction({ id: 'workbench.notebook.action.openInTextEditor', label: localize('notebookOpenInTextEditor', "Open in Text Editor"), run: async () => { const activeEditorPane = this._editorService.activeEditorPane; @@ -317,7 +316,7 @@ export class NotebookEditor extends EditorPane implements IEditorPaneWithSelecti return; } }) - ]; + ]); throw error; } -- cgit v1.2.3 From 497e420d238db172ce1e9b8d834a4aa74f1401e9 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 8 Apr 2022 10:47:35 +0200 Subject: debug: offer configure action on debug task error fyi @bpasero @roblourens --- src/vs/workbench/contrib/debug/browser/debugTaskRunner.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debugTaskRunner.ts b/src/vs/workbench/contrib/debug/browser/debugTaskRunner.ts index a9a006c2a4b..4667fc38a3e 100644 --- a/src/vs/workbench/contrib/debug/browser/debugTaskRunner.ts +++ b/src/vs/workbench/contrib/debug/browser/debugTaskRunner.ts @@ -17,6 +17,10 @@ import { IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/marke import { IDebugConfiguration } from 'vs/workbench/contrib/debug/common/debug'; import { IViewsService } from 'vs/workbench/common/views'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +import { createErrorWithActions } from 'vs/base/common/errorMessage'; +import { Action } from 'vs/base/common/actions'; +import { DEBUG_CONFIGURE_COMMAND_ID, DEBUG_CONFIGURE_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import { ICommandService } from 'vs/platform/commands/common/commands'; function once(match: (e: TaskEvent) => boolean, event: Event): Event { return (listener, thisArgs = null, disposables?) => { @@ -47,7 +51,8 @@ export class DebugTaskRunner { @IConfigurationService private readonly configurationService: IConfigurationService, @IViewsService private readonly viewsService: IViewsService, @IDialogService private readonly dialogService: IDialogService, - @IStorageService private readonly storageService: IStorageService + @IStorageService private readonly storageService: IStorageService, + @ICommandService private readonly commandService: ICommandService ) { } cancel(): void { @@ -157,7 +162,7 @@ export class DebugTaskRunner { const errorMessage = typeof taskId === 'string' ? nls.localize('DebugTaskNotFoundWithTaskId', "Could not find the task '{0}'.", taskId) : nls.localize('DebugTaskNotFound', "Could not find the specified task."); - return Promise.reject(new Error(errorMessage)); + return Promise.reject(createErrorWithActions(errorMessage, [new Action(DEBUG_CONFIGURE_COMMAND_ID, DEBUG_CONFIGURE_LABEL, undefined, true, () => this.commandService.executeCommand(DEBUG_CONFIGURE_COMMAND_ID))])); } // If a task is missing the problem matcher the promise will never complete, so we need to have a workaround #35340 -- cgit v1.2.3 From 49b4fded1693875849bd723a2f0b6a82b9ecc518 Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Fri, 8 Apr 2022 09:59:13 -0400 Subject: Add a few sample of the new typings --- .../contrib/preferences/browser/settingsEditor2.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 938d0029a08..f925cd60830 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -1018,13 +1018,15 @@ export class SettingsEditor2 extends EditorPane { target: string; }; type SettingsEditorModifiedSettingClassification = { - key: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; owner: 'rzhao271'; comment: 'The setting that is being modified.' }; - groupId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; owner: 'rzhao271'; comment: 'Whether the setting is from the local search or remote search provider, if applicable.' }; - nlpIndex: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; owner: 'rzhao271'; comment: 'The index of the setting in the remote search provider results, if applicable.' }; - displayIndex: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; owner: 'rzhao271'; comment: 'The index of the setting in the combined search results, if applicable.' }; - showConfiguredOnly: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; 'owner': 'rzhao271'; comment: 'Whether the user is in the modified view, which shows configured settings only.' }; - isReset: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; owner: 'rzhao271'; comment: 'Identifies whether a setting was reset to its default value.' }; - target: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; owner: 'rzhao271'; comment: 'The scope of the setting, such as user or workspace.' }; + key: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The setting that is being modified.' }; + groupId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the setting is from the local search or remote search provider, if applicable.' }; + nlpIndex: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'The index of the setting in the remote search provider results, if applicable.' }; + displayIndex: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'The index of the setting in the combined search results, if applicable.' }; + showConfiguredOnly: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the user is in the modified view, which shows configured settings only.' }; + isReset: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Identifies whether a setting was reset to its default value.' }; + target: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The scope of the setting, such as user or workspace.' }; + owner: 'rzhao271'; + comment: 'Event which fires when the user modifies a setting in the settings editor'; }; this.pendingSettingUpdate = null; -- cgit v1.2.3 From b60fefb1d40de60ccafb00289d1e44255b43f626 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 8 Apr 2022 19:53:18 +0200 Subject: Opening VSCode results in a mostly blank window with some GUI outlines (fix #147086) --- .../contrib/localHistory/browser/localHistory.ts | 16 +++++++++++++++- .../contrib/localHistory/browser/localHistoryCommands.ts | 2 +- .../contrib/localHistory/browser/localHistoryTimeline.ts | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/localHistory/browser/localHistory.ts b/src/vs/workbench/contrib/localHistory/browser/localHistory.ts index c182f0ccfd1..20bd201237b 100644 --- a/src/vs/workbench/contrib/localHistory/browser/localHistory.ts +++ b/src/vs/workbench/contrib/localHistory/browser/localHistory.ts @@ -8,8 +8,22 @@ import { Codicon } from 'vs/base/common/codicons'; import { language } from 'vs/base/common/platform'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; +import { IdleValue } from 'vs/base/common/async'; -export const LOCAL_HISTORY_DATE_FORMATTER = new Intl.DateTimeFormat(language, { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' }); +export const LOCAL_HISTORY_DATE_FORMATTER: IdleValue<{ format: (timestamp: number) => string }> = new IdleValue(() => { + const options: Intl.DateTimeFormatOptions = { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' }; + + let formatter: Intl.DateTimeFormat; + try { + formatter = new Intl.DateTimeFormat(language, options); + } catch (error) { + formatter = new Intl.DateTimeFormat(undefined, options); // error can happen when language is invalid (https://github.com/microsoft/vscode/issues/147086) + } + + return { + format: date => formatter.format(date) + }; +}); export const LOCAL_HISTORY_MENU_CONTEXT_VALUE = 'localHistory:item'; export const LOCAL_HISTORY_MENU_CONTEXT_KEY = ContextKeyExpr.equals('timelineItem', LOCAL_HISTORY_MENU_CONTEXT_VALUE); diff --git a/src/vs/workbench/contrib/localHistory/browser/localHistoryCommands.ts b/src/vs/workbench/contrib/localHistory/browser/localHistoryCommands.ts index 0b2a709a069..49a5a67e8e7 100644 --- a/src/vs/workbench/contrib/localHistory/browser/localHistoryCommands.ts +++ b/src/vs/workbench/contrib/localHistory/browser/localHistoryCommands.ts @@ -632,7 +632,7 @@ export async function findLocalHistoryEntry(workingCopyHistoryService: IWorkingC const SEP = /\//g; function toLocalHistoryEntryDateLabel(timestamp: number): string { - return `${LOCAL_HISTORY_DATE_FORMATTER.format(timestamp).replace(SEP, '-')}`; // preserving `/` will break editor labels, so replace it with a non-path symbol + return `${LOCAL_HISTORY_DATE_FORMATTER.value.format(timestamp).replace(SEP, '-')}`; // preserving `/` will break editor labels, so replace it with a non-path symbol } //#endregion diff --git a/src/vs/workbench/contrib/localHistory/browser/localHistoryTimeline.ts b/src/vs/workbench/contrib/localHistory/browser/localHistoryTimeline.ts index ca34fae943c..c0e31f90dd3 100644 --- a/src/vs/workbench/contrib/localHistory/browser/localHistoryTimeline.ts +++ b/src/vs/workbench/contrib/localHistory/browser/localHistoryTimeline.ts @@ -151,7 +151,7 @@ export class LocalHistoryTimeline extends Disposable implements IWorkbenchContri return { handle: entry.id, label: SaveSourceRegistry.getSourceLabel(entry.source), - tooltip: new MarkdownString(`$(history) ${LOCAL_HISTORY_DATE_FORMATTER.format(entry.timestamp)}\n\n${SaveSourceRegistry.getSourceLabel(entry.source)}`, { supportThemeIcons: true }), + tooltip: new MarkdownString(`$(history) ${LOCAL_HISTORY_DATE_FORMATTER.value.format(entry.timestamp)}\n\n${SaveSourceRegistry.getSourceLabel(entry.source)}`, { supportThemeIcons: true }), source: LocalHistoryTimeline.ID, timestamp: entry.timestamp, themeIcon: LOCAL_HISTORY_ICON_ENTRY, -- cgit v1.2.3 From d3a0e1c0fb2bb1a20408f101ee1341103fb95f0e Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 8 Apr 2022 13:37:16 -0700 Subject: Add separate CKS for callstack view rows. Fix #144285 --- .../contrib/debug/browser/callStackView.ts | 216 ++++++++++++++------- 1 file changed, 148 insertions(+), 68 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/callStackView.ts b/src/vs/workbench/contrib/debug/browser/callStackView.ts index 747b990c3fc..035a1abc2d7 100644 --- a/src/vs/workbench/contrib/debug/browser/callStackView.ts +++ b/src/vs/workbench/contrib/debug/browser/callStackView.ts @@ -137,14 +137,9 @@ export class CallStackView extends ViewPane { private needsRefresh = false; private ignoreSelectionChangedEvent = false; private ignoreFocusStackFrameEvent = false; - private callStackItemType: IContextKey; - private callStackSessionIsAttach: IContextKey; - private callStackItemStopped: IContextKey; - private stackFrameSupportsRestart: IContextKey; - private sessionHasOneThread: IContextKey; + private dataSource!: CallStackDataSource; private tree!: WorkbenchCompressibleAsyncDataTree; - private menu: IMenu; private autoExpandedSessions = new Set(); private selectionNeedsUpdate = false; @@ -157,21 +152,13 @@ export class CallStackView extends ViewPane { @IViewDescriptorService viewDescriptorService: IViewDescriptorService, @IEditorService private readonly editorService: IEditorService, @IConfigurationService configurationService: IConfigurationService, - @IMenuService menuService: IMenuService, @IContextKeyService contextKeyService: IContextKeyService, @IOpenerService openerService: IOpenerService, @IThemeService themeService: IThemeService, - @ITelemetryService telemetryService: ITelemetryService + @ITelemetryService telemetryService: ITelemetryService, + @IMenuService private readonly menuService: IMenuService, ) { super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService); - this.callStackItemType = CONTEXT_CALLSTACK_ITEM_TYPE.bindTo(contextKeyService); - this.callStackSessionIsAttach = CONTEXT_CALLSTACK_SESSION_IS_ATTACH.bindTo(contextKeyService); - this.stackFrameSupportsRestart = CONTEXT_STACK_FRAME_SUPPORTS_RESTART.bindTo(contextKeyService); - this.callStackItemStopped = CONTEXT_CALLSTACK_ITEM_STOPPED.bindTo(contextKeyService); - this.sessionHasOneThread = CONTEXT_CALLSTACK_SESSION_HAS_ONE_THREAD.bindTo(contextKeyService); - - this.menu = menuService.createMenu(MenuId.DebugCallStackContext, contextKeyService); - this._register(this.menu); // Create scheduler to prevent unnecessary flashing of tree when reacting to changes this.onCallStackChangeScheduler = this._register(new RunOnceScheduler(async () => { @@ -240,9 +227,9 @@ export class CallStackView extends ViewPane { this.dataSource = new CallStackDataSource(this.debugService); this.tree = >this.instantiationService.createInstance(WorkbenchCompressibleAsyncDataTree, 'CallStackView', treeContainer, new CallStackDelegate(), new CallStackCompressionDelegate(this.debugService), [ - this.instantiationService.createInstance(SessionsRenderer, this.menu, this.callStackItemType, this.callStackSessionIsAttach, this.callStackItemStopped, this.sessionHasOneThread), - new ThreadsRenderer(this.menu, this.callStackItemType, this.callStackItemStopped), - this.instantiationService.createInstance(StackFramesRenderer, this.callStackItemType), + this.instantiationService.createInstance(SessionsRenderer), + this.instantiationService.createInstance(ThreadsRenderer), + this.instantiationService.createInstance(StackFramesRenderer), new ErrorsRenderer(), new LoadAllRenderer(this.themeService), new ShowMoreRenderer(this.themeService) @@ -456,22 +443,21 @@ export class CallStackView extends ViewPane { private onContextMenu(e: ITreeContextMenuEvent): void { const element = e.element; - this.stackFrameSupportsRestart.reset(); + let overlay: [string, any][] = []; if (isDebugSession(element)) { - this.callStackItemType.set('session'); + overlay = getSessionContextOverlay(element); } else if (element instanceof Thread) { - this.callStackItemType.set('thread'); + overlay = getThreadContextOverlay(element); } else if (element instanceof StackFrame) { - this.callStackItemType.set('stackFrame'); - this.stackFrameSupportsRestart.set(element.canRestart); - } else { - this.callStackItemType.reset(); + overlay = getStackFrameContextOverlay(element); } const primary: IAction[] = []; const secondary: IAction[] = []; const result = { primary, secondary }; - const actionsDisposable = createAndFillInContextMenuActions(this.menu, { arg: getContextForContributedActions(element), shouldForwardArgs: true }, result, 'inline'); + const contextKeyService = this.contextKeyService.createOverlay(overlay); + const menu = this.menuService.createMenu(MenuId.DebugCallStackContext, contextKeyService); + const actionsDisposable = createAndFillInContextMenuActions(menu, { arg: getContextForContributedActions(element), shouldForwardArgs: true }, result, 'inline'); this.contextMenuService.showContextMenu({ getAnchor: () => e.anchor, @@ -488,7 +474,10 @@ interface IThreadTemplateData { stateLabel: HTMLSpanElement; label: HighlightedLabel; actionBar: ActionBar; - elementDisposable: IDisposable[]; + menu: IMenu; + contextKeyHelper: ThreadRendererContextKeyHelper; + elementDisposable: DisposableStore; + templateDisposable: IDisposable; } interface ISessionTemplateData { @@ -496,8 +485,10 @@ interface ISessionTemplateData { name: HTMLElement; stateLabel: HTMLSpanElement; label: HighlightedLabel; + menu: IMenu; actionBar: ActionBar; - elementDisposable: IDisposable[]; + contextKeyHelper: SessionRendererContextKeyHelper; + elementDisposable: DisposableStore; templateDisposable: IDisposable; } @@ -517,18 +508,48 @@ interface IStackFrameTemplateData { lineNumber: HTMLElement; label: HighlightedLabel; actionBar: ActionBar; + templateDisposable: IDisposable; +} + +class SessionRendererContextKeyHelper { + private callStackItemType: IContextKey; + private callStackSessionIsAttach: IContextKey; + private callStackItemStopped: IContextKey; + private sessionHasOneThread: IContextKey; + + constructor( + contextKeyService: IContextKeyService + ) { + this.callStackItemType = CONTEXT_CALLSTACK_ITEM_TYPE.bindTo(contextKeyService); + this.callStackSessionIsAttach = CONTEXT_CALLSTACK_SESSION_IS_ATTACH.bindTo(contextKeyService); + this.callStackItemStopped = CONTEXT_CALLSTACK_ITEM_STOPPED.bindTo(contextKeyService); + this.sessionHasOneThread = CONTEXT_CALLSTACK_SESSION_HAS_ONE_THREAD.bindTo(contextKeyService); + this.callStackItemType.set('session'); + } + + update(session: IDebugSession) { + this.callStackSessionIsAttach.set(isSessionAttach(session)); + this.callStackItemStopped.set(session.state === State.Stopped); + this.sessionHasOneThread.set(session.getAllThreads().length === 1); + } +} + +function getSessionContextOverlay(session: IDebugSession): [string, any][] { + return [ + [CONTEXT_CALLSTACK_ITEM_TYPE.key, 'session'], + [CONTEXT_CALLSTACK_SESSION_IS_ATTACH.key, isSessionAttach(session)], + [CONTEXT_CALLSTACK_ITEM_STOPPED.key, session.state === State.Stopped], + [CONTEXT_CALLSTACK_SESSION_HAS_ONE_THREAD.key, session.getAllThreads().length === 1], + ]; } class SessionsRenderer implements ICompressibleTreeRenderer { static readonly ID = 'session'; constructor( - private menu: IMenu, - private callStackItemType: IContextKey, - private callStackSessionIsAttach: IContextKey, - private callStackItemStopped: IContextKey, - private sessionHasOneThread: IContextKey, @IInstantiationService private readonly instantiationService: IInstantiationService, + @IContextKeyService private readonly contextKeyService: IContextKeyService, + @IMenuService private readonly menuService: IMenuService, ) { } get templateId(): string { @@ -542,6 +563,11 @@ class SessionsRenderer implements ICompressibleTreeRenderer { @@ -563,7 +589,8 @@ class SessionsRenderer implements ICompressibleTreeRenderer, _: number, data: ISessionTemplateData): void { @@ -581,20 +608,26 @@ class SessionsRenderer implements ICompressibleTreeRenderer t.stopped); - const primary: IAction[] = []; - const secondary: IAction[] = []; - const result = { primary, secondary }; - this.callStackItemType.set('session'); - this.callStackItemStopped.set(session.state === State.Stopped); - this.sessionHasOneThread.set(session.getAllThreads().length === 1); - this.callStackSessionIsAttach.set(isSessionAttach(session)); - data.elementDisposable.push(createAndFillInActionBarActions(this.menu, { arg: getContextForContributedActions(session), shouldForwardArgs: true }, result, 'inline')); - data.actionBar.clear(); - data.actionBar.push(primary, { icon: true, label: false }); - // We need to set our internal context on the action bar, since our commands depend on that one - // While the external context our extensions rely on - data.actionBar.context = getContext(session); + data.contextKeyHelper.update(session); + const menuDisposables = data.elementDisposable.add(new DisposableStore()); + const setupActionBar = () => { + menuDisposables.clear(); + data.actionBar.clear(); + + const primary: IAction[] = []; + const secondary: IAction[] = []; + const result = { primary, secondary }; + + menuDisposables.add(createAndFillInActionBarActions(data.menu, { arg: getContextForContributedActions(session), shouldForwardArgs: true }, result, 'inline')); + data.actionBar.push(primary, { icon: true, label: false }); + // We need to set our internal context on the action bar, since our commands depend on that one + // While the external context our extensions rely on + data.actionBar.context = getContext(session); + }; + data.elementDisposable.add(data.menu.onDidChange(() => setupActionBar())); + setupActionBar(); + data.stateLabel.style.display = ''; if (stoppedDetails) { @@ -616,17 +649,40 @@ class SessionsRenderer implements ICompressibleTreeRenderer, _: number, templateData: ISessionTemplateData): void { - dispose(templateData.elementDisposable); + templateData.elementDisposable.clear(); + } +} + +class ThreadRendererContextKeyHelper { + private callStackItemType: IContextKey; + private callStackItemStopped: IContextKey; + + constructor( + contextKeyService: IContextKeyService + ) { + this.callStackItemType = CONTEXT_CALLSTACK_ITEM_TYPE.bindTo(contextKeyService); + this.callStackItemStopped = CONTEXT_CALLSTACK_ITEM_STOPPED.bindTo(contextKeyService); + this.callStackItemType.set('thread'); } + + update(thread: IThread) { + this.callStackItemStopped.set(thread.stopped); + } +} + +function getThreadContextOverlay(thread: IThread): [string, any][] { + return [ + [CONTEXT_CALLSTACK_ITEM_TYPE.key, 'thread'], + [CONTEXT_CALLSTACK_ITEM_STOPPED.key, thread.stopped] + ]; } class ThreadsRenderer implements ICompressibleTreeRenderer { static readonly ID = 'thread'; constructor( - private menu: IMenu, - private callStackItemType: IContextKey, - private callStackItemStopped: IContextKey + @IContextKeyService private readonly contextKeyService: IContextKeyService, + @IMenuService private readonly menuService: IMenuService, ) { } get templateId(): string { @@ -638,10 +694,16 @@ class ThreadsRenderer implements ICompressibleTreeRenderer, _index: number, data: IThreadTemplateData): void { @@ -651,13 +713,24 @@ class ThreadsRenderer implements ICompressibleTreeRenderer { + menuDisposables.clear(); + data.actionBar.clear(); + + const primary: IAction[] = []; + const secondary: IAction[] = []; + const result = { primary, secondary }; + + menuDisposables.add(createAndFillInActionBarActions(data.menu, { arg: getContextForContributedActions(thread), shouldForwardArgs: true }, result, 'inline')); + data.actionBar.push(primary, { icon: true, label: false }); + // We need to set our internal context on the action bar, since our commands depend on that one + // While the external context our extensions rely on + data.actionBar.context = getContext(thread); + }; + data.elementDisposable.add(data.menu.onDidChange(() => setupActionBar())); + setupActionBar(); } renderCompressedElements(_node: ITreeNode, FuzzyScore>, _index: number, _templateData: IThreadTemplateData, _height: number | undefined): void { @@ -665,19 +738,25 @@ class ThreadsRenderer implements ICompressibleTreeRenderer { static readonly ID = 'stackFrame'; constructor( - private callStackItemType: IContextKey, @ILabelService private readonly labelService: ILabelService, @INotificationService private readonly notificationService: INotificationService, ) { } @@ -694,9 +773,11 @@ class StackFramesRenderer implements ICompressibleTreeRenderer, index: number, data: IStackFrameTemplateData): void { @@ -724,7 +805,6 @@ class StackFramesRenderer implements ICompressibleTreeRenderer { try { -- cgit v1.2.3 From 55d04653f8425c2f1744d27f697455ff893e71c9 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 8 Apr 2022 13:43:20 -0700 Subject: Use more readonly in DebugModel --- .../workbench/contrib/debug/common/debugModel.ts | 66 +++++++++++----------- 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/common/debugModel.ts b/src/vs/workbench/contrib/debug/common/debugModel.ts index 52994951b34..3e2cb2e1a16 100644 --- a/src/vs/workbench/contrib/debug/common/debugModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugModel.ts @@ -42,9 +42,9 @@ export class ExpressionContainer implements IExpressionContainer { constructor( protected session: IDebugSession | undefined, - protected threadId: number | undefined, + protected readonly threadId: number | undefined, private _reference: number | undefined, - private id: string, + private readonly id: string, public namedVariables: number | undefined = 0, public indexedVariables: number | undefined = 0, public memoryReference: string | undefined = undefined, @@ -275,9 +275,9 @@ export class Variable extends ExpressionContainer implements IExpression { constructor( session: IDebugSession | undefined, threadId: number | undefined, - public parent: IExpressionContainer, + public readonly parent: IExpressionContainer, reference: number | undefined, - public name: string, + public readonly name: string, public evaluateName: string | undefined, value: string | undefined, namedVariables: number | undefined, @@ -285,8 +285,8 @@ export class Variable extends ExpressionContainer implements IExpression { memoryReference: string | undefined, presentationHint: DebugProtocol.VariablePresentationHint | undefined, type: string | undefined = undefined, - public variableMenuContext: string | undefined = undefined, - public available = true, + public readonly variableMenuContext: string | undefined = undefined, + public readonly available = true, startOfVariables = 0, idDuplicationIndex = '', ) { @@ -346,12 +346,12 @@ export class Scope extends ExpressionContainer implements IScope { constructor( stackFrame: IStackFrame, index: number, - public name: string, + public readonly name: string, reference: number, public expensive: boolean, namedVariables?: number, indexedVariables?: number, - public range?: IRange + public readonly range?: IRange ) { super(stackFrame.thread.session, stackFrame.thread.threadId, reference, `scope:${name}:${index}`, namedVariables, indexedVariables); } @@ -389,15 +389,15 @@ export class StackFrame implements IStackFrame { private scopes: Promise | undefined; constructor( - public thread: Thread, - public frameId: number, - public source: Source, - public name: string, - public presentationHint: string | undefined, - public range: IRange, - private index: number, - public canRestart: boolean, - public instructionPointerReference?: string + public readonly thread: Thread, + public readonly frameId: number, + public readonly source: Source, + public readonly name: string, + public readonly presentationHint: string | undefined, + public readonly range: IRange, + private readonly index: number, + public readonly canRestart: boolean, + public readonly instructionPointerReference?: string ) { } getId(): string { @@ -482,7 +482,7 @@ export class Thread implements IThread { public reachedEndOfCallStack = false; public lastSteppingGranularity: DebugProtocol.SteppingGranularity | undefined; - constructor(public session: IDebugSession, public name: string, public threadId: number) { + constructor(public readonly session: IDebugSession, public name: string, public readonly threadId: number) { this.callStack = []; this.staleCallStack = []; this.stopped = false; @@ -721,7 +721,7 @@ export class MemoryRegion extends Disposable implements IMemoryRegion { export class Enablement implements IEnablement { constructor( public enabled: boolean, - private id: string + private readonly id: string ) { } getId(): string { @@ -851,7 +851,7 @@ export abstract class BaseBreakpoint extends Enablement implements IBaseBreakpoi export class Breakpoint extends BaseBreakpoint implements IBreakpoint { constructor( - private _uri: uri, + private readonly _uri: uri, private _lineNumber: number, private _column: number | undefined, enabled: boolean, @@ -1006,15 +1006,15 @@ export class FunctionBreakpoint extends BaseBreakpoint implements IFunctionBreak export class DataBreakpoint extends BaseBreakpoint implements IDataBreakpoint { constructor( - public description: string, - public dataId: string, - public canPersist: boolean, + public readonly description: string, + public readonly dataId: string, + public readonly canPersist: boolean, enabled: boolean, hitCondition: string | undefined, condition: string | undefined, logMessage: string | undefined, - public accessTypes: DebugProtocol.DataBreakpointAccessType[] | undefined, - public accessType: DebugProtocol.DataBreakpointAccessType, + public readonly accessTypes: DebugProtocol.DataBreakpointAccessType[] | undefined, + public readonly accessType: DebugProtocol.DataBreakpointAccessType, id = generateUuid() ) { super(enabled, hitCondition, condition, logMessage, id); @@ -1045,13 +1045,13 @@ export class DataBreakpoint extends BaseBreakpoint implements IDataBreakpoint { export class ExceptionBreakpoint extends BaseBreakpoint implements IExceptionBreakpoint { constructor( - public filter: string, - public label: string, + public readonly filter: string, + public readonly label: string, enabled: boolean, - public supportsCondition: boolean, + public readonly supportsCondition: boolean, condition: string | undefined, - public description: string | undefined, - public conditionDescription: string | undefined + public readonly description: string | undefined, + public readonly conditionDescription: string | undefined ) { super(enabled, undefined, condition, undefined, generateUuid()); } @@ -1079,9 +1079,9 @@ export class ExceptionBreakpoint extends BaseBreakpoint implements IExceptionBre export class InstructionBreakpoint extends BaseBreakpoint implements IInstructionBreakpoint { constructor( - public instructionReference: string, - public offset: number, - public canPersist: boolean, + public readonly instructionReference: string, + public readonly offset: number, + public readonly canPersist: boolean, enabled: boolean, hitCondition: string | undefined, condition: string | undefined, -- cgit v1.2.3 From 5a830437805c392ad076b2e2742708b0f74b3bde Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 8 Apr 2022 13:54:24 -0700 Subject: Simplify #144285, use OverlayContextKeyService --- .../contrib/debug/browser/callStackView.ts | 75 ++++------------------ 1 file changed, 14 insertions(+), 61 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/callStackView.ts b/src/vs/workbench/contrib/debug/browser/callStackView.ts index 035a1abc2d7..b23aa7e10af 100644 --- a/src/vs/workbench/contrib/debug/browser/callStackView.ts +++ b/src/vs/workbench/contrib/debug/browser/callStackView.ts @@ -23,9 +23,9 @@ import { commonSuffixLength } from 'vs/base/common/strings'; import { localize } from 'vs/nls'; import { Icon } from 'vs/platform/action/common/action'; import { createAndFillInActionBarActions, createAndFillInContextMenuActions, MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { IMenu, IMenuService, MenuId, MenuItemAction, MenuRegistry, registerAction2, SubmenuItemAction } from 'vs/platform/actions/common/actions'; +import { IMenuService, MenuId, MenuItemAction, MenuRegistry, registerAction2, SubmenuItemAction } from 'vs/platform/actions/common/actions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ContextKeyExpr, ContextKeyExpression, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyExpr, ContextKeyExpression, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -474,8 +474,6 @@ interface IThreadTemplateData { stateLabel: HTMLSpanElement; label: HighlightedLabel; actionBar: ActionBar; - menu: IMenu; - contextKeyHelper: ThreadRendererContextKeyHelper; elementDisposable: DisposableStore; templateDisposable: IDisposable; } @@ -485,9 +483,7 @@ interface ISessionTemplateData { name: HTMLElement; stateLabel: HTMLSpanElement; label: HighlightedLabel; - menu: IMenu; actionBar: ActionBar; - contextKeyHelper: SessionRendererContextKeyHelper; elementDisposable: DisposableStore; templateDisposable: IDisposable; } @@ -511,29 +507,6 @@ interface IStackFrameTemplateData { templateDisposable: IDisposable; } -class SessionRendererContextKeyHelper { - private callStackItemType: IContextKey; - private callStackSessionIsAttach: IContextKey; - private callStackItemStopped: IContextKey; - private sessionHasOneThread: IContextKey; - - constructor( - contextKeyService: IContextKeyService - ) { - this.callStackItemType = CONTEXT_CALLSTACK_ITEM_TYPE.bindTo(contextKeyService); - this.callStackSessionIsAttach = CONTEXT_CALLSTACK_SESSION_IS_ATTACH.bindTo(contextKeyService); - this.callStackItemStopped = CONTEXT_CALLSTACK_ITEM_STOPPED.bindTo(contextKeyService); - this.sessionHasOneThread = CONTEXT_CALLSTACK_SESSION_HAS_ONE_THREAD.bindTo(contextKeyService); - this.callStackItemType.set('session'); - } - - update(session: IDebugSession) { - this.callStackSessionIsAttach.set(isSessionAttach(session)); - this.callStackItemStopped.set(session.state === State.Stopped); - this.sessionHasOneThread.set(session.getAllThreads().length === 1); - } -} - function getSessionContextOverlay(session: IDebugSession): [string, any][] { return [ [CONTEXT_CALLSTACK_ITEM_TYPE.key, 'session'], @@ -564,10 +537,6 @@ class SessionsRenderer implements ICompressibleTreeRenderer { @@ -590,7 +559,7 @@ class SessionsRenderer implements ICompressibleTreeRenderer, _: number, data: ISessionTemplateData): void { @@ -609,7 +578,9 @@ class SessionsRenderer implements ICompressibleTreeRenderer t.stopped); - data.contextKeyHelper.update(session); + const contextKeyService = this.contextKeyService.createOverlay(getSessionContextOverlay(session)); + const menu = data.elementDisposable.add(this.menuService.createMenu(MenuId.DebugCallStackContext, contextKeyService)); + const menuDisposables = data.elementDisposable.add(new DisposableStore()); const setupActionBar = () => { menuDisposables.clear(); @@ -619,13 +590,13 @@ class SessionsRenderer implements ICompressibleTreeRenderer setupActionBar())); + data.elementDisposable.add(menu.onDidChange(() => setupActionBar())); setupActionBar(); data.stateLabel.style.display = ''; @@ -653,23 +624,6 @@ class SessionsRenderer implements ICompressibleTreeRenderer; - private callStackItemStopped: IContextKey; - - constructor( - contextKeyService: IContextKeyService - ) { - this.callStackItemType = CONTEXT_CALLSTACK_ITEM_TYPE.bindTo(contextKeyService); - this.callStackItemStopped = CONTEXT_CALLSTACK_ITEM_STOPPED.bindTo(contextKeyService); - this.callStackItemType.set('thread'); - } - - update(thread: IThread) { - this.callStackItemStopped.set(thread.stopped); - } -} - function getThreadContextOverlay(thread: IThread): [string, any][] { return [ [CONTEXT_CALLSTACK_ITEM_TYPE.key, 'thread'], @@ -697,13 +651,10 @@ class ThreadsRenderer implements ICompressibleTreeRenderer, _index: number, data: IThreadTemplateData): void { @@ -713,7 +664,9 @@ class ThreadsRenderer implements ICompressibleTreeRenderer { menuDisposables.clear(); @@ -723,13 +676,13 @@ class ThreadsRenderer implements ICompressibleTreeRenderer setupActionBar())); + data.elementDisposable.add(menu.onDidChange(() => setupActionBar())); setupActionBar(); } -- cgit v1.2.3 From 807fd90ffe694f2416ab909fe2dd0fc9feb35664 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 8 Apr 2022 14:33:59 -0700 Subject: supports supportSuspendDebuggee requires supportTerminateDebuggee. For #134412 --- src/vs/workbench/contrib/debug/browser/debug.contribution.ts | 4 ++-- src/vs/workbench/contrib/debug/browser/debugToolBar.ts | 2 +- src/vs/workbench/contrib/debug/browser/rawDebugSession.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 6e0fdd58b40..03a03efeb2a 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -107,7 +107,7 @@ registerDebugCommandPaletteItem(STEP_INTO_ID, STEP_INTO_LABEL, CONTEXT_IN_DEBUG_ registerDebugCommandPaletteItem(STEP_OUT_ID, STEP_OUT_LABEL, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); registerDebugCommandPaletteItem(PAUSE_ID, PAUSE_LABEL, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('running')); registerDebugCommandPaletteItem(DISCONNECT_ID, DISCONNECT_LABEL, CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.or(CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED)); -registerDebugCommandPaletteItem(DISCONNECT_AND_SUSPEND_ID, DISCONNECT_AND_SUSPEND_LABEL, CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.or(CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED)); +registerDebugCommandPaletteItem(DISCONNECT_AND_SUSPEND_ID, DISCONNECT_AND_SUSPEND_LABEL, CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.or(CONTEXT_FOCUSED_SESSION_IS_ATTACH, ContextKeyExpr.and(CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED))); registerDebugCommandPaletteItem(STOP_ID, STOP_LABEL, CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.or(CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED)); registerDebugCommandPaletteItem(CONTINUE_ID, CONTINUE_LABEL, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); registerDebugCommandPaletteItem(FOCUS_REPL_ID, nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugFocusConsole' }, 'Focus on Debug Console View')); @@ -139,7 +139,7 @@ const registerDebugViewMenuItem = (menuId: MenuId, id: string, title: string, or }; registerDebugViewMenuItem(MenuId.DebugCallStackContext, RESTART_SESSION_ID, RESTART_LABEL, 10, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('session'), undefined, '3_modification'); registerDebugViewMenuItem(MenuId.DebugCallStackContext, DISCONNECT_ID, DISCONNECT_LABEL, 20, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('session'), undefined, '3_modification'); -registerDebugViewMenuItem(MenuId.DebugCallStackContext, DISCONNECT_AND_SUSPEND_ID, DISCONNECT_AND_SUSPEND_LABEL, 21, ContextKeyExpr.and(CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('session'), CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED), undefined, '3_modification'); +registerDebugViewMenuItem(MenuId.DebugCallStackContext, DISCONNECT_AND_SUSPEND_ID, DISCONNECT_AND_SUSPEND_LABEL, 21, ContextKeyExpr.and(CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('session'), CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED), undefined, '3_modification'); registerDebugViewMenuItem(MenuId.DebugCallStackContext, STOP_ID, STOP_LABEL, 30, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('session'), undefined, '3_modification'); registerDebugViewMenuItem(MenuId.DebugCallStackContext, PAUSE_ID, PAUSE_LABEL, 10, ContextKeyExpr.and(CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('running'))); registerDebugViewMenuItem(MenuId.DebugCallStackContext, CONTINUE_ID, CONTINUE_LABEL, 10, ContextKeyExpr.and(CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('stopped'))); diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index fdd1c3a61e0..d9d8118daa2 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -379,7 +379,7 @@ MenuRegistry.appendMenuItem(MenuId.DebugToolBarStop, { MenuRegistry.appendMenuItem(MenuId.DebugToolBarStop, { group: 'navigation', - when: ContextKeyExpr.and(CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED), + when: ContextKeyExpr.and(CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED), order: 0, command: { id: DISCONNECT_AND_SUSPEND_ID, diff --git a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts index 1f57bf3b7a9..848245e3978 100644 --- a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts @@ -284,7 +284,7 @@ export class RawDebugSession implements IDisposable { */ disconnect(args: DebugProtocol.DisconnectArguments): Promise { const terminateDebuggee = this.capabilities.supportTerminateDebuggee ? args.terminateDebuggee : undefined; - const suspendDebuggee = this.capabilities.supportSuspendDebuggee ? args.suspendDebuggee : undefined; + const suspendDebuggee = this.capabilities.supportTerminateDebuggee && this.capabilities.supportSuspendDebuggee ? args.suspendDebuggee : undefined; return this.shutdown(undefined, args.restart, terminateDebuggee, suspendDebuggee); } -- cgit v1.2.3 From eb4f5e11aa0de04e818db2ca8b2ae9370a44ac98 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 8 Apr 2022 14:43:16 -0700 Subject: Don't show debugger disconnect alt when not supported. Fix #145650 --- src/vs/workbench/contrib/debug/browser/debugToolBar.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index d9d8118daa2..4cf1809bb1a 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -345,8 +345,8 @@ MenuRegistry.onDidChangeMenu(e => { registerDebugToolBarItem(CONTINUE_ID, CONTINUE_LABEL, 10, icons.debugContinue, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); registerDebugToolBarItem(PAUSE_ID, PAUSE_LABEL, 10, icons.debugPause, CONTEXT_DEBUG_STATE.notEqualsTo('stopped'), CONTEXT_DEBUG_STATE.isEqualTo('running')); -registerDebugToolBarItem(STOP_ID, STOP_LABEL, 70, icons.debugStop, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), undefined, { id: DISCONNECT_ID, title: DISCONNECT_LABEL, icon: icons.debugDisconnect }); -registerDebugToolBarItem(DISCONNECT_ID, DISCONNECT_LABEL, 70, icons.debugDisconnect, CONTEXT_FOCUSED_SESSION_IS_ATTACH, undefined, { id: STOP_ID, title: STOP_LABEL, icon: icons.debugStop }); +registerDebugToolBarItem(STOP_ID, STOP_LABEL, 70, icons.debugStop, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), undefined, { id: DISCONNECT_ID, title: DISCONNECT_LABEL, icon: icons.debugDisconnect, precondition: ContextKeyExpr.and(CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED), }); +registerDebugToolBarItem(DISCONNECT_ID, DISCONNECT_LABEL, 70, icons.debugDisconnect, CONTEXT_FOCUSED_SESSION_IS_ATTACH, undefined, { id: STOP_ID, title: STOP_LABEL, icon: icons.debugStop, precondition: ContextKeyExpr.and(CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED), }); registerDebugToolBarItem(STEP_OVER_ID, STEP_OVER_LABEL, 20, icons.debugStepOver, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); registerDebugToolBarItem(STEP_INTO_ID, STEP_INTO_LABEL, 30, icons.debugStepInto, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); registerDebugToolBarItem(STEP_OUT_ID, STEP_OUT_LABEL, 40, icons.debugStepOut, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); -- cgit v1.2.3 From 0f7a2264101d708d8bbfcfe1f6ac6c3bb52398c0 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Fri, 8 Apr 2022 15:21:54 -0700 Subject: Fix #145996 --- src/vs/workbench/contrib/search/browser/searchView.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 2984e51c32f..7cec0e4491a 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -1065,8 +1065,10 @@ export class SearchView extends ViewPane { this.inputPatternExcludes.setWidth(this.size.width - 28 /* container margin */); this.inputPatternIncludes.setWidth(this.size.width - 28 /* container margin */); - - this.tree.layout(); // The tree will measure its container + const widgetHeight = dom.getTotalHeight(this.searchWidget.domNode); + const messagesHeight = dom.getTotalHeight(this.messagesElement); + const margin = 25; + this.tree.layout(this.size.height - widgetHeight - messagesHeight - margin, this.size.width - 28); } protected override layoutBody(height: number, width: number): void { -- cgit v1.2.3 From b84feecf9231d404a766e251f8a37c730089511b Mon Sep 17 00:00:00 2001 From: Harald Kirschner Date: Sun, 10 Apr 2022 21:49:42 -0700 Subject: Snippet instrumentation (#146874) --- .../contrib/snippets/browser/snippetCompletionProvider.ts | 3 +++ src/vs/workbench/contrib/snippets/browser/snippetsFile.ts | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts b/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts index af03f2ea749..2b7c3c8ed98 100644 --- a/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts +++ b/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts @@ -18,6 +18,7 @@ import { isPatternInWord } from 'vs/base/common/filters'; import { StopWatch } from 'vs/base/common/stopwatch'; import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry'; import { getWordAtText } from 'vs/editor/common/core/wordHelper'; +import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; export class SnippetCompletion implements CompletionItem { @@ -29,6 +30,7 @@ export class SnippetCompletion implements CompletionItem { sortText: string; kind: CompletionItemKind; insertTextRules: CompletionItemInsertTextRule; + extensionId?: ExtensionIdentifier; constructor( readonly snippet: Snippet, @@ -37,6 +39,7 @@ export class SnippetCompletion implements CompletionItem { this.label = { label: snippet.prefix, description: snippet.name }; this.detail = localize('detail.snippet', "{0} ({1})", snippet.description || snippet.name, snippet.source); this.insertText = snippet.codeSnippet; + this.extensionId = snippet.extensionId; this.range = range; this.sortText = `${snippet.snippetSource === SnippetSource.Extension ? 'z' : 'a'}-${snippet.prefix}`; this.kind = CompletionItemKind.Snippet; diff --git a/src/vs/workbench/contrib/snippets/browser/snippetsFile.ts b/src/vs/workbench/contrib/snippets/browser/snippetsFile.ts index 25fafbfeda6..84f407b5f3e 100644 --- a/src/vs/workbench/contrib/snippets/browser/snippetsFile.ts +++ b/src/vs/workbench/contrib/snippets/browser/snippetsFile.ts @@ -12,7 +12,7 @@ import { KnownSnippetVariableNames } from 'vs/editor/contrib/snippet/browser/sni import { isFalsyOrWhitespace } from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; import { IFileService } from 'vs/platform/files/common/files'; -import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { IdleValue } from 'vs/base/common/async'; import { IExtensionResourceLoaderService } from 'vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader'; import { relativePath } from 'vs/base/common/resources'; @@ -114,7 +114,8 @@ export class Snippet { readonly body: string, readonly source: string, readonly snippetSource: SnippetSource, - readonly snippetIdentifier?: string + readonly snippetIdentifier?: string, + readonly extensionId?: ExtensionIdentifier, ) { this.prefixLow = prefix.toLowerCase(); this._bodyInsights = new IdleValue(() => new SnippetBodyInsights(this.body)); @@ -332,7 +333,8 @@ export class SnippetFile { body, source, this.source, - this._extension && `${relativePath(this._extension.extensionLocation, this.location)}/${name}` + this._extension && `${relativePath(this._extension.extensionLocation, this.location)}/${name}`, + this._extension?.identifier, )); } } -- cgit v1.2.3 From e78ca55defc1aeec364d2c58f843d68eb022db13 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Mon, 11 Apr 2022 16:03:31 +0200 Subject: Adopts bracket pair AST for bracket pair matching when AST is available. Implements #132536. --- src/vs/workbench/contrib/debug/browser/breakpointWidget.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts b/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts index 4be819c4cb4..3df0cf71a74 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts @@ -48,14 +48,10 @@ export interface IPrivateBreakpointWidgetService { } const DECORATION_KEY = 'breakpointwidgetdecoration'; -function isCurlyBracketOpen(input: IActiveCodeEditor): boolean { +function isPositionInCurlyBracketBlock(input: IActiveCodeEditor): boolean { const model = input.getModel(); - const prevBracket = model.bracketPairs.findPrevBracket(input.getPosition()); - if (prevBracket && prevBracket.isOpen) { - return true; - } - - return false; + const bracketPairs = model.bracketPairs.getBracketPairsInRange(Range.fromPositions(input.getPosition())); + return bracketPairs.some(p => p.openingBracketInfo.bracketText === '{'); } function createDecorations(theme: IColorTheme, placeHolder: string): IDecorationOptions[] { @@ -251,7 +247,7 @@ export class BreakpointWidget extends ZoneWidget implements IPrivateBreakpointWi provideCompletionItems: (model: ITextModel, position: Position, _context: CompletionContext, token: CancellationToken): Promise => { let suggestionsPromise: Promise; const underlyingModel = this.editor.getModel(); - if (underlyingModel && (this.context === Context.CONDITION || (this.context === Context.LOG_MESSAGE && isCurlyBracketOpen(this.input)))) { + if (underlyingModel && (this.context === Context.CONDITION || (this.context === Context.LOG_MESSAGE && isPositionInCurlyBracketBlock(this.input)))) { suggestionsPromise = provideSuggestionItems(this.languageFeaturesService.completionProvider, underlyingModel, new Position(this.lineNumber, 1), new CompletionOptions(undefined, new Set().add(CompletionItemKind.Snippet)), _context, token).then(suggestions => { let overwriteBefore = 0; -- cgit v1.2.3 From 112a5c44ead0d077c0a87d52ed3aef0b8d3991f4 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 11 Apr 2022 16:54:45 +0200 Subject: editors - better implement error when opening a folder --- .../files/browser/editors/textFileEditor.ts | 37 +++++++++++----------- 1 file changed, 18 insertions(+), 19 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts index dc8fd63c3ae..e77d66da61a 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts @@ -6,7 +6,7 @@ import { localize } from 'vs/nls'; import { assertIsDefined } from 'vs/base/common/types'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; -import { toAction } from 'vs/base/common/actions'; +import { IAction, toAction } from 'vs/base/common/actions'; import { VIEWLET_ID, TEXT_FILE_EDITOR_ID, BINARY_TEXT_FILE_MODE } from 'vs/workbench/contrib/files/common/files'; import { ITextFileService, TextFileOperationError, TextFileOperationResult } from 'vs/workbench/services/textfile/common/textfiles'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; @@ -180,9 +180,24 @@ export class TextFileEditor extends BaseTextEditor { // Similar, handle case where we were asked to open a folder in the text editor. if ((error).fileOperationResult === FileOperationResult.FILE_IS_DIRECTORY) { - this.openAsFolder(input); + let action: IAction; + if (this.contextService.isInsideWorkspace(input.preferredResource)) { + action = toAction({ + id: 'workbench.files.action.reveal', label: localize('reveal', "Reveal in Explorer View"), run: async () => { + await this.paneCompositeService.openPaneComposite(VIEWLET_ID, ViewContainerLocation.Sidebar, true); - throw new Error(localize('openFolderError', "File is a directory")); + return this.explorerService.select(input.preferredResource, true); + } + }); + } else { + action = toAction({ + id: 'workbench.files.action.ok', label: localize('ok', "OK"), run: async () => { + // No operation possible, but clicking OK will close the editor + } + }); + } + + throw createErrorWithActions(new FileOperationError(localize('fileIsDirectoryError', "File is a directory"), FileOperationResult.FILE_IS_DIRECTORY), [action]); } // Offer to create a file from the error if we have a file not found and the name is valid @@ -261,22 +276,6 @@ export class TextFileEditor extends BaseTextEditor { group.openEditor(editor, editorOptions); } - private async openAsFolder(input: FileEditorInput): Promise { - if (!this.group) { - return; - } - - // Since we cannot open a folder, we have to restore the previous input if any and close the editor - await this.group.closeEditor(this.input); - - // Best we can do is to reveal the folder in the explorer - if (this.contextService.isInsideWorkspace(input.preferredResource)) { - await this.paneCompositeService.openPaneComposite(VIEWLET_ID, ViewContainerLocation.Sidebar); - - this.explorerService.select(input.preferredResource, true); - } - } - override clearInput(): void { super.clearInput(); -- cgit v1.2.3 From 860221a1933842f41afc19c304ed3c1a04da0671 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 11 Apr 2022 08:05:40 -0700 Subject: two kernel types --- .../contrib/editorStatusBar/editorStatusBar.ts | 5 +++ .../notebook/browser/controller/apiActions.ts | 6 ++-- .../notebook/browser/notebookEditorWidget.ts | 10 +++++- .../browser/notebookExecutionServiceImpl.ts | 24 +++++++++++++- .../notebook/browser/notebookKernelServiceImpl.ts | 28 +++++++++++++++- .../browser/view/cellParts/cellExecution.ts | 3 +- .../notebook/browser/view/cellParts/cellOutput.ts | 9 +++--- .../browser/view/renderers/backLayerWebView.ts | 12 +++---- .../viewParts/notebookEditorWidgetContextKeys.ts | 4 +-- .../viewParts/notebookKernelActionViewItem.ts | 27 ++++++++++++++-- .../notebook/common/notebookKernelService.ts | 37 ++++++++++++++++++++-- .../test/browser/notebookExecutionService.test.ts | 5 +-- .../browser/notebookExecutionStateService.test.ts | 5 +-- .../test/browser/notebookKernelService.test.ts | 5 +-- 14 files changed, 150 insertions(+), 30 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts index 83b35ce916d..c93c6b17ba2 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts @@ -197,6 +197,11 @@ registerAction2(class extends Action2 { quickPickItems.push(...suggestions.map(toQuickPick)); } + quickPickItems.push({ + id: 'install', + label: nls.localize('installKernels', "Install kernels from the marketplace"), + }); + // Next display all of the kernels grouped by categories or extensions. // If we don't have a kind, always display those at the bottom. const picks = all.filter(item => !suggestions.includes(item)).map(toQuickPick); diff --git a/src/vs/workbench/contrib/notebook/browser/controller/apiActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/apiActions.ts index d0c6379a54b..68d9d0f8dcc 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/apiActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/apiActions.ts @@ -7,7 +7,7 @@ import * as glob from 'vs/base/common/glob'; import { URI, UriComponents } from 'vs/base/common/uri'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { isDocumentExcludePattern, TransientCellMetadata, TransientDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernelService, IResolvedNotebookKernel, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; CommandsRegistry.registerCommand('_resolveNotebookContentProvider', (accessor): { @@ -66,13 +66,13 @@ CommandsRegistry.registerCommand('_resolveNotebookKernels', async (accessor, arg const uri = URI.revive(args.uri as UriComponents); const kernels = notebookKernelService.getMatchingKernel({ uri, viewType: args.viewType }); - return kernels.all.map(provider => ({ + return kernels.all.filter(kernel => kernel.type === NotebookKernelType.Resolved).map((provider) => ({ id: provider.id, label: provider.label, kind: provider.kind, description: provider.description, detail: provider.detail, isPreferred: false, // todo@jrieken,@rebornix - preloads: provider.preloadUris, + preloads: (provider as IResolvedNotebookKernel).preloadUris, })); }); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index aa1bcc7853f..bafa9981455 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -76,7 +76,7 @@ import { CellKind, INotebookSearchOptions, SelectionStateType } from 'vs/workben import { NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; import { INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; -import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernelService, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { NotebookOptions, OutputInnerContainerTopPadding } from 'vs/workbench/contrib/notebook/common/notebookOptions'; import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance'; import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; @@ -2108,6 +2108,14 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD return; } const { selected } = this.notebookKernelService.getMatchingKernel(this.textModel); + if (!selected) { + return; + } + + if (selected.type === NotebookKernelType.Proxy) { + return; + } + if (!this._webview?.isResolved()) { await this._resolveWebview(); } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts index 000c7b3b72c..b8877a553a2 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts @@ -12,7 +12,7 @@ import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/mode import { CellKind, INotebookTextModel, NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; -import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernelService, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; export class NotebookExecutionService implements INotebookExecutionService { declare _serviceBrand: undefined; @@ -45,6 +45,23 @@ export class NotebookExecutionService implements INotebookExecutionService { return; } + if (kernel.type === NotebookKernelType.Proxy) { + // we should actually resolve the kernel + const resolved = await kernel.resolveKernel(notebook.uri); + let kernels = this._notebookKernelService.getMatchingKernel(notebook); + const newlyMatchedKernel = kernels.all.find(k => k.id === resolved); + + if (!newlyMatchedKernel) { + return; + } + + kernel = newlyMatchedKernel; + } + + if (kernel.type === NotebookKernelType.Proxy) { + return; + } + const executeCells: NotebookCellTextModel[] = []; for (const cell of cellsArr) { const cellExe = this._notebookExecutionStateService.getCellExecution(cell.uri); @@ -75,6 +92,11 @@ export class NotebookExecutionService implements INotebookExecutionService { this._logService.debug(`NotebookExecutionService#cancelNotebookCellHandles ${JSON.stringify(cellsArr)}`); const kernel = this._notebookKernelService.getSelectedOrSuggestedKernel(notebook); if (kernel) { + if (kernel.type === NotebookKernelType.Proxy) { + // we should handle cancelling proxy kernel too + return; + } + await kernel.cancelNotebookCellExecution(notebook.uri, cellsArr); } } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts index 1f2e2e72032..09e75953d84 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts @@ -6,7 +6,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { INotebookTextModel } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { INotebookKernel, ISelectedNotebooksChangeEvent, INotebookKernelMatchResult, INotebookKernelService, INotebookTextModelLike } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernel, ISelectedNotebooksChangeEvent, INotebookKernelMatchResult, INotebookKernelService, INotebookTextModelLike, INotebookProxyKernel } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { LRUCache, ResourceMap } from 'vs/base/common/map'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { URI } from 'vs/base/common/uri'; @@ -164,6 +164,32 @@ export class NotebookKernelService extends Disposable implements INotebookKernel }); } + registerProxyKernel(kernel: INotebookProxyKernel): IDisposable { + if (this._kernels.has(kernel.id)) { + throw new Error(`NOTEBOOK CONTROLLER with id '${kernel.id}' already exists`); + } + + this._kernels.set(kernel.id, new KernelInfo(kernel)); + this._onDidAddKernel.fire(kernel); + + // auto associate the new kernel to existing notebooks it was + // associated to in the past. + for (const notebook of this._notebookService.getNotebookTextModels()) { + this._tryAutoBindNotebook(notebook, kernel); + } + + return toDisposable(() => { + if (this._kernels.delete(kernel.id)) { + this._onDidRemoveKernel.fire(kernel); + } + for (const [key, candidate] of Array.from(this._notebookBindings)) { + if (candidate === kernel.id) { + this._onDidChangeNotebookKernelBinding.fire({ notebook: NotebookTextModelLikeId.obj(key).uri, oldKernel: kernel.id, newKernel: undefined }); + } + } + }); + } + getMatchingKernel(notebook: INotebookTextModelLike): INotebookKernelMatchResult { // all applicable kernels diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts index d4745c02a43..eb6e260ec10 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts @@ -9,6 +9,7 @@ import { ICellViewModel, INotebookEditorDelegate } from 'vs/workbench/contrib/no import { CellViewModelStateChangeEvent } from 'vs/workbench/contrib/notebook/browser/notebookViewEvents'; import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart'; import { NotebookCellInternalMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; export class CellExecutionPart extends CellPart { private kernelDisposables = this._register(new DisposableStore()); @@ -41,7 +42,7 @@ export class CellExecutionPart extends CellPart { } private updateExecutionOrder(internalMetadata: NotebookCellInternalMetadata): void { - if (this._notebookEditor.activeKernel?.implementsExecutionOrder) { + if (this._notebookEditor.activeKernel?.type === NotebookKernelType.Resolved && this._notebookEditor.activeKernel?.implementsExecutionOrder) { const executionOrderLabel = typeof internalMetadata.executionOrder === 'number' ? `[${internalMetadata.executionOrder}]` : '[ ]'; diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts index 7306836ac30..7ed12d9bb09 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts @@ -31,7 +31,7 @@ import { CodeCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/vi import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { CellUri, IOrderedMimeType, NotebookCellOutputsSplice, RENDERER_NOT_AVAILABLE } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { INotebookKernel } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernel, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; @@ -127,7 +127,8 @@ export class CellOutputElement extends Disposable { this.notebookEditor.hasModel() && this.innerContainer && this.renderResult && - this.renderResult.type === RenderOutputType.Extension + this.renderResult.type === RenderOutputType.Extension && + this.notebookEditor.activeKernel?.type === NotebookKernelType.Resolved ) { // Output rendered by extension renderer got an update const [mimeTypes, pick] = this.output.resolveMimeTypes(this.notebookEditor.textModel, this.notebookEditor.activeKernel?.preloadProvides); @@ -191,7 +192,7 @@ export class CellOutputElement extends Disposable { const notebookTextModel = this.notebookEditor.textModel; - const [mimeTypes, pick] = this.output.resolveMimeTypes(notebookTextModel, this.notebookEditor.activeKernel?.preloadProvides); + const [mimeTypes, pick] = this.output.resolveMimeTypes(notebookTextModel, this.notebookEditor.activeKernel?.type === NotebookKernelType.Resolved ? this.notebookEditor.activeKernel?.preloadProvides : undefined); if (!mimeTypes.find(mimeType => mimeType.isTrusted) || mimeTypes.length === 0) { this.viewCell.updateOutputHeight(index, 0, 'CellOutputElement#noMimeType'); @@ -299,7 +300,7 @@ export class CellOutputElement extends Disposable { } private async _pickActiveMimeTypeRenderer(outputItemDiv: HTMLElement, notebookTextModel: NotebookTextModel, kernel: INotebookKernel | undefined, viewModel: ICellOutputViewModel) { - const [mimeTypes, currIndex] = viewModel.resolveMimeTypes(notebookTextModel, kernel?.preloadProvides); + const [mimeTypes, currIndex] = viewModel.resolveMimeTypes(notebookTextModel, kernel?.type === NotebookKernelType.Resolved ? kernel?.preloadProvides : undefined); const items: IMimeTypeRenderer[] = []; const unsupportedItems: IMimeTypeRenderer[] = []; diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index 7bda661ed4e..669bcb2a519 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -37,7 +37,7 @@ import { preloadsScriptStr, RendererMetadata } from 'vs/workbench/contrib/notebo import { transformWebviewThemeVars } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewThemeMapping'; import { MarkupCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markupCellViewModel'; import { CellUri, INotebookRendererInfo, NotebookSetting, RendererMessagingSpec } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { INotebookKernel } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernel, IResolvedNotebookKernel, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { IScopedRendererMessaging } from 'vs/workbench/contrib/notebook/common/notebookRendererMessagingService'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IWebviewElement, IWebviewService, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview'; @@ -897,7 +897,7 @@ var requirejs = (function() { } this._preloadsCache.clear(); - if (this._currentKernel) { + if (this._currentKernel && this._currentKernel.type === NotebookKernelType.Resolved) { this._updatePreloadsFromKernel(this._currentKernel); } @@ -1394,14 +1394,14 @@ var requirejs = (function() { const previousKernel = this._currentKernel; this._currentKernel = kernel; - if (previousKernel && previousKernel.preloadUris.length > 0) { + if (previousKernel && previousKernel.type === NotebookKernelType.Resolved && previousKernel.preloadUris.length > 0) { this.webview?.reload(); // preloads will be restored after reload - } else if (kernel) { + } else if (kernel?.type === NotebookKernelType.Resolved) { this._updatePreloadsFromKernel(kernel); } } - private _updatePreloadsFromKernel(kernel: INotebookKernel) { + private _updatePreloadsFromKernel(kernel: IResolvedNotebookKernel) { const resources: IControllerPreload[] = []; for (const preload of kernel.preloadUris) { const uri = this.environmentService.isExtensionDevelopment && (preload.scheme === 'http' || preload.scheme === 'https') @@ -1427,7 +1427,7 @@ var requirejs = (function() { const mixedResourceRoots = [ ...(this.localResourceRootsCache || []), - ...(this._currentKernel ? [this._currentKernel.localResourceRoot] : []), + ...(this._currentKernel && this._currentKernel.type === NotebookKernelType.Resolved ? [this._currentKernel.localResourceRoot] : []), ]; this.webview.localResourcesRoot = mixedResourceRoots; diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts index a90477db542..b1cf70a4946 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts @@ -8,7 +8,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c import { ICellViewModel, INotebookEditorDelegate, KERNEL_EXTENSIONS } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NOTEBOOK_CELL_TOOLBAR_LOCATION, NOTEBOOK_HAS_OUTPUTS, NOTEBOOK_HAS_RUNNING_CELL, NOTEBOOK_INTERRUPTIBLE_KERNEL, NOTEBOOK_KERNEL, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_KERNEL_SELECTED, NOTEBOOK_MISSING_KERNEL_EXTENSION, NOTEBOOK_USE_CONSOLIDATED_OUTPUT_BUTTON, NOTEBOOK_VIEW_TYPE } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; -import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernelService, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; export class NotebookEditorContextKeys { @@ -148,7 +148,7 @@ export class NotebookEditorContextKeys { const { selected, all } = this._notebookKernelService.getMatchingKernel(this._editor.textModel); this._notebookKernelCount.set(all.length); - this._interruptibleKernel.set(selected?.implementsInterrupt ?? false); + this._interruptibleKernel.set((selected?.type === NotebookKernelType.Resolved && selected.implementsInterrupt) ?? false); this._notebookKernelSelected.set(Boolean(selected)); this._notebookKernel.set(selected?.id ?? ''); } diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts index dc9a494193e..41e1ec74773 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts @@ -9,14 +9,16 @@ import { Action, IAction } from 'vs/base/common/actions'; import { localize } from 'vs/nls'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { selectKernelIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; -import { INotebookKernelMatchResult, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernelMatchResult, INotebookKernelService, ProxyKernelState } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { Event } from 'vs/base/common/event'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { DisposableStore } from 'vs/base/common/lifecycle'; export class NotebooKernelActionViewItem extends ActionViewItem { private _kernelLabel?: HTMLAnchorElement; + private _kernelDisposable: DisposableStore; constructor( actualAction: IAction, @@ -31,6 +33,7 @@ export class NotebooKernelActionViewItem extends ActionViewItem { this._register(_editor.onDidChangeModel(this._update, this)); this._register(_notebookKernelService.onDidChangeNotebookAffinity(this._update, this)); this._register(_notebookKernelService.onDidChangeSelectedNotebooks(this._update, this)); + this._kernelDisposable = this._register(new DisposableStore()); } override render(container: HTMLElement): void { @@ -63,9 +66,9 @@ export class NotebooKernelActionViewItem extends ActionViewItem { } private _updateActionFromKernelInfo(info: INotebookKernelMatchResult): void { - + this._kernelDisposable.clear(); this._action.enabled = true; - const selectedOrSuggested = info.selected ?? (info.all.length === 1 && info.suggestions.length === 1 ? info.suggestions[0] : undefined); + const selectedOrSuggested = info.selected ?? ((info.all.length === 1 && info.suggestions.length === 1 && !('resolveKernel' in info.suggestions[0])) ? info.suggestions[0] : undefined); if (selectedOrSuggested) { // selected or suggested kernel this._action.label = selectedOrSuggested.label; @@ -74,6 +77,24 @@ export class NotebooKernelActionViewItem extends ActionViewItem { // special UI for selected kernel? } + if ('resolveKernel' in selectedOrSuggested) { + if (selectedOrSuggested.connectionState === ProxyKernelState.Initializing) { + this._action.label = localize('initializing', "Initializing..."); + } else { + this._action.label = selectedOrSuggested.label; + } + + this._kernelDisposable.add(selectedOrSuggested.onDidChange(e => { + if (e.connectionState) { + if (selectedOrSuggested.connectionState === ProxyKernelState.Initializing) { + this._action.label = localize('initializing', "Initializing..."); + } else { + this._action.label = selectedOrSuggested.label; + } + } + })); + } + } else { // many kernels or no kernels this._action.label = localize('select', "Select Kernel"); diff --git a/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts b/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts index 6610fe7177d..19ee2cf2b66 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts @@ -31,8 +31,13 @@ export interface INotebookKernelChangeEvent { hasExecutionOrder?: true; } -export interface INotebookKernel { +export const enum NotebookKernelType { + Resolved, + Proxy = 1 +} +export interface IResolvedNotebookKernel { + readonly type: NotebookKernelType.Resolved; readonly id: string; readonly viewType: string; readonly onDidChange: Event>; @@ -54,6 +59,33 @@ export interface INotebookKernel { cancelNotebookCellExecution(uri: URI, cellHandles: number[]): Promise; } +export const enum ProxyKernelState { + Disconnected = 1, + Connected = 2, + Initializing = 3 +} + +export interface INotebookProxyKernelChangeEvent extends INotebookKernelChangeEvent { + connectionState?: true; +} + +export interface INotebookProxyKernel { + readonly type: NotebookKernelType.Proxy; + readonly id: string; + readonly viewType: string; + readonly extension: ExtensionIdentifier; + readonly onDidChange: Event>; + label: string; + description?: string; + detail?: string; + kind?: string; + supportedLanguages: string[]; + connectionState: ProxyKernelState; + resolveKernel(uri: URI): Promise; +} + +export type INotebookKernel = IResolvedNotebookKernel | INotebookProxyKernel; + export interface INotebookTextModelLike { uri: URI; viewType: string } export const INotebookKernelService = createDecorator('INotebookKernelService'); @@ -66,7 +98,8 @@ export interface INotebookKernelService { readonly onDidChangeSelectedNotebooks: Event; readonly onDidChangeNotebookAffinity: Event; - registerKernel(kernel: INotebookKernel): IDisposable; + registerKernel(kernel: IResolvedNotebookKernel): IDisposable; + registerProxyKernel(proxyKernel: INotebookProxyKernel): IDisposable; getMatchingKernel(notebook: INotebookTextModelLike): INotebookKernelMatchResult; diff --git a/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionService.test.ts b/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionService.test.ts index 6f65268830f..8d3bff7a83a 100644 --- a/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionService.test.ts +++ b/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionService.test.ts @@ -20,7 +20,7 @@ import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewMod import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { CellKind, IOutputDto, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; -import { INotebookKernel, INotebookKernelService, ISelectedNotebooksChangeEvent } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernelService, IResolvedNotebookKernel, ISelectedNotebooksChangeEvent, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { setupInstantiationService, withTestNotebook as _withTestNotebook } from 'vs/workbench/contrib/notebook/test/browser/testNotebookEditor'; @@ -166,7 +166,8 @@ suite('NotebookExecutionService', () => { }); }); -class TestNotebookKernel implements INotebookKernel { +class TestNotebookKernel implements IResolvedNotebookKernel { + type: NotebookKernelType.Resolved = NotebookKernelType.Resolved; id: string = 'test'; label: string = ''; viewType = '*'; diff --git a/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionStateService.test.ts b/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionStateService.test.ts index 887a4a05443..e5b7f84b8bf 100644 --- a/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionStateService.test.ts +++ b/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionStateService.test.ts @@ -21,7 +21,7 @@ import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/no import { CellEditType, CellKind, CellUri, IOutputDto, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; -import { INotebookKernel, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernelService, IResolvedNotebookKernel, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { setupInstantiationService, withTestNotebook as _withTestNotebook } from 'vs/workbench/contrib/notebook/test/browser/testNotebookEditor'; @@ -170,7 +170,8 @@ suite('NotebookExecutionStateService', () => { }); }); -class TestNotebookKernel implements INotebookKernel { +class TestNotebookKernel implements IResolvedNotebookKernel { + type: NotebookKernelType.Resolved = NotebookKernelType.Resolved; id: string = 'test'; label: string = ''; viewType = '*'; diff --git a/src/vs/workbench/contrib/notebook/test/browser/notebookKernelService.test.ts b/src/vs/workbench/contrib/notebook/test/browser/notebookKernelService.test.ts index b1ebabc1db2..62d6afecb8b 100644 --- a/src/vs/workbench/contrib/notebook/test/browser/notebookKernelService.test.ts +++ b/src/vs/workbench/contrib/notebook/test/browser/notebookKernelService.test.ts @@ -8,7 +8,7 @@ import { URI } from 'vs/base/common/uri'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { setupInstantiationService, withTestNotebook as _withTestNotebook } from 'vs/workbench/contrib/notebook/test/browser/testNotebookEditor'; import { Emitter, Event } from 'vs/base/common/event'; -import { INotebookKernel, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernelService, IResolvedNotebookKernel, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { NotebookKernelService } from 'vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { mock } from 'vs/base/test/common/mock'; @@ -159,7 +159,8 @@ suite('NotebookKernelService', () => { }); }); -class TestNotebookKernel implements INotebookKernel { +class TestNotebookKernel implements IResolvedNotebookKernel { + type: NotebookKernelType.Resolved = NotebookKernelType.Resolved; id: string = Math.random() + 'kernel'; label: string = 'test-label'; viewType = '*'; -- cgit v1.2.3 From 016c20ff035c0f25dc5431ab964e89b087c7b6bc Mon Sep 17 00:00:00 2001 From: Quan Zhuo Date: Tue, 12 Apr 2022 01:05:42 +0800 Subject: fix #140612: toggle the Toggle Button when the context line number larger than 0 (#147141) --- src/vs/workbench/contrib/search/browser/searchWidget.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/search/browser/searchWidget.ts b/src/vs/workbench/contrib/search/browser/searchWidget.ts index d9d0f908be9..aed2458e00b 100644 --- a/src/vs/workbench/contrib/search/browser/searchWidget.ts +++ b/src/vs/workbench/contrib/search/browser/searchWidget.ts @@ -366,7 +366,12 @@ export class SearchWidget extends Widget { this.contextLinesInput = new InputBox(searchInputContainer, this.contextViewService, { type: 'number' }); this.contextLinesInput.element.classList.add('context-lines-input'); this.contextLinesInput.value = '' + (this.configurationService.getValue('search').searchEditor.defaultNumberOfContextLines ?? 1); - this._register(this.contextLinesInput.onDidChange(() => this.onContextLinesChanged())); + this._register(this.contextLinesInput.onDidChange((value: string) => { + if (value !== '0') { + this.showContextToggle.checked = true; + } + this.onContextLinesChanged(); + })); this._register(attachInputBoxStyler(this.contextLinesInput, this.themeService)); dom.append(searchInputContainer, this.showContextToggle.domNode); } -- cgit v1.2.3 From 8abb91b949a8a560d762ccd80e1e73d14028fded Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Mon, 11 Apr 2022 14:11:35 -0400 Subject: Fix #96784 --- src/vs/workbench/contrib/timeline/browser/timelinePane.ts | 3 +++ src/vs/workbench/contrib/timeline/common/timeline.ts | 1 + 2 files changed, 4 insertions(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index 98ed6664ed8..10c04d75a9c 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -66,6 +66,7 @@ function isTimelineItem(item: TreeElement | undefined): item is TimelineItem { function updateRelativeTime(item: TimelineItem, lastRelativeTime: string | undefined): string | undefined { item.relativeTime = isTimelineItem(item) ? fromNow(item.timestamp) : undefined; + item.relativeTimeFullWord = isTimelineItem(item) ? fromNow(item.timestamp, false, true) : undefined; if (lastRelativeTime === undefined || item.relativeTime !== lastRelativeTime) { lastRelativeTime = item.relativeTime; item.hideRelativeTime = false; @@ -196,6 +197,7 @@ class LoadMoreCommand { readonly iconDark = undefined; readonly source = undefined; readonly relativeTime = undefined; + readonly relativeTimeFullWord = undefined; readonly hideRelativeTime = undefined; constructor(loading: boolean) { @@ -1172,6 +1174,7 @@ class TimelineTreeRenderer implements ITreeRenderer Date: Mon, 11 Apr 2022 15:18:30 -0400 Subject: Remove property level owner from telemetry types --- .../workbench/contrib/preferences/browser/settingsEditor2.ts | 10 ++++++---- src/vs/workbench/contrib/webview/browser/webviewElement.ts | 4 +++- .../contrib/welcomeGettingStarted/browser/gettingStarted.ts | 8 +++++--- 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index f925cd60830..780ebf0a742 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -1380,10 +1380,12 @@ export class SettingsEditor2 extends EditorPane { 'requestCount': number | undefined; }; type SettingsEditorFilterClassification = { - 'durations.nlpResult': { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; owner: 'rzhao271'; 'comment': 'How long the remote search provider took, if applicable.' }; - 'counts.nlpResult': { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; owner: 'rzhao271'; 'comment': 'The number of matches found by the remote search provider, if applicable.' }; - 'counts.filterResult': { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; owner: 'rzhao271'; 'comment': 'The number of matches found by the local search provider, if applicable.' }; - 'requestCount': { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; owner: 'rzhao271'; 'comment': 'The number of requests sent to Bing, if applicable.' }; + 'durations.nlpResult': { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; 'comment': 'How long the remote search provider took, if applicable.' }; + 'counts.nlpResult': { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; 'comment': 'The number of matches found by the remote search provider, if applicable.' }; + 'counts.filterResult': { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; 'comment': 'The number of matches found by the local search provider, if applicable.' }; + 'requestCount': { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; 'comment': 'The number of requests sent to Bing, if applicable.' }; + owner: 'rzhao271'; + comment: 'Tracks the number of requests and performance of the built-in search providers'; }; const nlpResult = results[SearchResultIdx.Remote]; diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts index 1c312d73bdd..27d6ce75d84 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts @@ -530,7 +530,9 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD } as const; type Classification = { - extension: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; owner: 'mjbvz'; comment: 'The id of the extension that created the webview.' }; + extension: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The id of the extension that created the webview.' }; + owner: 'mjbz'; + comment: 'Helps find which extensions are contributing webviews with invalid CSPs'; }; this._telemetryService.publicLog2('webviewMissingCsp', payload); diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts index 6f8b332a0d0..7015fa5e7b4 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts @@ -99,9 +99,11 @@ const parsedStartEntries: IWelcomePageStartEntry[] = startEntries.map((e, i) => })); type GettingStartedActionClassification = { - command: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; owner: 'JacksonKearl'; comment: 'Help understand what actions are most commonly taken on the getting started page' }; - walkthroughId: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; owner: 'JacksonKearl'; comment: 'As above' }; - argument: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; owner: 'JacksonKearl'; comment: 'As above' }; + command: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; comment: 'The command being executed on the getting started page.' }; + walkthroughId: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; comment: 'The walkthrough which the command is in' }; + argument: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; comment: 'The arguments being passed to the command' }; + owner: 'lramos15'; + comment: 'Help understand what actions are most commonly taken on the getting started page'; }; type GettingStartedActionEvent = { -- cgit v1.2.3 From a4e3e86c5955b42fa0168c943f52d433b263ba56 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 11 Apr 2022 13:59:40 -0700 Subject: Revert "delay editor restore." This reverts commit 960e1bd963aeee2b6d5cfa7c5750e32b1728ef34. --- .../contrib/notebook/browser/viewModel/baseCellViewModel.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index 8b7c306af28..11b51e17e2f 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -156,8 +156,6 @@ export abstract class BaseCellViewModel extends Disposable { this._onDidChangeState.fire({ outputCollapsedChanged: true }); } - private _textEditorRestore: any; - constructor( readonly viewType: string, readonly model: NotebookCellTextModel, @@ -236,9 +234,7 @@ export abstract class BaseCellViewModel extends Disposable { this._textEditor = editor; if (this._editorViewStates) { - this._textEditorRestore = setTimeout(() => { - this._restoreViewState(this._editorViewStates); - }); + this._restoreViewState(this._editorViewStates); } if (this._editorTransientState) { @@ -264,7 +260,6 @@ export abstract class BaseCellViewModel extends Disposable { } detachTextEditor() { - clearTimeout(this._textEditorRestore); this.saveViewState(); this.saveTransientState(); // decorations need to be cleared first as editors can be resued. @@ -589,7 +584,6 @@ export abstract class BaseCellViewModel extends Disposable { super.dispose(); dispose(this._editorListeners); - clearTimeout(this._textEditorRestore); // Only remove the undo redo stack if we map this cell uri to itself // If we are not in perCell mode, it will map to the full NotebookDocument and -- cgit v1.2.3 From 21173541e165b0327c67bcaeac82a8a2fe44c949 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 11 Apr 2022 15:17:58 -0700 Subject: Make postMessage's behavior more sane Fixes #146253 Two parts to this change: - Make postMessage return false if a message cannot be delivered to a webview - Don't queue messages for hidden (and non-retained) webviews. This was potentially causing a huge flood of messages to be dumped into the webview once it becomes visible again --- .../contrib/webview/browser/overlayWebview.ts | 13 ++++------- .../workbench/contrib/webview/browser/webview.ts | 2 +- .../contrib/webview/browser/webviewElement.ts | 27 ++++++++++++++++------ 3 files changed, 25 insertions(+), 17 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/webview/browser/overlayWebview.ts b/src/vs/workbench/contrib/webview/browser/overlayWebview.ts index bb25dfdc171..7231d6577fb 100644 --- a/src/vs/workbench/contrib/webview/browser/overlayWebview.ts +++ b/src/vs/workbench/contrib/webview/browser/overlayWebview.ts @@ -21,7 +21,6 @@ export class OverlayWebview extends Disposable implements IOverlayWebview { private readonly _onDidWheel = this._register(new Emitter()); public readonly onDidWheel = this._onDidWheel.event; - private readonly _pendingMessages = new Set<{ readonly message: any; readonly transfer?: readonly ArrayBuffer[] }>(); private readonly _webview = this._register(new MutableDisposable()); private readonly _webviewEvents = this._register(new DisposableStore()); @@ -199,9 +198,6 @@ export class OverlayWebview extends Disposable implements IOverlayWebview { this._state = state; this._onDidUpdateState.fire(state); })); - - this._pendingMessages.forEach(msg => webview.postMessage(msg.message, msg.transfer)); - this._pendingMessages.clear(); } this.container.style.visibility = 'visible'; @@ -268,12 +264,11 @@ export class OverlayWebview extends Disposable implements IOverlayWebview { private readonly _onMissingCsp = this._register(new Emitter()); public readonly onMissingCsp: Event = this._onMissingCsp.event; - public postMessage(message: any, transfer?: readonly ArrayBuffer[]): void { - if (this._webview.value) { - this._webview.value.postMessage(message, transfer); - } else { - this._pendingMessages.add({ message, transfer }); + public async postMessage(message: any, transfer?: readonly ArrayBuffer[]): Promise { + if (!this._webview.value) { + return false; } + return this._webview.value.postMessage(message, transfer); } focus(): void { this._webview.value?.focus(); } diff --git a/src/vs/workbench/contrib/webview/browser/webview.ts b/src/vs/workbench/contrib/webview/browser/webview.ts index 0db26467cba..284a3d7f897 100644 --- a/src/vs/workbench/contrib/webview/browser/webview.ts +++ b/src/vs/workbench/contrib/webview/browser/webview.ts @@ -183,7 +183,7 @@ export interface IWebview extends IDisposable { readonly onMessage: Event; readonly onMissingCsp: Event; - postMessage(message: any, transfer?: readonly ArrayBuffer[]): void; + postMessage(message: any, transfer?: readonly ArrayBuffer[]): Promise; focus(): void; reload(): void; diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts index 27d6ce75d84..c790753eb0b 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts @@ -85,10 +85,11 @@ namespace WebviewState { readonly type = Type.Initializing; constructor( - public readonly pendingMessages: Array<{ + public pendingMessages: Array<{ readonly channel: string; readonly data?: any; readonly transferable: Transferable[]; + readonly resolve: (posted: boolean) => void; }> ) { } } @@ -369,6 +370,13 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD this.messagePort = undefined; + if (this._state.type === WebviewState.Type.Initializing) { + for (const message of this._state.pendingMessages) { + message.resolve(false); + } + this._state.pendingMessages = []; + } + this._onDidDispose.fire(); this._resourceLoadingCts.dispose(true); @@ -410,15 +418,18 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD private readonly _onDidDispose = this._register(new Emitter()); public readonly onDidDispose = this._onDidDispose.event; - public postMessage(message: any, transfer?: ArrayBuffer[]): void { - this._send('message', { message, transfer }); + public postMessage(message: any, transfer?: ArrayBuffer[]): Promise { + return this._send('message', { message, transfer }); } - protected _send(channel: string, data?: any, transferable: Transferable[] = []): void { + protected async _send(channel: string, data?: any, transferable: Transferable[] = []): Promise { if (this._state.type === WebviewState.Type.Initializing) { - this._state.pendingMessages.push({ channel, data, transferable }); + let resolve: (x: boolean) => void; + const promise = new Promise(r => resolve = r); + this._state.pendingMessages.push({ channel, data, transferable, resolve: resolve! }); + return promise; } else { - this.doPostMessage(channel, data, transferable); + return this.doPostMessage(channel, data, transferable); } } @@ -494,10 +505,12 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD return uri.scheme + '://' + uri.authority.toLowerCase(); } - private doPostMessage(channel: string, data?: any, transferable: Transferable[] = []): void { + private doPostMessage(channel: string, data?: any, transferable: Transferable[] = []): boolean { if (this.element && this.messagePort) { this.messagePort.postMessage({ channel, args: data }, transferable); + return true; } + return false; } protected on(channel: WebviewMessageChannels, handler: (data: T, e: MessageEvent) => void): IDisposable { -- cgit v1.2.3 From 8a8e3bc99c363bdc13f3cc6bd89314afb19973d4 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 11 Apr 2022 16:20:35 -0700 Subject: Partal revert of 21173541e165b0327c67bcaeac82a8a2fe44c949 This adds back in the pending message buffer only for the first load of a webview --- .../contrib/webview/browser/overlayWebview.ts | 29 +++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/webview/browser/overlayWebview.ts b/src/vs/workbench/contrib/webview/browser/overlayWebview.ts index 7231d6577fb..112efec0ac3 100644 --- a/src/vs/workbench/contrib/webview/browser/overlayWebview.ts +++ b/src/vs/workbench/contrib/webview/browser/overlayWebview.ts @@ -21,6 +21,8 @@ export class OverlayWebview extends Disposable implements IOverlayWebview { private readonly _onDidWheel = this._register(new Emitter()); public readonly onDidWheel = this._onDidWheel.event; + private _isFirstLoad = true; + private readonly _firstLoadPendingMessages = new Set<{ readonly message: any; readonly transfer?: readonly ArrayBuffer[]; readonly resolve: (value: boolean) => void }>(); private readonly _webview = this._register(new MutableDisposable()); private readonly _webviewEvents = this._register(new DisposableStore()); @@ -69,6 +71,11 @@ export class OverlayWebview extends Disposable implements IOverlayWebview { this._container?.remove(); this._container = undefined; + for (const msg of this._firstLoadPendingMessages) { + msg.resolve(false); + } + this._firstLoadPendingMessages.clear(); + this._onDidDispose.fire(); super.dispose(); @@ -198,6 +205,14 @@ export class OverlayWebview extends Disposable implements IOverlayWebview { this._state = state; this._onDidUpdateState.fire(state); })); + + if (this._isFirstLoad) { + this._firstLoadPendingMessages.forEach(async msg => { + msg.resolve(await webview.postMessage(msg.message, msg.transfer)); + }); + } + this._isFirstLoad = false; + this._firstLoadPendingMessages.clear(); } this.container.style.visibility = 'visible'; @@ -265,10 +280,18 @@ export class OverlayWebview extends Disposable implements IOverlayWebview { public readonly onMissingCsp: Event = this._onMissingCsp.event; public async postMessage(message: any, transfer?: readonly ArrayBuffer[]): Promise { - if (!this._webview.value) { - return false; + if (this._webview.value) { + return this._webview.value.postMessage(message, transfer); + } + + if (this._isFirstLoad) { + let resolve: (x: boolean) => void; + const p = new Promise(r => resolve = r); + this._firstLoadPendingMessages.add({ message, transfer, resolve: resolve! }); + return p; } - return this._webview.value.postMessage(message, transfer); + + return false; } focus(): void { this._webview.value?.focus(); } -- cgit v1.2.3 From b0c5a282e53fb4c1eb138b9bff0f8e8c169592e1 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 11 Apr 2022 19:31:28 -0700 Subject: Restore additionalProperties=false to launch.json schema. Fix #142642 --- src/vs/workbench/contrib/debug/common/debugger.ts | 48 +++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/common/debugger.ts b/src/vs/workbench/contrib/debug/common/debugger.ts index c1c0166702d..8a41ba6c603 100644 --- a/src/vs/workbench/contrib/debug/common/debugger.ts +++ b/src/vs/workbench/contrib/debug/common/debugger.ts @@ -217,6 +217,7 @@ export class Debugger implements IDebugger { const attributes: IJSONSchema = this.debuggerContribution.configurationAttributes[request]; const defaultRequired = ['name', 'type', 'request']; attributes.required = attributes.required && attributes.required.length ? defaultRequired.concat(attributes.required) : defaultRequired; + attributes.additionalProperties = false; attributes.type = 'object'; if (!attributes.properties) { attributes.properties = {}; @@ -239,38 +240,37 @@ export class Debugger implements IDebugger { $ref: `#/definitions/common/properties/${prop}` }; } - definitions[definitionId] = attributes; - Object.keys(properties).forEach(name => { // Use schema allOf property to get independent error reporting #21113 ConfigurationResolverUtils.applyDeprecatedVariableMessage(properties[name]); }); - const result = { - allOf: [{ - $ref: `#/definitions/${definitionId}` - }, { - properties: { - windows: { - $ref: `#/definitions/${definitionId}`, - description: nls.localize('debugWindowsConfiguration', "Windows specific launch configuration attributes."), - required: [], - }, - osx: { - $ref: `#/definitions/${definitionId}`, - description: nls.localize('debugOSXConfiguration', "OS X specific launch configuration attributes."), - required: [], - }, - linux: { - $ref: `#/definitions/${definitionId}`, - description: nls.localize('debugLinuxConfiguration', "Linux specific launch configuration attributes."), - required: [], - } + definitions[definitionId] = { ...attributes }; + + // Don't add the OS props to the real attributes object so they don't show up in 'definitions' + const attributesCopy = { ...attributes }; + attributesCopy.properties = { + ...properties, + ...{ + windows: { + $ref: `#/definitions/${definitionId}`, + description: nls.localize('debugWindowsConfiguration', "Windows specific launch configuration attributes."), + required: [], + }, + osx: { + $ref: `#/definitions/${definitionId}`, + description: nls.localize('debugOSXConfiguration', "OS X specific launch configuration attributes."), + required: [], + }, + linux: { + $ref: `#/definitions/${definitionId}`, + description: nls.localize('debugLinuxConfiguration', "Linux specific launch configuration attributes."), + required: [], } - }] + } }; - return result; + return attributesCopy; }); } } -- cgit v1.2.3 From fcaeb69ec8e96057423f7dadd52e116e29b80cae Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 11 Apr 2022 20:25:17 -0700 Subject: More accurate escaping and quoting for debug commands in terminal. Fix #145265 --- src/vs/workbench/contrib/debug/node/terminals.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/node/terminals.ts b/src/vs/workbench/contrib/debug/node/terminals.ts index c27c88f27a6..5f89e708bc7 100644 --- a/src/vs/workbench/contrib/debug/node/terminals.ts +++ b/src/vs/workbench/contrib/debug/node/terminals.ts @@ -121,7 +121,7 @@ export function prepareCommand(shell: string, args: string[], cwd?: string, env? quote = (s: string) => { s = s.replace(/\"/g, '""'); - return (s.indexOf(' ') >= 0 || s.indexOf('"') >= 0 || s.length === 0) ? `"${s}"` : s; + return (' "> s.includes(char)) || s.length === 0) ? `"${s}"` : s; }; if (cwd) { @@ -154,8 +154,8 @@ export function prepareCommand(shell: string, args: string[], cwd?: string, env? case ShellType.bash: { quote = (s: string) => { - s = s.replace(/(["'\\\$])/g, '\\$1'); - return (s.indexOf(' ') >= 0 || s.indexOf(';') >= 0 || s.length === 0) ? `"${s}"` : s; + s = s.replace(/(["'\\\$!><#()\[\]*&^])/g, '\\$1'); + return (' ;'.split('').some(char => s.includes(char)) || s.length === 0) ? `"${s}"` : s; }; const hardQuote = (s: string) => { -- cgit v1.2.3 From e1bd9c0ba200c94b003e23a465b25491917d9ada Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 12 Apr 2022 11:10:01 +0530 Subject: use cancellation error --- .../contrib/extensions/browser/extensionsWorkbenchService.ts | 4 ++-- src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index 2b0a0fad05b..50152dc1f51 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -8,7 +8,7 @@ import * as semver from 'vs/base/common/semver/semver'; import { Event, Emitter } from 'vs/base/common/event'; import { index, distinct } from 'vs/base/common/arrays'; import { Promises, ThrottledDelayer } from 'vs/base/common/async'; -import { canceled, isCancellationError } from 'vs/base/common/errors'; +import { CancellationError, isCancellationError } from 'vs/base/common/errors'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IPager, singlePagePager } from 'vs/base/common/paging'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -1353,7 +1353,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension } } ], { - onCancel: () => reject(canceled()) + onCancel: () => reject(new CancellationError()) }); }); } diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts b/src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts index f5c142d6cca..8f833f178f6 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts @@ -19,7 +19,7 @@ import { IExtensionManagementService, ILocalExtension } from 'vs/platform/extens import { IWorkbenchExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { ILogService } from 'vs/platform/log/common/log'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { canceled } from 'vs/base/common/errors'; +import { CancellationError } from 'vs/base/common/errors'; import { ExtensionType } from 'vs/platform/extensions/common/extensions'; import { nullRange } from 'vs/workbench/services/preferences/common/preferencesModels'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -191,7 +191,7 @@ class RemoteSearchProvider implements ISearchProvider { } if (token && token.isCancellationRequested) { - throw canceled(); + throw new CancellationError(); } const resultKeys = Object.keys(remoteResult.scoredResults); -- cgit v1.2.3 From df11e521e8201821f79fb66fa7965b367a48ed8b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 12 Apr 2022 09:42:14 +0200 Subject: feedback :lipstick: --- .../workbench/contrib/feedback/browser/feedback.ts | 103 +++++++++++---------- 1 file changed, 52 insertions(+), 51 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/feedback/browser/feedback.ts b/src/vs/workbench/contrib/feedback/browser/feedback.ts index 46fc36b304e..77be54e32c4 100644 --- a/src/vs/workbench/contrib/feedback/browser/feedback.ts +++ b/src/vs/workbench/contrib/feedback/browser/feedback.ts @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/feedback'; -import * as nls from 'vs/nls'; +import { localize } from 'vs/nls'; import { IDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import * as dom from 'vs/base/browser/dom'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IIntegrityService } from 'vs/workbench/services/integrity/common/integrity'; import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { attachButtonStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; import { editorWidgetBackground, editorWidgetForeground, widgetShadow, inputBorder, inputForeground, inputBackground, inputActiveOptionBorder, editorBackground, textLinkForeground, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; +import { append, $, addDisposableListener, EventType, EventHelper, prepend } from 'vs/base/browser/dom'; import { IAnchor } from 'vs/base/browser/ui/contextview/contextview'; import { Button } from 'vs/base/browser/ui/button/button'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -114,25 +114,26 @@ export class FeedbackWidget extends Disposable { container.classList.add('monaco-menu-container'); // Form - this.feedbackForm = dom.append(container, dom.$('form.feedback-form')); + this.feedbackForm = append(container, $('form.feedback-form')); this.feedbackForm.setAttribute('action', 'javascript:void(0);'); // Title - dom.append(this.feedbackForm, dom.$('h2.title')).textContent = nls.localize("label.sendASmile", "Tweet us your feedback."); + append(this.feedbackForm, $('h2.title')).textContent = localize("label.sendASmile", "Tweet us your feedback."); // Close Button (top right) - const closeBtn = dom.append(this.feedbackForm, dom.$('div.cancel' + Codicon.close.cssSelector)); + const closeBtn = append(this.feedbackForm, $(`div.cancel${Codicon.close.cssSelector}`)); closeBtn.tabIndex = 0; closeBtn.setAttribute('role', 'button'); - closeBtn.title = nls.localize('close', "Close"); + closeBtn.title = localize('close', "Close"); - disposables.add(dom.addDisposableListener(container, dom.EventType.KEY_DOWN, keyboardEvent => { + disposables.add(addDisposableListener(container, EventType.KEY_DOWN, keyboardEvent => { const standardKeyboardEvent = new StandardKeyboardEvent(keyboardEvent); if (standardKeyboardEvent.keyCode === KeyCode.Escape) { this.hide(); } })); - disposables.add(dom.addDisposableListener(closeBtn, dom.EventType.MOUSE_OVER, () => { + + disposables.add(addDisposableListener(closeBtn, EventType.MOUSE_OVER, () => { const theme = this.themeService.getColorTheme(); let darkenFactor: number | undefined; switch (theme.type) { @@ -155,47 +156,47 @@ export class FeedbackWidget extends Disposable { } })); - disposables.add(dom.addDisposableListener(closeBtn, dom.EventType.MOUSE_OUT, () => { + disposables.add(addDisposableListener(closeBtn, EventType.MOUSE_OUT, () => { closeBtn.style.backgroundColor = ''; })); this.invoke(closeBtn, disposables, () => this.hide()); // Content - const content = dom.append(this.feedbackForm, dom.$('div.content')); + const content = append(this.feedbackForm, $('div.content')); // Sentiment Buttons - const sentimentContainer = dom.append(content, dom.$('div')); + const sentimentContainer = append(content, $('div')); if (!this.isPure) { - dom.append(sentimentContainer, dom.$('span')).textContent = nls.localize("patchedVersion1", "Your installation is corrupt."); + append(sentimentContainer, $('span')).textContent = localize("patchedVersion1", "Your installation is corrupt."); sentimentContainer.appendChild(document.createElement('br')); - dom.append(sentimentContainer, dom.$('span')).textContent = nls.localize("patchedVersion2", "Please specify this if you submit a bug."); + append(sentimentContainer, $('span')).textContent = localize("patchedVersion2", "Please specify this if you submit a bug."); sentimentContainer.appendChild(document.createElement('br')); } - dom.append(sentimentContainer, dom.$('span')).textContent = nls.localize("sentiment", "How was your experience?"); + append(sentimentContainer, $('span')).textContent = localize("sentiment", "How was your experience?"); - const feedbackSentiment = dom.append(sentimentContainer, dom.$('div.feedback-sentiment')); + const feedbackSentiment = append(sentimentContainer, $('div.feedback-sentiment')); // Sentiment: Smiley - this.smileyInput = dom.append(feedbackSentiment, dom.$('div.sentiment')); + this.smileyInput = append(feedbackSentiment, $('div.sentiment')); this.smileyInput.classList.add('smile'); this.smileyInput.setAttribute('aria-checked', 'false'); - this.smileyInput.setAttribute('aria-label', nls.localize('smileCaption', "Happy Feedback Sentiment")); + this.smileyInput.setAttribute('aria-label', localize('smileCaption', "Happy Feedback Sentiment")); this.smileyInput.setAttribute('role', 'checkbox'); - this.smileyInput.title = nls.localize('smileCaption', "Happy Feedback Sentiment"); + this.smileyInput.title = localize('smileCaption', "Happy Feedback Sentiment"); this.smileyInput.tabIndex = 0; this.invoke(this.smileyInput, disposables, () => this.setSentiment(true)); // Sentiment: Frowny - this.frownyInput = dom.append(feedbackSentiment, dom.$('div.sentiment')); + this.frownyInput = append(feedbackSentiment, $('div.sentiment')); this.frownyInput.classList.add('frown'); this.frownyInput.setAttribute('aria-checked', 'false'); - this.frownyInput.setAttribute('aria-label', nls.localize('frownCaption', "Sad Feedback Sentiment")); + this.frownyInput.setAttribute('aria-label', localize('frownCaption', "Sad Feedback Sentiment")); this.frownyInput.setAttribute('role', 'checkbox'); - this.frownyInput.title = nls.localize('frownCaption', "Sad Feedback Sentiment"); + this.frownyInput.title = localize('frownCaption', "Sad Feedback Sentiment"); this.frownyInput.tabIndex = 0; this.invoke(this.frownyInput, disposables, () => this.setSentiment(false)); @@ -209,23 +210,23 @@ export class FeedbackWidget extends Disposable { } // Contact Us Box - const contactUsContainer = dom.append(content, dom.$('div.contactus')); + const contactUsContainer = append(content, $('div.contactus')); - dom.append(contactUsContainer, dom.$('span')).textContent = nls.localize("other ways to contact us", "Other ways to contact us"); + append(contactUsContainer, $('span')).textContent = localize("other ways to contact us", "Other ways to contact us"); - const channelsContainer = dom.append(contactUsContainer, dom.$('div.channels')); + const channelsContainer = append(contactUsContainer, $('div.channels')); // Contact: Submit a Bug - const submitBugLinkContainer = dom.append(channelsContainer, dom.$('div')); + const submitBugLinkContainer = append(channelsContainer, $('div')); - const submitBugLink = dom.append(submitBugLinkContainer, dom.$('a')); + const submitBugLink = append(submitBugLinkContainer, $('a')); submitBugLink.setAttribute('target', '_blank'); submitBugLink.setAttribute('href', '#'); - submitBugLink.textContent = nls.localize("submit a bug", "Submit a bug"); + submitBugLink.textContent = localize("submit a bug", "Submit a bug"); submitBugLink.tabIndex = 0; - disposables.add(dom.addDisposableListener(submitBugLink, 'click', e => { - dom.EventHelper.stop(e); + disposables.add(addDisposableListener(submitBugLink, 'click', e => { + EventHelper.stop(e); const actionId = 'workbench.action.openIssueReporter'; this.commandService.executeCommand(actionId); this.hide(); @@ -234,57 +235,57 @@ export class FeedbackWidget extends Disposable { // Contact: Request a Feature if (!!this.requestFeatureLink) { - const requestFeatureLinkContainer = dom.append(channelsContainer, dom.$('div')); + const requestFeatureLinkContainer = append(channelsContainer, $('div')); - const requestFeatureLink = dom.append(requestFeatureLinkContainer, dom.$('a')); + const requestFeatureLink = append(requestFeatureLinkContainer, $('a')); requestFeatureLink.setAttribute('target', '_blank'); requestFeatureLink.setAttribute('href', this.requestFeatureLink); - requestFeatureLink.textContent = nls.localize("request a missing feature", "Request a missing feature"); + requestFeatureLink.textContent = localize("request a missing feature", "Request a missing feature"); requestFeatureLink.tabIndex = 0; - disposables.add(dom.addDisposableListener(requestFeatureLink, 'click', e => this.hide())); + disposables.add(addDisposableListener(requestFeatureLink, 'click', e => this.hide())); } // Remaining Characters - const remainingCharacterCountContainer = dom.append(this.feedbackForm, dom.$('h3')); - remainingCharacterCountContainer.textContent = nls.localize("tell us why", "Tell us why?"); + const remainingCharacterCountContainer = append(this.feedbackForm, $('h3')); + remainingCharacterCountContainer.textContent = localize("tell us why", "Tell us why?"); - this.remainingCharacterCount = dom.append(remainingCharacterCountContainer, dom.$('span.char-counter')); + this.remainingCharacterCount = append(remainingCharacterCountContainer, $('span.char-counter')); this.remainingCharacterCount.textContent = this.getCharCountText(0); // Feedback Input Form - this.feedbackDescriptionInput = dom.append(this.feedbackForm, dom.$('textarea.feedback-description')); + this.feedbackDescriptionInput = append(this.feedbackForm, $('textarea.feedback-description')); this.feedbackDescriptionInput.rows = 3; this.feedbackDescriptionInput.maxLength = this.maxFeedbackCharacters; this.feedbackDescriptionInput.textContent = this.feedback; this.feedbackDescriptionInput.required = true; - this.feedbackDescriptionInput.setAttribute('aria-label', nls.localize("feedbackTextInput", "Tell us your feedback")); + this.feedbackDescriptionInput.setAttribute('aria-label', localize("feedbackTextInput", "Tell us your feedback")); this.feedbackDescriptionInput.focus(); - disposables.add(dom.addDisposableListener(this.feedbackDescriptionInput, 'keyup', () => this.updateCharCountText())); + disposables.add(addDisposableListener(this.feedbackDescriptionInput, 'keyup', () => this.updateCharCountText())); // Feedback Input Form Buttons Container - const buttonsContainer = dom.append(this.feedbackForm, dom.$('div.form-buttons')); + const buttonsContainer = append(this.feedbackForm, $('div.form-buttons')); // Checkbox: Hide Feedback Smiley - const hideButtonContainer = dom.append(buttonsContainer, dom.$('div.hide-button-container')); + const hideButtonContainer = append(buttonsContainer, $('div.hide-button-container')); - this.hideButton = dom.append(hideButtonContainer, dom.$('input.hide-button')) as HTMLInputElement; + this.hideButton = append(hideButtonContainer, $('input.hide-button')) as HTMLInputElement; this.hideButton.type = 'checkbox'; this.hideButton.checked = true; this.hideButton.id = 'hide-button'; - const hideButtonLabel = dom.append(hideButtonContainer, dom.$('label')); + const hideButtonLabel = append(hideButtonContainer, $('label')); hideButtonLabel.setAttribute('for', 'hide-button'); - hideButtonLabel.textContent = nls.localize('showFeedback', "Show Feedback Icon in Status Bar"); + hideButtonLabel.textContent = localize('showFeedback', "Show Feedback Icon in Status Bar"); // Button: Send Feedback this.sendButton = new Button(buttonsContainer); this.sendButton.enabled = false; - this.sendButton.label = nls.localize('tweet', "Tweet"); - dom.prepend(this.sendButton.element, dom.$('span' + Codicon.twitter.cssSelector)); + this.sendButton.label = localize('tweet', "Tweet"); + prepend(this.sendButton.element, $(`span${Codicon.twitter.cssSelector}`)); this.sendButton.element.classList.add('send'); - this.sendButton.element.title = nls.localize('tweetFeedback', "Tweet Feedback"); + this.sendButton.element.title = localize('tweetFeedback', "Tweet Feedback"); disposables.add(attachButtonStyler(this.sendButton, this.themeService)); this.sendButton.onDidClick(() => this.onSubmit()); @@ -326,8 +327,8 @@ export class FeedbackWidget extends Disposable { private getCharCountText(charCount: number): string { const remaining = this.maxFeedbackCharacters - charCount; const text = (remaining === 1) - ? nls.localize("character left", "character left") - : nls.localize("characters left", "characters left"); + ? localize("character left", "character left") + : localize("characters left", "characters left"); return `(${remaining} ${text})`; } @@ -370,9 +371,9 @@ export class FeedbackWidget extends Disposable { } private invoke(element: HTMLElement, disposables: DisposableStore, callback: () => void): HTMLElement { - disposables.add(dom.addDisposableListener(element, 'click', callback)); + disposables.add(addDisposableListener(element, 'click', callback)); - disposables.add(dom.addDisposableListener(element, 'keypress', e => { + disposables.add(addDisposableListener(element, 'keypress', e => { if (e instanceof KeyboardEvent) { const keyboardEvent = e; if (keyboardEvent.keyCode === 13 || keyboardEvent.keyCode === 32) { // Enter or Spacebar -- cgit v1.2.3 From 71cba766553cc2551ba98b072f4b28b2657b0e58 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 8 Apr 2022 16:39:00 +0200 Subject: Fixed missed comment range start/end line --- src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index 79048b422ce..9e2c2ca12d6 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -565,7 +565,7 @@ export class CommentController implements IEditorContribution { private displayCommentThread(owner: string, thread: languages.CommentThread, pendingComment: string | null): void { const zoneWidget = this.instantiationService.createInstance(ReviewZoneWidget, this.editor, owner, thread, pendingComment); - zoneWidget.display(thread.range.startLineNumber); + zoneWidget.display(thread.range.endLineNumber); this._commentWidgets.push(zoneWidget); } -- cgit v1.2.3 From 57faf0f9082219f0a0279ef9456cdee59a18c611 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 11 Apr 2022 15:45:02 +0200 Subject: Add background and border to comments with a range Part of #146510 --- .../contrib/comments/browser/commentColors.ts | 6 +- .../browser/commentThreadRangeDecorator.ts | 67 ++++++++++++++++++++++ .../comments/browser/commentsEditorContribution.ts | 22 ++++++- 3 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentColors.ts b/src/vs/workbench/contrib/comments/browser/commentColors.ts index 9fd3ade031c..f906c411aad 100644 --- a/src/vs/workbench/contrib/comments/browser/commentColors.ts +++ b/src/vs/workbench/contrib/comments/browser/commentColors.ts @@ -7,11 +7,13 @@ import { Color } from 'vs/base/common/color'; import * as languages from 'vs/editor/common/languages'; import { peekViewBorder } from 'vs/editor/contrib/peekView/browser/peekView'; import * as nls from 'vs/nls'; -import { contrastBorder, disabledForeground, registerColor } from 'vs/platform/theme/common/colorRegistry'; +import { contrastBorder, disabledForeground, registerColor, transparent } from 'vs/platform/theme/common/colorRegistry'; import { IColorTheme } from 'vs/platform/theme/common/themeService'; const resolvedCommentBorder = registerColor('editorCommentsWidget.resolvedBorder', { dark: disabledForeground, light: disabledForeground, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('resolvedCommentBorder', 'Color of borders and arrow for resolved comments.')); const unresolvedCommentBorder = registerColor('editorCommentsWidget.unresolvedBorder', { dark: peekViewBorder, light: peekViewBorder, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('unresolvedCommentBorder', 'Color of borders and arrow for unresolved comments.')); +export const commentThreadRangeBackground = registerColor('editorCommentsWidget.rangeBackground', { dark: transparent(unresolvedCommentBorder, .1), light: transparent(unresolvedCommentBorder, .1), hcDark: transparent(unresolvedCommentBorder, .1), hcLight: transparent(unresolvedCommentBorder, .1) }, nls.localize('commentThreadRangeBackground', 'Color of background for comment ranges.')); +export const commentThreadRangeBorder = registerColor('editorCommentsWidget.rangeBorder', { dark: transparent(unresolvedCommentBorder, .4), light: transparent(unresolvedCommentBorder, .4), hcDark: transparent(unresolvedCommentBorder, .4), hcLight: transparent(unresolvedCommentBorder, .4) }, nls.localize('commentThreadRangeBackground', 'Color of background for comment ranges.')); const commentThreadStateColors = new Map([ [languages.CommentThreadState.Unresolved, unresolvedCommentBorder], @@ -21,6 +23,8 @@ const commentThreadStateColors = new Map([ export const commentThreadStateColorVar = '--comment-thread-state-color'; export const commentViewThreadStateColorVar = '--comment-view-thread-state-color'; export const commentThreadStateBackgroundColorVar = '--comment-thread-state-background-color'; +export const commentThreadRangeBackgroundColorVar = '--vscode-comment-thread-range-background'; +export const commentThreadRangeBorderColorVar = '--vscode-comment-thread-range-border'; export function getCommentThreadStateColor(state: languages.CommentThreadState | undefined, theme: IColorTheme): Color | undefined { const colorId = (state !== undefined) ? commentThreadStateColors.get(state) : undefined; diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts b/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts new file mode 100644 index 00000000000..2121f88033c --- /dev/null +++ b/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts @@ -0,0 +1,67 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { IRange } from 'vs/editor/common/core/range'; +import { IModelDecorationOptions, IModelDeltaDecoration } from 'vs/editor/common/model'; +import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; +import { ICommentInfo } from 'vs/workbench/contrib/comments/browser/commentService'; + +class CommentThreadRangeDecoration implements IModelDeltaDecoration { + private _decorationId: string | undefined; + + public get id(): string | undefined { + return this._decorationId; + } + + public set id(id: string | undefined) { + this._decorationId = id; + } + + constructor( + public readonly range: IRange, + public readonly options: ModelDecorationOptions) { + } +} + +export class CommentThreadRangeDecorator { + public static description = 'comment-thread-range-decorator'; + private decorationOptions: ModelDecorationOptions; + private decorationIds: string[] = []; + + constructor() { + const decorationOptions: IModelDecorationOptions = { + description: CommentThreadRangeDecorator.description, + isWholeLine: false, + zIndex: 20, + className: 'comment-thread-range' + }; + + this.decorationOptions = ModelDecorationOptions.createDynamic(decorationOptions); + } + + public update(editor: ICodeEditor, commentInfos: ICommentInfo[]) { + const model = editor.getModel(); + if (!model) { + return; + } + + const commentThreadRangeDecorations: CommentThreadRangeDecoration[] = []; + for (const info of commentInfos) { + info.threads.forEach(thread => { + const range = thread.range; + // We only want to show a range decoration when there's the range spans either multiple lines + // or, when is spans multiple characters on the sample line + if ((range.startLineNumber === range.endLineNumber) && (range.startColumn === range.endColumn)) { + return; + } + commentThreadRangeDecorations.push(new CommentThreadRangeDecoration(range, this.decorationOptions)); + }); + } + + this.decorationIds = editor.deltaDecorations(this.decorationIds, commentThreadRangeDecorations); + commentThreadRangeDecorations.forEach((decoration, index) => decoration.id = this.decorationIds[index]); + } +} diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index 9e2c2ca12d6..29bedfd869e 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -46,6 +46,8 @@ import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { Position } from 'vs/editor/common/core/position'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; +import { CommentThreadRangeDecorator } from 'vs/workbench/contrib/comments/browser/commentThreadRangeDecorator'; +import { commentThreadRangeBackground, commentThreadRangeBorder } from 'vs/workbench/contrib/comments/browser/commentColors'; export const ID = 'editor.contrib.review'; @@ -239,6 +241,7 @@ export class CommentController implements IEditorContribution { private _commentWidgets: ReviewZoneWidget[]; private _commentInfos: ICommentInfo[]; private _commentingRangeDecorator!: CommentingRangeDecorator; + private _commentThreadRangeDecorator!: CommentThreadRangeDecorator; private mouseDownInfo: { lineNumber: number } | null = null; private _commentingRangeSpaceReserved = false; private _computePromise: CancelablePromise> | null; @@ -282,6 +285,8 @@ export class CommentController implements IEditorContribution { } })); + this._commentThreadRangeDecorator = new CommentThreadRangeDecorator(); + this.globalToDispose.add(this.commentService.onDidDeleteDataProvider(ownerId => { delete this._pendingCommentCache[ownerId]; this.beginCompute(); @@ -552,7 +557,7 @@ export class CommentController implements IEditorContribution { this.displayCommentThread(e.owner, thread, pendingCommentText); this._commentInfos.filter(info => info.owner === e.owner)[0].threads.push(thread); }); - + this._commentThreadRangeDecorator.update(this.editor, commentInfo); })); this.beginCompute().then(() => { @@ -755,6 +760,7 @@ export class CommentController implements IEditorContribution { }); this._commentingRangeDecorator.update(this.editor, this._commentInfos); + this._commentThreadRangeDecorator.update(this.editor, this._commentInfos); } public closeWidget(): void { @@ -993,4 +999,18 @@ registerThemingParticipant((theme, collector) => { if (statusBarItemActiveBackground) { collector.addRule(`.review-widget .body .review-comment .review-comment-contents .comment-reactions .action-item a.action-label:active { background-color: ${statusBarItemActiveBackground}; border: 1px solid transparent;}`); } + + const commentThreadRangeBackgroundColor = theme.getColor(commentThreadRangeBackground); + if (commentThreadRangeBackgroundColor) { + collector.addRule(`.monaco-editor .comment-thread-range { background-color: ${commentThreadRangeBackgroundColor};}`); + } + + const commentThreadRangeBorderColor = theme.getColor(commentThreadRangeBorder); + if (commentThreadRangeBorderColor) { + collector.addRule(`.monaco-editor .comment-thread-range { + border-color: ${commentThreadRangeBorderColor}; + border-width: 1px; + border-style: solid; + box-sizing: border-box; }`); + } }); -- cgit v1.2.3 From a1ba200c714d6d4bf96128b53ba2b979b7293ad8 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 12 Apr 2022 14:45:53 +0200 Subject: UX for leaving a comment on a range Part of #146510 --- .../browser/commentThreadRangeDecorator.ts | 3 + .../comments/browser/commentsEditorContribution.ts | 103 ++++++++++++++++++--- .../contrib/comments/browser/media/review.css | 1 + 3 files changed, 95 insertions(+), 12 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts b/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts index 2121f88033c..adadb4a6617 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts @@ -51,6 +51,9 @@ export class CommentThreadRangeDecorator { const commentThreadRangeDecorations: CommentThreadRangeDecoration[] = []; for (const info of commentInfos) { info.threads.forEach(thread => { + if (thread.isDisposed) { + return; + } const range = thread.range; // We only want to show a range decoration when there's the range spans either multiple lines // or, when is spans multiple characters on the sample line diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index 29bedfd869e..0fa7eaf9ded 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -48,6 +48,7 @@ import { Position } from 'vs/editor/common/core/position'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { CommentThreadRangeDecorator } from 'vs/workbench/contrib/comments/browser/commentThreadRangeDecorator'; import { commentThreadRangeBackground, commentThreadRangeBorder } from 'vs/workbench/contrib/comments/browser/commentColors'; +import { ICursorSelectionChangedEvent } from 'vs/editor/common/cursorEvents'; export const ID = 'editor.contrib.review'; @@ -120,13 +121,16 @@ class CommentingRangeDecoration implements IModelDeltaDecoration { class CommentingRangeDecorator { public static description = 'commenting-range-decorator'; - private decorationOptions!: ModelDecorationOptions; - private hoverDecorationOptions!: ModelDecorationOptions; + private decorationOptions: ModelDecorationOptions; + private hoverDecorationOptions: ModelDecorationOptions; + private multilineDecorationOptions: ModelDecorationOptions; private commentingRangeDecorations: CommentingRangeDecoration[] = []; private decorationIds: string[] = []; private _editor: ICodeEditor | undefined; private _infos: ICommentInfo[] | undefined; private _lastHover: number = -1; + private _lastSelection: Range | undefined; + private _lastSelectionCursor: number | undefined; private _onDidChangeDecorationsCount: Emitter = new Emitter(); public readonly onDidChangeDecorationsCount = this._onDidChangeDecorationsCount.event; @@ -146,6 +150,14 @@ class CommentingRangeDecorator { }; this.hoverDecorationOptions = ModelDecorationOptions.createDynamic(hoverDecorationOptions); + + const multilineDecorationOptions: IModelDecorationOptions = { + description: CommentingRangeDecorator.description, + isWholeLine: true, + linesDecorationsClassName: `comment-range-glyph comment-diff-added multiline-add` + }; + + this.multilineDecorationOptions = ModelDecorationOptions.createDynamic(multilineDecorationOptions); } public updateHover(hoverLine?: number) { @@ -155,27 +167,72 @@ class CommentingRangeDecorator { this._lastHover = hoverLine ?? -1; } + public updateSelection(cursorLine: number, range: Range) { + this._lastSelection = range.isEmpty() ? undefined : range; + this._lastSelectionCursor = range.isEmpty() ? undefined : cursorLine; + // Some scenarios: + // Selection is made. Emphasis should show on the drag/selection end location. + // Selection is made, then user clicks elsewhere. We should still show the decoration. + if (this._editor && this._infos) { + this._doUpdate(this._editor, this._infos, cursorLine, range); + } + } + public update(editor: ICodeEditor, commentInfos: ICommentInfo[]) { this._editor = editor; this._infos = commentInfos; this._doUpdate(editor, commentInfos); } - private _doUpdate(editor: ICodeEditor, commentInfos: ICommentInfo[], hoverLine: number = -1) { + private _doUpdate(editor: ICodeEditor, commentInfos: ICommentInfo[], emphasisLine: number = -1, selectionRange: Range | undefined = this._lastSelection) { let model = editor.getModel(); if (!model) { return; } + // If there's still a selection, use that. + emphasisLine = this._lastSelectionCursor ?? emphasisLine; + let commentingRangeDecorations: CommentingRangeDecoration[] = []; for (const info of commentInfos) { info.commentingRanges.ranges.forEach(range => { - if ((range.startLineNumber <= hoverLine) && (range.endLineNumber >= hoverLine)) { - const beforeRange = new Range(range.startLineNumber, 1, hoverLine, 1); - const hoverRange = new Range(hoverLine, 1, hoverLine, 1); - const afterRange = new Range(hoverLine, 1, range.endLineNumber, 1); + const rangeObject = new Range(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn); + let intersectingSelectionRange = selectionRange ? rangeObject.intersectRanges(selectionRange) : undefined; + if ((selectionRange && (emphasisLine >= 0) && intersectingSelectionRange) + // If there's only one selection line, then just drop into the else if and show an emphasis line. + && !((intersectingSelectionRange.startLineNumber === intersectingSelectionRange.endLineNumber) + && (emphasisLine === intersectingSelectionRange.startLineNumber))) { + // The emphasisLine should be the within the commenting range, even if the selection range stretches + // outside of the commenting range. + // Clip the emphasis and selection ranges to the commenting range + let intersectingEmphasisRange: Range; + if (emphasisLine <= intersectingSelectionRange.startLineNumber) { + intersectingEmphasisRange = intersectingSelectionRange.collapseToStart(); + intersectingSelectionRange = new Range(intersectingSelectionRange.startLineNumber + 1, 1, intersectingSelectionRange.endLineNumber, 1); + } else { + intersectingEmphasisRange = new Range(intersectingSelectionRange.endLineNumber, 1, intersectingSelectionRange.endLineNumber, 1); + intersectingSelectionRange = new Range(intersectingSelectionRange.startLineNumber, 1, intersectingSelectionRange.endLineNumber - 1, 1); + } + commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, intersectingSelectionRange, this.multilineDecorationOptions, info.commentingRanges, true)); + commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, intersectingEmphasisRange, this.hoverDecorationOptions, info.commentingRanges, true)); + + const beforeRangeEndLine = Math.min(intersectingEmphasisRange.startLineNumber, intersectingSelectionRange.startLineNumber) - 1; + const hasBeforeRange = rangeObject.startLineNumber <= beforeRangeEndLine; + const afterRangeStartLine = Math.max(intersectingEmphasisRange.endLineNumber, intersectingSelectionRange.endLineNumber) + 1; + const hasAfterRange = rangeObject.endLineNumber >= afterRangeStartLine; + if (hasBeforeRange) { + const beforeRange = new Range(range.startLineNumber, 1, beforeRangeEndLine, 1); + commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, beforeRange, this.decorationOptions, info.commentingRanges, true)); + } + if (hasAfterRange) { + const afterRange = new Range(afterRangeStartLine, 1, range.endLineNumber, 1); + commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, afterRange, this.decorationOptions, info.commentingRanges, true)); + } + } else if ((rangeObject.startLineNumber <= emphasisLine) && (emphasisLine <= rangeObject.endLineNumber)) { + const beforeRange = new Range(range.startLineNumber, 1, emphasisLine, 1); + const afterRange = new Range(emphasisLine, 1, range.endLineNumber, 1); commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, beforeRange, this.decorationOptions, info.commentingRanges, true)); - commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, hoverRange, this.hoverDecorationOptions, info.commentingRanges, true)); + commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, new Range(emphasisLine, 1, emphasisLine, 1), this.hoverDecorationOptions, info.commentingRanges, true)); commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, afterRange, this.decorationOptions, info.commentingRanges, true)); } else { commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, range, this.decorationOptions, info.commentingRanges)); @@ -199,9 +256,9 @@ class CommentingRangeDecorator { for (const decoration of this.commentingRangeDecorations) { const range = decoration.getActiveRange(); if (range && ((range.startLineNumber <= commentRange.startLineNumber) || (commentRange.endLineNumber <= range.endLineNumber))) { - // We can have 3 commenting ranges that match from the same owner because of how - // the line hover decoration is done. - // The 3 ranges must be merged so that we can see if the new commentRange fits within them. + // We can have several commenting ranges that match from the same owner because of how + // the line hover and selection decoration is done. + // The ranges must be merged so that we can see if the new commentRange fits within them. const action = decoration.getCommentAction(); const alreadyFoundInfo = foundHoverActions.get(action.ownerId); if (alreadyFoundInfo?.action.commentingRangesInfo === action.commentingRangesInfo) { @@ -311,6 +368,7 @@ export class CommentController implements IEditorContribution { this._editorDisposables.push(this.editor.onMouseMove(e => this.onEditorMouseMove(e))); this._editorDisposables.push(this.editor.onDidChangeCursorPosition(e => this.onEditorChangeCursorPosition(e.position))); this._editorDisposables.push(this.editor.onDidFocusEditorWidget(() => this.onEditorChangeCursorPosition(this.editor.getPosition()))); + this._editorDisposables.push(this.editor.onDidChangeCursorSelection(e => this.onEditorChangeCursorSelection(e))); } private clearEditorListeners() { @@ -322,6 +380,13 @@ export class CommentController implements IEditorContribution { this._commentingRangeDecorator.updateHover(e.target.position?.lineNumber); } + private onEditorChangeCursorSelection(e: ICursorSelectionChangedEvent): void { + const position = this.editor.getPosition()?.lineNumber; + if (position) { + this._commentingRangeDecorator.updateSelection(position, e.selection); + } + } + private onEditorChangeCursorPosition(e: Position | null) { const decorations = e ? this.editor.getDecorationsInRange(Range.fromPositions(e, { column: -1, lineNumber: e.lineNumber })) : undefined; let hasCommentingRange = false; @@ -531,6 +596,13 @@ export class CommentController implements IEditorContribution { this._commentWidgets.splice(index, 1); matchedZone.dispose(); } + const infosThreads = this._commentInfos.filter(info => info.owner === e.owner)[0].threads; + for (let i = 0; i < infosThreads.length; i++) { + if (infosThreads[i] === thread) { + infosThreads.splice(i, 1); + i--; + } + } }); changed.forEach(thread => { @@ -588,7 +660,14 @@ export class CommentController implements IEditorContribution { if (e.target.element.className.indexOf('comment-diff-added') >= 0) { const lineNumber = e.target.position!.lineNumber; - this.addOrToggleCommentAtLine(new Range(lineNumber, 1, lineNumber, 1), e); + // Check for selection at line number. + let range: Range = new Range(lineNumber, 1, lineNumber, 1); + const selection = this.editor.getSelection(); + if (selection?.containsRange(range)) { + range = selection; + this.editor.setSelection(new Range(selection.endLineNumber, 1, selection.endLineNumber, 1)); + } + this.addOrToggleCommentAtLine(range, e); } } diff --git a/src/vs/workbench/contrib/comments/browser/media/review.css b/src/vs/workbench/contrib/comments/browser/media/review.css index 2539c3e3960..b87a2db8b42 100644 --- a/src/vs/workbench/contrib/comments/browser/media/review.css +++ b/src/vs/workbench/contrib/comments/browser/media/review.css @@ -393,6 +393,7 @@ div.preview.inline .monaco-editor .comment-range-glyph { .monaco-editor .margin-view-overlays > div:hover > .comment-range-glyph.comment-diff-added:before, .monaco-editor .margin-view-overlays .comment-range-glyph.comment-diff-added.line-hover:before, +.monaco-editor .margin-view-overlays .comment-range-glyph.comment-diff-added.multiline-add:before, .monaco-editor .comment-range-glyph.comment-thread:before { position: absolute; height: 100%; -- cgit v1.2.3 From 20bd040c95fb761b4aa13f67ea3cb70aac8cce63 Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Tue, 12 Apr 2022 14:14:19 -0400 Subject: Merge internal options to timeline options (#147304) --- .../contrib/localHistory/browser/localHistoryTimeline.ts | 4 ++-- src/vs/workbench/contrib/timeline/browser/timelinePane.ts | 5 +++-- src/vs/workbench/contrib/timeline/common/timeline.ts | 11 ++++------- src/vs/workbench/contrib/timeline/common/timelineService.ts | 6 +++--- 4 files changed, 12 insertions(+), 14 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/localHistory/browser/localHistoryTimeline.ts b/src/vs/workbench/contrib/localHistory/browser/localHistoryTimeline.ts index c0e31f90dd3..2dee3866cbd 100644 --- a/src/vs/workbench/contrib/localHistory/browser/localHistoryTimeline.ts +++ b/src/vs/workbench/contrib/localHistory/browser/localHistoryTimeline.ts @@ -8,7 +8,7 @@ import { Emitter } from 'vs/base/common/event'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { InternalTimelineOptions, ITimelineService, Timeline, TimelineChangeEvent, TimelineItem, TimelineOptions, TimelineProvider } from 'vs/workbench/contrib/timeline/common/timeline'; +import { ITimelineService, Timeline, TimelineChangeEvent, TimelineItem, TimelineOptions, TimelineProvider } from 'vs/workbench/contrib/timeline/common/timeline'; import { IWorkingCopyHistoryEntry, IWorkingCopyHistoryService } from 'vs/workbench/services/workingCopy/common/workingCopyHistory'; import { URI } from 'vs/base/common/uri'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; @@ -102,7 +102,7 @@ export class LocalHistoryTimeline extends Disposable implements IWorkbenchContri }); } - async provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: InternalTimelineOptions): Promise { + async provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken): Promise { const items: TimelineItem[] = []; // Try to convert the provided `uri` into a form that is likely diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index 10c04d75a9c..6c2233986e1 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -571,9 +571,10 @@ export class TimelinePane extends ViewPane { } } request?.tokenSource.dispose(true); - + options.cacheResults = true; + options.resetCache = reset; request = this.timelineService.getTimeline( - source, uri, options, new CancellationTokenSource(), { cacheResults: true, resetCache: reset } + source, uri, options, new CancellationTokenSource() ); if (request === undefined) { diff --git a/src/vs/workbench/contrib/timeline/common/timeline.ts b/src/vs/workbench/contrib/timeline/common/timeline.ts index 8b9f870c14d..5185f65703e 100644 --- a/src/vs/workbench/contrib/timeline/common/timeline.ts +++ b/src/vs/workbench/contrib/timeline/common/timeline.ts @@ -77,11 +77,8 @@ export interface TimelineChangeEvent { export interface TimelineOptions { cursor?: string; limit?: number | { timestamp: number; id?: string }; -} - -export interface InternalTimelineOptions { - cacheResults: boolean; - resetCache: boolean; + resetCache?: boolean; + cacheResults?: boolean; } export interface Timeline { @@ -101,7 +98,7 @@ export interface Timeline { export interface TimelineProvider extends TimelineProviderDescriptor, IDisposable { onDidChange?: Event; - provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: InternalTimelineOptions): Promise; + provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken): Promise; } export interface TimelineSource { @@ -152,7 +149,7 @@ export interface ITimelineService { getSources(): TimelineSource[]; - getTimeline(id: string, uri: URI, options: TimelineOptions, tokenSource: CancellationTokenSource, internalOptions?: InternalTimelineOptions): TimelineRequest | undefined; + getTimeline(id: string, uri: URI, options: TimelineOptions, tokenSource: CancellationTokenSource): TimelineRequest | undefined; setUri(uri: URI): void; } diff --git a/src/vs/workbench/contrib/timeline/common/timelineService.ts b/src/vs/workbench/contrib/timeline/common/timelineService.ts index 52bc586f90d..190dfa2501c 100644 --- a/src/vs/workbench/contrib/timeline/common/timelineService.ts +++ b/src/vs/workbench/contrib/timeline/common/timelineService.ts @@ -8,7 +8,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { ILogService } from 'vs/platform/log/common/log'; -import { ITimelineService, TimelineChangeEvent, TimelineOptions, TimelineProvidersChangeEvent, TimelineProvider, InternalTimelineOptions, TimelinePaneId } from './timeline'; +import { ITimelineService, TimelineChangeEvent, TimelineOptions, TimelineProvidersChangeEvent, TimelineProvider, TimelinePaneId } from './timeline'; import { IViewsService } from 'vs/workbench/common/views'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -44,7 +44,7 @@ export class TimelineService implements ITimelineService { return [...this.providers.values()].map(p => ({ id: p.id, label: p.label })); } - getTimeline(id: string, uri: URI, options: TimelineOptions, tokenSource: CancellationTokenSource, internalOptions?: InternalTimelineOptions) { + getTimeline(id: string, uri: URI, options: TimelineOptions, tokenSource: CancellationTokenSource) { this.logService.trace(`TimelineService#getTimeline(${id}): uri=${uri.toString()}`); const provider = this.providers.get(id); @@ -61,7 +61,7 @@ export class TimelineService implements ITimelineService { } return { - result: provider.provideTimeline(uri, options, tokenSource.token, internalOptions) + result: provider.provideTimeline(uri, options, tokenSource.token) .then(result => { if (result === undefined) { return undefined; -- cgit v1.2.3 From fbf7708053bb1b96f8d9ed048bdeeae8505c4ec3 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Apr 2022 17:17:36 -0700 Subject: Block pointer events on webviews when dragging from desktop into VS Code Fixes #146967 When dragging a file from desktop over a webview, by default the iframe of the webview will eat all of the dnd events To fix this, we handle the events inside the webview and tell the outer renderer to start handling them. We do this by disabling pointer events on the iframe, which causes Chrome to start dispatching future dnd events back to the iframe container's element (this also works around https://bugs.chromium.org/p/chromium/issues/detail?id=923651) For now I've tried to limit this change to cases where files are being dragged from desktop (drags within VS Code should already be handled) --- .../workbench/contrib/webview/browser/pre/main.js | 18 ++++++++++ .../contrib/webview/browser/webviewElement.ts | 40 +++++++++++++++++----- 2 files changed, 50 insertions(+), 8 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/webview/browser/pre/main.js b/src/vs/workbench/contrib/webview/browser/pre/main.js index 48beccb020a..8c91fdae9c9 100644 --- a/src/vs/workbench/contrib/webview/browser/pre/main.js +++ b/src/vs/workbench/contrib/webview/browser/pre/main.js @@ -1021,6 +1021,24 @@ onDomReady(() => { }); }); + const dragHandler = (/** @type {DragEvent} */ e) => { + if (e.defaultPrevented) { + // Extension code has already handled this event + return; + } + + if (!e.dataTransfer) { + return; + } + + // Only handle drags from outside editor for now + if (e.target === contentWindow.document.documentElement) { + hostMessaging.postMessage('drag-start'); + } + }; + contentWindow.addEventListener('dragenter', dragHandler); + contentWindow.addEventListener('dragover', dragHandler); + unloadMonitor.onIframeLoaded(newFrame); } }); diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts index c790753eb0b..6cd87f63f28 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { isFirefox } from 'vs/base/browser/browser'; -import { addDisposableListener } from 'vs/base/browser/dom'; +import { addDisposableListener, EventType } from 'vs/base/browser/dom'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { IAction } from 'vs/base/common/actions'; import { ThrottledDelayer } from 'vs/base/common/async'; @@ -59,6 +59,7 @@ export const enum WebviewMessageChannels { didKeydown = 'did-keydown', didKeyup = 'did-keyup', didContextMenu = 'did-context-menu', + dragStart = 'drag-start', } interface IKeydownEvent { @@ -350,6 +351,10 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD } })); + this._register(this.on(WebviewMessageChannels.dragStart, () => { + this.startBlockingIframeDragEvents(); + })); + if (options.enableFindWidget) { this._webviewFindWidget = this._register(instantiationService.createInstance(WebviewFindWidget, this)); this.styledFindWidget(); @@ -489,9 +494,32 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD if (this._webviewFindWidget) { parent.appendChild(this._webviewFindWidget.getDomNode()); } + + [EventType.MOUSE_DOWN, EventType.MOUSE_MOVE, EventType.DROP].forEach(eventName => { + this._register(addDisposableListener(parent, eventName, () => { + this.stopBlockingIframeDragEvents(); + })); + }); + + [parent, window].forEach(node => this._register(addDisposableListener(node as HTMLElement, EventType.DRAG_END, () => { + this.stopBlockingIframeDragEvents(); + }))); + parent.appendChild(this.element); } + private startBlockingIframeDragEvents() { + if (this.element) { + this.element.style.pointerEvents = 'none'; + } + } + + private stopBlockingIframeDragEvents() { + if (this.element) { + this.element.style.pointerEvents = 'auto'; + } + } + protected webviewContentEndpoint(encodedWebviewOrigin: string): string { const endpoint = this._environmentService.webviewExternalEndpoint!.replace('{{uuid}}', encodedWebviewOrigin); if (endpoint[endpoint.length - 1] === '/') { @@ -685,18 +713,14 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD } windowDidDragStart(): void { - // Webview break drag and droping around the main window (no events are generated when you are over them) + // Webview break drag and dropping around the main window (no events are generated when you are over them) // Work around this by disabling pointer events during the drag. // https://github.com/electron/electron/issues/18226 - if (this.element) { - this.element.style.pointerEvents = 'none'; - } + this.startBlockingIframeDragEvents(); } windowDidDragEnd(): void { - if (this.element) { - this.element.style.pointerEvents = ''; - } + this.stopBlockingIframeDragEvents(); } public selectAll() { -- cgit v1.2.3 From 214ff3b7eb534732a041f83c8860bbcfd13bd0c3 Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Tue, 12 Apr 2022 19:49:10 -0700 Subject: Add settings editor search funnel button (#147260) Ref #145710 --- .../preferences/browser/media/settingsEditor2.css | 4 +- .../preferences/browser/preferencesIcons.ts | 1 + .../contrib/preferences/browser/settingsEditor2.ts | 16 ++- .../preferences/browser/settingsSearchMenu.ts | 125 +++++++++++++++++++++ .../contrib/preferences/common/preferences.ts | 2 + 5 files changed, 141 insertions(+), 7 deletions(-) create mode 100644 src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css b/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css index 7145fe94aa9..a09f097b305 100644 --- a/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css +++ b/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css @@ -39,7 +39,7 @@ .settings-editor > .settings-header > .search-container > .settings-count-widget { position: absolute; - right: 35px; + right: 46px; top: 0px; margin: 4px 0px; } @@ -55,7 +55,7 @@ top: 0; right: 0; height: 100%; - width: 30px; + width: 43px; } .settings-editor > .settings-header > .search-container > .settings-clear-widget .action-label { diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesIcons.ts b/src/vs/workbench/contrib/preferences/browser/preferencesIcons.ts index 6692bf47bd4..0c31b455aaf 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesIcons.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesIcons.ts @@ -25,4 +25,5 @@ export const settingsRemoveIcon = registerIcon('settings-remove', Codicon.close, export const settingsDiscardIcon = registerIcon('settings-discard', Codicon.discard, localize('preferencesDiscardIcon', 'Icon for the discard action in the Settings UI.')); export const preferencesClearInputIcon = registerIcon('preferences-clear-input', Codicon.clearAll, localize('preferencesClearInput', 'Icon for clear input in the Settings and keybinding UI.')); +export const preferencesFilterIcon = registerIcon('preferences-filter', Codicon.filter, localize('settingsFilter', 'Icon for the button that suggests filters for the Settings UI.')); export const preferencesOpenSettingsIcon = registerIcon('preferences-open-settings', Codicon.goToFile, localize('preferencesOpenSettings', 'Icon for open settings commands.')); diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 780ebf0a742..392abf569fe 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -43,14 +43,14 @@ import { commonlyUsedData, tocData } from 'vs/workbench/contrib/preferences/brow import { AbstractSettingRenderer, HeightChangeParams, ISettingLinkClickEvent, ISettingOverrideClickEvent, resolveConfiguredUntrustedSettings, createTocTreeForExtensionSettings, resolveSettingsTree, SettingsTree, SettingTreeRenderers } from 'vs/workbench/contrib/preferences/browser/settingsTree'; import { ISettingsEditorViewState, parseQuery, SearchResultIdx, SearchResultModel, SettingsTreeElement, SettingsTreeGroupChild, SettingsTreeGroupElement, SettingsTreeModel, SettingsTreeSettingElement } from 'vs/workbench/contrib/preferences/browser/settingsTreeModels'; import { createTOCIterator, TOCTree, TOCTreeModel } from 'vs/workbench/contrib/preferences/browser/tocTree'; -import { CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, ENABLE_LANGUAGE_FILTER, EXTENSION_SETTING_TAG, FEATURE_SETTING_TAG, ID_SETTING_TAG, IPreferencesSearchService, ISearchProvider, LANGUAGE_SETTING_TAG, MODIFIED_SETTING_TAG, REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, WORKSPACE_TRUST_SETTING_TAG } from 'vs/workbench/contrib/preferences/common/preferences'; +import { CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, ENABLE_LANGUAGE_FILTER, EXTENSION_SETTING_TAG, FEATURE_SETTING_TAG, ID_SETTING_TAG, IPreferencesSearchService, ISearchProvider, LANGUAGE_SETTING_TAG, MODIFIED_SETTING_TAG, REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_SUGGEST_FILTERS, WORKSPACE_TRUST_SETTING_TAG } from 'vs/workbench/contrib/preferences/common/preferences'; import { settingsHeaderBorder, settingsSashBorder, settingsTextInputBorder } from 'vs/workbench/contrib/preferences/common/settingsEditorColorRegistry'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IOpenSettingsOptions, IPreferencesService, ISearchResult, ISettingsEditorModel, ISettingsEditorOptions, SettingMatchType, SettingValueType, validateSettingsEditorOptions } from 'vs/workbench/services/preferences/common/preferences'; import { SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; import { Settings2EditorModel } from 'vs/workbench/services/preferences/common/preferencesModels'; import { IUserDataSyncWorkbenchService } from 'vs/workbench/services/userDataSync/common/userDataSync'; -import { preferencesClearInputIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; +import { preferencesClearInputIcon, preferencesFilterIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust'; import { IWorkbenchConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; @@ -58,6 +58,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten import { Orientation, Sizing, SplitView } from 'vs/base/browser/ui/splitview/splitview'; import { Color } from 'vs/base/common/color'; import { ILanguageService } from 'vs/editor/common/languages/language'; +import { SettingsSearchFilterDropdownMenuActionViewItem } from 'vs/workbench/contrib/preferences/browser/settingsSearchMenu'; export const enum SettingsFocusContext { Search, @@ -525,7 +526,7 @@ export class SettingsEditor2 extends EditorPane { const searchContainer = DOM.append(this.headerContainer, $('.search-container')); const clearInputAction = new Action(SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, localize('clearInput', "Clear Settings Search Input"), ThemeIcon.asClassName(preferencesClearInputIcon), false, async () => this.clearSearchResults()); - + const filterAction = new Action(SETTINGS_EDITOR_COMMAND_SUGGEST_FILTERS, localize('filterInput', "Filter Settings"), ThemeIcon.asClassName(preferencesFilterIcon)); this.searchWidget = this._register(this.instantiationService.createInstance(SuggestEnabledInput, `${SettingsEditor2.ID}.searchbox`, searchContainer, { triggerCharacters: ['@', ':'], provideResults: (query: string) => { @@ -603,10 +604,15 @@ export class SettingsEditor2 extends EditorPane { const actionBar = this._register(new ActionBar(this.controlsElement, { animated: false, - actionViewItemProvider: (_action) => { return undefined; } + actionViewItemProvider: (_action) => { + if (_action.id === filterAction.id) { + return this.instantiationService.createInstance(SettingsSearchFilterDropdownMenuActionViewItem, _action, this.actionRunner, this.searchWidget); + } + return undefined; + } })); - actionBar.push([clearInputAction], { label: false, icon: true }); + actionBar.push([clearInputAction, filterAction], { label: false, icon: true }); } private onDidSettingsTargetChange(target: SettingsTarget): void { diff --git a/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts b/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts new file mode 100644 index 00000000000..d739a8752f5 --- /dev/null +++ b/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts @@ -0,0 +1,125 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; +import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem'; +import { IAction, IActionRunner } from 'vs/base/common/actions'; +import { localize } from 'vs/nls'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { SuggestEnabledInput } from 'vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput'; +import { EXTENSION_SETTING_TAG, FEATURE_SETTING_TAG, GENERAL_TAG_SETTING_TAG, ID_SETTING_TAG, LANGUAGE_SETTING_TAG, MODIFIED_SETTING_TAG } from 'vs/workbench/contrib/preferences/common/preferences'; + +export class SettingsSearchFilterDropdownMenuActionViewItem extends DropdownMenuActionViewItem { + constructor( + action: IAction, + actionRunner: IActionRunner | undefined, + private readonly searchWidget: SuggestEnabledInput, + @IContextMenuService contextMenuService: IContextMenuService, + @ICommandService private readonly commandService: ICommandService + ) { + super(action, + { getActions: () => this.getActions() }, + contextMenuService, + { + actionRunner, + classNames: action.class, + anchorAlignmentProvider: () => AnchorAlignment.RIGHT, + menuAsChild: true + } + ); + } + + override render(container: HTMLElement): void { + super.render(container); + } + + private doSearchWidgetAction(queryToAppend: string, triggerSuggest: boolean) { + this.searchWidget.setValue(this.searchWidget.getValue().trimEnd() + ' ' + queryToAppend); + this.searchWidget.focus(); + if (triggerSuggest) { + this.commandService.executeCommand('editor.action.triggerSuggest'); + } + } + + private createAction(id: string, label: string, tooltip: string, queryToAppend: string, triggerSuggest: boolean): IAction { + return { + id, + label, + tooltip, + class: undefined, + enabled: true, + checked: false, + run: () => { this.doSearchWidgetAction(queryToAppend, triggerSuggest); }, + dispose: () => { } + }; + } + + private createModifiedAction(): IAction { + // The modified action works slightly differently than the other actions. + // It is more like a checkbox on/off toggle. + const queryContainsModifiedTag = this.searchWidget.getValue().split(' ').some(word => word === `@${MODIFIED_SETTING_TAG}`); + return { + id: 'modifiedSettingsSearch', + label: localize('modifiedSettingsSearch', "Modified"), + tooltip: localize('modifiedSettingsSearchTooltip', "View modified settings only"), + class: undefined, + enabled: true, + checked: queryContainsModifiedTag, + run: () => { + // Append the tag, otherwise remove it from the query. + if (!queryContainsModifiedTag) { + this.searchWidget.setValue(this.searchWidget.getValue().trimEnd() + ` @${MODIFIED_SETTING_TAG}`); + } else { + const queryWithoutModifiedTag = this.searchWidget.getValue().split(' ').filter(word => word !== `@${MODIFIED_SETTING_TAG}`).join(' '); + this.searchWidget.setValue(queryWithoutModifiedTag); + } + this.searchWidget.focus(); + }, + dispose: () => { } + }; + } + + getActions(): IAction[] { + return [ + this.createModifiedAction(), + this.createAction( + 'extSettingsSearch', + localize('extSettingsSearch', "Extension ID"), + localize('extSettingsSearchTooltip', "Add extension ID filter"), + `@${EXTENSION_SETTING_TAG}`, + false + ), + this.createAction( + 'featuresSettingsSearch', + localize('featureSettingsSearch', "Feature"), + localize('featureSettingsSearchTooltip', "Add feature filter"), + `@${FEATURE_SETTING_TAG}`, + true + ), + this.createAction( + 'idSettingsSearch', + localize('idSettingsSearch', "Setting ID"), + localize('idSettingsSearchTooltip', "Add setting ID filter"), + `@${ID_SETTING_TAG}`, + false + ), + this.createAction( + 'langSettingsSearch', + localize('langSettingsSearch', "Language"), + localize('langSettingsSearchTooltip', "Add language ID filter"), + `@${LANGUAGE_SETTING_TAG}`, + true + ), + this.createAction( + 'tagSettingsSearch', + localize('tagSettingsSearch', "Tag"), + localize('tagSettingsSearchTooltip', "Add tag filter"), + `@${GENERAL_TAG_SETTING_TAG}`, + true + ), + ]; + } +} diff --git a/src/vs/workbench/contrib/preferences/common/preferences.ts b/src/vs/workbench/contrib/preferences/common/preferences.ts index ec3a14f1bf4..6138098d36f 100644 --- a/src/vs/workbench/contrib/preferences/common/preferences.ts +++ b/src/vs/workbench/contrib/preferences/common/preferences.ts @@ -42,6 +42,7 @@ export interface ISearchProvider { export const SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS = 'settings.action.clearSearchResults'; export const SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU = 'settings.action.showContextMenu'; +export const SETTINGS_EDITOR_COMMAND_SUGGEST_FILTERS = 'settings.action.suggestFilters'; export const CONTEXT_SETTINGS_EDITOR = new RawContextKey('inSettingsEditor', false); export const CONTEXT_SETTINGS_JSON_EDITOR = new RawContextKey('inSettingsJSONEditor', false); @@ -76,6 +77,7 @@ export const EXTENSION_SETTING_TAG = 'ext:'; export const FEATURE_SETTING_TAG = 'feature:'; export const ID_SETTING_TAG = 'id:'; export const LANGUAGE_SETTING_TAG = 'lang:'; +export const GENERAL_TAG_SETTING_TAG = 'tag:'; export const WORKSPACE_TRUST_SETTING_TAG = 'workspaceTrust'; export const REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG = 'requireTrustedWorkspace'; export const KEYBOARD_LAYOUT_OPEN_PICKER = 'workbench.action.openKeyboardLayoutPicker'; -- cgit v1.2.3 From 7e3c3e6e42fc0abaccc89ba84e40e36b8ccab5b9 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 13 Apr 2022 11:33:18 +0530 Subject: #68410 disable updating builtin extensions in stable --- .../contrib/extensions/browser/extensionsWorkbenchService.ts | 8 ++++++-- .../contrib/extensions/test/electron-browser/extension.test.ts | 8 ++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index 50152dc1f51..701473fe624 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -206,6 +206,10 @@ export class Extension implements IExtension { if (!this.gallery || !this.local) { return false; } + // Do not allow updating system extensions in stable + if (this.type === ExtensionType.System && this.productService.quality === 'stable') { + return false; + } if (!this.local.preRelease && this.gallery.properties.isPreReleaseVersion) { return false; } @@ -1057,8 +1061,8 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension // Skip if check updates only for builtin extensions and current extension is not builtin. continue; } - if (installed.isBuiltin && !installed.local?.identifier.uuid) { - // Skip if the builtin extension does not have Marketplace id + if (installed.isBuiltin && (!installed.local?.identifier.uuid || this.productService.quality !== 'stable')) { + // Skip if the builtin extension does not have Marketplace identifier or the current quality is not stable. continue; } infos.push({ ...installed.identifier, preRelease: !!installed.local?.preRelease }); diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts index 335679af2a9..f07341fe991 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts @@ -12,6 +12,7 @@ import { URI } from 'vs/base/common/uri'; import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { generateUuid } from 'vs/base/common/uuid'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; +import { IProductService } from 'vs/platform/product/common/productService'; suite('Extension Test', () => { @@ -19,6 +20,7 @@ suite('Extension Test', () => { setup(() => { instantiationService = new TestInstantiationService(); + instantiationService.stub(IProductService, >{ quality: 'insiders' }); }); test('extension is not outdated when there is no local and gallery', () => { @@ -51,6 +53,12 @@ suite('Extension Test', () => { assert.strictEqual(extension.outdated, true); }); + test('extension is not outdated when local is built in and older than gallery but product quality is stable', () => { + instantiationService.stub(IProductService, >{ quality: 'stable' }); + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension('somext', { version: '1.0.0' }, { type: ExtensionType.System }), aGalleryExtension('somext', { version: '1.0.1' })); + assert.strictEqual(extension.outdated, false); + }); + test('extension is outdated when local and gallery are on same version but on different target platforms', () => { const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension('somext', {}, { targetPlatform: TargetPlatform.WIN32_IA32 }), aGalleryExtension('somext', {}, { targetPlatform: TargetPlatform.WIN32_X64 })); assert.strictEqual(extension.outdated, true); -- cgit v1.2.3 From eda166b7fa6377d2bd2fd2c33e5a844ea1b7bddd Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 13 Apr 2022 12:00:09 +0530 Subject: Move output service to workbench/services --- src/vs/workbench/contrib/debug/node/debugAdapter.ts | 2 +- .../workbench/contrib/keybindings/browser/keybindings.contribution.ts | 2 +- src/vs/workbench/contrib/logs/common/logs.contribution.ts | 3 +-- .../contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts | 2 +- src/vs/workbench/contrib/output/browser/logViewer.ts | 3 +-- src/vs/workbench/contrib/output/browser/output.contribution.ts | 3 +-- src/vs/workbench/contrib/output/browser/outputLinkProvider.ts | 2 +- src/vs/workbench/contrib/output/browser/outputServices.ts | 3 +-- src/vs/workbench/contrib/output/browser/outputView.ts | 3 +-- src/vs/workbench/contrib/output/common/outputChannelModel.ts | 2 +- src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts | 2 +- src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts | 2 +- src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts | 2 +- src/vs/workbench/contrib/tasks/electron-sandbox/taskService.ts | 2 +- src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts | 2 +- 15 files changed, 15 insertions(+), 20 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/node/debugAdapter.ts b/src/vs/workbench/contrib/debug/node/debugAdapter.ts index 6347d7ba2a5..4f0bf897787 100644 --- a/src/vs/workbench/contrib/debug/node/debugAdapter.ts +++ b/src/vs/workbench/contrib/debug/node/debugAdapter.ts @@ -13,7 +13,7 @@ import * as strings from 'vs/base/common/strings'; import * as objects from 'vs/base/common/objects'; import * as platform from 'vs/base/common/platform'; import { ExtensionsChannelId } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { IOutputService } from 'vs/workbench/contrib/output/common/output'; +import { IOutputService } from 'vs/workbench/services/output/common/output'; import { IDebugAdapterExecutable, IDebuggerContribution, IPlatformSpecificAdapterContribution, IDebugAdapterServer, IDebugAdapterNamedPipeServer } from 'vs/workbench/contrib/debug/common/debug'; import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { AbstractDebugAdapter } from '../common/abstractDebugAdapter'; diff --git a/src/vs/workbench/contrib/keybindings/browser/keybindings.contribution.ts b/src/vs/workbench/contrib/keybindings/browser/keybindings.contribution.ts index 6fc249b03be..5f6cdfb3298 100644 --- a/src/vs/workbench/contrib/keybindings/browser/keybindings.contribution.ts +++ b/src/vs/workbench/contrib/keybindings/browser/keybindings.contribution.ts @@ -9,7 +9,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { CATEGORIES } from 'vs/workbench/common/actions'; import { rendererLogChannelId } from 'vs/workbench/contrib/logs/common/logConstants'; -import { IOutputService } from 'vs/workbench/contrib/output/common/output'; +import { IOutputService } from 'vs/workbench/services/output/common/output'; class ToggleKeybindingsLogAction extends Action2 { diff --git a/src/vs/workbench/contrib/logs/common/logs.contribution.ts b/src/vs/workbench/contrib/logs/common/logs.contribution.ts index 6cbfdc4cd7b..9485c762876 100644 --- a/src/vs/workbench/contrib/logs/common/logs.contribution.ts +++ b/src/vs/workbench/contrib/logs/common/logs.contribution.ts @@ -14,14 +14,13 @@ import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IFileService, whenProviderRegistered } from 'vs/platform/files/common/files'; import { URI } from 'vs/base/common/uri'; -import { IOutputChannelRegistry, Extensions as OutputExt } from 'vs/workbench/services/output/common/output'; +import { IOutputChannelRegistry, Extensions as OutputExt, IOutputService } from 'vs/workbench/services/output/common/output'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { ILogService, LogLevel } from 'vs/platform/log/common/log'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { isWeb } from 'vs/base/common/platform'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { LogsDataCleaner } from 'vs/workbench/contrib/logs/common/logsDataCleaner'; -import { IOutputService } from 'vs/workbench/contrib/output/common/output'; import { supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils'; import { IProductService } from 'vs/platform/product/common/productService'; import { createCancelablePromise, timeout } from 'vs/base/common/async'; diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts b/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts index 10037c96943..8fbc0999419 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts @@ -27,7 +27,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions'; import { IWebview } from 'vs/workbench/contrib/webview/browser/webview'; import { CATEGORIES } from 'vs/workbench/common/actions'; -import { IOutputService } from 'vs/workbench/contrib/output/common/output'; +import { IOutputService } from 'vs/workbench/services/output/common/output'; import { rendererLogChannelId } from 'vs/workbench/contrib/logs/common/logConstants'; import { ILogService } from 'vs/platform/log/common/log'; diff --git a/src/vs/workbench/contrib/output/browser/logViewer.ts b/src/vs/workbench/contrib/output/browser/logViewer.ts index a542e7dbe91..3c78aa114d1 100644 --- a/src/vs/workbench/contrib/output/browser/logViewer.ts +++ b/src/vs/workbench/contrib/output/browser/logViewer.ts @@ -15,8 +15,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { URI } from 'vs/base/common/uri'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { LOG_SCHEME } from 'vs/workbench/contrib/output/common/output'; -import { IFileOutputChannelDescriptor } from 'vs/workbench/services/output/common/output'; +import { LOG_SCHEME, IFileOutputChannelDescriptor } from 'vs/workbench/services/output/common/output'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; diff --git a/src/vs/workbench/contrib/output/browser/output.contribution.ts b/src/vs/workbench/contrib/output/browser/output.contribution.ts index b6dbbb8caf7..f9e4814794e 100644 --- a/src/vs/workbench/contrib/output/browser/output.contribution.ts +++ b/src/vs/workbench/contrib/output/browser/output.contribution.ts @@ -12,7 +12,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { MenuId, registerAction2, Action2 } from 'vs/platform/actions/common/actions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { OutputService, LogContentProvider } from 'vs/workbench/contrib/output/browser/outputServices'; -import { OUTPUT_MODE_ID, OUTPUT_MIME, OUTPUT_VIEW_ID, IOutputService, CONTEXT_IN_OUTPUT, LOG_SCHEME, LOG_MODE_ID, LOG_MIME, CONTEXT_ACTIVE_LOG_OUTPUT, CONTEXT_OUTPUT_SCROLL_LOCK } from 'vs/workbench/contrib/output/common/output'; +import { OUTPUT_MODE_ID, OUTPUT_MIME, OUTPUT_VIEW_ID, IOutputService, CONTEXT_IN_OUTPUT, LOG_SCHEME, LOG_MODE_ID, LOG_MIME, CONTEXT_ACTIVE_LOG_OUTPUT, CONTEXT_OUTPUT_SCROLL_LOCK, IOutputChannelDescriptor, IFileOutputChannelDescriptor } from 'vs/workbench/services/output/common/output'; import { OutputViewPane } from 'vs/workbench/contrib/output/browser/outputView'; import { IEditorPaneRegistry, EditorPaneDescriptor } from 'vs/workbench/browser/editor'; import { LogViewer, LogViewerInput } from 'vs/workbench/contrib/output/browser/logViewer'; @@ -25,7 +25,6 @@ import { ViewContainer, IViewContainersRegistry, ViewContainerLocation, Extensio import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IQuickPickItem, IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; -import { IOutputChannelDescriptor, IFileOutputChannelDescriptor } from 'vs/workbench/services/output/common/output'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { assertIsDefined } from 'vs/base/common/types'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; diff --git a/src/vs/workbench/contrib/output/browser/outputLinkProvider.ts b/src/vs/workbench/contrib/output/browser/outputLinkProvider.ts index eb346086655..ca06b37e21f 100644 --- a/src/vs/workbench/contrib/output/browser/outputLinkProvider.ts +++ b/src/vs/workbench/contrib/output/browser/outputLinkProvider.ts @@ -8,7 +8,7 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { IModelService } from 'vs/editor/common/services/model'; import { ILink } from 'vs/editor/common/languages'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { OUTPUT_MODE_ID, LOG_MODE_ID } from 'vs/workbench/contrib/output/common/output'; +import { OUTPUT_MODE_ID, LOG_MODE_ID } from 'vs/workbench/services/output/common/output'; import { MonacoWebWorker, createWebWorker } from 'vs/editor/browser/services/webWorker'; import { ICreateData, OutputLinkComputer } from 'vs/workbench/contrib/output/common/outputLinkComputer'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; diff --git a/src/vs/workbench/contrib/output/browser/outputServices.ts b/src/vs/workbench/contrib/output/browser/outputServices.ts index 4901c9f23ce..dffb7046911 100644 --- a/src/vs/workbench/contrib/output/browser/outputServices.ts +++ b/src/vs/workbench/contrib/output/browser/outputServices.ts @@ -9,8 +9,7 @@ import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IOutputChannel, IOutputService, OUTPUT_VIEW_ID, OUTPUT_SCHEME, LOG_SCHEME, LOG_MIME, OUTPUT_MIME, OutputChannelUpdateMode } from 'vs/workbench/contrib/output/common/output'; -import { IOutputChannelDescriptor, Extensions, IOutputChannelRegistry } from 'vs/workbench/services/output/common/output'; +import { IOutputChannel, IOutputService, OUTPUT_VIEW_ID, OUTPUT_SCHEME, LOG_SCHEME, LOG_MIME, OUTPUT_MIME, OutputChannelUpdateMode, IOutputChannelDescriptor, Extensions, IOutputChannelRegistry } from 'vs/workbench/services/output/common/output'; import { OutputLinkProvider } from 'vs/workbench/contrib/output/browser/outputLinkProvider'; import { ITextModelService, ITextModelContentProvider } from 'vs/editor/common/services/resolverService'; import { ITextModel } from 'vs/editor/common/model'; diff --git a/src/vs/workbench/contrib/output/browser/outputView.ts b/src/vs/workbench/contrib/output/browser/outputView.ts index ee9c7eadf5d..545d41fdcee 100644 --- a/src/vs/workbench/contrib/output/browser/outputView.ts +++ b/src/vs/workbench/contrib/output/browser/outputView.ts @@ -14,7 +14,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IEditorOpenContext } from 'vs/workbench/common/editor'; import { AbstractTextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor'; -import { OUTPUT_VIEW_ID, IOutputService, CONTEXT_IN_OUTPUT, IOutputChannel, CONTEXT_ACTIVE_LOG_OUTPUT, CONTEXT_OUTPUT_SCROLL_LOCK } from 'vs/workbench/contrib/output/common/output'; +import { OUTPUT_VIEW_ID, IOutputService, CONTEXT_IN_OUTPUT, IOutputChannel, CONTEXT_ACTIVE_LOG_OUTPUT, CONTEXT_OUTPUT_SCROLL_LOCK, IOutputChannelDescriptor, IOutputChannelRegistry, Extensions } from 'vs/workbench/services/output/common/output'; import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -27,7 +27,6 @@ import { IContextMenuService, IContextViewService } from 'vs/platform/contextvie import { IViewDescriptorService } from 'vs/workbench/common/views'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IOutputChannelDescriptor, IOutputChannelRegistry, Extensions } from 'vs/workbench/services/output/common/output'; import { Registry } from 'vs/platform/registry/common/platform'; import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; import { ISelectOptionItem } from 'vs/base/browser/ui/selectBox/selectBox'; diff --git a/src/vs/workbench/contrib/output/common/outputChannelModel.ts b/src/vs/workbench/contrib/output/common/outputChannelModel.ts index cb24f441e21..4c01e67797c 100644 --- a/src/vs/workbench/contrib/output/common/outputChannelModel.ts +++ b/src/vs/workbench/contrib/output/common/outputChannelModel.ts @@ -21,7 +21,7 @@ import { Range } from 'vs/editor/common/core/range'; import { VSBuffer } from 'vs/base/common/buffer'; import { ILogger, ILoggerService, ILogService } from 'vs/platform/log/common/log'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; -import { OutputChannelUpdateMode } from 'vs/workbench/contrib/output/common/output'; +import { OutputChannelUpdateMode } from 'vs/workbench/services/output/common/output'; export interface IOutputChannelModel extends IDisposable { readonly onDispose: Event; diff --git a/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts b/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts index d1a3d7680d5..4a278af2146 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import { IQuickPickSeparator, IQuickInputService, ItemActivation } from 'vs/platform/quickinput/common/quickInput'; import { IPickerQuickAccessItem, PickerQuickAccessProvider } from 'vs/platform/quickinput/browser/pickerQuickAccess'; import { IViewDescriptorService, IViewsService, ViewContainer, ViewContainerLocation } from 'vs/workbench/common/views'; -import { IOutputService } from 'vs/workbench/contrib/output/common/output'; +import { IOutputService } from 'vs/workbench/services/output/common/output'; import { ITerminalGroupService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { PaneCompositeDescriptor } from 'vs/workbench/browser/panecomposite'; diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index 70c269e4a69..2e0f5f76e40 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -41,7 +41,7 @@ import { IConfigurationResolverService } from 'vs/workbench/services/configurati import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder, IWorkspace, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { IOutputService, IOutputChannel } from 'vs/workbench/contrib/output/common/output'; +import { IOutputService, IOutputChannel } from 'vs/workbench/services/output/common/output'; import { ITerminalGroupService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { ITerminalProfileResolverService } from 'vs/workbench/contrib/terminal/common/terminal'; diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index c0547a2ae39..992ecb05aec 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -29,7 +29,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { ITerminalProfileResolverService, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'; import { ITerminalService, ITerminalInstance, ITerminalGroupService } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { IOutputService } from 'vs/workbench/contrib/output/common/output'; +import { IOutputService } from 'vs/workbench/services/output/common/output'; import { StartStopProblemCollector, WatchingProblemCollector, ProblemCollectorEventKind, ProblemHandlingStrategy } from 'vs/workbench/contrib/tasks/common/problemCollectors'; import { Task, CustomTask, ContributedTask, RevealKind, CommandOptions, ShellConfiguration, RuntimeType, PanelKind, diff --git a/src/vs/workbench/contrib/tasks/electron-sandbox/taskService.ts b/src/vs/workbench/contrib/tasks/electron-sandbox/taskService.ts index 436f0194e19..a17d4185861 100644 --- a/src/vs/workbench/contrib/tasks/electron-sandbox/taskService.ts +++ b/src/vs/workbench/contrib/tasks/electron-sandbox/taskService.ts @@ -30,7 +30,7 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IViewsService, IViewDescriptorService } from 'vs/workbench/common/views'; -import { IOutputService } from 'vs/workbench/contrib/output/common/output'; +import { IOutputService } from 'vs/workbench/services/output/common/output'; import { ITerminalGroupService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 07d50613857..4a7fe8b6202 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -37,7 +37,7 @@ import { EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/ed import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import * as Constants from 'vs/workbench/contrib/logs/common/logConstants'; -import { IOutputService } from 'vs/workbench/contrib/output/common/output'; +import { IOutputService } from 'vs/workbench/services/output/common/output'; import { IActivityService, IBadge, NumberBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activity'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -- cgit v1.2.3 From 711b0708690159cf8e9a5205ad97d39e0d47d424 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Wed, 13 Apr 2022 11:01:23 +0200 Subject: Fixes #147329. --- .../contrib/debug/browser/breakpointEditorContribution.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts index 762b74c8201..7d8351ddb7d 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts @@ -485,7 +485,6 @@ export class BreakpointEditorContribution implements IBreakpointEditorContributi inlineWidget }; }); - } finally { this.ignoreDecorationsChangedEvent = false; } @@ -511,6 +510,12 @@ export class BreakpointEditorContribution implements IBreakpointEditorContributi inlineWidget }; }); + + for (const d of this.breakpointDecorations) { + if (d.inlineWidget) { + this.editor.layoutContentWidget(d.inlineWidget); + } + } } private async onModelDecorationsChanged(): Promise { -- cgit v1.2.3 From 534aacf7f27c7b262df243ebb2eeebdf50bc4043 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 13 Apr 2022 11:54:47 +0200 Subject: Change default of comments.openView to firstFile Fixes #147365 --- .../comments/browser/comments.contribution.ts | 6 +++--- .../comments/browser/commentsEditorContribution.ts | 20 ++++++++++++++++---- .../contrib/comments/browser/commentsView.ts | 6 +++++- .../contrib/comments/common/commentsConfiguration.ts | 2 +- 4 files changed, 25 insertions(+), 9 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/comments.contribution.ts b/src/vs/workbench/contrib/comments/browser/comments.contribution.ts index 0d515f2ae79..2ba619a7c0c 100644 --- a/src/vs/workbench/contrib/comments/browser/comments.contribution.ts +++ b/src/vs/workbench/contrib/comments/browser/comments.contribution.ts @@ -24,9 +24,9 @@ Registry.as(ConfigurationExtensions.Configuration).regis markdownDeprecationMessage: nls.localize('comments.openPanel.deprecated', "This setting is deprecated in favor of `comments.openView`.") }, 'comments.openView': { - enum: ['never', 'file'], - enumDescriptions: [nls.localize('comments.openView.never', "The comments view will never be opened."), nls.localize('comments.openView.file', "The comments view will open when a file with comments is active.")], - default: 'file', + enum: ['never', 'file', 'firstFile'], + enumDescriptions: [nls.localize('comments.openView.never', "The comments view will never be opened."), nls.localize('comments.openView.file', "The comments view will open when a file with comments is active."), nls.localize('comments.openView.firstFile', "If the comments view has not been opened yet during this session it will open the first time during a session that a file with comments is active.")], + default: 'firstFile', description: nls.localize('comments.openView', "Controls when the comments view should open."), restricted: false }, diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index 0fa7eaf9ded..14f1f730236 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -49,6 +49,7 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { CommentThreadRangeDecorator } from 'vs/workbench/contrib/comments/browser/commentThreadRangeDecorator'; import { commentThreadRangeBackground, commentThreadRangeBorder } from 'vs/workbench/contrib/comments/browser/commentColors'; import { ICursorSelectionChangedEvent } from 'vs/editor/common/cursorEvents'; +import { CommentsPanel } from 'vs/workbench/contrib/comments/browser/commentsView'; export const ID = 'editor.contrib.review'; @@ -633,13 +634,24 @@ export class CommentController implements IEditorContribution { })); this.beginCompute().then(() => { - if (this._commentWidgets.length - && (this.configurationService.getValue(COMMENTS_SECTION).openView === 'file')) { - this.viewsService.openView(COMMENTS_VIEW_ID); - } + return this.openCommentsView(); }); } + private async openCommentsView() { + if (this._commentWidgets.length) { + if (this.configurationService.getValue(COMMENTS_SECTION).openView === 'file') { + return this.viewsService.openView(COMMENTS_VIEW_ID); + } else if (this.configurationService.getValue(COMMENTS_SECTION).openView === 'firstFile') { + const hasShownView = this.viewsService.getViewWithId(COMMENTS_VIEW_ID)?.hasRendered; + if (!hasShownView) { + return this.viewsService.openView(COMMENTS_VIEW_ID); + } + } + } + return undefined; + } + private displayCommentThread(owner: string, thread: languages.CommentThread, pendingComment: string | null): void { const zoneWidget = this.instantiationService.createInstance(ReviewZoneWidget, this.editor, owner, thread, pendingComment); zoneWidget.display(thread.range.endLineNumber); diff --git a/src/vs/workbench/contrib/comments/browser/commentsView.ts b/src/vs/workbench/contrib/comments/browser/commentsView.ts index ad852ea3b7e..7077d35338b 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsView.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsView.ts @@ -120,7 +120,7 @@ export class CommentsPanel extends ViewPane { const focusColor = theme.getColor(focusBorder); if (focusColor) { - content.push(`.comments-panel .commenst-panel-container a:focus { outline-color: ${focusColor}; }`); + content.push(`.comments-panel .comments-panel-container a:focus { outline-color: ${focusColor}; }`); } const codeTextForegroundColor = theme.getColor(textPreformatForeground); @@ -147,6 +147,10 @@ export class CommentsPanel extends ViewPane { } } + public get hasRendered(): boolean { + return !!this.tree; + } + public override layoutBody(height: number, width: number): void { super.layoutBody(height, width); this.tree.layout(height, width); diff --git a/src/vs/workbench/contrib/comments/common/commentsConfiguration.ts b/src/vs/workbench/contrib/comments/common/commentsConfiguration.ts index 1ef2ba67cb7..d3c180e69a4 100644 --- a/src/vs/workbench/contrib/comments/common/commentsConfiguration.ts +++ b/src/vs/workbench/contrib/comments/common/commentsConfiguration.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ export interface ICommentsConfiguration { - openView: 'never' | 'file'; + openView: 'never' | 'file' | 'firstFile'; useRelativeTime: boolean; } -- cgit v1.2.3 From 55a30fcca81846c03e57f1201aa634c9336cc983 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 13 Apr 2022 14:59:03 +0200 Subject: More comment thread range polishing Part of #146510 --- .../contrib/comments/browser/commentColors.ts | 4 +-- .../contrib/comments/browser/commentService.ts | 17 ++++++++++ .../contrib/comments/browser/commentThreadBody.ts | 10 ++++-- .../browser/commentThreadRangeDecorator.ts | 37 +++++++++++++++++++--- .../comments/browser/commentThreadWidget.ts | 35 ++++++++++++++++++++ .../comments/browser/commentsEditorContribution.ts | 18 +++++++++-- .../contrib/comments/browser/commentsTreeViewer.ts | 6 +++- .../contrib/comments/browser/media/panel.css | 5 +++ 8 files changed, 121 insertions(+), 11 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentColors.ts b/src/vs/workbench/contrib/comments/browser/commentColors.ts index f906c411aad..78555e0e9e3 100644 --- a/src/vs/workbench/contrib/comments/browser/commentColors.ts +++ b/src/vs/workbench/contrib/comments/browser/commentColors.ts @@ -14,6 +14,8 @@ const resolvedCommentBorder = registerColor('editorCommentsWidget.resolvedBorder const unresolvedCommentBorder = registerColor('editorCommentsWidget.unresolvedBorder', { dark: peekViewBorder, light: peekViewBorder, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('unresolvedCommentBorder', 'Color of borders and arrow for unresolved comments.')); export const commentThreadRangeBackground = registerColor('editorCommentsWidget.rangeBackground', { dark: transparent(unresolvedCommentBorder, .1), light: transparent(unresolvedCommentBorder, .1), hcDark: transparent(unresolvedCommentBorder, .1), hcLight: transparent(unresolvedCommentBorder, .1) }, nls.localize('commentThreadRangeBackground', 'Color of background for comment ranges.')); export const commentThreadRangeBorder = registerColor('editorCommentsWidget.rangeBorder', { dark: transparent(unresolvedCommentBorder, .4), light: transparent(unresolvedCommentBorder, .4), hcDark: transparent(unresolvedCommentBorder, .4), hcLight: transparent(unresolvedCommentBorder, .4) }, nls.localize('commentThreadRangeBackground', 'Color of background for comment ranges.')); +export const commentThreadRangeActiveBackground = registerColor('editorCommentsWidget.rangeActiveBackground', { dark: transparent(unresolvedCommentBorder, .1), light: transparent(unresolvedCommentBorder, .1), hcDark: transparent(unresolvedCommentBorder, .1), hcLight: transparent(unresolvedCommentBorder, .1) }, nls.localize('commentThreadRangeBackground', 'Color of background for comment ranges.')); +export const commentThreadRangeActiveBorder = registerColor('editorCommentsWidget.rangeActiveBorder', { dark: transparent(unresolvedCommentBorder, .4), light: transparent(unresolvedCommentBorder, .4), hcDark: transparent(unresolvedCommentBorder, .4), hcLight: transparent(unresolvedCommentBorder, .2) }, nls.localize('commentThreadRangeBackground', 'Color of background for comment ranges.')); const commentThreadStateColors = new Map([ [languages.CommentThreadState.Unresolved, unresolvedCommentBorder], @@ -23,8 +25,6 @@ const commentThreadStateColors = new Map([ export const commentThreadStateColorVar = '--comment-thread-state-color'; export const commentViewThreadStateColorVar = '--comment-view-thread-state-color'; export const commentThreadStateBackgroundColorVar = '--comment-thread-state-background-color'; -export const commentThreadRangeBackgroundColorVar = '--vscode-comment-thread-range-background'; -export const commentThreadRangeBorderColorVar = '--vscode-comment-thread-range-border'; export function getCommentThreadStateColor(state: languages.CommentThreadState | undefined, theme: IColorTheme): Color | undefined { const colorId = (state !== undefined) ? commentThreadStateColors.get(state) : undefined; diff --git a/src/vs/workbench/contrib/comments/browser/commentService.ts b/src/vs/workbench/contrib/comments/browser/commentService.ts index a11e4b8fb15..eed900b49eb 100644 --- a/src/vs/workbench/contrib/comments/browser/commentService.ts +++ b/src/vs/workbench/contrib/comments/browser/commentService.ts @@ -67,6 +67,7 @@ export interface ICommentService { readonly onDidUpdateCommentThreads: Event; readonly onDidUpdateNotebookCommentThreads: Event; readonly onDidChangeActiveCommentThread: Event; + readonly onDidChangeCurrentCommentThread: Event; readonly onDidUpdateCommentingRanges: Event<{ owner: string }>; readonly onDidChangeActiveCommentingRange: Event<{ range: Range; commentingRangesInfo: CommentingRanges }>; readonly onDidSetDataProvider: Event; @@ -90,6 +91,7 @@ export interface ICommentService { hasReactionHandler(owner: string): boolean; toggleReaction(owner: string, resource: URI, thread: CommentThread, comment: Comment, reaction: CommentReaction): Promise; setActiveCommentThread(commentThread: CommentThread | null): void; + setCurrentCommentThread(commentThread: CommentThread | undefined): void; } export class CommentService extends Disposable implements ICommentService { @@ -119,6 +121,9 @@ export class CommentService extends Disposable implements ICommentService { private readonly _onDidChangeActiveCommentThread = this._register(new Emitter()); readonly onDidChangeActiveCommentThread = this._onDidChangeActiveCommentThread.event; + private readonly _onDidChangeCurrentCommentThread = this._register(new Emitter()); + readonly onDidChangeCurrentCommentThread = this._onDidChangeCurrentCommentThread.event; + private readonly _onDidChangeActiveCommentingRange: Emitter<{ range: Range; commentingRangesInfo: CommentingRanges; @@ -137,6 +142,18 @@ export class CommentService extends Disposable implements ICommentService { super(); } + /** + * The current comment thread is the thread that has focus or is being hovered. + * @param commentThread + */ + setCurrentCommentThread(commentThread: CommentThread | undefined) { + this._onDidChangeCurrentCommentThread.fire(commentThread); + } + + /** + * The active comment thread is the the thread that is currently being edited. + * @param commentThread + */ setActiveCommentThread(commentThread: CommentThread | null) { this._onDidChangeActiveCommentThread.fire(commentThread); } diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadBody.ts b/src/vs/workbench/contrib/comments/browser/commentThreadBody.ts index fca40378daa..59a1d57b12b 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadBody.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadBody.ts @@ -209,8 +209,14 @@ export class CommentThreadBody extends D } private _updateAriaLabel() { - this._commentsElement.ariaLabel = nls.localize('commentThreadAria', "Comment thread with {0} comments. {1}.", - this._commentThread.comments?.length, this._commentThread.label); + if (this._commentThread.isDocumentCommentThread()) { + this._commentsElement.ariaLabel = nls.localize('commentThreadAria.withRange', "Comment thread with {0} comments on lines {1} through {2}. {3}.", + this._commentThread.comments?.length, this._commentThread.range.startLineNumber, this._commentThread.range.endLineNumber, + this._commentThread.label); + } else { + this._commentsElement.ariaLabel = nls.localize('commentThreadAria', "Comment thread with {0} comments. {1}.", + this._commentThread.comments?.length, this._commentThread.label); + } } private _setFocusedComment(value: number | undefined) { diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts b/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts index adadb4a6617..5af04a9fe0c 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts @@ -3,11 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Disposable } from 'vs/base/common/lifecycle'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IRange } from 'vs/editor/common/core/range'; import { IModelDecorationOptions, IModelDeltaDecoration } from 'vs/editor/common/model'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; -import { ICommentInfo } from 'vs/workbench/contrib/comments/browser/commentService'; +import { ICommentInfo, ICommentService } from 'vs/workbench/contrib/comments/browser/commentService'; class CommentThreadRangeDecoration implements IModelDeltaDecoration { private _decorationId: string | undefined; @@ -26,12 +27,16 @@ class CommentThreadRangeDecoration implements IModelDeltaDecoration { } } -export class CommentThreadRangeDecorator { - public static description = 'comment-thread-range-decorator'; +export class CommentThreadRangeDecorator extends Disposable { + private static description = 'comment-thread-range-decorator'; private decorationOptions: ModelDecorationOptions; + private activeDecorationOptions: ModelDecorationOptions; private decorationIds: string[] = []; + private activeDecorationIds: string[] = []; + private editor: ICodeEditor | undefined; - constructor() { + constructor(commentService: ICommentService) { + super(); const decorationOptions: IModelDecorationOptions = { description: CommentThreadRangeDecorator.description, isWholeLine: false, @@ -40,6 +45,29 @@ export class CommentThreadRangeDecorator { }; this.decorationOptions = ModelDecorationOptions.createDynamic(decorationOptions); + + const activeDecorationOptions: IModelDecorationOptions = { + description: CommentThreadRangeDecorator.description, + isWholeLine: false, + zIndex: 20, + className: 'comment-thread-range-current' + }; + + this.activeDecorationOptions = ModelDecorationOptions.createDynamic(activeDecorationOptions); + this._register(commentService.onDidChangeCurrentCommentThread(thread => { + if (!this.editor) { + return; + } + let newDecoration: CommentThreadRangeDecoration[] = []; + if (thread) { + const range = thread.range; + if (!((range.startLineNumber === range.endLineNumber) && (range.startColumn === range.endColumn))) { + newDecoration.push(new CommentThreadRangeDecoration(range, this.activeDecorationOptions)); + } + } + this.activeDecorationIds = this.editor.deltaDecorations(this.activeDecorationIds, newDecoration); + newDecoration.forEach((decoration, index) => decoration.id = this.decorationIds[index]); + })); } public update(editor: ICodeEditor, commentInfos: ICommentInfo[]) { @@ -47,6 +75,7 @@ export class CommentThreadRangeDecorator { if (!model) { return; } + this.editor = editor; const commentThreadRangeDecorations: CommentThreadRangeDecoration[] = []; for (const info of commentInfos) { diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts index 0f9f5fd1500..92b06773800 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts @@ -109,6 +109,41 @@ export class CommentThreadWidget extends if (controller) { commentControllerKey.set(controller.contextValue); } + + this.currentThreadListeners(); + } + + private updateCurrentThread(hasMouse: boolean, hasFocus: boolean) { + if (hasMouse || hasFocus) { + this.commentService.setCurrentCommentThread(this.commentThread); + } else { + this.commentService.setCurrentCommentThread(undefined); + } + } + + private currentThreadListeners() { + let hasMouse = false; + let hasFocus = false; + this._register(dom.addDisposableListener(this.container, dom.EventType.MOUSE_ENTER, (e) => { + if ((e).toElement === this.container) { + hasMouse = true; + this.updateCurrentThread(hasMouse, hasFocus); + } + }, true)); + this._register(dom.addDisposableListener(this.container, dom.EventType.MOUSE_LEAVE, (e) => { + if ((e).fromElement === this.container) { + hasMouse = false; + this.updateCurrentThread(hasMouse, hasFocus); + } + }, true)); + this._register(dom.addDisposableListener(this.container, dom.EventType.FOCUS_IN, () => { + hasFocus = true; + this.updateCurrentThread(hasMouse, hasFocus); + }, true)); + this._register(dom.addDisposableListener(this.container, dom.EventType.FOCUS_OUT, () => { + hasFocus = false; + this.updateCurrentThread(hasMouse, hasFocus); + }, true)); } updateCommentThread(commentThread: languages.CommentThread) { diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index 14f1f730236..5d80b0e5dfd 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -47,7 +47,7 @@ import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/cont import { Position } from 'vs/editor/common/core/position'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { CommentThreadRangeDecorator } from 'vs/workbench/contrib/comments/browser/commentThreadRangeDecorator'; -import { commentThreadRangeBackground, commentThreadRangeBorder } from 'vs/workbench/contrib/comments/browser/commentColors'; +import { commentThreadRangeActiveBackground, commentThreadRangeActiveBorder, commentThreadRangeBackground, commentThreadRangeBorder } from 'vs/workbench/contrib/comments/browser/commentColors'; import { ICursorSelectionChangedEvent } from 'vs/editor/common/cursorEvents'; import { CommentsPanel } from 'vs/workbench/contrib/comments/browser/commentsView'; @@ -343,7 +343,7 @@ export class CommentController implements IEditorContribution { } })); - this._commentThreadRangeDecorator = new CommentThreadRangeDecorator(); + this.globalToDispose.add(this._commentThreadRangeDecorator = new CommentThreadRangeDecorator(this.commentService)); this.globalToDispose.add(this.commentService.onDidDeleteDataProvider(ownerId => { delete this._pendingCommentCache[ownerId]; @@ -1104,4 +1104,18 @@ registerThemingParticipant((theme, collector) => { border-style: solid; box-sizing: border-box; }`); } + + const commentThreadRangeActiveBackgroundColor = theme.getColor(commentThreadRangeActiveBackground); + if (commentThreadRangeActiveBackgroundColor) { + collector.addRule(`.monaco-editor .comment-thread-range-current { background-color: ${commentThreadRangeActiveBackgroundColor};}`); + } + + const commentThreadRangeActiveBorderColor = theme.getColor(commentThreadRangeActiveBorder); + if (commentThreadRangeActiveBorderColor) { + collector.addRule(`.monaco-editor .comment-thread-range-current { + border-color: ${commentThreadRangeActiveBorderColor}; + border-width: 1px; + border-style: solid; + box-sizing: border-box; }`); + } }); diff --git a/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts b/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts index ebe8b7b9de2..a65cffe56f7 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts @@ -58,6 +58,7 @@ interface ICommentThreadTemplateData { timestamp: TimestampWidget; separator: HTMLElement; commentPreview: HTMLSpanElement; + range: HTMLSpanElement; }; repliesMetadata: { container: HTMLElement; @@ -138,7 +139,8 @@ export class CommentNodeRenderer implements IListRenderer userNames: dom.append(metadataContainer, dom.$('.user')), timestamp: new TimestampWidget(this.configurationService, dom.append(metadataContainer, dom.$('.timestamp-container'))), separator: dom.append(metadataContainer, dom.$('.separator')), - commentPreview: dom.append(metadataContainer, dom.$('.text')) + commentPreview: dom.append(metadataContainer, dom.$('.text')), + range: dom.append(metadataContainer, dom.$('.range')) }; data.threadMetadata.separator.innerText = '\u00b7'; @@ -210,6 +212,8 @@ export class CommentNodeRenderer implements IListRenderer templateData.threadMetadata.commentPreview.title = renderedComment.element.textContent ?? ''; } + templateData.threadMetadata.range.textContent = `[${node.element.range.startLineNumber}-${node.element.range.endLineNumber}]`; + if (!node.element.hasReply()) { templateData.repliesMetadata.container.style.display = 'none'; return; diff --git a/src/vs/workbench/contrib/comments/browser/media/panel.css b/src/vs/workbench/contrib/comments/browser/media/panel.css index 8b2e685cb8b..0775ef6a1aa 100644 --- a/src/vs/workbench/contrib/comments/browser/media/panel.css +++ b/src/vs/workbench/contrib/comments/browser/media/panel.css @@ -74,6 +74,11 @@ text-overflow: ellipsis; max-width: 500px; overflow: hidden; + padding-right: 5px; +} + +.comments-panel .comments-panel-container .tree-container .comment-thread-container .range { + opacity: 0.8; } .comments-panel .comments-panel-container .tree-container .comment-thread-container .comment-snippet-container .text code { -- cgit v1.2.3 From 340efad49570e01e4f17c78c804dc8b6933c5a42 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Wed, 13 Apr 2022 16:05:28 +0200 Subject: SCM - Source Control Repositories view sort setting (#147001) --- .../contrib/scm/browser/scm.contribution.ts | 11 + .../contrib/scm/browser/scmViewService.ts | 270 +++++++++++++-------- 2 files changed, 183 insertions(+), 98 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index 2b5f202e350..75866cdf644 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -259,6 +259,17 @@ Registry.as(ConfigurationExtensions.Configuration).regis markdownDescription: localize('alwaysShowRepository', "Controls whether repositories should always be visible in the Source Control view."), default: false }, + 'scm.repositories.sortOrder': { + type: 'string', + enum: ['discovery time', 'name', 'path'], + enumDescriptions: [ + localize('scm.repositoriesSortOrder.discoveryTime', "Repositories in the Source Control Repositories view are sorted by discovery time. Repositories in the Source Control view are sorted in the order that they were selected."), + localize('scm.repositoriesSortOrder.name', "Repositories in the Source Control Repositories and Source Control views are sorted by repository name."), + localize('scm.repositoriesSortOrder.path', "Repositories in the Source Control Repositories and Source Control views are sorted by repository path.") + ], + description: localize('repositoriesSortOrder', "Controls the sort order of the repositories in the source control repositories view."), + default: 'discovery time' + }, 'scm.repositories.visible': { type: 'number', description: localize('providersVisible', "Controls how many repositories are visible in the Source Control Repositories section. Set to `0` to be able to manually resize the view."), diff --git a/src/vs/workbench/contrib/scm/browser/scmViewService.ts b/src/vs/workbench/contrib/scm/browser/scmViewService.ts index 757c5526c7a..caba59981f3 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewService.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewService.ts @@ -15,6 +15,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { compareFileNames, comparePaths } from 'vs/base/common/comparers'; import { basename } from 'vs/base/common/resources'; import { binarySearch } from 'vs/base/common/arrays'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; function getProviderStorageKey(provider: ISCMProvider): string { return `${provider.contextValue}:${provider.label}${provider.rootUri ? `:${provider.rootUri.toString()}` : ''}`; @@ -29,8 +30,18 @@ function getRepositoryName(workspaceContextService: IWorkspaceContextService, re return folder?.uri.toString() === repository.provider.rootUri.toString() ? folder.name : basename(repository.provider.rootUri); } +type ISCMRepositoryViewSortKey = 'discovery time' | 'name' | 'path'; + +interface ISCMRepositoryView { + readonly repository: ISCMRepository; + readonly discoveryTime: number; + focused: boolean; + selectionIndex: number; +} + export interface ISCMViewServiceState { readonly all: string[]; + readonly sortKey: ISCMRepositoryViewSortKey; readonly visible: number[]; } @@ -45,20 +56,24 @@ export class SCMViewService implements ISCMViewService { private previousState: ISCMViewServiceState | undefined; private disposables = new DisposableStore(); - private _repositories: ISCMRepository[] = []; + private _repositories: ISCMRepositoryView[] = []; get repositories(): ISCMRepository[] { - return this._repositories; + return this._repositories.map(r => r.repository); } - private _onDidChangeRepositories = new Emitter(); - readonly onDidChangeRepositories = this._onDidChangeRepositories.event; - - private _visibleRepositoriesSet = new Set(); - private _visibleRepositories: ISCMRepository[] = []; - get visibleRepositories(): ISCMRepository[] { - return this._visibleRepositories; + // In order to match the legacy behaviour, when the repositories are sorted by discovery time, + // the visible repositories are sorted by the selection index instead of the discovery time. + if (this._repositoriesSortKey === 'discovery time') { + return this._repositories.filter(r => r.selectionIndex !== -1) + .sort((r1, r2) => r1.selectionIndex - r2.selectionIndex) + .map(r => r.repository); + } + + return this._repositories + .filter(r => r.selectionIndex !== -1) + .map(r => r.repository); } set visibleRepositories(visibleRepositories: ISCMRepository[]) { @@ -66,15 +81,18 @@ export class SCMViewService implements ISCMViewService { const added = new Set(); const removed = new Set(); - for (const repository of visibleRepositories) { - if (!this._visibleRepositoriesSet.has(repository)) { - added.add(repository); + for (const repositoryView of this._repositories) { + // Selected -> !Selected + if (!set.has(repositoryView.repository) && repositoryView.selectionIndex !== -1) { + repositoryView.selectionIndex = -1; + removed.add(repositoryView.repository); } - } - - for (const repository of this._visibleRepositories) { - if (!set.has(repository)) { - removed.add(repository); + // Selected | !Selected -> Selected + if (set.has(repositoryView.repository)) { + if (repositoryView.selectionIndex === -1) { + added.add(repositoryView.repository); + } + repositoryView.selectionIndex = visibleRepositories.indexOf(repositoryView.repository); } } @@ -82,15 +100,17 @@ export class SCMViewService implements ISCMViewService { return; } - this._visibleRepositories = visibleRepositories.sort(this._compareRepositories); - this._visibleRepositoriesSet = set; this._onDidSetVisibleRepositories.fire({ added, removed }); - if (this._focusedRepository && removed.has(this._focusedRepository)) { - this.focus(this._visibleRepositories[0]); + // Update focus if the focused repository is not visible anymore + if (this._repositories.find(r => r.focused && r.selectionIndex === -1)) { + this.focus(this._repositories.find(r => r.selectionIndex !== -1)?.repository); } } + private _onDidChangeRepositories = new Emitter(); + readonly onDidChangeRepositories = this._onDidChangeRepositories.event; + private _onDidSetVisibleRepositories = new Emitter(); readonly onDidChangeVisibleRepositories = Event.any( this._onDidSetVisibleRepositories.event, @@ -101,53 +121,66 @@ export class SCMViewService implements ISCMViewService { return e; } - return { - added: Iterable.concat(last.added, e.added), - removed: Iterable.concat(last.removed, e.removed), - }; + const added = new Set(last.added); + const removed = new Set(last.removed); + + for (const repository of e.added) { + if (removed.has(repository)) { + removed.delete(repository); + } else { + added.add(repository); + } + } + for (const repository of e.removed) { + if (added.has(repository)) { + added.delete(repository); + } else { + removed.add(repository); + } + } + + return { added, removed }; }, 0) ); - private _focusedRepository: ISCMRepository | undefined; - get focusedRepository(): ISCMRepository | undefined { - return this._focusedRepository; + return this._repositories.find(r => r.focused)?.repository; } private _onDidFocusRepository = new Emitter(); readonly onDidFocusRepository = this._onDidFocusRepository.event; - private _compareRepositories: (op1: ISCMRepository, op2: ISCMRepository) => number; + private _repositoriesSortKey: ISCMRepositoryViewSortKey; constructor( - @ISCMService private readonly scmService: ISCMService, + @ISCMService scmService: ISCMService, @IInstantiationService instantiationService: IInstantiationService, + @IConfigurationService private readonly configurationService: IConfigurationService, @IStorageService private readonly storageService: IStorageService, - @IWorkspaceContextService workspaceContextService: IWorkspaceContextService + @IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService ) { this.menus = instantiationService.createInstance(SCMMenus); - this._compareRepositories = (op1: ISCMRepository, op2: ISCMRepository): number => { - const name1 = getRepositoryName(workspaceContextService, op1); - const name2 = getRepositoryName(workspaceContextService, op2); - - const nameComparison = compareFileNames(name1, name2); - if (nameComparison === 0 && op1.provider.rootUri && op2.provider.rootUri) { - return comparePaths(op1.provider.rootUri.fsPath, op2.provider.rootUri.fsPath); - } - - return nameComparison; - }; - - scmService.onDidAddRepository(this.onDidAddRepository, this, this.disposables); - scmService.onDidRemoveRepository(this.onDidRemoveRepository, this, this.disposables); - try { this.previousState = JSON.parse(storageService.get('scm:view:visibleRepositories', StorageScope.WORKSPACE, '')); } catch { // noop } + this._repositoriesSortKey = this.previousState?.sortKey ?? this.getViewSortOrder(); + + scmService.onDidAddRepository(this.onDidAddRepository, this, this.disposables); + scmService.onDidRemoveRepository(this.onDidRemoveRepository, this, this.disposables); + + configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('scm.repositories.sortOrder')) { + this._repositoriesSortKey = this.getViewSortOrder(); + this._repositories.sort(this.compareRepositories.bind(this)); + + this._onDidChangeRepositories.fire({ added: Iterable.empty(), removed: Iterable.empty() }); + } + }); + for (const repository of scmService.repositories) { this.onDidAddRepository(repository); } @@ -160,50 +193,61 @@ export class SCMViewService implements ISCMViewService { this.eventuallyFinishLoading(); } - this.insertRepository(this._repositories, repository); + const repositoryView: ISCMRepositoryView = { + repository, discoveryTime: Date.now(), focused: false, selectionIndex: -1 + }; + let removed: Iterable = Iterable.empty(); if (this.previousState) { const index = this.previousState.all.indexOf(getProviderStorageKey(repository.provider)); - if (index === -1) { // saw a repo we did not expect + if (index === -1) { + // This repository is not part of the previous state which means that it + // was either manually closed in the previous session, or the repository + // was added after the previous session.In this case, we should select all + // of the repositories. const added: ISCMRepository[] = []; - for (const repo of this.scmService.repositories) { // all should be visible - if (!this._visibleRepositoriesSet.has(repo)) { - added.push(repository); + + this.insertRepositoryView(this._repositories, repositoryView); + this._repositories.forEach((repositoryView, index) => { + if (repositoryView.selectionIndex === -1) { + added.push(repositoryView.repository); } - } + repositoryView.selectionIndex = index; + }); - this._visibleRepositoriesSet = new Set(this.scmService.repositories); - this._visibleRepositories = [...this.scmService.repositories.sort(this._compareRepositories)]; this._onDidChangeRepositories.fire({ added, removed: Iterable.empty() }); - this.finishLoading(); + this.didSelectRepository = false; return; } - if (this.previousState.visible.indexOf(index) > -1) { - // First visible repository - if (!this.didSelectRepository) { - removed = this._visibleRepositories; - - this._visibleRepositories = []; - this._visibleRepositoriesSet = new Set(); - this.didSelectRepository = true; - } - } else { + if (this.previousState.visible.indexOf(index) === -1) { // Explicit selection started if (this.didSelectRepository) { + this.insertRepositoryView(this._repositories, repositoryView); this._onDidChangeRepositories.fire({ added: Iterable.empty(), removed: Iterable.empty() }); return; } + } else { + // First visible repository + if (!this.didSelectRepository) { + removed = [...this.visibleRepositories]; + this._repositories.forEach(r => { + r.focused = false; + r.selectionIndex = -1; + }); + + this.didSelectRepository = true; + } } } - this._visibleRepositoriesSet.add(repository); - this.insertRepository(this._visibleRepositories, repository); - this._onDidChangeRepositories.fire({ added: [repository], removed }); + const maxSelectionIndex = this.getMaxSelectionIndex(); + this.insertRepositoryView(this._repositories, { ...repositoryView, selectionIndex: maxSelectionIndex + 1 }); + this._onDidChangeRepositories.fire({ added: [repositoryView.repository], removed }); - if (!this._focusedRepository) { + if (!this._repositories.find(r => r.focused)) { this.focus(repository); } } @@ -213,39 +257,29 @@ export class SCMViewService implements ISCMViewService { this.eventuallyFinishLoading(); } - let added: Iterable = Iterable.empty(); + const repositoriesIndex = this._repositories.findIndex(r => r.repository === repository); - const repositoriesIndex = this._repositories.indexOf(repository); - const visibleRepositoriesIndex = this._visibleRepositories.indexOf(repository); - - if (repositoriesIndex > -1) { - this._repositories.splice(repositoriesIndex, 1); + if (repositoriesIndex === -1) { + return; } - if (visibleRepositoriesIndex > -1) { - this._visibleRepositories.splice(visibleRepositoriesIndex, 1); - this._visibleRepositoriesSet.delete(repository); - - if (this._repositories.length > 0 && this._visibleRepositories.length === 0) { - const first = this._repositories[0]; + let added: Iterable = Iterable.empty(); + const repositoryView = this._repositories.splice(repositoriesIndex, 1); - this._visibleRepositories.push(first); - this._visibleRepositoriesSet.add(first); - added = [first]; - } + if (this._repositories.length > 0 && this.visibleRepositories.length === 0) { + this._repositories[0].selectionIndex = 0; + added = [this._repositories[0].repository]; } - if (repositoriesIndex > -1 || visibleRepositoriesIndex > -1) { - this._onDidChangeRepositories.fire({ added, removed: [repository] }); - } + this._onDidChangeRepositories.fire({ added, removed: repositoryView.map(r => r.repository) }); - if (this._focusedRepository === repository) { - this.focus(this._visibleRepositories[0]); + if (repositoryView.length === 1 && repositoryView[0].focused && this.visibleRepositories.length > 0) { + this.focus(this.visibleRepositories[0]); } } isVisible(repository: ISCMRepository): boolean { - return this._visibleRepositoriesSet.has(repository); + return this._repositories.find(r => r.repository === repository)?.selectionIndex !== -1; } toggleVisibility(repository: ISCMRepository, visible?: boolean): void { @@ -270,17 +304,57 @@ export class SCMViewService implements ISCMViewService { } focus(repository: ISCMRepository | undefined): void { - if (repository && !this.visibleRepositories.includes(repository)) { + if (repository && !this.isVisible(repository)) { return; } - this._focusedRepository = repository; - this._onDidFocusRepository.fire(repository); + this._repositories.forEach(r => r.focused = r.repository === repository); + + if (this._repositories.find(r => r.focused)) { + this._onDidFocusRepository.fire(repository); + } + } + + private compareRepositories(op1: ISCMRepositoryView, op2: ISCMRepositoryView): number { + // Sort by discovery time + if (this._repositoriesSortKey === 'discovery time') { + return op1.discoveryTime - op2.discoveryTime; + } + + // Sort by path + if (this._repositoriesSortKey === 'path' && op1.repository.provider.rootUri && op2.repository.provider.rootUri) { + return comparePaths(op1.repository.provider.rootUri.fsPath, op2.repository.provider.rootUri.fsPath); + } + + // Sort by name, path + const name1 = getRepositoryName(this.workspaceContextService, op1.repository); + const name2 = getRepositoryName(this.workspaceContextService, op2.repository); + + const nameComparison = compareFileNames(name1, name2); + if (nameComparison === 0 && op1.repository.provider.rootUri && op2.repository.provider.rootUri) { + return comparePaths(op1.repository.provider.rootUri.fsPath, op2.repository.provider.rootUri.fsPath); + } + + return nameComparison; + } + + private getMaxSelectionIndex(): number { + return this._repositories.length === 0 ? -1 : + Math.max(...this._repositories.map(r => r.selectionIndex)); + } + + private getViewSortOrder(): ISCMRepositoryViewSortKey { + const sortOder = this.configurationService.getValue('scm.repositories.sortOrder'); + if (sortOder !== 'discovery time' && sortOder !== 'name' && sortOder !== 'path') { + return 'discovery time'; + } + + return sortOder; } - private insertRepository(repositories: ISCMRepository[], repository: ISCMRepository): void { - const index = binarySearch(repositories, repository, this._compareRepositories); - repositories.splice(index < 0 ? ~index : index, 0, repository); + private insertRepositoryView(repositories: ISCMRepositoryView[], repositoryView: ISCMRepositoryView): void { + const index = binarySearch(repositories, repositoryView, this.compareRepositories.bind(this)); + repositories.splice(index < 0 ? ~index : index, 0, repositoryView); } private onWillSaveState(): void { @@ -290,7 +364,7 @@ export class SCMViewService implements ISCMViewService { const all = this.repositories.map(r => getProviderStorageKey(r.provider)); const visible = this.visibleRepositories.map(r => all.indexOf(getProviderStorageKey(r.provider))); - const raw = JSON.stringify({ all, visible }); + const raw = JSON.stringify({ all, sortKey: this._repositoriesSortKey, visible }); this.storageService.store('scm:view:visibleRepositories', raw, StorageScope.WORKSPACE, StorageTarget.MACHINE); } -- cgit v1.2.3 From 9a87fe7eaf2bcf29de4f5ec7c02044c410c95c0f Mon Sep 17 00:00:00 2001 From: aamunger Date: Mon, 11 Apr 2022 12:44:15 -0700 Subject: added setting for notebook output line height --- .../contrib/notebook/browser/notebook.contribution.ts | 6 ++++++ .../contrib/notebook/browser/notebookEditorWidget.ts | 2 +- .../browser/view/renderers/backLayerWebView.ts | 2 ++ .../contrib/notebook/common/notebookCommon.ts | 3 ++- .../contrib/notebook/common/notebookOptions.ts | 18 ++++++++++++++++-- 5 files changed, 27 insertions(+), 4 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index 2b793c40961..f1c5936099e 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -892,5 +892,11 @@ configurationRegistry.registerConfiguration({ enum: ['always', 'never', 'fromEditor'], default: 'fromEditor' }, + [NotebookSetting.outputLineHeight]: { + markdownDescription: nls.localize('notebook.outputLineHeight', "line height of the output text"), + type: 'number', + default: 22, + tags: ['notebookLayout'] + }, } }); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index aa1bcc7853f..3cc81adc47a 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -397,7 +397,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD this._updateForNotebookConfiguration(); } - if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.markupFontSize || e.insertToolbarAlignment) { + if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.markupFontSize || e.insertToolbarAlignment || e.outputLineHeight) { this._styleElement?.remove(); this._createLayoutStyles(); this._webview?.updateOptions({ diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index 7bda661ed4e..4917457e7dc 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -81,6 +81,7 @@ export interface INotebookDelegateForWebview { interface BacklayerWebviewOptions { readonly outputNodePadding: number; readonly outputNodeLeftPadding: number; + readonly outputLineHeight: number; readonly previewNodePadding: number; readonly markdownLeftMargin: number; readonly leftMargin: number; @@ -205,6 +206,7 @@ export class BackLayerWebView extends Disposable { 'notebook-markdown-min-height': `${this.options.previewNodePadding * 2}px`, 'notebook-markup-font-size': typeof this.options.markupFontSize === 'number' && this.options.markupFontSize > 0 ? `${this.options.markupFontSize}px` : `calc(${this.options.fontSize}px * 1.2)`, 'notebook-cell-output-font-size': `${this.options.fontSize}px`, + 'notebook-cell-output-line-height': `${this.options.outputLineHeight}px`, 'notebook-cell-output-font-family': this.options.fontFamily, 'notebook-cell-markup-empty-content': nls.localize('notebook.emptyMarkdownPlaceholder', "Empty markdown cell, double click or press enter to edit."), 'notebook-cell-renderer-not-found-error': nls.localize({ diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index b93c8a7449f..4a2b3f9e405 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -913,7 +913,8 @@ export const NotebookSetting = { textOutputLineLimit: 'notebook.output.textLineLimit', globalToolbarShowLabel: 'notebook.globalToolbarShowLabel', markupFontSize: 'notebook.markup.fontSize', - interactiveWindowCollapseCodeCells: 'interactiveWindow.collapseCellInputCode' + interactiveWindowCollapseCodeCells: 'interactiveWindow.collapseCellInputCode', + outputLineHeight: 'notebook.outputLineHeight' } as const; export const enum CellStatusbarAlignment { diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 9564a563def..91d23a63e48 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -62,6 +62,7 @@ export interface NotebookLayoutConfiguration { showFoldingControls: 'always' | 'mouseover'; dragAndDropEnabled: boolean; fontSize: number; + outputLineHeight: number; markupFontSize: number; focusIndicatorLeftMargin: number; editorOptionsCustomizations: any | undefined; @@ -87,6 +88,7 @@ export interface NotebookOptionsChangeEvent { readonly markupFontSize?: boolean; readonly editorOptionsCustomizations?: boolean; readonly interactiveWindowCollapseCodeCells?: boolean; + readonly outputLineHeight?: boolean; } const defaultConfigConstants = Object.freeze({ @@ -137,6 +139,7 @@ export class NotebookOptions extends Disposable { const markupFontSize = this.configurationService.getValue(NotebookSetting.markupFontSize); const editorOptionsCustomizations = this.configurationService.getValue(NotebookSetting.cellEditorOptionsCustomizations); const interactiveWindowCollapseCodeCells: InteractiveWindowCollapseCodeCells = this.configurationService.getValue(NotebookSetting.interactiveWindowCollapseCodeCells); + const outputLineHeight = this.configurationService.getValue(NotebookSetting.outputLineHeight); this._layoutConfiguration = { ...(compactView ? compactConfigConstants : defaultConfigConstants), @@ -166,6 +169,7 @@ export class NotebookOptions extends Disposable { insertToolbarAlignment, showFoldingControls, fontSize, + outputLineHeight, markupFontSize, editorOptionsCustomizations, focusIndicatorGap: 3, @@ -202,6 +206,7 @@ export class NotebookOptions extends Disposable { const markupFontSize = e.affectsConfiguration(NotebookSetting.markupFontSize); const editorOptionsCustomizations = e.affectsConfiguration(NotebookSetting.cellEditorOptionsCustomizations); const interactiveWindowCollapseCodeCells = e.affectsConfiguration(NotebookSetting.interactiveWindowCollapseCodeCells); + const outputLineHeight = e.affectsConfiguration(NotebookSetting.outputLineHeight); if ( !cellStatusBarVisibility @@ -219,7 +224,8 @@ export class NotebookOptions extends Disposable { && !fontSize && !markupFontSize && !editorOptionsCustomizations - && !interactiveWindowCollapseCodeCells) { + && !interactiveWindowCollapseCodeCells + && !outputLineHeight) { return; } @@ -293,8 +299,13 @@ export class NotebookOptions extends Disposable { configuration.interactiveWindowCollapseCodeCells = this.configurationService.getValue(NotebookSetting.interactiveWindowCollapseCodeCells); } + if (outputLineHeight) { + configuration.outputLineHeight = this.configurationService.getValue(NotebookSetting.outputLineHeight); + } + this._layoutConfiguration = Object.freeze(configuration); + // add new configuration to the event? // trigger event this._onDidChangeOptions.fire({ cellStatusBarVisibility, @@ -312,7 +323,8 @@ export class NotebookOptions extends Disposable { fontSize, markupFontSize, editorOptionsCustomizations, - interactiveWindowCollapseCodeCells + interactiveWindowCollapseCodeCells, + outputLineHeight }); } @@ -503,6 +515,7 @@ export class NotebookOptions extends Disposable { dragAndDropEnabled: this._layoutConfiguration.dragAndDropEnabled, fontSize: this._layoutConfiguration.fontSize, markupFontSize: this._layoutConfiguration.markupFontSize, + outputLineHeight: this._layoutConfiguration.outputLineHeight, }; } @@ -518,6 +531,7 @@ export class NotebookOptions extends Disposable { dragAndDropEnabled: false, fontSize: this._layoutConfiguration.fontSize, markupFontSize: this._layoutConfiguration.markupFontSize, + outputLineHeight: this._layoutConfiguration.outputLineHeight, }; } -- cgit v1.2.3 From 51ab78f535d8537e031e1ae77cac678ae22b0249 Mon Sep 17 00:00:00 2001 From: aamunger Date: Tue, 12 Apr 2022 08:32:14 -0700 Subject: added setting to override notebook output font family and size --- .../notebook/browser/notebook.contribution.ts | 13 +++++++++- .../notebook/browser/notebookEditorWidget.ts | 2 +- .../browser/view/renderers/backLayerWebView.ts | 8 +++--- .../contrib/notebook/common/notebookCommon.ts | 4 ++- .../contrib/notebook/common/notebookOptions.ts | 30 ++++++++++++++++++++++ 5 files changed, 51 insertions(+), 6 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index f1c5936099e..17c7255ad50 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -893,10 +893,21 @@ configurationRegistry.registerConfiguration({ default: 'fromEditor' }, [NotebookSetting.outputLineHeight]: { - markdownDescription: nls.localize('notebook.outputLineHeight', "line height of the output text"), + markdownDescription: nls.localize('notebook.outputLineHeight', "Line height of the output text"), type: 'number', default: 22, tags: ['notebookLayout'] }, + [NotebookSetting.outputFontSize]: { + markdownDescription: nls.localize('notebook.outputFontSize', "Font size for plain text outputs. When set to 0 `#editor.fontSize#` is used."), + type: 'number', + default: 0, + tags: ['notebookLayout'] + }, + [NotebookSetting.outputFontFamily]: { + markdownDescription: nls.localize('notebook.outputFontFamily', "The font family for plain text output of notebook cells. When set to empty, the `#editor.fontFamily#` is used."), + type: 'string', + tags: ['notebookLayout'] + }, } }); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 3cc81adc47a..15e56226ccd 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -397,7 +397,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD this._updateForNotebookConfiguration(); } - if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.markupFontSize || e.insertToolbarAlignment || e.outputLineHeight) { + if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.outputFontSize || e.fontFamily || e.outputFontFamily || e.markupFontSize || e.insertToolbarAlignment || e.outputLineHeight) { this._styleElement?.remove(); this._createLayoutStyles(); this._webview?.updateOptions({ diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index 4917457e7dc..d5ad9679436 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -81,7 +81,6 @@ export interface INotebookDelegateForWebview { interface BacklayerWebviewOptions { readonly outputNodePadding: number; readonly outputNodeLeftPadding: number; - readonly outputLineHeight: number; readonly previewNodePadding: number; readonly markdownLeftMargin: number; readonly leftMargin: number; @@ -89,8 +88,11 @@ interface BacklayerWebviewOptions { readonly runGutter: number; readonly dragAndDropEnabled: boolean; readonly fontSize: number; + readonly outputFontSize: number; readonly fontFamily: string; + readonly outputFontFamily: string; readonly markupFontSize: number; + readonly outputLineHeight: number; } export class BackLayerWebView extends Disposable { @@ -205,9 +207,9 @@ export class BackLayerWebView extends Disposable { 'notebook-output-node-left-padding': `${this.options.outputNodeLeftPadding}px`, 'notebook-markdown-min-height': `${this.options.previewNodePadding * 2}px`, 'notebook-markup-font-size': typeof this.options.markupFontSize === 'number' && this.options.markupFontSize > 0 ? `${this.options.markupFontSize}px` : `calc(${this.options.fontSize}px * 1.2)`, - 'notebook-cell-output-font-size': `${this.options.fontSize}px`, + 'notebook-cell-output-font-size': `${this.options.outputFontSize || this.options.fontSize}px`, 'notebook-cell-output-line-height': `${this.options.outputLineHeight}px`, - 'notebook-cell-output-font-family': this.options.fontFamily, + 'notebook-cell-output-font-family': this.options.outputFontFamily || this.options.fontFamily, 'notebook-cell-markup-empty-content': nls.localize('notebook.emptyMarkdownPlaceholder', "Empty markdown cell, double click or press enter to edit."), 'notebook-cell-renderer-not-found-error': nls.localize({ key: 'notebook.error.rendererNotFound', diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 4a2b3f9e405..121ac0689da 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -914,7 +914,9 @@ export const NotebookSetting = { globalToolbarShowLabel: 'notebook.globalToolbarShowLabel', markupFontSize: 'notebook.markup.fontSize', interactiveWindowCollapseCodeCells: 'interactiveWindow.collapseCellInputCode', - outputLineHeight: 'notebook.outputLineHeight' + outputLineHeight: 'notebook.outputLineHeight', + outputFontSize: 'notebook.outputFontSize', + outputFontFamily: 'notebook.fontFamily' } as const; export const enum CellStatusbarAlignment { diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 91d23a63e48..b7c9b89a926 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -62,6 +62,8 @@ export interface NotebookLayoutConfiguration { showFoldingControls: 'always' | 'mouseover'; dragAndDropEnabled: boolean; fontSize: number; + outputFontSize: number; + outputFontFamily: string; outputLineHeight: number; markupFontSize: number; focusIndicatorLeftMargin: number; @@ -85,6 +87,9 @@ export interface NotebookOptionsChangeEvent { readonly consolidatedRunButton?: boolean; readonly dragAndDropEnabled?: boolean; readonly fontSize?: boolean; + readonly outputFontSize?: boolean; + readonly fontFamily?: boolean; + readonly outputFontFamily?: boolean; readonly markupFontSize?: boolean; readonly editorOptionsCustomizations?: boolean; readonly interactiveWindowCollapseCodeCells?: boolean; @@ -136,6 +141,8 @@ export class NotebookOptions extends Disposable { const showFoldingControls = this._computeShowFoldingControlsOption(); // const { bottomToolbarGap, bottomToolbarHeight } = this._computeBottomToolbarDimensions(compactView, insertToolbarPosition, insertToolbarAlignment); const fontSize = this.configurationService.getValue('editor.fontSize'); + const outputFontSize = this.configurationService.getValue(NotebookSetting.outputFontSize); + const outputFontFamily = this.configurationService.getValue(NotebookSetting.outputFontFamily); const markupFontSize = this.configurationService.getValue(NotebookSetting.markupFontSize); const editorOptionsCustomizations = this.configurationService.getValue(NotebookSetting.cellEditorOptionsCustomizations); const interactiveWindowCollapseCodeCells: InteractiveWindowCollapseCodeCells = this.configurationService.getValue(NotebookSetting.interactiveWindowCollapseCodeCells); @@ -169,6 +176,8 @@ export class NotebookOptions extends Disposable { insertToolbarAlignment, showFoldingControls, fontSize, + outputFontSize, + outputFontFamily, outputLineHeight, markupFontSize, editorOptionsCustomizations, @@ -203,11 +212,15 @@ export class NotebookOptions extends Disposable { const showFoldingControls = e.affectsConfiguration(NotebookSetting.showFoldingControls); const dragAndDropEnabled = e.affectsConfiguration(NotebookSetting.dragAndDropEnabled); const fontSize = e.affectsConfiguration('editor.fontSize'); + const outputFontSize = e.affectsConfiguration(NotebookSetting.outputFontSize); + const fontFamily = e.affectsConfiguration('editor.fontFamily'); + const outputFontFamily = e.affectsConfiguration(NotebookSetting.outputFontFamily); const markupFontSize = e.affectsConfiguration(NotebookSetting.markupFontSize); const editorOptionsCustomizations = e.affectsConfiguration(NotebookSetting.cellEditorOptionsCustomizations); const interactiveWindowCollapseCodeCells = e.affectsConfiguration(NotebookSetting.interactiveWindowCollapseCodeCells); const outputLineHeight = e.affectsConfiguration(NotebookSetting.outputLineHeight); + if ( !cellStatusBarVisibility && !cellToolbarLocation @@ -222,6 +235,9 @@ export class NotebookOptions extends Disposable { && !showFoldingControls && !dragAndDropEnabled && !fontSize + && !outputFontSize + && !fontFamily + && !outputFontFamily && !markupFontSize && !editorOptionsCustomizations && !interactiveWindowCollapseCodeCells @@ -287,6 +303,14 @@ export class NotebookOptions extends Disposable { configuration.fontSize = this.configurationService.getValue('editor.fontSize'); } + if (outputFontSize) { + configuration.outputFontSize = this.configurationService.getValue(NotebookSetting.outputFontSize); + } + + if (outputFontFamily) { + configuration.outputFontFamily = this.configurationService.getValue(NotebookSetting.outputFontFamily); + } + if (markupFontSize) { configuration.markupFontSize = this.configurationService.getValue(NotebookSetting.markupFontSize); } @@ -321,6 +345,8 @@ export class NotebookOptions extends Disposable { consolidatedRunButton, dragAndDropEnabled, fontSize, + outputFontSize, + outputFontFamily, markupFontSize, editorOptionsCustomizations, interactiveWindowCollapseCodeCells, @@ -514,6 +540,8 @@ export class NotebookOptions extends Disposable { runGutter: this._layoutConfiguration.cellRunGutter, dragAndDropEnabled: this._layoutConfiguration.dragAndDropEnabled, fontSize: this._layoutConfiguration.fontSize, + outputFontSize: this._layoutConfiguration.outputFontSize, + outputFontFamily: this._layoutConfiguration.outputFontFamily, markupFontSize: this._layoutConfiguration.markupFontSize, outputLineHeight: this._layoutConfiguration.outputLineHeight, }; @@ -530,6 +558,8 @@ export class NotebookOptions extends Disposable { runGutter: 0, dragAndDropEnabled: false, fontSize: this._layoutConfiguration.fontSize, + outputFontSize: this._layoutConfiguration.outputFontSize, + outputFontFamily: this._layoutConfiguration.outputFontFamily, markupFontSize: this._layoutConfiguration.markupFontSize, outputLineHeight: this._layoutConfiguration.outputLineHeight, }; -- cgit v1.2.3 From fe38a7b3bd41d5f7fe0e29579308f625d68ea170 Mon Sep 17 00:00:00 2001 From: aamunger Date: Tue, 12 Apr 2022 12:46:09 -0700 Subject: line height as ratio when < 8 --- .../notebook/browser/notebook.contribution.ts | 6 ++-- .../notebook/browser/notebookEditorWidget.ts | 2 +- .../contrib/notebook/common/notebookCommon.ts | 2 +- .../contrib/notebook/common/notebookOptions.ts | 42 ++++++++++++++-------- 4 files changed, 32 insertions(+), 20 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index 17c7255ad50..b96059530d4 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -893,19 +893,19 @@ configurationRegistry.registerConfiguration({ default: 'fromEditor' }, [NotebookSetting.outputLineHeight]: { - markdownDescription: nls.localize('notebook.outputLineHeight', "Line height of the output text"), + markdownDescription: nls.localize('notebook.outputLineHeight', "Line height of the output text for notebook cells.\n - Values between 0 and 8 will be used as a multiplier with the font size.\n - Values greater than or equal to 8 will be used as effective values."), type: 'number', default: 22, tags: ['notebookLayout'] }, [NotebookSetting.outputFontSize]: { - markdownDescription: nls.localize('notebook.outputFontSize', "Font size for plain text outputs. When set to 0 `#editor.fontSize#` is used."), + markdownDescription: nls.localize('notebook.outputFontSize', "Font size for the output text for notebook cells. When set to 0 `#editor.fontSize#` is used."), type: 'number', default: 0, tags: ['notebookLayout'] }, [NotebookSetting.outputFontFamily]: { - markdownDescription: nls.localize('notebook.outputFontFamily', "The font family for plain text output of notebook cells. When set to empty, the `#editor.fontFamily#` is used."), + markdownDescription: nls.localize('notebook.outputFontFamily', "The font family for the output text for notebook cells. When set to empty, the `#editor.fontFamily#` is used."), type: 'string', tags: ['notebookLayout'] }, diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 15e56226ccd..93bcb157f61 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -397,7 +397,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD this._updateForNotebookConfiguration(); } - if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.outputFontSize || e.fontFamily || e.outputFontFamily || e.markupFontSize || e.insertToolbarAlignment || e.outputLineHeight) { + if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.outputFontSize || e.markupFontSize || e.insertToolbarAlignment || e.outputLineHeight) { this._styleElement?.remove(); this._createLayoutStyles(); this._webview?.updateOptions({ diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 121ac0689da..5f70d558da1 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -916,7 +916,7 @@ export const NotebookSetting = { interactiveWindowCollapseCodeCells: 'interactiveWindow.collapseCellInputCode', outputLineHeight: 'notebook.outputLineHeight', outputFontSize: 'notebook.outputFontSize', - outputFontFamily: 'notebook.fontFamily' + outputFontFamily: 'notebook.outputFontFamily' } as const; export const enum CellStatusbarAlignment { diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index b7c9b89a926..2964a52df79 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -88,8 +88,6 @@ export interface NotebookOptionsChangeEvent { readonly dragAndDropEnabled?: boolean; readonly fontSize?: boolean; readonly outputFontSize?: boolean; - readonly fontFamily?: boolean; - readonly outputFontFamily?: boolean; readonly markupFontSize?: boolean; readonly editorOptionsCustomizations?: boolean; readonly interactiveWindowCollapseCodeCells?: boolean; @@ -146,7 +144,7 @@ export class NotebookOptions extends Disposable { const markupFontSize = this.configurationService.getValue(NotebookSetting.markupFontSize); const editorOptionsCustomizations = this.configurationService.getValue(NotebookSetting.cellEditorOptionsCustomizations); const interactiveWindowCollapseCodeCells: InteractiveWindowCollapseCodeCells = this.configurationService.getValue(NotebookSetting.interactiveWindowCollapseCodeCells); - const outputLineHeight = this.configurationService.getValue(NotebookSetting.outputLineHeight); + const outputLineHeight = this._computeOutputLineHeight(); this._layoutConfiguration = { ...(compactView ? compactConfigConstants : defaultConfigConstants), @@ -198,6 +196,29 @@ export class NotebookOptions extends Disposable { })); } + private _computeOutputLineHeight(): number { + const minimumLineHeight = 8; + let lineHeight = this.configurationService.getValue(NotebookSetting.outputLineHeight); + + if (lineHeight < minimumLineHeight) { + // Values too small to be line heights in pixels are in ems. + let fontSize = this.configurationService.getValue(NotebookSetting.outputFontSize); + if (fontSize === 0) { + fontSize = this.configurationService.getValue('editor.fontSize'); + } + + lineHeight = lineHeight * fontSize; + } + + // Enforce integer, minimum constraints + lineHeight = Math.round(lineHeight); + if (lineHeight < minimumLineHeight) { + lineHeight = minimumLineHeight; + } + + return lineHeight; + } + private _updateConfiguration(e: IConfigurationChangeEvent) { const cellStatusBarVisibility = e.affectsConfiguration(NotebookSetting.showCellStatusBar); const cellToolbarLocation = e.affectsConfiguration(NotebookSetting.cellToolbarLocation); @@ -213,8 +234,6 @@ export class NotebookOptions extends Disposable { const dragAndDropEnabled = e.affectsConfiguration(NotebookSetting.dragAndDropEnabled); const fontSize = e.affectsConfiguration('editor.fontSize'); const outputFontSize = e.affectsConfiguration(NotebookSetting.outputFontSize); - const fontFamily = e.affectsConfiguration('editor.fontFamily'); - const outputFontFamily = e.affectsConfiguration(NotebookSetting.outputFontFamily); const markupFontSize = e.affectsConfiguration(NotebookSetting.markupFontSize); const editorOptionsCustomizations = e.affectsConfiguration(NotebookSetting.cellEditorOptionsCustomizations); const interactiveWindowCollapseCodeCells = e.affectsConfiguration(NotebookSetting.interactiveWindowCollapseCodeCells); @@ -236,8 +255,6 @@ export class NotebookOptions extends Disposable { && !dragAndDropEnabled && !fontSize && !outputFontSize - && !fontFamily - && !outputFontFamily && !markupFontSize && !editorOptionsCustomizations && !interactiveWindowCollapseCodeCells @@ -304,11 +321,7 @@ export class NotebookOptions extends Disposable { } if (outputFontSize) { - configuration.outputFontSize = this.configurationService.getValue(NotebookSetting.outputFontSize); - } - - if (outputFontFamily) { - configuration.outputFontFamily = this.configurationService.getValue(NotebookSetting.outputFontFamily); + configuration.outputFontSize = this.configurationService.getValue(NotebookSetting.outputFontSize) ?? configuration.fontSize; } if (markupFontSize) { @@ -323,8 +336,8 @@ export class NotebookOptions extends Disposable { configuration.interactiveWindowCollapseCodeCells = this.configurationService.getValue(NotebookSetting.interactiveWindowCollapseCodeCells); } - if (outputLineHeight) { - configuration.outputLineHeight = this.configurationService.getValue(NotebookSetting.outputLineHeight); + if (outputLineHeight || fontSize || outputFontSize) { + configuration.outputLineHeight = this._computeOutputLineHeight(); } this._layoutConfiguration = Object.freeze(configuration); @@ -346,7 +359,6 @@ export class NotebookOptions extends Disposable { dragAndDropEnabled, fontSize, outputFontSize, - outputFontFamily, markupFontSize, editorOptionsCustomizations, interactiveWindowCollapseCodeCells, -- cgit v1.2.3 From 82d8e0f018b20cac98983440042233533ac82922 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Wed, 13 Apr 2022 10:27:56 -0700 Subject: web: add telemetry api for embedders (#146931) * web: add telemetry api for embedders * fixup! expose just the telemetry level instead of publicLog * fixup! move telemetry level under env * fixup! pr comments * fixup! build --- src/vs/workbench/contrib/debug/browser/debugSession.ts | 2 +- .../search/test/electron-browser/textsearch.perf.integrationTest.ts | 3 ++- src/vs/workbench/contrib/tags/electron-sandbox/workspaceTags.ts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index 9109c4f0145..0bd109a80d9 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -1071,7 +1071,7 @@ export class DebugSession implements IDebugSession { // only log telemetry events from debug adapter if the debug extension provided the telemetry key // and the user opted in telemetry const telemetryEndpoint = this.raw.dbgr.getCustomTelemetryEndpoint(); - if (telemetryEndpoint && this.telemetryService.telemetryLevel !== TelemetryLevel.NONE) { + if (telemetryEndpoint && this.telemetryService.telemetryLevel.value !== TelemetryLevel.NONE) { // __GDPR__TODO__ We're sending events in the name of the debug extension and we can not ensure that those are declared correctly. let data = event.body.data; if (!telemetryEndpoint.sendErrorTelemetry && event.body.data) { diff --git a/src/vs/workbench/contrib/search/test/electron-browser/textsearch.perf.integrationTest.ts b/src/vs/workbench/contrib/search/test/electron-browser/textsearch.perf.integrationTest.ts index d1a74339e79..cfcbec62d50 100644 --- a/src/vs/workbench/contrib/search/test/electron-browser/textsearch.perf.integrationTest.ts +++ b/src/vs/workbench/contrib/search/test/electron-browser/textsearch.perf.integrationTest.ts @@ -43,6 +43,7 @@ import { TestContextService, TestTextResourcePropertiesService } from 'vs/workbe import { TestEnvironmentService } from 'vs/workbench/test/electron-browser/workbenchTestServices'; import { LanguageFeatureDebounceService } from 'vs/editor/common/services/languageFeatureDebounce'; import { LanguageFeaturesService } from 'vs/editor/common/services/languageFeaturesService'; +import { staticObservableValue } from 'vs/base/common/observableValue'; // declare var __dirname: string; @@ -182,7 +183,7 @@ suite.skip('TextSearch performance (integration)', () => { class TestTelemetryService implements ITelemetryService { public _serviceBrand: undefined; - public telemetryLevel = TelemetryLevel.USAGE; + public telemetryLevel = staticObservableValue(TelemetryLevel.USAGE); public sendErrorTelemetry = true; public events: any[] = []; diff --git a/src/vs/workbench/contrib/tags/electron-sandbox/workspaceTags.ts b/src/vs/workbench/contrib/tags/electron-sandbox/workspaceTags.ts index 395145ee8b4..8e263a87401 100644 --- a/src/vs/workbench/contrib/tags/electron-sandbox/workspaceTags.ts +++ b/src/vs/workbench/contrib/tags/electron-sandbox/workspaceTags.ts @@ -36,7 +36,7 @@ export class WorkspaceTags implements IWorkbenchContribution { @IProductService private readonly productService: IProductService, @INativeHostService private readonly nativeHostService: INativeHostService ) { - if (this.telemetryService.telemetryLevel === TelemetryLevel.USAGE) { + if (this.telemetryService.telemetryLevel.value === TelemetryLevel.USAGE) { this.report(); } } -- cgit v1.2.3 From e9c551906f44c50eef1e0246c3d9b876f4ed4084 Mon Sep 17 00:00:00 2001 From: Aman Khalid Date: Wed, 13 Apr 2022 13:41:36 -0400 Subject: testing: UI filter survives window reload * Close #143241: Testing UI filter survives window reload * Apply suggestions from review of PR #147344 Co-authored-by: Connor Peet Co-authored-by: Connor Peet --- src/vs/workbench/contrib/testing/browser/testingExplorerFilter.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/testing/browser/testingExplorerFilter.ts b/src/vs/workbench/contrib/testing/browser/testingExplorerFilter.ts index c32661787e3..4d1af363aa7 100644 --- a/src/vs/workbench/contrib/testing/browser/testingExplorerFilter.ts +++ b/src/vs/workbench/contrib/testing/browser/testingExplorerFilter.ts @@ -65,6 +65,11 @@ export class TestingExplorerFilter extends BaseActionViewItem { const wrapper = this.wrapper = dom.$('.testing-filter-wrapper'); container.appendChild(wrapper); + const history = this.history.get([]); + if (history.length) { + this.state.setText(history[history.length - 1]); + } + const input = this.input = this._register(this.instantiationService.createInstance(ContextScopedSuggestEnabledInputWithHistory, { id: 'testing.explorer.filter', ariaLabel: localize('testExplorerFilterLabel', "Filter text for tests in the explorer"), @@ -89,7 +94,7 @@ export class TestingExplorerFilter extends BaseActionViewItem { value: this.state.text.value, placeholderText: localize('testExplorerFilter', "Filter (e.g. text, !exclude, @tag)"), }, - history: this.history.get([]) + history })); this._register(attachSuggestEnabledInputBoxStyler(input, this.themeService)); -- cgit v1.2.3 From 5f9e98878e327fa7f77dd9ba4c28e872dcdbc3f4 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 13 Apr 2022 10:42:51 -0700 Subject: Better fix for #145996 --- src/vs/workbench/contrib/search/browser/searchView.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 7cec0e4491a..a587b74597b 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -8,7 +8,6 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import * as aria from 'vs/base/browser/ui/aria/aria'; import { MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; import { IIdentityProvider } from 'vs/base/browser/ui/list/list'; -import { Orientation } from 'vs/base/browser/ui/sash/sash'; import { ITreeContextMenuEvent, ITreeElement } from 'vs/base/browser/ui/tree/tree'; import { IAction } from 'vs/base/common/actions'; import { Delayer } from 'vs/base/common/async'; @@ -1065,10 +1064,10 @@ export class SearchView extends ViewPane { this.inputPatternExcludes.setWidth(this.size.width - 28 /* container margin */); this.inputPatternIncludes.setWidth(this.size.width - 28 /* container margin */); - const widgetHeight = dom.getTotalHeight(this.searchWidget.domNode); + + const widgetHeight = dom.getTotalHeight(this.searchWidgetsContainerElement); const messagesHeight = dom.getTotalHeight(this.messagesElement); - const margin = 25; - this.tree.layout(this.size.height - widgetHeight - messagesHeight - margin, this.size.width - 28); + this.tree.layout(this.size.height - widgetHeight - messagesHeight, this.size.width - 28); } protected override layoutBody(height: number, width: number): void { @@ -1285,7 +1284,7 @@ export class SearchView extends ViewPane { } if (!skipLayout && this.size) { - this.layout(this._orientation === Orientation.VERTICAL ? this.size.height : this.size.width); + this.reLayout(); } } -- cgit v1.2.3 From 4e697d42086b7535f90deecce642d4bc7fd8b0e7 Mon Sep 17 00:00:00 2001 From: aamunger Date: Wed, 13 Apr 2022 10:51:23 -0700 Subject: update output style when font family changes --- .../contrib/notebook/browser/notebookEditorWidget.ts | 6 +++++- .../workbench/contrib/notebook/common/notebookOptions.ts | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 93bcb157f61..40712d1eaa3 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -397,7 +397,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD this._updateForNotebookConfiguration(); } - if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.outputFontSize || e.markupFontSize || e.insertToolbarAlignment || e.outputLineHeight) { + if (e.fontFamily) { + this._generateFontInfo(); + } + + if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.outputFontSize || e.markupFontSize || e.fontFamily || e.outputFontFamily || e.insertToolbarAlignment || e.outputLineHeight) { this._styleElement?.remove(); this._createLayoutStyles(); this._webview?.updateOptions({ diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 2964a52df79..426871f84fa 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -89,6 +89,8 @@ export interface NotebookOptionsChangeEvent { readonly fontSize?: boolean; readonly outputFontSize?: boolean; readonly markupFontSize?: boolean; + readonly fontFamily?: boolean; + readonly outputFontFamily?: boolean; readonly editorOptionsCustomizations?: boolean; readonly interactiveWindowCollapseCodeCells?: boolean; readonly outputLineHeight?: boolean; @@ -235,11 +237,12 @@ export class NotebookOptions extends Disposable { const fontSize = e.affectsConfiguration('editor.fontSize'); const outputFontSize = e.affectsConfiguration(NotebookSetting.outputFontSize); const markupFontSize = e.affectsConfiguration(NotebookSetting.markupFontSize); + const fontFamily = e.affectsConfiguration('editor.fontFamily'); + const outputFontFamily = e.affectsConfiguration(NotebookSetting.outputFontFamily); const editorOptionsCustomizations = e.affectsConfiguration(NotebookSetting.cellEditorOptionsCustomizations); const interactiveWindowCollapseCodeCells = e.affectsConfiguration(NotebookSetting.interactiveWindowCollapseCodeCells); const outputLineHeight = e.affectsConfiguration(NotebookSetting.outputLineHeight); - if ( !cellStatusBarVisibility && !cellToolbarLocation @@ -256,6 +259,8 @@ export class NotebookOptions extends Disposable { && !fontSize && !outputFontSize && !markupFontSize + && !fontFamily + && !outputFontFamily && !editorOptionsCustomizations && !interactiveWindowCollapseCodeCells && !outputLineHeight) { @@ -328,6 +333,10 @@ export class NotebookOptions extends Disposable { configuration.markupFontSize = this.configurationService.getValue(NotebookSetting.markupFontSize); } + if (outputFontFamily) { + configuration.outputFontFamily = this.configurationService.getValue(NotebookSetting.outputFontFamily); + } + if (editorOptionsCustomizations) { configuration.editorOptionsCustomizations = this.configurationService.getValue(NotebookSetting.cellEditorOptionsCustomizations); } @@ -342,7 +351,6 @@ export class NotebookOptions extends Disposable { this._layoutConfiguration = Object.freeze(configuration); - // add new configuration to the event? // trigger event this._onDidChangeOptions.fire({ cellStatusBarVisibility, @@ -360,6 +368,8 @@ export class NotebookOptions extends Disposable { fontSize, outputFontSize, markupFontSize, + fontFamily, + outputFontFamily, editorOptionsCustomizations, interactiveWindowCollapseCodeCells, outputLineHeight -- cgit v1.2.3 From e764ae3c12787ba034fe5b3082e2d5f7ec5a6be5 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 13 Apr 2022 11:40:45 -0700 Subject: Check files instead of srcElement for dragging --- src/vs/workbench/contrib/webview/browser/pre/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/webview/browser/pre/main.js b/src/vs/workbench/contrib/webview/browser/pre/main.js index 8c91fdae9c9..18451a01bb8 100644 --- a/src/vs/workbench/contrib/webview/browser/pre/main.js +++ b/src/vs/workbench/contrib/webview/browser/pre/main.js @@ -1027,12 +1027,12 @@ onDomReady(() => { return; } - if (!e.dataTransfer) { + if (!e.dataTransfer || e.shiftKey) { return; } // Only handle drags from outside editor for now - if (e.target === contentWindow.document.documentElement) { + if (e.dataTransfer.items.length && Array.prototype.every.call(e.dataTransfer.items, item => item.kind === 'file')) { hostMessaging.postMessage('drag-start'); } }; -- cgit v1.2.3 From bb5c5cba0b33f10c191bdddca18ce25e41c87f36 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Wed, 13 Apr 2022 12:10:39 -0700 Subject: get overview ruler color to upate (#147116) --- .../contrib/terminal/browser/terminalFindWidget.ts | 20 +++++++++++++++++--- .../terminal/browser/xterm/decorationAddon.ts | 10 ++++++---- 2 files changed, 23 insertions(+), 7 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts b/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts index 6168afff93b..ffd839a6c18 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts @@ -10,6 +10,8 @@ import { FindReplaceState } from 'vs/editor/contrib/find/browser/findState'; import { ITerminalGroupService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; import { TerminalLocation } from 'vs/platform/terminal/common/terminal'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; export class TerminalFindWidget extends SimpleFindWidget { protected _findInputFocused: IContextKey; @@ -21,7 +23,9 @@ export class TerminalFindWidget extends SimpleFindWidget { @IContextViewService _contextViewService: IContextViewService, @IContextKeyService private readonly _contextKeyService: IContextKeyService, @ITerminalService private readonly _terminalService: ITerminalService, - @ITerminalGroupService private readonly _terminalGroupService: ITerminalGroupService + @ITerminalGroupService private readonly _terminalGroupService: ITerminalGroupService, + @IThemeService private readonly _themeService: IThemeService, + @IConfigurationService private readonly _configurationService: IConfigurationService ) { super(_contextViewService, _contextKeyService, findState, { showOptionButtons: true, showResultCount: true }); @@ -31,15 +35,25 @@ export class TerminalFindWidget extends SimpleFindWidget { this._findInputFocused = TerminalContextKeys.findInputFocus.bindTo(this._contextKeyService); this._findWidgetFocused = TerminalContextKeys.findFocus.bindTo(this._contextKeyService); this._findWidgetVisible = TerminalContextKeys.findVisible.bindTo(_contextKeyService); + this._register(this._themeService.onDidColorThemeChange(() => { + if (this._findWidgetVisible) { + this.find(true, true); + } + })); + this._register(this._configurationService.onDidChangeConfiguration((e) => { + if (e.affectsConfiguration('workbench.colorCustomizations') && this._findWidgetVisible) { + this.find(true, true); + } + })); } - find(previous: boolean) { + find(previous: boolean, update?: boolean) { const instance = this._terminalService.activeInstance; if (!instance) { return; } if (previous) { - instance.xterm?.findPrevious(this.inputValue, { regex: this._getRegexValue(), wholeWord: this._getWholeWordValue(), caseSensitive: this._getCaseSensitiveValue() }); + instance.xterm?.findPrevious(this.inputValue, { regex: this._getRegexValue(), wholeWord: this._getWholeWordValue(), caseSensitive: this._getCaseSensitiveValue(), incremental: update }); } else { instance.xterm?.findNext(this.inputValue, { regex: this._getRegexValue(), wholeWord: this._getWholeWordValue(), caseSensitive: this._getCaseSensitiveValue() }); } diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts b/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts index 40b75ff1352..3f07b624fa7 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts @@ -73,6 +73,8 @@ export class DecorationAddon extends Disposable implements ITerminalAddon { this._refreshStyles(); } else if (e.affectsConfiguration(TerminalSettingId.FontSize) || e.affectsConfiguration(TerminalSettingId.LineHeight)) { this.refreshLayouts(); + } else if (e.affectsConfiguration('workbench.colorCustomizations')) { + this._refreshStyles(true); } }); this._themeService.onDidColorThemeChange(() => this._refreshStyles(true)); @@ -94,10 +96,10 @@ export class DecorationAddon extends Disposable implements ITerminalAddon { } else { color = ''; } - if (decoration.decoration.overviewRulerOptions) { - decoration.decoration.overviewRulerOptions.color = color; - } else { - decoration.decoration.overviewRulerOptions = { color }; + if (decoration.decoration.options?.overviewRulerOptions) { + decoration.decoration.options.overviewRulerOptions.color = color; + } else if (decoration.decoration.options) { + decoration.decoration.options.overviewRulerOptions = { color }; } } } -- cgit v1.2.3 From ab0b7d2399b3be9c30d811d5dc290f068f70cd3f Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 13 Apr 2022 15:49:25 -0700 Subject: Eliminate duplicate openEditor call. Fix #136829 --- src/vs/workbench/contrib/debug/browser/callStackView.ts | 14 ++++++++------ src/vs/workbench/contrib/debug/browser/debugCommands.ts | 2 +- src/vs/workbench/contrib/debug/browser/debugService.ts | 6 +++--- src/vs/workbench/contrib/debug/browser/debugSession.ts | 2 +- src/vs/workbench/contrib/debug/browser/repl.ts | 2 +- src/vs/workbench/contrib/debug/common/debug.ts | 2 +- 6 files changed, 15 insertions(+), 13 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/callStackView.ts b/src/vs/workbench/contrib/debug/browser/callStackView.ts index b23aa7e10af..6a045d3ce23 100644 --- a/src/vs/workbench/contrib/debug/browser/callStackView.ts +++ b/src/vs/workbench/contrib/debug/browser/callStackView.ts @@ -47,7 +47,6 @@ import { createDisconnectMenuItemAction } from 'vs/workbench/contrib/debug/brows import { CALLSTACK_VIEW_ID, CONTEXT_CALLSTACK_ITEM_STOPPED, CONTEXT_CALLSTACK_ITEM_TYPE, CONTEXT_CALLSTACK_SESSION_HAS_ONE_THREAD, CONTEXT_CALLSTACK_SESSION_IS_ATTACH, CONTEXT_DEBUG_STATE, CONTEXT_STACK_FRAME_SUPPORTS_RESTART, getStateLabel, IDebugModel, IDebugService, IDebugSession, IRawStoppedDetails, IStackFrame, IThread, State } from 'vs/workbench/contrib/debug/common/debug'; import { StackFrame, Thread, ThreadAndSessionIds } from 'vs/workbench/contrib/debug/common/debugModel'; import { isSessionAttach } from 'vs/workbench/contrib/debug/common/debugUtils'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; const $ = dom.$; @@ -150,7 +149,6 @@ export class CallStackView extends ViewPane { @IKeybindingService keybindingService: IKeybindingService, @IInstantiationService instantiationService: IInstantiationService, @IViewDescriptorService viewDescriptorService: IViewDescriptorService, - @IEditorService private readonly editorService: IEditorService, @IConfigurationService configurationService: IConfigurationService, @IContextKeyService contextKeyService: IContextKeyService, @IOpenerService openerService: IOpenerService, @@ -287,10 +285,10 @@ export class CallStackView extends ViewPane { return; } - const focusStackFrame = (stackFrame: IStackFrame | undefined, thread: IThread | undefined, session: IDebugSession) => { + const focusStackFrame = (stackFrame: IStackFrame | undefined, thread: IThread | undefined, session: IDebugSession, options: { explicit?: boolean; preserveFocus?: boolean; sideBySide?: boolean; pinned?: boolean } = {}) => { this.ignoreFocusStackFrameEvent = true; try { - this.debugService.focusStackFrame(stackFrame, thread, session, true); + this.debugService.focusStackFrame(stackFrame, thread, session, { ...options, ...{ explicit: true } }); } finally { this.ignoreFocusStackFrameEvent = false; } @@ -298,8 +296,12 @@ export class CallStackView extends ViewPane { const element = e.element; if (element instanceof StackFrame) { - focusStackFrame(element, element.thread, element.thread.session); - element.openInEditor(this.editorService, e.editorOptions.preserveFocus, e.sideBySide, e.editorOptions.pinned); + const opts = { + preserveFocus: e.editorOptions.preserveFocus, + sideBySide: e.sideBySide, + pinned: e.editorOptions.pinned + }; + focusStackFrame(element, element.thread, element.thread.session, opts); } if (element instanceof Thread) { focusStackFrame(undefined, element, element.session); diff --git a/src/vs/workbench/contrib/debug/browser/debugCommands.ts b/src/vs/workbench/contrib/debug/browser/debugCommands.ts index 5f6e41bf0c6..3042792f8e8 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCommands.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCommands.ts @@ -406,7 +406,7 @@ CommandsRegistry.registerCommand({ if (stoppedChildSession && session.state !== State.Stopped) { session = stoppedChildSession; } - await debugService.focusStackFrame(undefined, undefined, session, true); + await debugService.focusStackFrame(undefined, undefined, session, { explicit: true }); const stackFrame = debugService.getViewModel().focusedStackFrame; if (stackFrame) { await stackFrame.openInEditor(editorService, true); diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index d2665b688bd..224b72fe4fa 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -852,11 +852,11 @@ export class DebugService implements IDebugService { //---- focus management - async focusStackFrame(_stackFrame: IStackFrame | undefined, _thread?: IThread, _session?: IDebugSession, explicit?: boolean): Promise { + async focusStackFrame(_stackFrame: IStackFrame | undefined, _thread?: IThread, _session?: IDebugSession, options?: { explicit?: boolean; preserveFocus?: boolean; sideBySide?: boolean; pinned?: boolean }): Promise { const { stackFrame, thread, session } = getStackFrameThreadAndSessionToFocus(this.model, _stackFrame, _thread, _session); if (stackFrame) { - const editor = await stackFrame.openInEditor(this.editorService, true); + const editor = await stackFrame.openInEditor(this.editorService, options?.preserveFocus ?? true, options?.sideBySide, options?.pinned); if (editor) { if (editor.input === DisassemblyViewInput.instance) { // Go to address is invoked via setFocus @@ -880,7 +880,7 @@ export class DebugService implements IDebugService { this.debugType.reset(); } - this.viewModel.setFocus(stackFrame, thread, session, !!explicit); + this.viewModel.setFocus(stackFrame, thread, session, !!options?.explicit); } //---- watches diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index 0bd109a80d9..0e8671611e0 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -1004,7 +1004,7 @@ export class DebugSession implements IDebugSession { this.passFocusScheduler.cancel(); if (focusedThread && event.body.threadId === focusedThread.threadId) { // De-focus the thread in case it was focused - this.debugService.focusStackFrame(undefined, undefined, viewModel.focusedSession, false); + this.debugService.focusStackFrame(undefined, undefined, viewModel.focusedSession, { explicit: false }); } } })); diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index cc2a06f698e..d171c967d4f 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -895,7 +895,7 @@ registerAction2(class extends ViewAction { session = stopppedChildSession; } } - await debugService.focusStackFrame(undefined, undefined, session, true); + await debugService.focusStackFrame(undefined, undefined, session, { explicit: true }); } // Need to select the session in the view since the focussed session might not have changed await view.selectSession(session); diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index b8e653916c5..fb0445b670e 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -951,7 +951,7 @@ export interface IDebugService { /** * Sets the focused stack frame and evaluates all expressions against the newly focused stack frame, */ - focusStackFrame(focusedStackFrame: IStackFrame | undefined, thread?: IThread, session?: IDebugSession, explicit?: boolean): Promise; + focusStackFrame(focusedStackFrame: IStackFrame | undefined, thread?: IThread, session?: IDebugSession, options?: { explicit?: boolean; preserveFocus?: boolean; sideBySide?: boolean; pinned?: boolean }): Promise; /** * Returns true if breakpoints can be set for a given editor model. Depends on mode. -- cgit v1.2.3 From ce80e8b243df25a530ea10d39970c110e935fa5f Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 13 Apr 2022 14:02:15 -0700 Subject: Fix drag from explorer into notebook --- .../contrib/notebook/browser/view/renderers/backLayerWebView.ts | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index d5ad9679436..f5b40f97620 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -41,6 +41,7 @@ import { INotebookKernel } from 'vs/workbench/contrib/notebook/common/notebookKe import { IScopedRendererMessaging } from 'vs/workbench/contrib/notebook/common/notebookRendererMessagingService'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IWebviewElement, IWebviewService, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview'; +import { WebviewWindowDragMonitor } from 'vs/workbench/contrib/webview/browser/webviewWindowDragMonitor'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { FromWebviewMessage, IAckOutputHeight, IClickedDataUrlMessage, ICodeBlockHighlightRequest, IContentWidgetTopRequest, IControllerPreload, ICreationContent, ICreationRequestMessage, IFindMatch, IMarkupCellInitialization, ToWebviewMessage } from './webviewMessages'; @@ -527,6 +528,8 @@ var requirejs = (function() { this.webview.mountTo(this.element); this._register(this.webview); + this._register(new WebviewWindowDragMonitor(() => this.webview)); + this._register(this.webview.onDidClickLink(link => { if (this._disposed) { return; -- cgit v1.2.3 From bf02dd3453a4414037e2ee1f67f994377b21a8ce Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 13 Apr 2022 16:39:22 -0700 Subject: Formatting --- src/vs/workbench/contrib/webview/browser/pre/main.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/webview/browser/pre/main.js b/src/vs/workbench/contrib/webview/browser/pre/main.js index 18451a01bb8..0ac6415cf3d 100644 --- a/src/vs/workbench/contrib/webview/browser/pre/main.js +++ b/src/vs/workbench/contrib/webview/browser/pre/main.js @@ -368,16 +368,14 @@ const unloadMonitor = new class { } switch (this.confirmBeforeClose) { - case 'always': - { - event.preventDefault(); - event.returnValue = ''; - return ''; - } - case 'never': - { - break; - } + case 'always': { + event.preventDefault(); + event.returnValue = ''; + return ''; + } + case 'never': { + break; + } case 'keyboardOnly': default: { if (this.isModifierKeyDown) { -- cgit v1.2.3 From c485c00298d3341d16539554ee66f6dace15811f Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 13 Apr 2022 16:49:55 -0700 Subject: Start forwarding events from webview even before contents have loaded Fixes #144797 --- .../workbench/contrib/webview/browser/pre/main.js | 40 +++++++++++++--------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/webview/browser/pre/main.js b/src/vs/workbench/contrib/webview/browser/pre/main.js index 0ac6415cf3d..d2c57f4aa10 100644 --- a/src/vs/workbench/contrib/webview/browser/pre/main.js +++ b/src/vs/workbench/contrib/webview/browser/pre/main.js @@ -678,6 +678,22 @@ const handleInnerScroll = (event) => { }); }; +function handleInnerDragStartEvent(/** @type {DragEvent} */ e) { + if (e.defaultPrevented) { + // Extension code has already handled this event + return; + } + + if (!e.dataTransfer || e.shiftKey) { + return; + } + + // Only handle drags from outside editor for now + if (e.dataTransfer.items.length && Array.prototype.every.call(e.dataTransfer.items, item => item.kind === 'file')) { + hostMessaging.postMessage('drag-start'); + } +} + /** * @param {() => void} callback */ @@ -1019,23 +1035,8 @@ onDomReady(() => { }); }); - const dragHandler = (/** @type {DragEvent} */ e) => { - if (e.defaultPrevented) { - // Extension code has already handled this event - return; - } - - if (!e.dataTransfer || e.shiftKey) { - return; - } - - // Only handle drags from outside editor for now - if (e.dataTransfer.items.length && Array.prototype.every.call(e.dataTransfer.items, item => item.kind === 'file')) { - hostMessaging.postMessage('drag-start'); - } - }; - contentWindow.addEventListener('dragenter', dragHandler); - contentWindow.addEventListener('dragover', dragHandler); + contentWindow.addEventListener('dragenter', handleInnerDragStartEvent); + contentWindow.addEventListener('dragover', handleInnerDragStartEvent); unloadMonitor.onIframeLoaded(newFrame); } @@ -1123,5 +1124,10 @@ onDomReady(() => { } }; + // Also forward events before the contents of the webview have loaded + window.addEventListener('keydown', handleInnerKeydown); + window.addEventListener('dragenter', handleInnerDragStartEvent); + window.addEventListener('dragover', handleInnerDragStartEvent); + hostMessaging.signalReady(); }); -- cgit v1.2.3 From f64927b52f894cdb1c0643f2dcfe8c75b1de03f7 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 13 Apr 2022 17:18:39 -0700 Subject: Use a real button for lazy variables. Fix #143602 --- src/vs/workbench/contrib/debug/browser/baseDebugView.ts | 3 ++- src/vs/workbench/contrib/debug/browser/debugColors.ts | 7 ++++++- .../contrib/debug/browser/media/debug.contribution.css | 13 +++++++------ 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/baseDebugView.ts b/src/vs/workbench/contrib/debug/browser/baseDebugView.ts index acdf0b9005d..89f39336b31 100644 --- a/src/vs/workbench/contrib/debug/browser/baseDebugView.ts +++ b/src/vs/workbench/contrib/debug/browser/baseDebugView.ts @@ -9,6 +9,7 @@ import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { HighlightedLabel, IHighlight } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; import { IInputValidationOptions, InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; import { ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree'; +import { Codicon } from 'vs/base/common/codicons'; import { createMatches, FuzzyScore } from 'vs/base/common/filters'; import { once } from 'vs/base/common/functional'; import { KeyCode } from 'vs/base/common/keyCodes'; @@ -158,7 +159,7 @@ export abstract class AbstractExpressionsRenderer implements ITreeRenderer Date: Thu, 14 Apr 2022 09:00:13 -0700 Subject: try closing editor before running command --- .../contrib/codeEditor/browser/untitledTextEditorHint.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts index 4f2918ddd94..f4fd71ba538 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts @@ -19,6 +19,7 @@ import { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { EventType as GestureEventType, Gesture } from 'vs/base/browser/touch'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; const $ = dom.$; @@ -32,6 +33,7 @@ export class UntitledTextEditorHintContribution implements IEditorContribution { constructor( private editor: ICodeEditor, + @IEditorGroupsService private readonly editorGroupsService: IEditorGroupsService, @ICommandService private readonly commandService: ICommandService, @IConfigurationService private readonly configurationService: IConfigurationService, @IKeybindingService private readonly keybindingService: IKeybindingService, @@ -53,7 +55,7 @@ export class UntitledTextEditorHintContribution implements IEditorContribution { const model = this.editor.getModel(); if (model && model.uri.scheme === Schemas.untitled && model.getLanguageId() === PLAINTEXT_LANGUAGE_ID && configValue === 'text') { - this.untitledTextHintContentWidget = new UntitledTextEditorHintContentWidget(this.editor, this.commandService, this.configurationService, this.keybindingService); + this.untitledTextHintContentWidget = new UntitledTextEditorHintContentWidget(this.editor, this.editorGroupsService, this.commandService, this.configurationService, this.keybindingService); } } @@ -72,6 +74,7 @@ class UntitledTextEditorHintContentWidget implements IContentWidget { constructor( private readonly editor: ICodeEditor, + private readonly editorGroupsService: IEditorGroupsService, private readonly commandService: ICommandService, private readonly configurationService: IConfigurationService, private readonly keybindingService: IKeybindingService, @@ -153,6 +156,13 @@ class UntitledTextEditorHintContentWidget implements IContentWidget { const chooseEditorOnClickOrTap = async (e: MouseEvent) => { e.stopPropagation(); + const activeEditorInput = this.editorGroupsService.activeGroup.activeEditor; + + // Close the active editor as long as it is untitled (swap the editors out) + if (activeEditorInput !== null && activeEditorInput.resource?.scheme === Schemas.untitled) { + this.editorGroupsService.activeGroup.closeEditor(activeEditorInput, { preserveFocus: true }); + } + await this.commandService.executeCommand('welcome.showNewFileEntries', { from: 'hint' }); }; this.toDispose.push(dom.addDisposableListener(chooseEditor, 'click', chooseEditorOnClickOrTap)); -- cgit v1.2.3 From 6c759218a82e65acd4a85e42d802ab5f4cefed53 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 14 Apr 2022 09:03:25 -0800 Subject: Scope drop into editor to specific editors (#147425) * Scope drop into editor to specific editors As part of #142990, I added support for dropping dragged files from the desktop into an editor by holding shift. To help users discover this feature, we also show a prompt in the editor overlay when dragging However there are a number of editor types that don't actually support drops. The welcome view for example. Readonly editors should also not support dropping. In those cases, it is confusing the show the `hold shift to drop into editor` prompt This change adds a new editor capability (`CanDropIntoEditor`) which signals that the editor does support dropping into the editor. I then enable this new capability on writable files, webviews, and notebooks * Making suggested changes --- src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts | 2 ++ src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index 119a41914f1..81dfae861af 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -124,6 +124,8 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput { public override get capabilities(): EditorInputCapabilities { let capabilities = EditorInputCapabilities.None; + capabilities |= EditorInputCapabilities.CanDropIntoEditor; + if (!this.customEditorService.getCustomEditorCapabilities(this.viewType)?.supportsMultipleEditorsPerDocument) { capabilities |= EditorInputCapabilities.Singleton; } diff --git a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput.ts b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput.ts index 1caa0e68f25..63e3f1cc124 100644 --- a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput.ts +++ b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput.ts @@ -23,7 +23,7 @@ export class WebviewInput extends EditorInput { } public override get capabilities(): EditorInputCapabilities { - return EditorInputCapabilities.Readonly | EditorInputCapabilities.Singleton; + return EditorInputCapabilities.Readonly | EditorInputCapabilities.Singleton | EditorInputCapabilities.CanDropIntoEditor; } private _name: string; -- cgit v1.2.3 From f2e6fe3b863d076a36a69b410ad29cf6729cf777 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 14 Apr 2022 10:10:38 -0700 Subject: Show value on lazy variables after icon. Fix #135147 --- src/vs/workbench/contrib/debug/browser/baseDebugView.ts | 2 +- src/vs/workbench/contrib/debug/browser/media/debug.contribution.css | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/baseDebugView.ts b/src/vs/workbench/contrib/debug/browser/baseDebugView.ts index 89f39336b31..e97efddd569 100644 --- a/src/vs/workbench/contrib/debug/browser/baseDebugView.ts +++ b/src/vs/workbench/contrib/debug/browser/baseDebugView.ts @@ -157,9 +157,9 @@ export abstract class AbstractExpressionsRenderer implements ITreeRenderer Date: Thu, 14 Apr 2022 10:48:33 -0700 Subject: Fixing capabilities for drop into - Copy logic into notebook and file editor since they override `capabilities` from `AbstractResourceEditorInput` - Remove unneeded override --- src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts | 4 ++++ src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts index 630cd3a523a..b6317eb2dd7 100644 --- a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts +++ b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts @@ -60,6 +60,10 @@ export class FileEditorInput extends AbstractTextResourceEditorInput implements } } + if (!(capabilities & EditorInputCapabilities.Readonly)) { + capabilities |= EditorInputCapabilities.CanDropIntoEditor; + } + return capabilities; } diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts index cffd2b0362d..6e28efdd088 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts @@ -102,6 +102,10 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { } } + if (!(capabilities & EditorInputCapabilities.Readonly)) { + capabilities |= EditorInputCapabilities.CanDropIntoEditor; + } + return capabilities; } -- cgit v1.2.3 From f20a0f2a10769b0c3eb5da43ba75c12ab44d0d43 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 14 Apr 2022 11:10:48 -0700 Subject: extract exthost/mainthread proxy kernels. --- .../notebook/browser/notebookKernelServiceImpl.ts | 28 +--------------------- .../notebook/browser/view/cellParts/cellOutput.ts | 9 ++++--- .../notebook/common/notebookKernelService.ts | 4 ++-- 3 files changed, 7 insertions(+), 34 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts index 09e75953d84..1f2e2e72032 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts @@ -6,7 +6,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { INotebookTextModel } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { INotebookKernel, ISelectedNotebooksChangeEvent, INotebookKernelMatchResult, INotebookKernelService, INotebookTextModelLike, INotebookProxyKernel } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernel, ISelectedNotebooksChangeEvent, INotebookKernelMatchResult, INotebookKernelService, INotebookTextModelLike } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { LRUCache, ResourceMap } from 'vs/base/common/map'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { URI } from 'vs/base/common/uri'; @@ -164,32 +164,6 @@ export class NotebookKernelService extends Disposable implements INotebookKernel }); } - registerProxyKernel(kernel: INotebookProxyKernel): IDisposable { - if (this._kernels.has(kernel.id)) { - throw new Error(`NOTEBOOK CONTROLLER with id '${kernel.id}' already exists`); - } - - this._kernels.set(kernel.id, new KernelInfo(kernel)); - this._onDidAddKernel.fire(kernel); - - // auto associate the new kernel to existing notebooks it was - // associated to in the past. - for (const notebook of this._notebookService.getNotebookTextModels()) { - this._tryAutoBindNotebook(notebook, kernel); - } - - return toDisposable(() => { - if (this._kernels.delete(kernel.id)) { - this._onDidRemoveKernel.fire(kernel); - } - for (const [key, candidate] of Array.from(this._notebookBindings)) { - if (candidate === kernel.id) { - this._onDidChangeNotebookKernelBinding.fire({ notebook: NotebookTextModelLikeId.obj(key).uri, oldKernel: kernel.id, newKernel: undefined }); - } - } - }); - } - getMatchingKernel(notebook: INotebookTextModelLike): INotebookKernelMatchResult { // all applicable kernels diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts index 7ed12d9bb09..7306836ac30 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts @@ -31,7 +31,7 @@ import { CodeCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/vi import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { CellUri, IOrderedMimeType, NotebookCellOutputsSplice, RENDERER_NOT_AVAILABLE } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { INotebookKernel, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernel } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; @@ -127,8 +127,7 @@ export class CellOutputElement extends Disposable { this.notebookEditor.hasModel() && this.innerContainer && this.renderResult && - this.renderResult.type === RenderOutputType.Extension && - this.notebookEditor.activeKernel?.type === NotebookKernelType.Resolved + this.renderResult.type === RenderOutputType.Extension ) { // Output rendered by extension renderer got an update const [mimeTypes, pick] = this.output.resolveMimeTypes(this.notebookEditor.textModel, this.notebookEditor.activeKernel?.preloadProvides); @@ -192,7 +191,7 @@ export class CellOutputElement extends Disposable { const notebookTextModel = this.notebookEditor.textModel; - const [mimeTypes, pick] = this.output.resolveMimeTypes(notebookTextModel, this.notebookEditor.activeKernel?.type === NotebookKernelType.Resolved ? this.notebookEditor.activeKernel?.preloadProvides : undefined); + const [mimeTypes, pick] = this.output.resolveMimeTypes(notebookTextModel, this.notebookEditor.activeKernel?.preloadProvides); if (!mimeTypes.find(mimeType => mimeType.isTrusted) || mimeTypes.length === 0) { this.viewCell.updateOutputHeight(index, 0, 'CellOutputElement#noMimeType'); @@ -300,7 +299,7 @@ export class CellOutputElement extends Disposable { } private async _pickActiveMimeTypeRenderer(outputItemDiv: HTMLElement, notebookTextModel: NotebookTextModel, kernel: INotebookKernel | undefined, viewModel: ICellOutputViewModel) { - const [mimeTypes, currIndex] = viewModel.resolveMimeTypes(notebookTextModel, kernel?.type === NotebookKernelType.Resolved ? kernel?.preloadProvides : undefined); + const [mimeTypes, currIndex] = viewModel.resolveMimeTypes(notebookTextModel, kernel?.preloadProvides); const items: IMimeTypeRenderer[] = []; const unsupportedItems: IMimeTypeRenderer[] = []; diff --git a/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts b/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts index 19ee2cf2b66..4f5304600b0 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts @@ -74,6 +74,7 @@ export interface INotebookProxyKernel { readonly id: string; readonly viewType: string; readonly extension: ExtensionIdentifier; + readonly preloadProvides: string[]; readonly onDidChange: Event>; label: string; description?: string; @@ -98,8 +99,7 @@ export interface INotebookKernelService { readonly onDidChangeSelectedNotebooks: Event; readonly onDidChangeNotebookAffinity: Event; - registerKernel(kernel: IResolvedNotebookKernel): IDisposable; - registerProxyKernel(proxyKernel: INotebookProxyKernel): IDisposable; + registerKernel(kernel: INotebookKernel): IDisposable; getMatchingKernel(notebook: INotebookTextModelLike): INotebookKernelMatchResult; -- cgit v1.2.3 From 280050dba576740f0350245409d147aa2c84aa94 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 14 Apr 2022 11:19:50 -0700 Subject: :lipstick: --- .../workbench/contrib/notebook/browser/notebookEditorWidget.ts | 10 +--------- .../notebook/browser/viewParts/notebookKernelActionViewItem.ts | 6 +++--- 2 files changed, 4 insertions(+), 12 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 96912b1f10c..40712d1eaa3 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -76,7 +76,7 @@ import { CellKind, INotebookSearchOptions, SelectionStateType } from 'vs/workben import { NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; import { INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; -import { INotebookKernelService, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { NotebookOptions, OutputInnerContainerTopPadding } from 'vs/workbench/contrib/notebook/common/notebookOptions'; import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance'; import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; @@ -2112,14 +2112,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD return; } const { selected } = this.notebookKernelService.getMatchingKernel(this.textModel); - if (!selected) { - return; - } - - if (selected.type === NotebookKernelType.Proxy) { - return; - } - if (!this._webview?.isResolved()) { await this._resolveWebview(); } diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts index 41e1ec74773..a4060aaa62e 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts @@ -6,14 +6,14 @@ import 'vs/css!./notebookKernelActionViewItem'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { Action, IAction } from 'vs/base/common/actions'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { localize } from 'vs/nls'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { selectKernelIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; -import { INotebookKernelMatchResult, INotebookKernelService, ProxyKernelState } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernelMatchResult, INotebookKernelService, NotebookKernelType, ProxyKernelState } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { Event } from 'vs/base/common/event'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { DisposableStore } from 'vs/base/common/lifecycle'; export class NotebooKernelActionViewItem extends ActionViewItem { @@ -77,7 +77,7 @@ export class NotebooKernelActionViewItem extends ActionViewItem { // special UI for selected kernel? } - if ('resolveKernel' in selectedOrSuggested) { + if (selectedOrSuggested.type === NotebookKernelType.Proxy) { if (selectedOrSuggested.connectionState === ProxyKernelState.Initializing) { this._action.label = localize('initializing', "Initializing..."); } else { -- cgit v1.2.3 From 3c9c0e36cd536805b8d376d1f1e09b6db0c53522 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 6 Apr 2022 10:39:47 -0700 Subject: Use SELECT_KERNEL_ID other than string literal --- .../notebook/browser/contrib/editorStatusBar/editorStatusBar.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts index cb7ab0f8586..83b35ce916d 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts @@ -38,7 +38,7 @@ import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeat registerAction2(class extends Action2 { constructor() { super({ - id: '_notebook.selectKernel', + id: SELECT_KERNEL_ID, category: NOTEBOOK_ACTIONS_CATEGORY, title: { value: nls.localize('notebookActions.selectKernel', "Select Notebook Kernel"), original: 'Select Notebook Kernel' }, // precondition: NOTEBOOK_IS_ACTIVE_EDITOR, @@ -381,7 +381,7 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution { tooltip: isSuggested ? nls.localize('tooltop', "{0} (suggestion)", tooltip) : tooltip, command: SELECT_KERNEL_ID, }, - '_notebook.selectKernel', + SELECT_KERNEL_ID, StatusbarAlignment.RIGHT, 10 )); @@ -399,7 +399,7 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution { command: SELECT_KERNEL_ID, backgroundColor: { id: 'statusBarItem.prominentBackground' } }, - '_notebook.selectKernel', + SELECT_KERNEL_ID, StatusbarAlignment.RIGHT, 10 )); -- cgit v1.2.3 From 9fe5271dac26ed9ebdf6b2ae24016d8cfb8aa9fc Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 14 Apr 2022 11:46:04 -0700 Subject: tweak install from marketplace entry on kernel quickpick. --- .../contrib/editorStatusBar/editorStatusBar.ts | 22 ++++++++++------------ .../browser/view/renderers/backLayerWebView.ts | 6 +++--- 2 files changed, 13 insertions(+), 15 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts index c93c6b17ba2..920669194f6 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts @@ -28,7 +28,7 @@ import { NotebookEditorWidget } from 'vs/workbench/contrib/notebook/browser/note import { configureKernelIcon, selectKernelIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { INotebookKernel, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernel, INotebookKernelService, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; @@ -182,12 +182,7 @@ registerAction2(class extends Action2 { return res; } const quickPickItems: QuickPickInput[] = []; - if (!all.length) { - quickPickItems.push({ - id: 'install', - label: nls.localize('installKernels', "Install kernels from the marketplace"), - }); - } else { + if (all.length) { // Always display suggested kernels on the top. if (suggestions.length) { quickPickItems.push({ @@ -197,11 +192,6 @@ registerAction2(class extends Action2 { quickPickItems.push(...suggestions.map(toQuickPick)); } - quickPickItems.push({ - id: 'install', - label: nls.localize('installKernels', "Install kernels from the marketplace"), - }); - // Next display all of the kernels grouped by categories or extensions. // If we don't have a kind, always display those at the bottom. const picks = all.filter(item => !suggestions.includes(item)).map(toQuickPick); @@ -215,6 +205,14 @@ registerAction2(class extends Action2 { }); } + if (!all.find(item => item.type === NotebookKernelType.Resolved)) { + // there is no resolved kernel, show the install from marketplace + quickPickItems.push({ + id: 'install', + label: nls.localize('installKernels', "Install kernels from the marketplace"), + }); + } + const pick = await quickInputService.pick(quickPickItems, { placeHolder: selected ? nls.localize('prompt.placeholder.change', "Change kernel for '{0}'", labelService.getUriLabel(notebook.uri, { relative: true })) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index f7a64b5b596..a7145c9ffc9 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -904,7 +904,7 @@ var requirejs = (function() { } this._preloadsCache.clear(); - if (this._currentKernel && this._currentKernel.type === NotebookKernelType.Resolved) { + if (this._currentKernel?.type === NotebookKernelType.Resolved) { this._updatePreloadsFromKernel(this._currentKernel); } @@ -1401,7 +1401,7 @@ var requirejs = (function() { const previousKernel = this._currentKernel; this._currentKernel = kernel; - if (previousKernel && previousKernel.type === NotebookKernelType.Resolved && previousKernel.preloadUris.length > 0) { + if (previousKernel?.type === NotebookKernelType.Resolved && previousKernel.preloadUris.length > 0) { this.webview?.reload(); // preloads will be restored after reload } else if (kernel?.type === NotebookKernelType.Resolved) { this._updatePreloadsFromKernel(kernel); @@ -1434,7 +1434,7 @@ var requirejs = (function() { const mixedResourceRoots = [ ...(this.localResourceRootsCache || []), - ...(this._currentKernel && this._currentKernel.type === NotebookKernelType.Resolved ? [this._currentKernel.localResourceRoot] : []), + ...(this._currentKernel?.type === NotebookKernelType.Resolved ? [this._currentKernel.localResourceRoot] : []), ]; this.webview.localResourcesRoot = mixedResourceRoots; -- cgit v1.2.3 From 7195f05a16a5e92147354c4ebfd040b1eb60d162 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 14 Apr 2022 12:05:38 -0700 Subject: allow notebook cancel execution with proxy kernel. --- .../browser/notebookExecutionServiceImpl.ts | 25 ++++++++++++++++------ .../viewParts/notebookKernelActionViewItem.ts | 3 +-- 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts index b8877a553a2..2d4fe4cebe0 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts @@ -4,6 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { IDisposable } from 'vs/base/common/lifecycle'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { ILogService } from 'vs/platform/log/common/log'; import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust'; @@ -14,8 +16,9 @@ import { INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/ import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; import { INotebookKernelService, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; -export class NotebookExecutionService implements INotebookExecutionService { +export class NotebookExecutionService implements INotebookExecutionService, IDisposable { declare _serviceBrand: undefined; + private _activeProxyKernelExecutionToken: CancellationTokenSource | undefined; constructor( @ICommandService private readonly _commandService: ICommandService, @@ -46,9 +49,10 @@ export class NotebookExecutionService implements INotebookExecutionService { } if (kernel.type === NotebookKernelType.Proxy) { - // we should actually resolve the kernel + this._activeProxyKernelExecutionToken?.dispose(true); + const tokenSource = this._activeProxyKernelExecutionToken = new CancellationTokenSource(); const resolved = await kernel.resolveKernel(notebook.uri); - let kernels = this._notebookKernelService.getMatchingKernel(notebook); + const kernels = this._notebookKernelService.getMatchingKernel(notebook); const newlyMatchedKernel = kernels.all.find(k => k.id === resolved); if (!newlyMatchedKernel) { @@ -56,6 +60,11 @@ export class NotebookExecutionService implements INotebookExecutionService { } kernel = newlyMatchedKernel; + if (tokenSource.token.isCancellationRequested) { + // execution was cancelled but we still need to update the active kernel + this._notebookKernelService.selectKernelForNotebook(kernel, notebook); + return; + } } if (kernel.type === NotebookKernelType.Proxy) { @@ -93,15 +102,19 @@ export class NotebookExecutionService implements INotebookExecutionService { const kernel = this._notebookKernelService.getSelectedOrSuggestedKernel(notebook); if (kernel) { if (kernel.type === NotebookKernelType.Proxy) { - // we should handle cancelling proxy kernel too - return; + this._activeProxyKernelExecutionToken?.dispose(true); + } else { + await kernel.cancelNotebookCellExecution(notebook.uri, cellsArr); } - await kernel.cancelNotebookCellExecution(notebook.uri, cellsArr); } } async cancelNotebookCells(notebook: INotebookTextModel, cells: Iterable): Promise { this.cancelNotebookCellHandles(notebook, Array.from(cells, cell => cell.handle)); } + + dispose() { + this._activeProxyKernelExecutionToken?.dispose(true); + } } diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts index a4060aaa62e..ed9098ad49d 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts @@ -68,7 +68,7 @@ export class NotebooKernelActionViewItem extends ActionViewItem { private _updateActionFromKernelInfo(info: INotebookKernelMatchResult): void { this._kernelDisposable.clear(); this._action.enabled = true; - const selectedOrSuggested = info.selected ?? ((info.all.length === 1 && info.suggestions.length === 1 && !('resolveKernel' in info.suggestions[0])) ? info.suggestions[0] : undefined); + const selectedOrSuggested = info.selected ?? ((info.all.length === 1 && info.suggestions.length === 1 && info.suggestions[0].type === NotebookKernelType.Resolved) ? info.suggestions[0] : undefined); if (selectedOrSuggested) { // selected or suggested kernel this._action.label = selectedOrSuggested.label; @@ -94,7 +94,6 @@ export class NotebooKernelActionViewItem extends ActionViewItem { } })); } - } else { // many kernels or no kernels this._action.label = localize('select', "Select Kernel"); -- cgit v1.2.3 From c3d09dbabf4a9dac6c2a8077a0f3744fd55beb95 Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Thu, 14 Apr 2022 13:48:06 -0700 Subject: Polish language filter button implementation (#147461) --- .../browser/suggestEnabledInput/suggestEnabledInput.ts | 2 +- .../contrib/preferences/browser/settingsEditor2.ts | 6 +++--- .../contrib/preferences/browser/settingsSearchMenu.ts | 13 ++++++++----- 3 files changed, 12 insertions(+), 9 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput.ts b/src/vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput.ts index 138f276bff7..9cadf75ecce 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput.ts @@ -111,7 +111,7 @@ export class SuggestEnabledInput extends Widget implements IThemable { private readonly _onInputDidChange = new Emitter(); readonly onInputDidChange: Event = this._onInputDidChange.event; - protected readonly inputWidget: CodeEditorWidget; + readonly inputWidget: CodeEditorWidget; private readonly inputModel: ITextModel; protected stylingContainer: HTMLDivElement; private placeholderText: HTMLDivElement; diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 392abf569fe..d71c2e6acec 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -604,9 +604,9 @@ export class SettingsEditor2 extends EditorPane { const actionBar = this._register(new ActionBar(this.controlsElement, { animated: false, - actionViewItemProvider: (_action) => { - if (_action.id === filterAction.id) { - return this.instantiationService.createInstance(SettingsSearchFilterDropdownMenuActionViewItem, _action, this.actionRunner, this.searchWidget); + actionViewItemProvider: (action) => { + if (action.id === filterAction.id) { + return this.instantiationService.createInstance(SettingsSearchFilterDropdownMenuActionViewItem, action, this.actionRunner, this.searchWidget); } return undefined; } diff --git a/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts b/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts index d739a8752f5..b8b09ebc8ff 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts @@ -6,19 +6,20 @@ import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem'; import { IAction, IActionRunner } from 'vs/base/common/actions'; +import { SuggestController } from 'vs/editor/contrib/suggest/browser/suggestController'; import { localize } from 'vs/nls'; -import { ICommandService } from 'vs/platform/commands/common/commands'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { SuggestEnabledInput } from 'vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput'; import { EXTENSION_SETTING_TAG, FEATURE_SETTING_TAG, GENERAL_TAG_SETTING_TAG, ID_SETTING_TAG, LANGUAGE_SETTING_TAG, MODIFIED_SETTING_TAG } from 'vs/workbench/contrib/preferences/common/preferences'; export class SettingsSearchFilterDropdownMenuActionViewItem extends DropdownMenuActionViewItem { + private readonly suggestController: SuggestController | null; + constructor( action: IAction, actionRunner: IActionRunner | undefined, private readonly searchWidget: SuggestEnabledInput, - @IContextMenuService contextMenuService: IContextMenuService, - @ICommandService private readonly commandService: ICommandService + @IContextMenuService contextMenuService: IContextMenuService ) { super(action, { getActions: () => this.getActions() }, @@ -30,6 +31,8 @@ export class SettingsSearchFilterDropdownMenuActionViewItem extends DropdownMenu menuAsChild: true } ); + + this.suggestController = SuggestController.get(this.searchWidget.inputWidget); } override render(container: HTMLElement): void { @@ -39,8 +42,8 @@ export class SettingsSearchFilterDropdownMenuActionViewItem extends DropdownMenu private doSearchWidgetAction(queryToAppend: string, triggerSuggest: boolean) { this.searchWidget.setValue(this.searchWidget.getValue().trimEnd() + ' ' + queryToAppend); this.searchWidget.focus(); - if (triggerSuggest) { - this.commandService.executeCommand('editor.action.triggerSuggest'); + if (triggerSuggest && this.suggestController) { + this.suggestController.triggerSuggest(); } } -- cgit v1.2.3 From ab174654a59846e885562ba2defcd1764677de5c Mon Sep 17 00:00:00 2001 From: SteVen Batten <6561887+sbatten@users.noreply.github.com> Date: Thu, 14 Apr 2022 13:51:57 -0700 Subject: improve select a different editor command (#147479) --- .../codeEditor/browser/untitledTextEditorHint.ts | 6 +++--- .../welcomeViews/common/newFile.contribution.ts | 22 +++++++++++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts index f4fd71ba538..c5e1a0cba17 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts @@ -156,14 +156,14 @@ class UntitledTextEditorHintContentWidget implements IContentWidget { const chooseEditorOnClickOrTap = async (e: MouseEvent) => { e.stopPropagation(); + const activeEditorInput = this.editorGroupsService.activeGroup.activeEditor; + const newEditorSelected = await this.commandService.executeCommand('welcome.showNewFileEntries', { from: 'hint' }); // Close the active editor as long as it is untitled (swap the editors out) - if (activeEditorInput !== null && activeEditorInput.resource?.scheme === Schemas.untitled) { + if (newEditorSelected && activeEditorInput !== null && activeEditorInput.resource?.scheme === Schemas.untitled) { this.editorGroupsService.activeGroup.closeEditor(activeEditorInput, { preserveFocus: true }); } - - await this.commandService.executeCommand('welcome.showNewFileEntries', { from: 'hint' }); }; this.toDispose.push(dom.addDisposableListener(chooseEditor, 'click', chooseEditorOnClickOrTap)); this.toDispose.push(dom.addDisposableListener(chooseEditor, GestureEventType.Tap, chooseEditorOnClickOrTap)); diff --git a/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts b/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts index 1fe5734dd99..3c20b55f28a 100644 --- a/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts +++ b/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts @@ -40,8 +40,8 @@ registerAction2(class extends Action2 { }); } - run(accessor: ServicesAccessor) { - assertIsDefined(NewFileTemplatesManager.Instance).run(); + async run(accessor: ServicesAccessor): Promise { + return assertIsDefined(NewFileTemplatesManager.Instance).run(); } }); @@ -79,20 +79,26 @@ class NewFileTemplatesManager extends Disposable { return items; } - run() { + async run(): Promise { const entries = this.allEntries(); if (entries.length === 0) { throw Error('Unexpected empty new items list'); } else if (entries.length === 1) { this.commandService.executeCommand(entries[0].commandID); + return true; } else { - this.selectNewEntry(entries); + return this.selectNewEntry(entries); } } - private async selectNewEntry(entries: NewFileItem[]) { + private async selectNewEntry(entries: NewFileItem[]): Promise { + let resolveResult: (res: boolean) => void; + const resultPromise = new Promise(resolve => { + resolveResult = resolve; + }); + const disposables = new DisposableStore(); const qp = this.quickInputService.createQuickPick(); qp.title = localize('createNew', "Create New..."); @@ -158,6 +164,8 @@ class NewFileTemplatesManager extends Disposable { disposables.add(qp.onDidAccept(async e => { const selected = qp.selectedItems[0] as (IQuickPickItem & NewFileItem); + resolveResult(!!selected); + qp.hide(); if (selected) { await this.commandService.executeCommand(selected.commandID); } })); @@ -165,14 +173,18 @@ class NewFileTemplatesManager extends Disposable { disposables.add(qp.onDidHide(() => { qp.dispose(); disposables.dispose(); + resolveResult(false); })); disposables.add(qp.onDidTriggerItemButton(e => { qp.hide(); this.commandService.executeCommand('workbench.action.openGlobalKeybindings', (e.item as (IQuickPickItem & NewFileItem)).commandID); + resolveResult(false); })); qp.show(); + + return resultPromise; } } -- cgit v1.2.3 From ac00898e447e8d5ea4b0ad120671fdb78622f7ab Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Thu, 14 Apr 2022 14:26:15 -0700 Subject: fix: compare origins in fetch requests against remote authority (#147467) The previous implementation did not consider what would happen if webview resources were served from the same domain. By first comparing the requestUrl.orgin with the sw.orgin (similar to how it's done for localhost), this is no longer a problem. And since the requests have the same origin, authentication will never be an issue as cookies will exist. --- src/vs/workbench/contrib/webview/browser/pre/service-worker.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/webview/browser/pre/service-worker.js b/src/vs/workbench/contrib/webview/browser/pre/service-worker.js index 70534ee470d..81a45ab6ca7 100644 --- a/src/vs/workbench/contrib/webview/browser/pre/service-worker.js +++ b/src/vs/workbench/contrib/webview/browser/pre/service-worker.js @@ -189,8 +189,10 @@ sw.addEventListener('fetch', (event) => { } // If we're making a request against the remote authority, we want to go - // back through VS Code itself so that we are authenticated properly - if (requestUrl.host === remoteAuthority) { + // through VS Code itself so that we are authenticated properly. If the + // service worker is hosted on the same origin we will have cookies and + // authentication will not be an issue. + if (requestUrl.origin !== sw.origin && requestUrl.host === remoteAuthority) { switch (event.request.method) { case 'GET': case 'HEAD': -- cgit v1.2.3 From b55d829608115a26fff5f13339fc0310f82e4441 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Thu, 14 Apr 2022 15:30:38 -0700 Subject: remove unneeded cast --- .../contrib/welcomeGettingStarted/browser/gettingStartedService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts index 75b3891db8d..5fe7dd326e7 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts @@ -340,7 +340,7 @@ export class WalkthroughsService extends Disposable implements IWalkthroughsServ } if (step.media.image) { - const altText = (step.media as any).altText; + const altText = step.media.altText; if (altText === undefined) { console.error('Walkthrough item:', fullyQualifiedID, 'is missing altText for its media element.'); } -- cgit v1.2.3 From 49d2821d445fa186312fee0635f7cc13f22cf097 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Thu, 14 Apr 2022 15:31:27 -0700 Subject: add note about legacy config --- .../contrib/welcomeGettingStarted/browser/gettingStartedService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts index 5fe7dd326e7..4be26d8aedc 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts @@ -362,7 +362,7 @@ export class WalkthroughsService extends Disposable implements IWalkthroughsServ }; } - // Legacy media config + // Legacy media config (only in use by remote-wsl at the moment) else { const legacyMedia = step.media as unknown as { path: string; altText: string }; if (typeof legacyMedia.path === 'string' && legacyMedia.path.endsWith('.md')) { -- cgit v1.2.3 From a9288be67bab4e9c4dbe62207f01fafc2bdaadcb Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 14 Apr 2022 17:41:16 -0700 Subject: Focus the editor on debug stop, by default. Fix #139950 --- src/vs/workbench/contrib/debug/browser/debug.contribution.ts | 5 +++++ src/vs/workbench/contrib/debug/browser/debugSession.ts | 3 ++- src/vs/workbench/contrib/debug/common/debug.ts | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 03a03efeb2a..2cdb553512b 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -511,6 +511,11 @@ configurationRegistry.registerConfiguration({ description: nls.localize('debug.focusWindowOnBreak', "Controls whether the workbench window should be focused when the debugger breaks."), default: true }, + 'debug.focusEditorOnBreak': { + type: 'boolean', + description: nls.localize('debug.focusEditorOnBreak', "Controls whether the editor should be focused when the debugger breaks."), + default: true + }, 'debug.onTaskErrors': { enum: ['debugAnyway', 'showErrors', 'prompt', 'abort'], enumDescriptions: [nls.localize('debugAnyway', "Ignore task errors and start debugging."), nls.localize('showErrors', "Show the Problems view and do not start debugging."), nls.localize('prompt', "Prompt user."), nls.localize('cancel', "Cancel debugging.")], diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index 0e8671611e0..8e119b5e5a3 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -958,7 +958,8 @@ export class DebugSession implements IDebugSession { const focusedStackFrame = this.debugService.getViewModel().focusedStackFrame; if (!focusedStackFrame || focusedStackFrame.thread.session === this) { // Only take focus if nothing is focused, or if the focus is already on the current session - await this.debugService.focusStackFrame(undefined, thread); + const preserveFocus = !this.configurationService.getValue('debug').focusEditorOnBreak; + await this.debugService.focusStackFrame(undefined, thread, undefined, { preserveFocus }); } if (thread.stoppedDetails) { diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index fb0445b670e..aa5625fe460 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -630,6 +630,7 @@ export interface IDebugConfiguration { acceptSuggestionOnEnter: 'off' | 'on'; }; focusWindowOnBreak: boolean; + focusEditorOnBreak: boolean; onTaskErrors: 'debugAnyway' | 'showErrors' | 'prompt' | 'abort'; showBreakpointsInOverviewRuler: boolean; showInlineBreakpointCandidates: boolean; -- cgit v1.2.3 From ff289ebac8c29c304c84d997ac181aada522eecc Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 15 Apr 2022 11:29:21 -0700 Subject: Support 'when' clause for breakpoints contribution. Fix #133585 --- .../contrib/debug/browser/debugAdapterManager.ts | 16 +++++-------- .../workbench/contrib/debug/common/breakpoints.ts | 27 ++++++++++++++++++++++ src/vs/workbench/contrib/debug/common/debug.ts | 5 ++++ .../workbench/contrib/debug/common/debugSchemas.ts | 15 ++++++------ 4 files changed, 46 insertions(+), 17 deletions(-) create mode 100644 src/vs/workbench/contrib/debug/common/breakpoints.ts (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts b/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts index 2a01435a6f5..24c64bc9f81 100644 --- a/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts @@ -10,8 +10,8 @@ import Severity from 'vs/base/common/severity'; import * as strings from 'vs/base/common/strings'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { IEditorModel } from 'vs/editor/common/editorCommon'; -import { ITextModel } from 'vs/editor/common/model'; import { ILanguageService } from 'vs/editor/common/languages/language'; +import { ITextModel } from 'vs/editor/common/model'; import * as nls from 'vs/nls'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -22,6 +22,7 @@ import { Extensions as JSONExtensions, IJSONContributionRegistry } from 'vs/plat import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { Breakpoints } from 'vs/workbench/contrib/debug/common/breakpoints'; import { CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUG_EXTENSION_AVAILABLE, IAdapterDescriptor, IAdapterManager, IConfig, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugAdapterFactory, IDebugConfiguration, IDebugSession, INTERNAL_CONSOLE_OPTIONS_SCHEMA } from 'vs/workbench/contrib/debug/common/debug'; import { Debugger } from 'vs/workbench/contrib/debug/common/debugger'; import { breakpointsExtPoint, debuggersExtPoint, launchSchema, presentationSchema } from 'vs/workbench/contrib/debug/common/debugSchemas'; @@ -42,7 +43,7 @@ export class AdapterManager extends Disposable implements IAdapterManager { private debugExtensionsAvailable: IContextKey; private readonly _onDidRegisterDebugger = new Emitter(); private readonly _onDidDebuggersExtPointRead = new Emitter(); - private breakpointLanguageIdsSet = new Set(); + private breakpointContributions: Breakpoints[] = []; private debuggerWhenKeys = new Set(); constructor( @@ -116,13 +117,8 @@ export class AdapterManager extends Disposable implements IAdapterManager { this._onDidDebuggersExtPointRead.fire(); }); - breakpointsExtPoint.setHandler((extensions, delta) => { - delta.removed.forEach(removed => { - removed.value.forEach(breakpoints => this.breakpointLanguageIdsSet.delete(breakpoints.language)); - }); - delta.added.forEach(added => { - added.value.forEach(breakpoints => this.breakpointLanguageIdsSet.add(breakpoints.language)); - }); + breakpointsExtPoint.setHandler(extensions => { + this.breakpointContributions = extensions.flatMap(ext => ext.value.map(breakpoint => this.instantiationService.createInstance(Breakpoints, breakpoint))); }); } @@ -281,7 +277,7 @@ export class AdapterManager extends Disposable implements IAdapterManager { return true; } - return this.breakpointLanguageIdsSet.has(languageId); + return this.breakpointContributions.some(breakpoints => breakpoints.language === languageId && breakpoints.enabled); } getDebugger(type: string): Debugger | undefined { diff --git a/src/vs/workbench/contrib/debug/common/breakpoints.ts b/src/vs/workbench/contrib/debug/common/breakpoints.ts new file mode 100644 index 00000000000..38bc0d5114d --- /dev/null +++ b/src/vs/workbench/contrib/debug/common/breakpoints.ts @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ContextKeyExpr, ContextKeyExpression, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IBreakpointContribution } from 'vs/workbench/contrib/debug/common/debug'; + +export class Breakpoints { + + private breakpointsWhen: ContextKeyExpression | undefined; + + constructor( + private readonly breakpointContribution: IBreakpointContribution, + @IContextKeyService private readonly contextKeyService: IContextKeyService, + ) { + this.breakpointsWhen = typeof breakpointContribution.when === 'string' ? ContextKeyExpr.deserialize(breakpointContribution.when) : undefined; + } + + get language(): string { + return this.breakpointContribution.language; + } + + get enabled(): boolean { + return !this.breakpointsWhen || this.contextKeyService.contextMatchesRules(this.breakpointsWhen); + } +} diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index aa5625fe460..1ea78541aff 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -772,6 +772,11 @@ export interface IDebuggerContribution extends IPlatformSpecificAdapterContribut when?: string; } +export interface IBreakpointContribution { + language: string; + when?: string; +} + export enum DebugConfigurationProviderTriggerKind { /** * `DebugConfigurationProvider.provideDebugConfigurations` is called to provide the initial debug configurations for a newly created launch.json. diff --git a/src/vs/workbench/contrib/debug/common/debugSchemas.ts b/src/vs/workbench/contrib/debug/common/debugSchemas.ts index 3613a1b44a4..a2a9c7f5480 100644 --- a/src/vs/workbench/contrib/debug/common/debugSchemas.ts +++ b/src/vs/workbench/contrib/debug/common/debugSchemas.ts @@ -5,7 +5,7 @@ import * as extensionsRegistry from 'vs/workbench/services/extensions/common/extensionsRegistry'; import * as nls from 'vs/nls'; -import { IDebuggerContribution, ICompound } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebuggerContribution, ICompound, IBreakpointContribution } from 'vs/workbench/contrib/debug/common/debug'; import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { inputsSchema } from 'vs/workbench/services/configurationResolver/common/configurationResolverSchema'; @@ -68,7 +68,7 @@ export const debuggersExtPoint = extensionsRegistry.ExtensionsRegistry.registerE type: 'object' }, when: { - description: nls.localize('vscode.extension.contributes.debuggers.when', "Condition which must be true to enable this type of debugger. Consider using 'shellExecutionSupported', 'virtualWorkspace', 'resourceScheme' or an extension defined context key as appropriate for this."), + description: nls.localize('vscode.extension.contributes.debuggers.when', "Condition which must be true to enable this type of debugger. Consider using 'shellExecutionSupported', 'virtualWorkspace', 'resourceScheme' or an extension-defined context key as appropriate for this."), type: 'string', default: '' }, @@ -107,12 +107,8 @@ export const debuggersExtPoint = extensionsRegistry.ExtensionsRegistry.registerE } }); -export interface IRawBreakpointContribution { - language: string; -} - // breakpoints extension point #9037 -export const breakpointsExtPoint = extensionsRegistry.ExtensionsRegistry.registerExtensionPoint({ +export const breakpointsExtPoint = extensionsRegistry.ExtensionsRegistry.registerExtensionPoint({ extensionPoint: 'breakpoints', jsonSchema: { description: nls.localize('vscode.extension.contributes.breakpoints', 'Contributes breakpoints.'), @@ -127,6 +123,11 @@ export const breakpointsExtPoint = extensionsRegistry.ExtensionsRegistry.registe description: nls.localize('vscode.extension.contributes.breakpoints.language', "Allow breakpoints for this language."), type: 'string' }, + when: { + description: nls.localize('vscode.extension.contributes.breakpoints.when', "Condition which must be true to enable breakpoints in this language. Consider matching this to the debugger when clause as appropriate."), + type: 'string', + default: '' + } } } } -- cgit v1.2.3 From 2fd2a6041557ea4c7784b8ee7f785a114452a434 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 15 Apr 2022 11:55:55 -0700 Subject: Add autoExpandLazyVariables setting. Fix #144861 --- src/vs/workbench/contrib/debug/browser/debug.contribution.ts | 5 +++++ src/vs/workbench/contrib/debug/browser/debugSession.ts | 5 +++++ src/vs/workbench/contrib/debug/common/debug.ts | 2 ++ src/vs/workbench/contrib/debug/common/debugModel.ts | 8 +++++++- 4 files changed, 19 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 2cdb553512b..d595b7768d1 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -558,5 +558,10 @@ configurationRegistry.registerConfiguration({ default: true, description: nls.localize('debug.disassemblyView.showSourceCode', "Show Source Code in Disassembly View.") }, + 'debug.autoExpandLazyVariables': { + type: 'boolean', + default: false, + description: nls.localize('debug.autoExpandLazyVariables', "Automatically show values for variables that are lazily resolved by the debugger, such as getters.") + } } }); diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index 8e119b5e5a3..3ff60d94d24 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -172,6 +172,11 @@ export class DebugSession implements IDebugSession { return this._options.debugUI?.simple ?? false; } + get autoExpandLazyVariables(): boolean { + // This tiny helper avoids converting the entire debug model to use service injection + return this.configurationService.getValue('debug').autoExpandLazyVariables; + } + setConfiguration(configuration: { resolved: IConfig; unresolved: IConfig | undefined }) { this._configuration = configuration; } diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 1ea78541aff..9457ae8c1b4 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -291,6 +291,7 @@ export interface IDebugSession extends ITreeElement { readonly compoundRoot: DebugCompoundRoot | undefined; readonly name: string; readonly isSimpleUI: boolean; + readonly autoExpandLazyVariables: boolean; setSubId(subId: string | undefined): void; @@ -638,6 +639,7 @@ export interface IDebugConfiguration { disassemblyView: { showSourceCode: boolean; }; + autoExpandLazyVariables: boolean; } export interface IGlobalConfig { diff --git a/src/vs/workbench/contrib/debug/common/debugModel.ts b/src/vs/workbench/contrib/debug/common/debugModel.ts index 3e2cb2e1a16..c05fc04c956 100644 --- a/src/vs/workbench/contrib/debug/common/debugModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugModel.ts @@ -152,7 +152,7 @@ export class ExpressionContainer implements IExpressionContainer { } const nameCount = new Map(); - return response.body.variables.filter(v => !!v).map((v: IDebugProtocolVariableWithContext) => { + const vars = response.body.variables.filter(v => !!v).map((v: IDebugProtocolVariableWithContext) => { if (isString(v.value) && isString(v.name) && typeof v.variablesReference === 'number') { const count = nameCount.get(v.name) || 0; const idDuplicationIndex = count > 0 ? count.toString() : ''; @@ -161,6 +161,12 @@ export class ExpressionContainer implements IExpressionContainer { } return new Variable(this.session, this.threadId, this, 0, '', undefined, nls.localize('invalidVariableAttributes', "Invalid variable attributes"), 0, 0, undefined, { kind: 'virtual' }, undefined, undefined, false); }); + + if (this.session!.autoExpandLazyVariables) { + await Promise.all(vars.map(v => v.presentationHint?.lazy && v.evaluateLazy())); + } + + return vars; } catch (e) { return [new Variable(this.session, this.threadId, this, 0, '', undefined, e.message, 0, 0, undefined, { kind: 'virtual' }, undefined, undefined, false)]; } -- cgit v1.2.3 From 1fb94816f2d40bdc77536eac44eada91a9a9e8ac Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Fri, 15 Apr 2022 13:35:40 -0700 Subject: Settings editor search widget polish (#147521) --- .../contrib/preferences/browser/settingsEditor2.ts | 9 +++---- .../preferences/browser/settingsSearchMenu.ts | 28 +++++++++++----------- 2 files changed, 19 insertions(+), 18 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index d71c2e6acec..6ac2b721752 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -500,11 +500,11 @@ export class SettingsEditor2 extends EditorPane { clearSearchFilters(): void { let query = this.searchWidget.getValue(); - SettingsEditor2.SUGGESTIONS.forEach(suggestion => { - query = query.replace(suggestion, ''); + const splitQuery = query.split(' ').filter(word => { + return word.length && !SettingsEditor2.SUGGESTIONS.some(suggestion => word.startsWith(suggestion)); }); - this.searchWidget.setValue(query.trim()); + this.searchWidget.setValue(splitQuery.join(' ')); } private updateInputAriaLabel() { @@ -534,9 +534,10 @@ export class SettingsEditor2 extends EditorPane { // for the ':' trigger, only return suggestions if there was a '@' before it in the same word. const queryParts = query.split(/\s/g); if (queryParts[queryParts.length - 1].startsWith(`@${LANGUAGE_SETTING_TAG}`)) { - return this.languageService.getRegisteredLanguageIds().map(languageId => { + const sortedLanguages = this.languageService.getRegisteredLanguageIds().map(languageId => { return `@${LANGUAGE_SETTING_TAG}${languageId} `; }).sort(); + return sortedLanguages.filter(langFilter => !query.includes(langFilter)); } else if (queryParts[queryParts.length - 1].startsWith('@')) { return SettingsEditor2.SUGGESTIONS.filter(tag => !query.includes(tag)).map(tag => tag.endsWith(':') ? tag : tag + ' '); } diff --git a/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts b/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts index b8b09ebc8ff..83675b77e00 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts @@ -90,39 +90,39 @@ export class SettingsSearchFilterDropdownMenuActionViewItem extends DropdownMenu this.createModifiedAction(), this.createAction( 'extSettingsSearch', - localize('extSettingsSearch', "Extension ID"), + localize('extSettingsSearch', "Extension ID..."), localize('extSettingsSearchTooltip', "Add extension ID filter"), `@${EXTENSION_SETTING_TAG}`, false ), this.createAction( 'featuresSettingsSearch', - localize('featureSettingsSearch', "Feature"), + localize('featureSettingsSearch', "Feature..."), localize('featureSettingsSearchTooltip', "Add feature filter"), `@${FEATURE_SETTING_TAG}`, true ), this.createAction( - 'idSettingsSearch', - localize('idSettingsSearch', "Setting ID"), - localize('idSettingsSearchTooltip', "Add setting ID filter"), - `@${ID_SETTING_TAG}`, - false + 'tagSettingsSearch', + localize('tagSettingsSearch', "Tag..."), + localize('tagSettingsSearchTooltip', "Add tag filter"), + `@${GENERAL_TAG_SETTING_TAG}`, + true ), this.createAction( 'langSettingsSearch', - localize('langSettingsSearch', "Language"), + localize('langSettingsSearch', "Language..."), localize('langSettingsSearchTooltip', "Add language ID filter"), `@${LANGUAGE_SETTING_TAG}`, true ), this.createAction( - 'tagSettingsSearch', - localize('tagSettingsSearch', "Tag"), - localize('tagSettingsSearchTooltip', "Add tag filter"), - `@${GENERAL_TAG_SETTING_TAG}`, - true - ), + 'idSettingsSearch', + localize('idSettingsSearch', "Setting ID..."), + localize('idSettingsSearchTooltip', "Add setting ID filter"), + `@${ID_SETTING_TAG}`, + false + ) ]; } } -- cgit v1.2.3 From 70c896184e317984db6f0ff6d605f940b4c1a41f Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 15 Apr 2022 15:28:33 -0700 Subject: Fix build --- src/vs/workbench/contrib/debug/test/browser/mockDebug.ts | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/test/browser/mockDebug.ts b/src/vs/workbench/contrib/debug/test/browser/mockDebug.ts index 81c394466ec..1bebaa31adb 100644 --- a/src/vs/workbench/contrib/debug/test/browser/mockDebug.ts +++ b/src/vs/workbench/contrib/debug/test/browser/mockDebug.ts @@ -168,6 +168,8 @@ export class MockDebugService implements IDebugService { } export class MockSession implements IDebugSession { + readonly autoExpandLazyVariables = false; + getMemory(memoryReference: string): IMemoryRegion { throw new Error('Method not implemented.'); } -- cgit v1.2.3 From 07e2a4e3f2908a5cad417d57e6ce9b3831d6955e Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 18 Apr 2022 15:02:49 -0700 Subject: Fix exec order indicator position when statusbar hidden. Fix #147333 --- .../workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts index eb6e260ec10..469e7cbef3d 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts @@ -63,7 +63,8 @@ export class CellExecutionPart extends CellPart { DOM.hide(this._executionOrderLabel); } else { DOM.show(this._executionOrderLabel); - this._executionOrderLabel.style.top = `${element.layoutInfo.editorHeight}px`; + const top = element.layoutInfo.editorHeight - 22 + element.layoutInfo.statusBarHeight; + this._executionOrderLabel.style.top = `${top}px`; } } } -- cgit v1.2.3 From 3b57fde7a85d12e4583c492c29f2dcae31434ed1 Mon Sep 17 00:00:00 2001 From: David Dossett Date: Mon, 18 Apr 2022 15:15:01 -0700 Subject: Fix #147652 --- src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts b/src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts index c47ff0b58ff..68185694831 100644 --- a/src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts +++ b/src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts @@ -121,7 +121,7 @@ code > div { } .vscode-high-contrast code > div { - background-color: rgb(0, 0, 0); + background-color: var(--vscode-textCodeBlock-background); } .vscode-high-contrast h1 { -- cgit v1.2.3 From e7c6ad74aff28965d0189ca1dd584f5e9829cf06 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Mon, 18 Apr 2022 19:16:54 -0700 Subject: get zsh startup files to run in the correct order (#147434) --- .../contrib/terminal/browser/media/shellIntegration-env.zsh | 8 ++++++++ .../contrib/terminal/browser/media/shellIntegration-profile.zsh | 8 ++++++++ .../contrib/terminal/browser/media/shellIntegration.zsh | 9 ++------- 3 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 src/vs/workbench/contrib/terminal/browser/media/shellIntegration-env.zsh create mode 100644 src/vs/workbench/contrib/terminal/browser/media/shellIntegration-profile.zsh (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-env.zsh b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-env.zsh new file mode 100644 index 00000000000..26ab335881a --- /dev/null +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-env.zsh @@ -0,0 +1,8 @@ +# --------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# --------------------------------------------------------------------------------------------- + +if [[ $options[norcs] = off && -o "login" && -f ~/.zshenv ]]; then + . ~/.zshenv +fi diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-profile.zsh b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-profile.zsh new file mode 100644 index 00000000000..734bb831e11 --- /dev/null +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-profile.zsh @@ -0,0 +1,8 @@ +# --------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# --------------------------------------------------------------------------------------------- + +if [[ $options[norcs] = off && -o "login" && -f ~/.zprofile ]]; then + . ~/.zprofile +fi diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.zsh b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.zsh index cfba2786a3e..2dec005daf4 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.zsh +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.zsh @@ -12,13 +12,8 @@ builtin unset ZDOTDIR # as disable it by unsetting the variable. VSCODE_SHELL_INTEGRATION=1 -if [ -f ~/.zshenv ]; then - . ~/.zshenv -fi -if [[ -o "login" && -f ~/.zprofile ]]; then - . ~/.zprofile -fi -if [ -f ~/.zshrc ]; then + +if [[ $options[norcs] = off && -f ~/.zshrc ]]; then . ~/.zshrc fi -- cgit v1.2.3 From c4769cfdcd522942f3d4c27cacaa13deb8905dac Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 19 Apr 2022 11:05:40 +0200 Subject: Confirmation of Clear Recent projects (fix #139392) --- .../contrib/quickaccess/browser/commandsQuickAccess.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts index 6d2258b96f1..755c6fa307c 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts @@ -188,9 +188,23 @@ export class ClearCommandHistoryAction extends Action2 { async run(accessor: ServicesAccessor): Promise { const configurationService = accessor.get(IConfigurationService); const storageService = accessor.get(IStorageService); + const dialogService = accessor.get(IDialogService); const commandHistoryLength = CommandsHistory.getConfiguredCommandHistoryLength(configurationService); if (commandHistoryLength > 0) { + + // Ask for confirmation + const { confirmed } = await dialogService.confirm({ + message: localize('confirmClearMessage', "Do you want to clear the history of recently used commands?"), + detail: localize('confirmClearDetail', "This action is irreversible!"), + primaryButton: localize({ key: 'clearButtonLabel', comment: ['&& denotes a mnemonic'] }, "&&Clear"), + type: 'warning' + }); + + if (!confirmed) { + return; + } + CommandsHistory.clearHistory(configurationService, storageService); } } -- cgit v1.2.3 From bab1b25c0be5956ad60e93d573a99660dc431fb2 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 19 Apr 2022 13:45:01 +0200 Subject: Polish comment line numbers in view Part of #146510 --- src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts b/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts index a65cffe56f7..78a63890aa3 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts @@ -212,7 +212,11 @@ export class CommentNodeRenderer implements IListRenderer templateData.threadMetadata.commentPreview.title = renderedComment.element.textContent ?? ''; } - templateData.threadMetadata.range.textContent = `[${node.element.range.startLineNumber}-${node.element.range.endLineNumber}]`; + if (node.element.range.startLineNumber === node.element.range.endLineNumber) { + templateData.threadMetadata.range.textContent = nls.localize('commentLine', "[Ln {0}]", node.element.range.startLineNumber); + } else { + templateData.threadMetadata.range.textContent = nls.localize('commentRange', "[Ln {0}-{1}]", node.element.range.startLineNumber, node.element.range.endLineNumber); + } if (!node.element.hasReply()) { templateData.repliesMetadata.container.style.display = 'none'; -- cgit v1.2.3 From 08f9528d33e01abaa21ff558330a3c6d4d268185 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 19 Apr 2022 16:03:44 -0700 Subject: Add 'notebookCellResource' context key. Fix #146686 --- .../notebook/browser/view/cellParts/cellContextKeys.ts | 11 +++++++---- .../workbench/contrib/notebook/common/notebookContextKeys.ts | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellContextKeys.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellContextKeys.ts index e1e2a982be5..364939e3456 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellContextKeys.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellContextKeys.ts @@ -5,15 +5,15 @@ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { CellEditState, CellFocusMode, ICellViewModel, INotebookEditorDelegate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { NotebookCellExecutionStateContext, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_EXECUTING, NOTEBOOK_CELL_EXECUTION_STATE, NOTEBOOK_CELL_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; +import { CellViewModelStateChangeEvent } from 'vs/workbench/contrib/notebook/browser/notebookViewEvents'; +import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { MarkupCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markupCellViewModel'; import { NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { NotebookCellExecutionStateContext, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_EXECUTING, NOTEBOOK_CELL_EXECUTION_STATE, NOTEBOOK_CELL_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_RESOURCE, NOTEBOOK_CELL_TYPE } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; -import { CellViewModelStateChangeEvent } from 'vs/workbench/contrib/notebook/browser/notebookViewEvents'; -import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; export class CellContextKeyPart extends CellPart { private cellContextKeyManager: CellContextKeyManager; @@ -44,6 +44,7 @@ export class CellContextKeyManager extends Disposable { private cellContentCollapsed!: IContextKey; private cellOutputCollapsed!: IContextKey; private cellLineNumbers!: IContextKey<'on' | 'off' | 'inherit'>; + private cellResource!: IContextKey; private markdownEditMode!: IContextKey; @@ -69,6 +70,7 @@ export class CellContextKeyManager extends Disposable { this.cellContentCollapsed = NOTEBOOK_CELL_INPUT_COLLAPSED.bindTo(this._contextKeyService); this.cellOutputCollapsed = NOTEBOOK_CELL_OUTPUT_COLLAPSED.bindTo(this._contextKeyService); this.cellLineNumbers = NOTEBOOK_CELL_LINE_NUMBERS.bindTo(this._contextKeyService); + this.cellResource = NOTEBOOK_CELL_RESOURCE.bindTo(this._contextKeyService); if (element) { this.updateForElement(element); @@ -112,6 +114,7 @@ export class CellContextKeyManager extends Disposable { this.updateForOutputs(); this.cellLineNumbers.set(this.element!.lineNumbers); + this.cellResource.set(this.element!.uri.toString()); }); } diff --git a/src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts b/src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts index fd2279cba63..689f9ca995e 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts @@ -38,6 +38,8 @@ export const NOTEBOOK_CELL_EXECUTING = new RawContextKey('notebookCellE export const NOTEBOOK_CELL_HAS_OUTPUTS = new RawContextKey('notebookCellHasOutputs', false); export const NOTEBOOK_CELL_INPUT_COLLAPSED = new RawContextKey('notebookCellInputIsCollapsed', false); export const NOTEBOOK_CELL_OUTPUT_COLLAPSED = new RawContextKey('notebookCellOutputIsCollapsed', false); +export const NOTEBOOK_CELL_RESOURCE = new RawContextKey('notebookCellResource', ''); + // Kernels export const NOTEBOOK_KERNEL = new RawContextKey('notebookKernel', undefined); export const NOTEBOOK_KERNEL_COUNT = new RawContextKey('notebookKernelCount', 0); -- cgit v1.2.3 From d472403e4294fd9aebd4d92074a03aad0fb83d9d Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 19 Apr 2022 19:43:01 -0700 Subject: update min contrast terminal setting description to include excluded powerline chars --- src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 4020b3e6fa0..3ddae516bb0 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -186,7 +186,7 @@ const terminalConfiguration: IConfigurationNode = { default: DEFAULT_LINE_HEIGHT }, [TerminalSettingId.MinimumContrastRatio]: { - markdownDescription: localize('terminal.integrated.minimumContrastRatio', "When set the foreground color of each cell will change to try meet the contrast ratio specified. Example values:\n\n- 1: Do nothing and use the standard theme colors.\n- 4.5: [WCAG AA compliance (minimum)](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html) (default).\n- 7: [WCAG AAA compliance (enhanced)](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast7.html).\n- 21: White on black or black on white."), + markdownDescription: localize('terminal.integrated.minimumContrastRatio', "When set, the foreground color of each cell will change to try meet the contrast ratio specified. Note that this will not apply to `powerline` characters per #146406. Example values:\n\n- 1: Do nothing and use the standard theme colors.\n- 4.5: [WCAG AA compliance (minimum)](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html) (default).\n- 7: [WCAG AAA compliance (enhanced)](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast7.html).\n- 21: White on black or black on white."), type: 'number', default: 4.5 }, -- cgit v1.2.3 From 89d10043719b48a6e6e5978fe61e93fd2c5a5d82 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 19 Apr 2022 20:07:27 -0700 Subject: Fix #145265 --- src/vs/workbench/contrib/debug/node/terminals.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/node/terminals.ts b/src/vs/workbench/contrib/debug/node/terminals.ts index 5f89e708bc7..b6c3ced13c5 100644 --- a/src/vs/workbench/contrib/debug/node/terminals.ts +++ b/src/vs/workbench/contrib/debug/node/terminals.ts @@ -121,7 +121,8 @@ export function prepareCommand(shell: string, args: string[], cwd?: string, env? quote = (s: string) => { s = s.replace(/\"/g, '""'); - return (' "> s.includes(char)) || s.length === 0) ? `"${s}"` : s; + s = s.replace(/([> s.includes(char)) || s.length === 0) ? `"${s}"` : s; }; if (cwd) { -- cgit v1.2.3 From 36d7dd2a5767767a907d43e6cb833dfa25c02aee Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 20 Apr 2022 13:26:29 +0200 Subject: Inconsistent font size in a comment with `code` blocks (#146542) Fixes #146183 --- src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts index 0e41198ccb2..c6a047179b0 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts @@ -193,7 +193,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget this._scopedInstantiationService, this._commentThread as unknown as languages.CommentThread, this._pendingComment, - { editor: this.editor }, + { editor: this.editor, codeBlockFontSize: '' }, this._commentOptions, { actionRunner: () => { -- cgit v1.2.3 From e0a3f8d33a46ca752d043be329a1543a98003613 Mon Sep 17 00:00:00 2001 From: aamunger Date: Wed, 20 Apr 2022 10:57:38 -0700 Subject: use css selector that includes IW scrollbar --- src/vs/workbench/contrib/notebook/browser/media/notebook.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index a660892ff1f..e4220b57b14 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -429,7 +429,7 @@ outline: none !important; } -.monaco-workbench .notebookOverlay.notebook-editor-editable > .cell-list-container > .monaco-list > .monaco-scrollable-element > .scrollbar.visible { +.monaco-workbench .notebookOverlay.notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .scrollbar.visible { z-index: var(--z-index-notebook-scrollbar); cursor: default; } -- cgit v1.2.3 From d7dbb0b8a2071de5b76ae6e18961bc6ef475aea1 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 20 Apr 2022 11:08:51 -0700 Subject: Also escape pipe character in bash shell. #145265 --- src/vs/workbench/contrib/debug/node/terminals.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/node/terminals.ts b/src/vs/workbench/contrib/debug/node/terminals.ts index b6c3ced13c5..d4338a5c04c 100644 --- a/src/vs/workbench/contrib/debug/node/terminals.ts +++ b/src/vs/workbench/contrib/debug/node/terminals.ts @@ -121,7 +121,7 @@ export function prepareCommand(shell: string, args: string[], cwd?: string, env? quote = (s: string) => { s = s.replace(/\"/g, '""'); - s = s.replace(/([> s.includes(char)) || s.length === 0) ? `"${s}"` : s; }; @@ -139,7 +139,7 @@ export function prepareCommand(shell: string, args: string[], cwd?: string, env? if (value === null) { command += `set "${key}=" && `; } else { - value = value.replace(/[\^\&\|\<\>]/g, s => `^${s}`); + value = value.replace(/[^&|<>]/g, s => `^${s}`); command += `set "${key}=${value}" && `; } } @@ -155,7 +155,7 @@ export function prepareCommand(shell: string, args: string[], cwd?: string, env? case ShellType.bash: { quote = (s: string) => { - s = s.replace(/(["'\\\$!><#()\[\]*&^])/g, '\\$1'); + s = s.replace(/(["'\\\$!><#()\[\]*&^|])/g, '\\$1'); return (' ;'.split('').some(char => s.includes(char)) || s.length === 0) ? `"${s}"` : s; }; -- cgit v1.2.3 From f171e5ecdef64be7ebd1d3b51957ff108b3d74ec Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Wed, 20 Apr 2022 12:03:16 -0700 Subject: Improve language filter placement, fixes #145711 (#147727) --- src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 6ac2b721752..3afedd34c39 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -838,7 +838,11 @@ export class SettingsEditor2 extends EditorPane { } })); this._register(this.settingRenderers.onApplyLanguageFilter((lang: string) => { - this.focusSearch(`@${LANGUAGE_SETTING_TAG}${lang}`); + if (this.searchWidget) { + // Prepend the language filter to the query. + const newQuery = `@${LANGUAGE_SETTING_TAG}${lang} ${this.searchWidget.getValue().trimStart()}`; + this.focusSearch(newQuery, false); + } })); this.settingsTree = this._register(this.instantiationService.createInstance(SettingsTree, -- cgit v1.2.3 From f291d53d74bac9a9e1d2bf1f76e3ce502caa9faa Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Wed, 20 Apr 2022 12:58:13 -0700 Subject: Add online services option to the search funnel (#147643) --- .../browser/preferences.contribution.ts | 46 ++---------------- .../preferences/browser/settingsSearchMenu.ts | 55 +++++++++++++--------- 2 files changed, 38 insertions(+), 63 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts index 42365a36d4f..b5230a5af22 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts @@ -34,7 +34,7 @@ import { ConfigureLanguageBasedSettingsAction } from 'vs/workbench/contrib/prefe import { SettingsEditorContribution } from 'vs/workbench/contrib/preferences/browser/preferencesEditor'; import { preferencesOpenSettingsIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; import { SettingsEditor2, SettingsFocusContext } from 'vs/workbench/contrib/preferences/browser/settingsEditor2'; -import { CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, CONTEXT_KEYBINDING_FOCUS, CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, CONTEXT_WHEN_FOCUS, KEYBINDINGS_EDITOR_COMMAND_ADD, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND_TITLE, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_DEFINE_WHEN, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SEARCH, KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR, KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE, KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_EXTENSION_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS, MODIFIED_SETTING_TAG, REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU } from 'vs/workbench/contrib/preferences/common/preferences'; +import { CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, CONTEXT_KEYBINDING_FOCUS, CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, CONTEXT_WHEN_FOCUS, KEYBINDINGS_EDITOR_COMMAND_ADD, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND_TITLE, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_DEFINE_WHEN, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SEARCH, KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR, KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE, KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_EXTENSION_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS, REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU } from 'vs/workbench/contrib/preferences/common/preferences'; import { PreferencesContribution } from 'vs/workbench/contrib/preferences/common/preferencesContribution'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -54,7 +54,6 @@ const SETTINGS_EDITOR_COMMAND_FOCUS_CONTROL = 'settings.action.focusSettingContr const SETTINGS_EDITOR_COMMAND_FOCUS_UP = 'settings.action.focusLevelUp'; const SETTINGS_EDITOR_COMMAND_SWITCH_TO_JSON = 'settings.switchToJSON'; -const SETTINGS_EDITOR_COMMAND_FILTER_MODIFIED = 'settings.filterByModified'; const SETTINGS_EDITOR_COMMAND_FILTER_ONLINE = 'settings.filterByOnline'; const SETTINGS_EDITOR_COMMAND_FILTER_TELEMETRY = 'settings.filterByTelemetry'; const SETTINGS_EDITOR_COMMAND_FILTER_UNTRUSTED = 'settings.filterUntrusted'; @@ -393,36 +392,15 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon return accessor.get(IPreferencesService).openFolderSettings({ folderUri: resource }); } }); - registerAction2(class extends Action2 { - constructor() { - super({ - id: SETTINGS_EDITOR_COMMAND_FILTER_MODIFIED, - title: { value: nls.localize('filterModifiedLabel', "Show modified settings"), original: 'Show modified settings' }, - menu: { - id: MenuId.EditorTitle, - group: '1_filter', - order: 1, - when: ContextKeyExpr.and(CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR.toNegated()) - } - }); - } - run(accessor: ServicesAccessor, resource: URI) { - const editorPane = accessor.get(IEditorService).activeEditorPane; - if (editorPane instanceof SettingsEditor2) { - editorPane.focusSearch(`@${MODIFIED_SETTING_TAG}`); - } - } - }); registerAction2(class extends Action2 { constructor() { super({ id: SETTINGS_EDITOR_COMMAND_FILTER_ONLINE, - title: { value: nls.localize('filterOnlineServicesLabel', "Show settings for online services"), original: 'Show settings for online services' }, + title: nls.localize({ key: 'miOpenOnlineSettings', comment: ['&& denotes a mnemonic'] }, "&&Online Services Settings"), menu: { - id: MenuId.EditorTitle, - group: '1_filter', + id: MenuId.MenubarPreferencesMenu, + group: '1_settings', order: 2, - when: ContextKeyExpr.and(CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR.toNegated()) } }); } @@ -435,22 +413,6 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon } } }); - MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, { - group: '1_settings', - command: { - id: SETTINGS_EDITOR_COMMAND_FILTER_ONLINE, - title: nls.localize({ key: 'miOpenOnlineSettings', comment: ['&& denotes a mnemonic'] }, "&&Online Services Settings") - }, - order: 2 - }); - MenuRegistry.appendMenuItem(MenuId.GlobalActivity, { - group: '2_configuration', - command: { - id: SETTINGS_EDITOR_COMMAND_FILTER_ONLINE, - title: nls.localize('onlineServices', "Online Services Settings") - }, - order: 2 - }); registerAction2(class extends Action2 { constructor() { diff --git a/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts b/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts index 83675b77e00..333d179f818 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts @@ -10,7 +10,7 @@ import { SuggestController } from 'vs/editor/contrib/suggest/browser/suggestCont import { localize } from 'vs/nls'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { SuggestEnabledInput } from 'vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput'; -import { EXTENSION_SETTING_TAG, FEATURE_SETTING_TAG, GENERAL_TAG_SETTING_TAG, ID_SETTING_TAG, LANGUAGE_SETTING_TAG, MODIFIED_SETTING_TAG } from 'vs/workbench/contrib/preferences/common/preferences'; +import { EXTENSION_SETTING_TAG, FEATURE_SETTING_TAG, GENERAL_TAG_SETTING_TAG, LANGUAGE_SETTING_TAG, MODIFIED_SETTING_TAG } from 'vs/workbench/contrib/preferences/common/preferences'; export class SettingsSearchFilterDropdownMenuActionViewItem extends DropdownMenuActionViewItem { private readonly suggestController: SuggestController | null; @@ -47,6 +47,9 @@ export class SettingsSearchFilterDropdownMenuActionViewItem extends DropdownMenu } } + /** + * The created action appends a query to the search widget search string. It optionally triggers suggestions. + */ private createAction(id: string, label: string, tooltip: string, queryToAppend: string, triggerSuggest: boolean): IAction { return { id, @@ -60,24 +63,30 @@ export class SettingsSearchFilterDropdownMenuActionViewItem extends DropdownMenu }; } - private createModifiedAction(): IAction { - // The modified action works slightly differently than the other actions. - // It is more like a checkbox on/off toggle. - const queryContainsModifiedTag = this.searchWidget.getValue().split(' ').some(word => word === `@${MODIFIED_SETTING_TAG}`); + /** + * The created action appends a query to the search widget search string, if the query does not exist. + * Otherwise, it removes the query from the search widget search string. + * The action does not trigger suggestions after adding or removing the query. + */ + private createToggleAction(id: string, label: string, tooltip: string, queryToAppend: string): IAction { + const splitCurrentQuery = this.searchWidget.getValue().split(' '); + const queryContainsQueryToAppend = splitCurrentQuery.includes(queryToAppend); return { - id: 'modifiedSettingsSearch', - label: localize('modifiedSettingsSearch', "Modified"), - tooltip: localize('modifiedSettingsSearchTooltip', "View modified settings only"), + id, + label, + tooltip, class: undefined, enabled: true, - checked: queryContainsModifiedTag, + checked: queryContainsQueryToAppend, run: () => { - // Append the tag, otherwise remove it from the query. - if (!queryContainsModifiedTag) { - this.searchWidget.setValue(this.searchWidget.getValue().trimEnd() + ` @${MODIFIED_SETTING_TAG}`); + if (!queryContainsQueryToAppend) { + const trimmedCurrentQuery = this.searchWidget.getValue().trimEnd(); + const newQuery = trimmedCurrentQuery ? trimmedCurrentQuery + ' ' + queryToAppend : queryToAppend; + this.searchWidget.setValue(newQuery); } else { - const queryWithoutModifiedTag = this.searchWidget.getValue().split(' ').filter(word => word !== `@${MODIFIED_SETTING_TAG}`).join(' '); - this.searchWidget.setValue(queryWithoutModifiedTag); + const queryWithRemovedTags = this.searchWidget.getValue().split(' ') + .filter(word => word !== queryToAppend).join(' '); + this.searchWidget.setValue(queryWithRemovedTags); } this.searchWidget.focus(); }, @@ -87,7 +96,12 @@ export class SettingsSearchFilterDropdownMenuActionViewItem extends DropdownMenu getActions(): IAction[] { return [ - this.createModifiedAction(), + this.createToggleAction( + 'modifiedSettingsSearch', + localize('modifiedSettingsSearch', "Modified"), + localize('modifiedSettingsSearchTooltip', "Add or remove modified settings filter"), + `@${MODIFIED_SETTING_TAG}` + ), this.createAction( 'extSettingsSearch', localize('extSettingsSearch', "Extension ID..."), @@ -116,12 +130,11 @@ export class SettingsSearchFilterDropdownMenuActionViewItem extends DropdownMenu `@${LANGUAGE_SETTING_TAG}`, true ), - this.createAction( - 'idSettingsSearch', - localize('idSettingsSearch', "Setting ID..."), - localize('idSettingsSearchTooltip', "Add setting ID filter"), - `@${ID_SETTING_TAG}`, - false + this.createToggleAction( + 'onlineSettingsSearch', + localize('onlineSettingsSearch', "Online services"), + localize('onlineSettingsSearchTooltip', "Show settings for online services"), + '@tag:usesOnlineServices' ) ]; } -- cgit v1.2.3 From 3124b9a5cc2f07860765980b459bd0900f9a8229 Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Wed, 20 Apr 2022 17:29:54 -0700 Subject: fixes #147644 --- src/vs/workbench/contrib/files/browser/fileActions.contribution.ts | 2 +- src/vs/workbench/contrib/files/browser/fileActions.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts index 3825aad9830..71422933855 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts @@ -206,7 +206,7 @@ appendToCommandPalette(SAVE_FILES_COMMAND_ID, { value: nls.localize('saveFiles', appendToCommandPalette(REVERT_FILE_COMMAND_ID, { value: nls.localize('revert', "Revert File"), original: 'Revert File' }, category); appendToCommandPalette(COMPARE_WITH_SAVED_COMMAND_ID, { value: nls.localize('compareActiveWithSaved', "Compare Active File with Saved"), original: 'Compare Active File with Saved' }, category); appendToCommandPalette(SAVE_FILE_AS_COMMAND_ID, { value: SAVE_FILE_AS_LABEL, original: 'Save As...' }, category); -appendToCommandPalette(NEW_FILE_COMMAND_ID, { value: NEW_FILE_LABEL, original: 'New Text File' }, category, WorkspaceFolderCountContext.notEqualsTo('0')); +appendToCommandPalette(NEW_FILE_COMMAND_ID, { value: NEW_FILE_LABEL, original: 'New File' }, category, WorkspaceFolderCountContext.notEqualsTo('0')); appendToCommandPalette(NEW_FOLDER_COMMAND_ID, { value: NEW_FOLDER_LABEL, original: 'New Folder' }, category, WorkspaceFolderCountContext.notEqualsTo('0')); appendToCommandPalette(NEW_UNTITLED_FILE_COMMAND_ID, { value: NEW_UNTITLED_FILE_LABEL, original: 'New Untitled File' }, category); diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index e482338009e..d3100d24946 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -53,7 +53,7 @@ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteA import { IPathService } from 'vs/workbench/services/path/common/pathService'; export const NEW_FILE_COMMAND_ID = 'explorer.newFile'; -export const NEW_FILE_LABEL = nls.localize('newFile', "New Text File"); +export const NEW_FILE_LABEL = nls.localize('newFile', "New File"); export const NEW_FOLDER_COMMAND_ID = 'explorer.newFolder'; export const NEW_FOLDER_LABEL = nls.localize('newFolder', "New Folder"); export const TRIGGER_RENAME_LABEL = nls.localize('rename', "Rename"); -- cgit v1.2.3 From 8cad47446f29c889b42f1678723fbc493d08d82f Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Wed, 20 Apr 2022 17:43:56 -0700 Subject: updates to the the new file flow refs #145046 --- .../codeEditor/browser/untitledTextEditorHint.ts | 34 +++++++++++----------- .../contrib/files/browser/views/explorerView.ts | 2 +- .../common/gettingStartedContent.ts | 4 +-- .../welcomeViews/common/newFile.contribution.ts | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts index c5e1a0cba17..353965fd9fa 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts @@ -106,6 +106,20 @@ class UntitledTextEditorHintContentWidget implements IContentWidget { if (!this.domNode) { this.domNode = $('.untitled-hint'); this.domNode.style.width = 'max-content'; + + const editorType = $('a.editor-type'); + editorType.style.cursor = 'pointer'; + editorType.innerText = localize('notLookingForTextEditor', "Not looking for a text editor?"); + const selectEditorTypeKeyBinding = this.keybindingService.lookupKeybinding('welcome.showNewFileEntries'); + const selectEditorTypeKeybindingLabel = selectEditorTypeKeyBinding?.getLabel(); + if (selectEditorTypeKeybindingLabel) { + editorType.title = localize('keyboardBindingTooltip', "{0}", selectEditorTypeKeybindingLabel); + } + this.domNode.appendChild(editorType); + + this.domNode.appendChild($('br')); + this.domNode.appendChild($('br')); + const language = $('a.language-mode'); language.style.cursor = 'pointer'; language.innerText = localize('selectAlanguage2', "Select a language"); @@ -116,20 +130,6 @@ class UntitledTextEditorHintContentWidget implements IContentWidget { } this.domNode.appendChild(language); - const or = $('span'); - or.innerText = localize('or', " or ",); - this.domNode.appendChild(or); - - const chooseEditor = $('a.choose-editor'); - chooseEditor.style.cursor = 'pointer'; - chooseEditor.innerText = localize('chooseEditor', "select a different editor"); - const chooseEditorKeyBinding = this.keybindingService.lookupKeybinding('welcome.showNewFileEntries'); - const chooseEditorKeybindingLabel = chooseEditorKeyBinding?.getLabel(); - if (chooseEditorKeybindingLabel) { - chooseEditor.title = localize('chooseEditorBindingTooltip', "{0}", chooseEditorKeybindingLabel); - } - this.domNode.appendChild(chooseEditor); - const toGetStarted = $('span'); toGetStarted.innerText = localize('toGetStarted', " to get started. Start typing to dismiss, or ",); this.domNode.appendChild(toGetStarted); @@ -165,9 +165,9 @@ class UntitledTextEditorHintContentWidget implements IContentWidget { this.editorGroupsService.activeGroup.closeEditor(activeEditorInput, { preserveFocus: true }); } }; - this.toDispose.push(dom.addDisposableListener(chooseEditor, 'click', chooseEditorOnClickOrTap)); - this.toDispose.push(dom.addDisposableListener(chooseEditor, GestureEventType.Tap, chooseEditorOnClickOrTap)); - this.toDispose.push(Gesture.addTarget(chooseEditor)); + this.toDispose.push(dom.addDisposableListener(editorType, 'click', chooseEditorOnClickOrTap)); + this.toDispose.push(dom.addDisposableListener(editorType, GestureEventType.Tap, chooseEditorOnClickOrTap)); + this.toDispose.push(Gesture.addTarget(editorType)); const dontShowOnClickOrTap = () => { this.configurationService.updateValue(untitledTextEditorHintSetting, 'hidden'); diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index a7885058f6a..c82cc35150a 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -891,7 +891,7 @@ registerAction2(class extends Action2 { constructor() { super({ id: 'workbench.files.action.createFileFromExplorer', - title: nls.localize('createNewEditor', "New Editor"), + title: nls.localize('createNewFile', "New File"), f1: false, icon: Codicon.newFile, precondition: ExplorerResourceNotReadonlyContext, diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/common/gettingStartedContent.ts b/src/vs/workbench/contrib/welcomeGettingStarted/common/gettingStartedContent.ts index ac4305b3e3d..a091be87b19 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/common/gettingStartedContent.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/common/gettingStartedContent.ts @@ -57,8 +57,8 @@ type GettingStartedStartEntryContent = BuiltinGettingStartedStartEntry[]; export const startEntries: GettingStartedStartEntryContent = [ { id: 'welcome.showNewFileEntries', - title: localize('gettingStarted.newEditor.title', "New Editor..."), - description: localize('gettingStarted.newEditor.description', "Open a new untitled file, notebook, or custom editor."), + title: localize('gettingStarted.newFile.title', "New File..."), + description: localize('gettingStarted.newFile.description', "Open a new untitled file, notebook, or custom editor."), icon: Codicon.newFile, content: { type: 'startEntry', diff --git a/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts b/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts index 3c20b55f28a..8b87c52e229 100644 --- a/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts +++ b/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.ts @@ -25,7 +25,7 @@ registerAction2(class extends Action2 { constructor() { super({ id: 'welcome.showNewFileEntries', - title: { value: localize('welcome.newEditor', "New Editor..."), original: 'New Editor...' }, + title: { value: localize('welcome.newFile', "New File..."), original: 'New File...' }, category, f1: true, keybinding: { -- cgit v1.2.3 From bd95a8d4516d590256eefecfce465a2f10e8f5e5 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 20 Apr 2022 20:38:20 -0700 Subject: Implement language detection for notebook cells (#147537) * Implement language detection for notebook cells * Add lightbulb for normal text editors as well Clean up mapping of language id's in neural model Add config to opt out of language detection hints --- .../browser/languageDetection.contribution.ts | 148 +++++++++++++++++++++ .../contrib/cellStatusBar/statusBarProviders.ts | 74 ++++++++++- .../notebook/browser/controller/editActions.ts | 66 ++++++--- .../contrib/notebook/browser/notebookBrowser.ts | 1 + 4 files changed, 270 insertions(+), 19 deletions(-) create mode 100644 src/vs/workbench/contrib/languageDetection/browser/languageDetection.contribution.ts (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/languageDetection/browser/languageDetection.contribution.ts b/src/vs/workbench/contrib/languageDetection/browser/languageDetection.contribution.ts new file mode 100644 index 00000000000..3df19dec7a5 --- /dev/null +++ b/src/vs/workbench/contrib/languageDetection/browser/languageDetection.contribution.ts @@ -0,0 +1,148 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { DisposableStore } from 'vs/base/common/lifecycle'; +import { getCodeEditor } from 'vs/editor/browser/editorBrowser'; +import { localize } from 'vs/nls'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { IStatusbarEntry, IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from 'vs/workbench/services/statusbar/browser/statusbar'; +import { ILanguageDetectionService } from 'vs/workbench/services/languageDetection/common/languageDetectionWorkerService'; +import { ThrottledDelayer } from 'vs/base/common/async'; +import { ILanguageService } from 'vs/editor/common/languages/language'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; +import { registerAction2, Action2 } from 'vs/platform/actions/common/actions'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { NOTEBOOK_EDITOR_EDITABLE } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; +import { Schemas } from 'vs/base/common/network'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; + +const detectLanguageCommandId = 'editor.detectLanguage'; + +class LanguageDetectionStatusContribution implements IWorkbenchContribution { + + private static readonly _id = 'status.languageDetectionStatus'; + + private readonly _disposables = new DisposableStore(); + private _combinedEntry?: IStatusbarEntryAccessor; + private _delayer = new ThrottledDelayer(1000); + private _renderDisposables = new DisposableStore(); + + constructor( + @ILanguageDetectionService private readonly _languageDetectionService: ILanguageDetectionService, + @IStatusbarService private readonly _statusBarService: IStatusbarService, + @IConfigurationService private readonly _configurationService: IConfigurationService, + @IEditorService private readonly _editorService: IEditorService, + @ILanguageService private readonly _languageService: ILanguageService, + @IKeybindingService private readonly _keybindingService: IKeybindingService, + ) { + _editorService.onDidActiveEditorChange(() => this._update(true), this, this._disposables); + this._update(false); + } + + dispose(): void { + this._disposables.dispose(); + this._delayer.dispose(); + this._combinedEntry?.dispose(); + this._renderDisposables.dispose(); + } + + private _update(clear: boolean): void { + if (clear) { + this._combinedEntry?.dispose(); + this._combinedEntry = undefined; + } + this._delayer.trigger(() => this._doUpdate()); + } + + private async _doUpdate(): Promise { + const editor = getCodeEditor(this._editorService.activeTextEditorControl); + + this._renderDisposables.clear(); + + // update when editor language changes + editor?.onDidChangeModelLanguage(() => this._update(true), this, this._renderDisposables); + editor?.onDidChangeModelContent(() => this._update(false), this, this._renderDisposables); + const editorModel = editor?.getModel(); + const editorUri = editorModel?.uri; + const existingId = editorModel?.getLanguageId(); + const enablementConfig = this._configurationService.getValue('workbench.editor.languageDetectionHints'); + const enabled = enablementConfig === 'always' || enablementConfig === 'textEditors'; + const disableLightbulb = !enabled || editorUri?.scheme !== Schemas.untitled || !existingId; + + if (disableLightbulb || !editorUri) { + this._combinedEntry?.dispose(); + this._combinedEntry = undefined; + } else { + const lang = await this._languageDetectionService.detectLanguage(editorUri); + const skip: Record = { 'jsonc': 'json' }; + const existing = editorModel.getLanguageId(); + if (lang && lang !== existing && skip[existing] !== lang) { + const detectedName = this._languageService.getLanguageName(lang) || lang; + let tooltip = localize('status.autoDetectLanguage', "Accept Detected Language: {0}", detectedName); + const keybinding = this._keybindingService.lookupKeybinding(detectLanguageCommandId); + const label = keybinding?.getLabel(); + if (label) { + tooltip += ` (${label})`; + } + + const props: IStatusbarEntry = { + name: localize('langDetection.name', "Language Detection"), + ariaLabel: localize('langDetection.aria', "Change to Detected Language: {0}", lang), + tooltip, + command: detectLanguageCommandId, + text: '$(lightbulb-autofix)', + }; + if (!this._combinedEntry) { + this._combinedEntry = this._statusBarService.addEntry(props, LanguageDetectionStatusContribution._id, StatusbarAlignment.RIGHT, { id: 'status.editor.mode', alignment: StatusbarAlignment.RIGHT, compact: true }); + } else { + this._combinedEntry.update(props); + } + } else { + this._combinedEntry?.dispose(); + this._combinedEntry = undefined; + } + } + } +} + +Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(LanguageDetectionStatusContribution, LifecyclePhase.Restored); + + +registerAction2(class extends Action2 { + + constructor() { + super({ + id: detectLanguageCommandId, + title: localize('detectlang', 'Detect Language from Content'), + f1: true, + precondition: ContextKeyExpr.and(NOTEBOOK_EDITOR_EDITABLE.toNegated(), EditorContextKeys.editorTextFocus), + keybinding: { primary: KeyCode.KeyE | KeyMod.CtrlCmd, weight: KeybindingWeight.WorkbenchContrib } + }); + } + + async run(accessor: ServicesAccessor): Promise { + const editorService = accessor.get(IEditorService); + const languageDetectionService = accessor.get(ILanguageDetectionService); + const editor = getCodeEditor(editorService.activeTextEditorControl); + const notificationService = accessor.get(INotificationService); + const editorUri = editor?.getModel()?.uri; + if (editorUri) { + const lang = await languageDetectionService.detectLanguage(editorUri); + if (lang) { + editor.getModel()?.setMode(lang); + } else { + notificationService.warn(localize('noDetection', "Unable to detect editor language")); + } + } + } +}); diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts b/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts index f1834e4ee96..3747a011ae7 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts @@ -3,18 +3,23 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Delayer } from 'vs/base/common/async'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Disposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { ILanguageService } from 'vs/editor/common/languages/language'; import { localize } from 'vs/nls'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; -import { CHANGE_CELL_LANGUAGE } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CHANGE_CELL_LANGUAGE, DETECT_CELL_LANGUAGE } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; import { CellKind, CellStatusbarAlignment, INotebookCellStatusBarItem, INotebookCellStatusBarItemList, INotebookCellStatusBarItemProvider } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; +import { ILanguageDetectionService } from 'vs/workbench/services/languageDetection/common/languageDetectionWorkerService'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; class CellStatusBarLanguagePickerProvider implements INotebookCellStatusBarItemProvider { @@ -50,6 +55,72 @@ class CellStatusBarLanguagePickerProvider implements INotebookCellStatusBarItemP } } +class CellStatusBarLanguageDetectionProvider implements INotebookCellStatusBarItemProvider { + + readonly viewType = '*'; + + private delayer = new Delayer(500); + + constructor( + @INotebookService private readonly _notebookService: INotebookService, + @INotebookKernelService private readonly _notebookKernelService: INotebookKernelService, + @ILanguageService private readonly _languageService: ILanguageService, + @IConfigurationService private readonly _configurationService: IConfigurationService, + @ILanguageDetectionService private readonly _languageDetectionService: ILanguageDetectionService, + @IKeybindingService private readonly _keybindingService: IKeybindingService, + ) { } + + async provideCellStatusBarItems(uri: URI, index: number, token: CancellationToken): Promise { + return await this.delayer.trigger(async () => { + const doc = this._notebookService.getNotebookTextModel(uri); + const cell = doc?.cells[index]; + if (!cell || token.isCancellationRequested) { + return; + } + + const enablementConfig = this._configurationService.getValue('workbench.editor.languageDetectionHints'); + const enabled = enablementConfig === 'always' || enablementConfig === 'notebookEditors'; + if (!enabled) { + return; + } + + const currentLanguageId = cell.cellKind === CellKind.Markup ? + 'markdown' : + (this._languageService.getLanguageIdByLanguageName(cell.language) || cell.language); + + const kernel = this._notebookKernelService.getMatchingKernel(doc); + const items: INotebookCellStatusBarItem[] = []; + + if (kernel.selected) { + const availableLangs = []; + availableLangs.push(...kernel.selected.supportedLanguages, 'markdown'); + const detectedLanguageId = await this._languageDetectionService.detectLanguage(cell.uri, availableLangs); + + if (detectedLanguageId && currentLanguageId !== detectedLanguageId) { + const detectedName = this._languageService.getLanguageName(detectedLanguageId) || detectedLanguageId; + let tooltip = localize('notebook.cell.status.autoDetectLanguage', "Accept Detected Language: {0}", detectedName); + const keybinding = this._keybindingService.lookupKeybinding(DETECT_CELL_LANGUAGE); + const label = keybinding?.getLabel(); + if (label) { + tooltip += ` (${label})`; + } + + items.push({ + text: '$(lightbulb-autofix)', + command: DETECT_CELL_LANGUAGE, + tooltip, + alignment: CellStatusbarAlignment.Right, + priority: -Number.MAX_SAFE_INTEGER + 1 + }); + } + } + + return { items }; + }); + + } +} + class BuiltinCellStatusBarProviders extends Disposable { constructor( @IInstantiationService instantiationService: IInstantiationService, @@ -58,6 +129,7 @@ class BuiltinCellStatusBarProviders extends Disposable { const builtinProviders = [ CellStatusBarLanguagePickerProvider, + CellStatusBarLanguageDetectionProvider, ]; builtinProviders.forEach(p => { this._register(notebookCellStatusBarService.registerCellStatusBarItemProvider(instantiationService.createInstance(p))); diff --git a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts index 588675f6403..27a1c5b7c21 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts @@ -21,12 +21,13 @@ import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/ import { changeCellToKind, runDeleteAction } from 'vs/workbench/contrib/notebook/browser/controller/cellOperations'; import { CellToolbarOrder, CELL_TITLE_CELL_GROUP_ID, CELL_TITLE_OUTPUT_GROUP_ID, executeNotebookCondition, INotebookActionContext, INotebookCellActionContext, NotebookAction, NotebookCellAction, NOTEBOOK_EDITOR_WIDGET_ACTION_WEIGHT } from 'vs/workbench/contrib/notebook/browser/controller/coreActions'; import { NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_HAS_OUTPUTS, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_USE_CONSOLIDATED_OUTPUT_BUTTON } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; -import { CellEditState, CHANGE_CELL_LANGUAGE, QUIT_EDIT_CELL_COMMAND_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, CHANGE_CELL_LANGUAGE, DETECT_CELL_LANGUAGE, QUIT_EDIT_CELL_COMMAND_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import * as icons from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { CellEditType, CellKind, ICellEditOperation, NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; import { ILanguageDetectionService } from 'vs/workbench/services/languageDetection/common/languageDetectionWorkerService'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; +import { INotificationService } from 'vs/platform/notification/common/notification'; const CLEAR_ALL_CELLS_OUTPUTS_COMMAND_ID = 'notebook.clearAllCellsOutputs'; const EDIT_CELL_COMMAND_ID = 'notebook.cell.edit'; @@ -437,23 +438,7 @@ registerAction2(class ChangeCellLanguageAction extends NotebookCellAction undefined, undefined, true - ); - } + await setCellToLanguage(languageId, context); } /** @@ -478,3 +463,48 @@ registerAction2(class ChangeCellLanguageAction extends NotebookCellAction { + const languageDetectionService = accessor.get(ILanguageDetectionService); + const notificationService = accessor.get(INotificationService); + const providerLanguages = [...context.notebookEditor.activeKernel?.supportedLanguages ?? []]; + providerLanguages.push('markdown'); + const detection = await languageDetectionService.detectLanguage(context.cell.uri, providerLanguages); + if (detection) { + setCellToLanguage(detection, context); + } else { + notificationService.warn(localize('noDetection', "Unable to detect cell language")); + } + } +}); + +async function setCellToLanguage(languageId: string, context: IChangeCellContext) { + if (languageId === 'markdown' && context.cell?.language !== 'markdown') { + const idx = context.notebookEditor.getCellIndex(context.cell); + await changeCellToKind(CellKind.Markup, { cell: context.cell, notebookEditor: context.notebookEditor, ui: true }, 'markdown', Mimes.markdown); + const newCell = context.notebookEditor.cellAt(idx); + + if (newCell) { + context.notebookEditor.focusNotebookCell(newCell, 'editor'); + } + } else if (languageId !== 'markdown' && context.cell?.cellKind === CellKind.Markup) { + await changeCellToKind(CellKind.Code, { cell: context.cell, notebookEditor: context.notebookEditor, ui: true }, languageId); + } else { + const index = context.notebookEditor.textModel.cells.indexOf(context.cell.model); + context.notebookEditor.textModel.applyEdits( + [{ editType: CellEditType.CellLanguage, index, language: languageId }], + true, undefined, () => undefined, undefined, true + ); + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 7153bcfe26c..34c9a2afe21 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -31,6 +31,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; //#region Shared commands export const EXPAND_CELL_INPUT_COMMAND_ID = 'notebook.cell.expandCellInput'; export const EXECUTE_CELL_COMMAND_ID = 'notebook.cell.execute'; +export const DETECT_CELL_LANGUAGE = 'notebook.cell.detectLanguage'; export const CHANGE_CELL_LANGUAGE = 'notebook.cell.changeLanguage'; export const QUIT_EDIT_CELL_COMMAND_ID = 'notebook.cell.quitEdit'; export const EXPAND_CELL_OUTPUT_COMMAND_ID = 'notebook.cell.expandCellOutput'; -- cgit v1.2.3 From 2fdb06ca285bf34c80e2425495677250b219fd2c Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Thu, 21 Apr 2022 10:17:48 -0400 Subject: Add minimum visible count to open editors (#147771) --- src/vs/workbench/contrib/files/browser/files.contribution.ts | 8 +++++++- src/vs/workbench/contrib/files/browser/views/openEditorsView.ts | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/browser/files.contribution.ts b/src/vs/workbench/contrib/files/browser/files.contribution.ts index 1a6f2c8f672..c113c495f27 100644 --- a/src/vs/workbench/contrib/files/browser/files.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/files.contribution.ts @@ -337,10 +337,16 @@ configurationRegistry.registerConfiguration({ 'properties': { 'explorer.openEditors.visible': { 'type': 'number', - 'description': nls.localize({ key: 'openEditorsVisible', comment: ['Open is an adjective'] }, "Number of editors shown in the Open Editors pane. Setting this to 0 hides the Open Editors pane."), + 'description': nls.localize({ key: 'openEditorsVisible', comment: ['Open is an adjective'] }, "The maximum number of editors shown in the Open Editors pane. Setting this to 0 hides the Open Editors pane."), 'default': 9, 'minimum': 0 }, + 'explorer.openEditors.minVisible': { + 'type': 'number', + 'description': nls.localize({ key: 'openEditorsVisibleMin', comment: ['Open is an adjective'] }, "The minimum number of editor slots shown in the Open Editors pane. If set to 0 the Open Editors pane will dynamically resize based on the number of editors."), + 'default': 0, + 'minimum': 0 + }, 'explorer.openEditors.sortOrder': { 'type': 'string', 'enum': ['editorOrder', 'alphabetical', 'fullPath'], diff --git a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts index b7bc23b3257..06ba5acdbde 100644 --- a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts @@ -59,6 +59,7 @@ const $ = dom.$; export class OpenEditorsView extends ViewPane { private static readonly DEFAULT_VISIBLE_OPEN_EDITORS = 9; + private static readonly DEFAULT_MIN_VISIBLE_OPEN_EDITORS = 0; static readonly ID = 'workbench.explorer.openEditorsView'; static readonly NAME = nls.localize({ key: 'openEditors', comment: ['Open is an adjective'] }, "Open Editors"); @@ -466,12 +467,17 @@ export class OpenEditorsView extends ViewPane { } private getMaxExpandedBodySize(): number { + let minVisibleOpenEditors = this.configurationService.getValue('explorer.openEditors.minVisible'); + // If it's not a number setting it to 0 will result in dynamic resizing. + if (typeof minVisibleOpenEditors !== 'number') { + minVisibleOpenEditors = OpenEditorsView.DEFAULT_MIN_VISIBLE_OPEN_EDITORS; + } const containerModel = this.viewDescriptorService.getViewContainerModel(this.viewDescriptorService.getViewContainerByViewId(this.id)!)!; if (containerModel.visibleViewDescriptors.length <= 1) { return Number.POSITIVE_INFINITY; } - return this.elementCount * OpenEditorsDelegate.ITEM_HEIGHT; + return (Math.max(this.elementCount, minVisibleOpenEditors)) * OpenEditorsDelegate.ITEM_HEIGHT; } private getMinExpandedBodySize(): number { -- cgit v1.2.3 From e4d0a1ff061ca8bc23c4459d6b38318354ba517b Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 21 Apr 2022 15:30:33 -0700 Subject: Support indexed base cell options. --- .../contrib/notebook/browser/notebookBrowser.ts | 3 ++- .../notebook/browser/notebookEditorWidget.ts | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 34c9a2afe21..77a50b8c655 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -11,7 +11,7 @@ import { IEditorContributionDescription } from 'vs/editor/browser/editorExtensio import * as editorCommon from 'vs/editor/common/editorCommon'; import { FontInfo } from 'vs/editor/common/config/fontInfo'; import { IPosition } from 'vs/editor/common/core/position'; -import { Range } from 'vs/editor/common/core/range'; +import { IRange, Range } from 'vs/editor/common/core/range'; import { FindMatch, IModelDeltaDecoration, IReadonlyTextBuffer, ITextModel, TrackedRangeStickiness } from 'vs/editor/common/model'; import { MenuId } from 'vs/platform/actions/common/actions'; import { ITextEditorOptions, ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; @@ -281,6 +281,7 @@ export interface INotebookEditorOptions extends ITextEditorOptions { readonly cellSelections?: ICellRange[]; readonly isReadOnly?: boolean; readonly viewState?: INotebookEditorViewState; + readonly indexedCellOptions?: { index: number; selection?: IRange }; } export type INotebookEditorContributionCtor = IConstructorSignature; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 40712d1eaa3..942f49772ca 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1220,8 +1220,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD this.viewModel.updateOptions({ isReadOnly: this._readOnly }); // reveal cell if editor options tell to do so - if (options?.cellOptions) { - const cellOptions = options.cellOptions; + const cellOptions = options?.cellOptions ?? this._parseIndexedCellOptions(options); + if (cellOptions) { const cell = this.viewModel.viewCells.find(cell => cell.uri.toString() === cellOptions.resource.toString()); if (cell) { this.focusElement(cell); @@ -1274,6 +1274,24 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD this._onDidChangeOptions.fire(); } + private _parseIndexedCellOptions(options: INotebookEditorOptions | undefined) { + if (options?.indexedCellOptions) { + // convert index based selections + const cell = this.cellAt(options.indexedCellOptions.index); + if (cell) { + return { + resource: cell.uri, + options: { + selection: options.indexedCellOptions.selection, + preserveFocus: false + } + }; + } + } + + return undefined; + } + private _detachModel() { this._localStore.clear(); dispose(this._localCellStateListeners); -- cgit v1.2.3 From 1e55117c0247a11952a2dca4ba10176831b09f1c Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 21 Apr 2022 09:56:20 -0700 Subject: Fix bad regex #145265 --- src/vs/workbench/contrib/debug/node/terminals.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/node/terminals.ts b/src/vs/workbench/contrib/debug/node/terminals.ts index d4338a5c04c..5418d9e8ffc 100644 --- a/src/vs/workbench/contrib/debug/node/terminals.ts +++ b/src/vs/workbench/contrib/debug/node/terminals.ts @@ -139,7 +139,7 @@ export function prepareCommand(shell: string, args: string[], cwd?: string, env? if (value === null) { command += `set "${key}=" && `; } else { - value = value.replace(/[^&|<>]/g, s => `^${s}`); + value = value.replace(/[&^|<>]/g, s => `^${s}`); command += `set "${key}=${value}" && `; } } -- cgit v1.2.3 From 9425cdded7fd229fd83df46774620f53e3106acc Mon Sep 17 00:00:00 2001 From: Max Belsky Date: Fri, 22 Apr 2022 01:06:23 +0200 Subject: Disable a breakpoint on shift+click (#147598) * Disable a breakpoint on shift+click * Disable a condition breakpoint/logpoint on shift+click * Update variable names * Apply suggestions from review * Fix shift+click for enabling conditional breakpoints * Remove duplicated check Co-authored-by: Rob Lourens --- .../debug/browser/breakpointEditorContribution.ts | 36 ++++++++++++++-------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts index 7d8351ddb7d..4eab6791a7f 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts @@ -235,38 +235,48 @@ export class BreakpointEditorContribution implements IBreakpointEditorContributi const breakpoints = this.debugService.getModel().getBreakpoints({ uri, lineNumber }); if (breakpoints.length) { - // Show the dialog if there is a potential condition to be accidently lost. - // Do not show dialog on linux due to electron issue freezing the mouse #50026 - if (!env.isLinux && breakpoints.some(bp => !!bp.condition || !!bp.logMessage || !!bp.hitCondition)) { + const isShiftPressed = e.event.shiftKey; + const enabled = breakpoints.some(bp => bp.enabled); + + if (isShiftPressed) { + breakpoints.forEach(bp => this.debugService.enableOrDisableBreakpoints(!enabled, bp)); + } else if (!env.isLinux && breakpoints.some(bp => !!bp.condition || !!bp.logMessage || !!bp.hitCondition)) { + // Show the dialog if there is a potential condition to be accidently lost. + // Do not show dialog on linux due to electron issue freezing the mouse #50026 const logPoint = breakpoints.every(bp => !!bp.logMessage); const breakpointType = logPoint ? nls.localize('logPoint', "Logpoint") : nls.localize('breakpoint', "Breakpoint"); - const disable = breakpoints.some(bp => bp.enabled); - const enabling = nls.localize('breakpointHasConditionDisabled', + const disabledBreakpointDialogMessage = nls.localize( + 'breakpointHasConditionDisabled', "This {0} has a {1} that will get lost on remove. Consider enabling the {0} instead.", breakpointType.toLowerCase(), logPoint ? nls.localize('message', "message") : nls.localize('condition', "condition") ); - const disabling = nls.localize('breakpointHasConditionEnabled', + const enabledBreakpointDialogMessage = nls.localize( + 'breakpointHasConditionEnabled', "This {0} has a {1} that will get lost on remove. Consider disabling the {0} instead.", breakpointType.toLowerCase(), logPoint ? nls.localize('message', "message") : nls.localize('condition', "condition") ); - const { choice } = await this.dialogService.show(severity.Info, disable ? disabling : enabling, [ - nls.localize('removeLogPoint', "Remove {0}", breakpointType), - nls.localize('disableLogPoint', "{0} {1}", disable ? nls.localize('disable', "Disable") : nls.localize('enable', "Enable"), breakpointType), - nls.localize('cancel', "Cancel") - ], { cancelId: 2 }); + const { choice } = await this.dialogService.show( + severity.Info, + enabled ? enabledBreakpointDialogMessage : disabledBreakpointDialogMessage, + [ + nls.localize('removeLogPoint', "Remove {0}", breakpointType), + nls.localize('disableLogPoint', "{0} {1}", enabled ? nls.localize('disable', "Disable") : nls.localize('enable', "Enable"), breakpointType), + nls.localize('cancel', "Cancel") + ], + { cancelId: 2 }, + ); if (choice === 0) { breakpoints.forEach(bp => this.debugService.removeBreakpoints(bp.getId())); } if (choice === 1) { - breakpoints.forEach(bp => this.debugService.enableOrDisableBreakpoints(!disable, bp)); + breakpoints.forEach(bp => this.debugService.enableOrDisableBreakpoints(!enabled, bp)); } } else { - const enabled = breakpoints.some(bp => bp.enabled); if (!enabled) { breakpoints.forEach(bp => this.debugService.enableOrDisableBreakpoints(!enabled, bp)); } else { -- cgit v1.2.3 From 3c8d308a1f1f5a80c605912ba761ea0cbfac866c Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Thu, 21 Apr 2022 16:59:35 -0700 Subject: add max threshold for find results for which to show decorations (#147879) --- .../contrib/codeEditor/browser/find/simpleFindWidget.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts index 1e220e2de14..f49139355d7 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts @@ -12,13 +12,14 @@ import { Delayer } from 'vs/base/common/async'; import { KeyCode } from 'vs/base/common/keyCodes'; import { FindReplaceState } from 'vs/editor/contrib/find/browser/findState'; import { IMessage as InputBoxMessage } from 'vs/base/browser/ui/inputbox/inputBox'; -import { SimpleButton, findPreviousMatchIcon, findNextMatchIcon } from 'vs/editor/contrib/find/browser/findWidget'; +import { SimpleButton, findPreviousMatchIcon, findNextMatchIcon, NLS_NO_RESULTS, NLS_MATCHES_LOCATION } from 'vs/editor/contrib/find/browser/findWidget'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { editorWidgetBackground, inputActiveOptionBorder, inputActiveOptionBackground, inputActiveOptionForeground, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationWarningForeground, widgetShadow, editorWidgetForeground, errorForeground } from 'vs/platform/theme/common/colorRegistry'; import { IColorTheme, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { ContextScopedFindInput } from 'vs/platform/history/browser/contextScopedHistoryWidget'; import { widgetClose } from 'vs/platform/theme/common/iconRegistry'; +import * as strings from 'vs/base/common/strings'; const NLS_FIND_INPUT_LABEL = nls.localize('label.find', "Find"); const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find"); @@ -307,7 +308,12 @@ export abstract class SimpleFindWidget extends Widget { this._matchesCount.className = 'matchesCount'; } this._matchesCount.innerText = ''; - const label = count === undefined || count.resultCount === 0 ? `No Results` : `${count.resultIndex + 1} of ${count.resultCount}`; + let label; + if (count?.resultCount === -1) { + label = ''; + } else { + label = count === undefined || count.resultCount === 0 ? NLS_NO_RESULTS : strings.format(NLS_MATCHES_LOCATION, count.resultIndex + 1, count?.resultCount); + } this._matchesCount.appendChild(document.createTextNode(label)); this._matchesCount.classList.toggle('no-results', !count || count.resultCount === 0); this._findInput?.domNode.insertAdjacentElement('afterend', this._matchesCount); -- cgit v1.2.3 From d982c14b664f8b6fcd649a31272066f129227306 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Thu, 21 Apr 2022 23:05:39 -0700 Subject: fix non windows shell type context key (#147884) --- src/vs/workbench/contrib/terminal/browser/terminalInstance.ts | 9 ++++----- src/vs/workbench/contrib/terminal/browser/terminalService.ts | 7 +++++++ 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 18be1c0ae4a..0adfa2cee9d 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -460,6 +460,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { // Re-establish the title after reconnect if (this.shellLaunchConfig.attachPersistentProcess) { this.refreshTabLabels(this.shellLaunchConfig.attachPersistentProcess.title, this.shellLaunchConfig.attachPersistentProcess.titleSource); + this.setShellType(this.shellType); } if (this._fixedCols) { @@ -1098,11 +1099,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._register(dom.addDisposableListener(xterm.raw.textarea, 'focus', () => { this._terminalFocusContextKey.set(true); - if (this.shellType) { - this._terminalShellTypeContextKey.set(this.shellType.toString()); - } else { - this._terminalShellTypeContextKey.reset(); - } this._onDidFocus.fire(this); })); @@ -1882,6 +1878,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { setShellType(shellType: TerminalShellType) { this._shellType = shellType; + if (shellType) { + this._terminalShellTypeContextKey.set(shellType?.toString()); + } } private _setAriaLabel(xterm: XTermTerminal | undefined, terminalId: number, title: string | undefined): void { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 8402e0e5362..62d52e82cc9 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -52,6 +52,7 @@ export class TerminalService implements ITerminalService { private _hostActiveTerminals: Map = new Map(); private _terminalEditorActive: IContextKey; + private readonly _terminalShellTypeContextKey: IContextKey; private _escapeSequenceLoggingEnabled: boolean = false; @@ -187,9 +188,15 @@ export class TerminalService implements ITerminalService { if (!instance && !this._isShuttingDown) { this._terminalGroupService.hidePanel(); } + if (instance?.shellType) { + this._terminalShellTypeContextKey.set(instance.shellType.toString()); + } else if (!instance) { + this._terminalShellTypeContextKey.reset(); + } }); this._handleInstanceContextKeys(); + this._terminalShellTypeContextKey = TerminalContextKeys.shellType.bindTo(this._contextKeyService); this._processSupportContextKey = TerminalContextKeys.processSupported.bindTo(this._contextKeyService); this._processSupportContextKey.set(!isWeb || this._remoteAgentService.getConnection() !== null); this._terminalHasBeenCreated = TerminalContextKeys.terminalHasBeenCreated.bindTo(this._contextKeyService); -- cgit v1.2.3 From e30ef407d10c65ab987ff4b639d051e23cd10a9a Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 22 Apr 2022 14:37:54 +0300 Subject: Fixes #146412 --- .../extensions/browser/extensions.contribution.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index 41515d1c2e2..ebbd930216f 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -200,9 +200,12 @@ Registry.as(ConfigurationExtensions.Configuration) } }, additionalProperties: false, - default: { - 'pub.name': false - } + default: {}, + defaultSnippets: [{ + 'body': { + 'pub.name': false + } + }] }, 'extensions.experimental.affinity': { type: 'object', @@ -214,9 +217,12 @@ Registry.as(ConfigurationExtensions.Configuration) } }, additionalProperties: false, - default: { - 'pub.name': 1 - } + default: {}, + defaultSnippets: [{ + 'body': { + 'pub.name': 1 + } + }] }, [WORKSPACE_TRUST_EXTENSION_SUPPORT]: { type: 'object', -- cgit v1.2.3 From bf58654958c3632475794f487531476d97e26de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 22 Apr 2022 14:41:47 +0200 Subject: fixes #147198 --- src/vs/workbench/contrib/scm/browser/scmViewPane.ts | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 79cce93a380..f1444d0fd6b 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -2381,6 +2381,10 @@ export class SCMViewPane extends ViewPane { override shouldShowWelcome(): boolean { return this.scmService.repositories.length === 0; } + + override getActionsContext(): unknown { + return this.scmViewService.visibleRepositories.length === 1 ? this.scmViewService.visibleRepositories[0].provider : undefined; + } } export const scmProviderSeparatorBorderColor = registerColor('scm.providerBorder', { dark: '#454545', light: '#C8C8C8', hcDark: contrastBorder, hcLight: contrastBorder }, localize('scm.providerBorder', "SCM Provider separator border.")); -- cgit v1.2.3 From b6dedccf52e9d27f31e5f46c3ecb9c694fbe350d Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Fri, 22 Apr 2022 15:14:46 +0200 Subject: SCM - surface sorting options in the menus (#147825) --- .../workbench/contrib/scm/browser/scmViewPane.ts | 55 +++++++++++++++++++++- .../contrib/scm/browser/scmViewService.ts | 53 ++++++++++++--------- src/vs/workbench/contrib/scm/common/scm.ts | 8 ++++ 3 files changed, 93 insertions(+), 23 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index f1444d0fd6b..cadb081fece 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -10,7 +10,7 @@ import { IDisposable, Disposable, DisposableStore, combinedDisposable, dispose, import { ViewPane, IViewPaneOptions, ViewAction } from 'vs/workbench/browser/parts/views/viewPane'; import { append, $, Dimension, asCSSUrl, trackFocus, clearNode } from 'vs/base/browser/dom'; import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list'; -import { ISCMResourceGroup, ISCMResource, InputValidationType, ISCMRepository, ISCMInput, IInputValidation, ISCMViewService, ISCMViewVisibleRepositoryChangeEvent, ISCMService, SCMInputChangeReason, VIEW_PANE_ID, ISCMActionButton, ISCMActionButtonDescriptor } from 'vs/workbench/contrib/scm/common/scm'; +import { ISCMResourceGroup, ISCMResource, InputValidationType, ISCMRepository, ISCMInput, IInputValidation, ISCMViewService, ISCMViewVisibleRepositoryChangeEvent, ISCMService, SCMInputChangeReason, VIEW_PANE_ID, ISCMActionButton, ISCMActionButtonDescriptor, ISCMRepositorySortKey, REPOSITORIES_VIEW_PANE_ID } from 'vs/workbench/contrib/scm/common/scm'; import { ResourceLabels, IResourceLabel, IFileLabelOptions } from 'vs/workbench/browser/labels'; import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -84,6 +84,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { MarkdownRenderer } from 'vs/editor/contrib/markdownRenderer/browser/markdownRenderer'; import { Button, ButtonWithDescription } from 'vs/base/browser/ui/button/button'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { RepositoryContextKeys } from 'vs/workbench/contrib/scm/browser/scmViewService'; type TreeElement = ISCMRepository | ISCMInput | ISCMActionButton | ISCMResourceGroup | IResourceNode | ISCMResource; @@ -944,7 +945,7 @@ class RepositoryVisibilityAction extends Action2 { f1: false, precondition: ContextKeyExpr.or(ContextKeys.RepositoryVisibilityCount.notEqualsTo(1), ContextKeys.RepositoryVisibility(repository).isEqualTo(false)), toggled: ContextKeys.RepositoryVisibility(repository).isEqualTo(true), - menu: { id: Menus.Repositories } + menu: { id: Menus.Repositories, group: '0_repositories' } }); this.repository = repository; } @@ -1503,6 +1504,56 @@ registerAction2(SetTreeViewModeAction); registerAction2(SetListViewModeNavigationAction); registerAction2(SetTreeViewModeNavigationAction); +abstract class RepositorySortAction extends ViewAction { + constructor(private sortKey: ISCMRepositorySortKey, title: string) { + super({ + id: `workbench.scm.action.repositories.setSortKey.${sortKey}`, + title, + viewId: VIEW_PANE_ID, + f1: false, + toggled: RepositoryContextKeys.RepositorySortKey.isEqualTo(sortKey), + menu: [ + { + id: Menus.Repositories, + group: '1_sort' + }, + { + id: MenuId.ViewTitle, + when: ContextKeyExpr.equals('view', REPOSITORIES_VIEW_PANE_ID), + group: '1_sort', + }, + ] + }); + } + + runInView(accessor: ServicesAccessor) { + accessor.get(ISCMViewService).toggleSortKey(this.sortKey); + } +} + + +class RepositorySortByDiscoveryTimeAction extends RepositorySortAction { + constructor() { + super(ISCMRepositorySortKey.DiscoveryTime, localize('repositorySortByDiscoveryTime', "Sort by Discovery Time")); + } +} + +class RepositorySortByNameAction extends RepositorySortAction { + constructor() { + super(ISCMRepositorySortKey.Name, localize('repositorySortByName', "Sort by Name")); + } +} + +class RepositorySortByPathAction extends RepositorySortAction { + constructor() { + super(ISCMRepositorySortKey.Path, localize('repositorySortByPath', "Sort by Path")); + } +} + +registerAction2(RepositorySortByDiscoveryTimeAction); +registerAction2(RepositorySortByNameAction); +registerAction2(RepositorySortByPathAction); + abstract class SetSortKeyAction extends ViewAction { constructor(private sortKey: ViewModelSortKey, title: string) { super({ diff --git a/src/vs/workbench/contrib/scm/browser/scmViewService.ts b/src/vs/workbench/contrib/scm/browser/scmViewService.ts index caba59981f3..be0176c4919 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewService.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewService.ts @@ -5,7 +5,7 @@ import { DisposableStore } from 'vs/base/common/lifecycle'; import { Emitter, Event } from 'vs/base/common/event'; -import { ISCMViewService, ISCMRepository, ISCMService, ISCMViewVisibleRepositoryChangeEvent, ISCMMenus, ISCMProvider } from 'vs/workbench/contrib/scm/common/scm'; +import { ISCMViewService, ISCMRepository, ISCMService, ISCMViewVisibleRepositoryChangeEvent, ISCMMenus, ISCMProvider, ISCMRepositorySortKey } from 'vs/workbench/contrib/scm/common/scm'; import { Iterable } from 'vs/base/common/iterator'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { SCMMenus } from 'vs/workbench/contrib/scm/browser/menus'; @@ -16,6 +16,7 @@ import { compareFileNames, comparePaths } from 'vs/base/common/comparers'; import { basename } from 'vs/base/common/resources'; import { binarySearch } from 'vs/base/common/arrays'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; function getProviderStorageKey(provider: ISCMProvider): string { return `${provider.contextValue}:${provider.label}${provider.rootUri ? `:${provider.rootUri.toString()}` : ''}`; @@ -30,7 +31,9 @@ function getRepositoryName(workspaceContextService: IWorkspaceContextService, re return folder?.uri.toString() === repository.provider.rootUri.toString() ? folder.name : basename(repository.provider.rootUri); } -type ISCMRepositoryViewSortKey = 'discovery time' | 'name' | 'path'; +export const RepositoryContextKeys = { + RepositorySortKey: new RawContextKey('scmRepositorySortKey', ISCMRepositorySortKey.DiscoveryTime), +}; interface ISCMRepositoryView { readonly repository: ISCMRepository; @@ -41,7 +44,7 @@ interface ISCMRepositoryView { export interface ISCMViewServiceState { readonly all: string[]; - readonly sortKey: ISCMRepositoryViewSortKey; + readonly sortKey: ISCMRepositorySortKey; readonly visible: number[]; } @@ -65,7 +68,7 @@ export class SCMViewService implements ISCMViewService { get visibleRepositories(): ISCMRepository[] { // In order to match the legacy behaviour, when the repositories are sorted by discovery time, // the visible repositories are sorted by the selection index instead of the discovery time. - if (this._repositoriesSortKey === 'discovery time') { + if (this._repositoriesSortKey === ISCMRepositorySortKey.DiscoveryTime) { return this._repositories.filter(r => r.selectionIndex !== -1) .sort((r1, r2) => r1.selectionIndex - r2.selectionIndex) .map(r => r.repository); @@ -150,10 +153,12 @@ export class SCMViewService implements ISCMViewService { private _onDidFocusRepository = new Emitter(); readonly onDidFocusRepository = this._onDidFocusRepository.event; - private _repositoriesSortKey: ISCMRepositoryViewSortKey; + private _repositoriesSortKey: ISCMRepositorySortKey; + private _sortKeyContextKey: IContextKey; constructor( @ISCMService scmService: ISCMService, + @IContextKeyService contextKeyService: IContextKeyService, @IInstantiationService instantiationService: IInstantiationService, @IConfigurationService private readonly configurationService: IConfigurationService, @IStorageService private readonly storageService: IStorageService, @@ -168,19 +173,12 @@ export class SCMViewService implements ISCMViewService { } this._repositoriesSortKey = this.previousState?.sortKey ?? this.getViewSortOrder(); + this._sortKeyContextKey = RepositoryContextKeys.RepositorySortKey.bindTo(contextKeyService); + this._sortKeyContextKey.set(this._repositoriesSortKey); scmService.onDidAddRepository(this.onDidAddRepository, this, this.disposables); scmService.onDidRemoveRepository(this.onDidRemoveRepository, this, this.disposables); - configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration('scm.repositories.sortOrder')) { - this._repositoriesSortKey = this.getViewSortOrder(); - this._repositories.sort(this.compareRepositories.bind(this)); - - this._onDidChangeRepositories.fire({ added: Iterable.empty(), removed: Iterable.empty() }); - } - }); - for (const repository of scmService.repositories) { this.onDidAddRepository(repository); } @@ -303,6 +301,14 @@ export class SCMViewService implements ISCMViewService { } } + toggleSortKey(sortKey: ISCMRepositorySortKey): void { + this._repositoriesSortKey = sortKey; + this._sortKeyContextKey.set(this._repositoriesSortKey); + this._repositories.sort(this.compareRepositories.bind(this)); + + this._onDidChangeRepositories.fire({ added: Iterable.empty(), removed: Iterable.empty() }); + } + focus(repository: ISCMRepository | undefined): void { if (repository && !this.isVisible(repository)) { return; @@ -317,7 +323,7 @@ export class SCMViewService implements ISCMViewService { private compareRepositories(op1: ISCMRepositoryView, op2: ISCMRepositoryView): number { // Sort by discovery time - if (this._repositoriesSortKey === 'discovery time') { + if (this._repositoriesSortKey === ISCMRepositorySortKey.DiscoveryTime) { return op1.discoveryTime - op2.discoveryTime; } @@ -343,13 +349,18 @@ export class SCMViewService implements ISCMViewService { Math.max(...this._repositories.map(r => r.selectionIndex)); } - private getViewSortOrder(): ISCMRepositoryViewSortKey { - const sortOder = this.configurationService.getValue('scm.repositories.sortOrder'); - if (sortOder !== 'discovery time' && sortOder !== 'name' && sortOder !== 'path') { - return 'discovery time'; + private getViewSortOrder(): ISCMRepositorySortKey { + const sortOder = this.configurationService.getValue<'discovery time' | 'name' | 'path'>('scm.repositories.sortOrder'); + switch (sortOder) { + case 'discovery time': + return ISCMRepositorySortKey.DiscoveryTime; + case 'name': + return ISCMRepositorySortKey.Name; + case 'path': + return ISCMRepositorySortKey.Path; + default: + return ISCMRepositorySortKey.DiscoveryTime; } - - return sortOder; } private insertRepositoryView(repositories: ISCMRepositoryView[], repositoryView: ISCMRepositoryView): void { diff --git a/src/vs/workbench/contrib/scm/common/scm.ts b/src/vs/workbench/contrib/scm/common/scm.ts index c46af5c54b5..a70726447a1 100644 --- a/src/vs/workbench/contrib/scm/common/scm.ts +++ b/src/vs/workbench/contrib/scm/common/scm.ts @@ -168,6 +168,12 @@ export interface ISCMMenus { getRepositoryMenus(provider: ISCMProvider): ISCMRepositoryMenus; } +export const enum ISCMRepositorySortKey { + DiscoveryTime = 'discoveryTime', + Name = 'name', + Path = 'path' +} + export const ISCMViewService = createDecorator('scmView'); export interface ISCMViewVisibleRepositoryChangeEvent { @@ -189,6 +195,8 @@ export interface ISCMViewService { isVisible(repository: ISCMRepository): boolean; toggleVisibility(repository: ISCMRepository, visible?: boolean): void; + toggleSortKey(sortKey: ISCMRepositorySortKey): void; + readonly focusedRepository: ISCMRepository | undefined; readonly onDidFocusRepository: Event; focus(repository: ISCMRepository): void; -- cgit v1.2.3 From 93c682fe068bc5517e2a04b7ef9847f39d917f30 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Fri, 22 Apr 2022 15:16:17 +0200 Subject: Polish changes sorting (#147849) --- .../contrib/scm/browser/scm.contribution.ts | 2 +- .../workbench/contrib/scm/browser/scmViewPane.ts | 129 ++++++++++++--------- 2 files changed, 76 insertions(+), 55 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index 75866cdf644..89b85c7ecae 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -236,7 +236,7 @@ Registry.as(ConfigurationExtensions.Configuration).regis localize('scm.defaultViewSortKey.path', "Sort the repository changes by path."), localize('scm.defaultViewSortKey.status', "Sort the repository changes by Source Control status.") ], - description: localize('scm.defaultViewSortKey', "Controls the default Source Control repository sort mode."), + description: localize('scm.defaultViewSortKey', "Controls the default Source Control repository changes sort order when viewed as a list."), default: 'path' }, 'scm.autoReveal': { diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index cadb081fece..3eb672f06c5 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -1070,9 +1070,14 @@ class ViewModel { } } + // Update sort key based on view mode + this.sortKey = this.getViewModelSortKey(); + this.refresh(); this._onDidChangeMode.fire(mode); this.modeContextKey.set(mode); + + this.storageService.store(`scm.viewMode`, mode, StorageScope.WORKSPACE, StorageTarget.USER); } get sortKey(): ViewModelSortKey { return this._sortKey; } @@ -1086,6 +1091,10 @@ class ViewModel { this.refresh(); this._onDidChangeSortKey.fire(sortKey); this.sortKeyContextKey.set(sortKey); + + if (this._mode === ViewModelMode.List) { + this.storageService.store(`scm.viewSortKey`, sortKey, StorageScope.WORKSPACE, StorageTarget.USER); + } } private _treeViewStateIsStale = false; @@ -1114,23 +1123,37 @@ class ViewModel { private scmProviderRootUriContextKey: IContextKey; private scmProviderHasRootUriContextKey: IContextKey; + private _mode: ViewModelMode; + private _sortKey: ViewModelSortKey; + private _treeViewState: ITreeViewState | undefined; + constructor( private tree: WorkbenchCompressibleObjectTree, private inputRenderer: InputRenderer, - private _mode: ViewModelMode, - private _sortKey: ViewModelSortKey, - private _treeViewState: ITreeViewState | undefined, @IInstantiationService protected instantiationService: IInstantiationService, @IEditorService protected editorService: IEditorService, @IConfigurationService protected configurationService: IConfigurationService, @ISCMViewService private scmViewService: ISCMViewService, + @IStorageService private storageService: IStorageService, @IUriIdentityService private uriIdentityService: IUriIdentityService, @IContextKeyService contextKeyService: IContextKeyService ) { + // View mode and sort key + this._mode = this.getViewModelMode(); + this._sortKey = this.getViewModelSortKey(); + + // TreeView state + const storageViewState = this.storageService.get(`scm.viewState`, StorageScope.WORKSPACE); + if (storageViewState) { + try { + this._treeViewState = JSON.parse(storageViewState); + } catch {/* noop */ } + } + this.modeContextKey = ContextKeys.ViewModelMode.bindTo(contextKeyService); - this.modeContextKey.set(_mode); + this.modeContextKey.set(this._mode); this.sortKeyContextKey = ContextKeys.ViewModelSortKey.bindTo(contextKeyService); - this.sortKeyContextKey.set(_sortKey); + this.sortKeyContextKey.set(this._sortKey); this.areAllRepositoriesCollapsedContextKey = ContextKeys.ViewModelAreAllRepositoriesCollapsed.bindTo(contextKeyService); this.isAnyRepositoryCollapsibleContextKey = ContextKeys.ViewModelIsAnyRepositoryCollapsible.bindTo(contextKeyService); this.scmProviderContextKey = ContextKeys.SCMProvider.bindTo(contextKeyService); @@ -1144,6 +1167,12 @@ class ViewModel { (this.updateRepositoryCollapseAllContextKeys, this, this.disposables); this.disposables.add(this.tree.onDidChangeCollapseState(() => this._treeViewStateIsStale = true)); + + this.storageService.onWillSaveState(e => { + if (e.reason === WillSaveStateReason.SHUTDOWN) { + this.storageService.store(`scm.viewState`, JSON.stringify(this.treeViewState), StorageScope.WORKSPACE, StorageTarget.MACHINE); + } + }); } private onDidChangeConfiguration(e?: IConfigurationChangeEvent): void { @@ -1433,6 +1462,45 @@ class ViewModel { } } + private getViewModelMode(): ViewModelMode { + let mode = this.configurationService.getValue<'tree' | 'list'>('scm.defaultViewMode') === 'list' ? ViewModelMode.List : ViewModelMode.Tree; + const storageMode = this.storageService.get(`scm.viewMode`, StorageScope.WORKSPACE) as ViewModelMode; + if (typeof storageMode === 'string') { + mode = storageMode; + } + + return mode; + } + + private getViewModelSortKey(): ViewModelSortKey { + // Tree + if (this._mode === ViewModelMode.Tree) { + return ViewModelSortKey.Path; + } + + // List + let viewSortKey: ViewModelSortKey; + const viewSortKeyString = this.configurationService.getValue<'path' | 'name' | 'status'>('scm.defaultViewSortKey'); + switch (viewSortKeyString) { + case 'name': + viewSortKey = ViewModelSortKey.Name; + break; + case 'status': + viewSortKey = ViewModelSortKey.Status; + break; + default: + viewSortKey = ViewModelSortKey.Path; + break; + } + + const storageSortKey = this.storageService.get(`scm.viewSortKey`, StorageScope.WORKSPACE) as ViewModelSortKey; + if (typeof storageSortKey === 'string') { + viewSortKey = storageSortKey; + } + + return viewSortKey; + } + dispose(): void { this.visibilityDisposables.dispose(); this.disposables.dispose(); @@ -1562,6 +1630,7 @@ abstract class SetSortKeyAction extends ViewAction { viewId: VIEW_PANE_ID, f1: false, toggled: ContextKeys.ViewModelSortKey.isEqualTo(sortKey), + precondition: ContextKeys.ViewModelMode.isEqualTo(ViewModelMode.List), menu: { id: Menus.ViewSort, group: '2_sort' } }); } @@ -2109,7 +2178,6 @@ export class SCMViewPane extends ViewPane { @IConfigurationService configurationService: IConfigurationService, @IContextKeyService contextKeyService: IContextKeyService, @IMenuService private menuService: IMenuService, - @IStorageService private storageService: IStorageService, @IOpenerService openerService: IOpenerService, @ITelemetryService telemetryService: ITelemetryService, ) { @@ -2196,44 +2264,9 @@ export class SCMViewPane extends ViewPane { append(this.listContainer, overflowWidgetsDomNode); - let viewMode = this.configurationService.getValue<'tree' | 'list'>('scm.defaultViewMode') === 'list' ? ViewModelMode.List : ViewModelMode.Tree; - - const storageMode = this.storageService.get(`scm.viewMode`, StorageScope.WORKSPACE) as ViewModelMode; - if (typeof storageMode === 'string') { - viewMode = storageMode; - } - - let viewSortKey: ViewModelSortKey; - const viewSortKeyString = this.configurationService.getValue<'path' | 'name' | 'status'>('scm.defaultViewSortKey'); - switch (viewSortKeyString) { - case 'name': - viewSortKey = ViewModelSortKey.Name; - break; - case 'status': - viewSortKey = ViewModelSortKey.Status; - break; - default: - viewSortKey = ViewModelSortKey.Path; - break; - } - - const storageSortKey = this.storageService.get(`scm.viewSortKey`, StorageScope.WORKSPACE) as ViewModelSortKey; - if (typeof storageSortKey === 'string') { - viewSortKey = storageSortKey; - } - - let viewState: ITreeViewState | undefined; - - const storageViewState = this.storageService.get(`scm.viewState`, StorageScope.WORKSPACE); - if (storageViewState) { - try { - viewState = JSON.parse(storageViewState); - } catch {/* noop */ } - } - this._register(this.instantiationService.createInstance(RepositoryVisibilityActionController)); - this._viewModel = this.instantiationService.createInstance(ViewModel, this.tree, this.inputRenderer, viewMode, viewSortKey, viewState); + this._viewModel = this.instantiationService.createInstance(ViewModel, this.tree, this.inputRenderer); this._register(this._viewModel); this.listContainer.classList.add('file-icon-themable-tree'); @@ -2242,18 +2275,11 @@ export class SCMViewPane extends ViewPane { this.updateIndentStyles(this.themeService.getFileIconTheme()); this._register(this.themeService.onDidFileIconThemeChange(this.updateIndentStyles, this)); this._register(this._viewModel.onDidChangeMode(this.onDidChangeMode, this)); - this._register(this._viewModel.onDidChangeSortKey(this.onDidChangeSortKey, this)); this._register(this.onDidChangeBodyVisibility(this._viewModel.setVisible, this._viewModel)); this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('scm.alwaysShowRepositories'))(this.updateActions, this)); this.updateActions(); - - this._register(this.storageService.onWillSaveState(e => { - if (e.reason === WillSaveStateReason.SHUTDOWN) { - this.storageService.store(`scm.viewState`, JSON.stringify(this._viewModel.treeViewState), StorageScope.WORKSPACE, StorageTarget.MACHINE); - } - })); } private updateIndentStyles(theme: IFileIconTheme): void { @@ -2265,11 +2291,6 @@ export class SCMViewPane extends ViewPane { private onDidChangeMode(): void { this.updateIndentStyles(this.themeService.getFileIconTheme()); - this.storageService.store(`scm.viewMode`, this._viewModel.mode, StorageScope.WORKSPACE, StorageTarget.USER); - } - - private onDidChangeSortKey(): void { - this.storageService.store(`scm.viewSortKey`, this._viewModel.sortKey, StorageScope.WORKSPACE, StorageTarget.USER); } override layoutBody(height: number | undefined = this.layoutCache.height, width: number | undefined = this.layoutCache.width): void { -- cgit v1.2.3 From cb796c6514b31b07b6aa5384edf9c84bae36d816 Mon Sep 17 00:00:00 2001 From: Laurent Le Brun Date: Fri, 22 Apr 2022 16:16:03 +0200 Subject: Comments panel: use the date of the last reply (#147922) --- src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts b/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts index 78a63890aa3..940de2d18d7 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts @@ -225,9 +225,9 @@ export class CommentNodeRenderer implements IListRenderer templateData.repliesMetadata.container.style.display = ''; templateData.repliesMetadata.count.textContent = this.getCountString(commentCount); - templateData.repliesMetadata.lastReplyDetail.textContent = nls.localize('lastReplyFrom', "Last reply from {0}", node.element.replies[node.element.replies.length - 1].comment.userName); - templateData.repliesMetadata.timestamp.setTimestamp(originalComment.comment.timestamp ? new Date(originalComment.comment.timestamp) : undefined); - + const lastComment = node.element.replies[node.element.replies.length - 1].comment; + templateData.repliesMetadata.lastReplyDetail.textContent = nls.localize('lastReplyFrom', "Last reply from {0}", lastComment.userName); + templateData.repliesMetadata.timestamp.setTimestamp(lastComment.timestamp ? new Date(lastComment.timestamp) : undefined); } private getCommentThreadWidgetStateColor(state: CommentThreadState | undefined, theme: IColorTheme): Color | undefined { -- cgit v1.2.3 From 1206d80f567d8a45a700f3c569f8e4344c4db023 Mon Sep 17 00:00:00 2001 From: Laurent Le Brun Date: Fri, 22 Apr 2022 16:48:40 +0200 Subject: Comments panel: do not truncate the author name (#147924) --- src/vs/workbench/contrib/comments/browser/media/panel.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/media/panel.css b/src/vs/workbench/contrib/comments/browser/media/panel.css index 0775ef6a1aa..37bc9a17a45 100644 --- a/src/vs/workbench/contrib/comments/browser/media/panel.css +++ b/src/vs/workbench/contrib/comments/browser/media/panel.css @@ -49,8 +49,7 @@ .comments-panel .comments-panel-container .tree-container .comment-thread-container .comment-snippet-container .count, .comments-panel .comments-panel-container .tree-container .comment-thread-container .comment-metadata-container .user { - overflow: hidden; - text-overflow: ellipsis; + min-width: fit-content; } .comments-panel .comments-panel-container .tree-container .comment-thread-container .comment-snippet-container .text { -- cgit v1.2.3 From 5b242ed4ffc85c6ca1a7f4bafecfd573f73245c4 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 22 Apr 2022 23:51:05 +0530 Subject: Implement export/import profiles - Introduce workbench profile service - Implement settings, global state, extension profiles - Implement import/export profile actions --- .../profiles/common/profiles.contribution.ts | 6 + .../workbench/contrib/profiles/common/profiles.ts | 10 ++ .../contrib/profiles/common/profilesActions.ts | 137 +++++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 src/vs/workbench/contrib/profiles/common/profiles.contribution.ts create mode 100644 src/vs/workbench/contrib/profiles/common/profiles.ts create mode 100644 src/vs/workbench/contrib/profiles/common/profilesActions.ts (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/profiles/common/profiles.contribution.ts b/src/vs/workbench/contrib/profiles/common/profiles.contribution.ts new file mode 100644 index 00000000000..facfa51c4a3 --- /dev/null +++ b/src/vs/workbench/contrib/profiles/common/profiles.contribution.ts @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import './profilesActions'; diff --git a/src/vs/workbench/contrib/profiles/common/profiles.ts b/src/vs/workbench/contrib/profiles/common/profiles.ts new file mode 100644 index 00000000000..46db3b23829 --- /dev/null +++ b/src/vs/workbench/contrib/profiles/common/profiles.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from 'vs/nls'; + +export const PROFILES_CATEGORY = localize('profiles', "Profiles"); +export const PROFILE_EXTENSION = 'code-profile'; +export const PROFILE_FILTER = [{ name: localize('profile', "Code Profile"), extensions: [PROFILE_EXTENSION] }]; diff --git a/src/vs/workbench/contrib/profiles/common/profilesActions.ts b/src/vs/workbench/contrib/profiles/common/profilesActions.ts new file mode 100644 index 00000000000..5c24616eaa4 --- /dev/null +++ b/src/vs/workbench/contrib/profiles/common/profilesActions.ts @@ -0,0 +1,137 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CancellationToken } from 'vs/base/common/cancellation'; +import { DisposableStore } from 'vs/base/common/lifecycle'; +import { joinPath } from 'vs/base/common/resources'; +import { localize } from 'vs/nls'; +import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; +import { IDialogService, IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { IFileService } from 'vs/platform/files/common/files'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; +import { asJson, asText, IRequestService } from 'vs/platform/request/common/request'; +import { PROFILES_CATEGORY, PROFILE_EXTENSION, PROFILE_FILTER } from 'vs/workbench/contrib/profiles/common/profiles'; +import { IProfile, isProfile, IWorkbenchProfileService } from 'vs/workbench/services/profiles/common/profile'; +import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; + +registerAction2(class ExportProfileAction extends Action2 { + constructor() { + super({ + id: 'workbench.profiles.actions.exportProfile', + title: { + value: localize('export profile', "Export customizations as a Profile..."), + original: 'Export customizations as a Profile...' + }, + category: PROFILES_CATEGORY, + f1: true + }); + } + + async run(accessor: ServicesAccessor) { + const textFileService = accessor.get(ITextFileService); + const fileDialogService = accessor.get(IFileDialogService); + const profileService = accessor.get(IWorkbenchProfileService); + const notificationService = accessor.get(INotificationService); + + const profileLocation = await fileDialogService.showSaveDialog({ + title: localize('export profile dialog', "Save Profile"), + filters: PROFILE_FILTER, + defaultUri: joinPath(await fileDialogService.defaultFilePath(undefined), `profile.${PROFILE_EXTENSION}`), + }); + + if (!profileLocation) { + return; + } + + const profile = await profileService.createProfile({ skipComments: true }); + await textFileService.create([{ resource: profileLocation, value: JSON.stringify(profile), options: { overwrite: true } }]); + + notificationService.info(localize('export success', "Profile successfully exported.")); + } +}); + +registerAction2(class ImportProfileAction extends Action2 { + constructor() { + super({ + id: 'workbench.profiles.actions.importProfile', + title: { + value: localize('import profile', "Import customizations from a Profile..."), + original: 'Import customizations from a Profile...' + }, + category: PROFILES_CATEGORY, + f1: true + }); + } + + async run(accessor: ServicesAccessor) { + const fileDialogService = accessor.get(IFileDialogService); + const quickInputService = accessor.get(IQuickInputService); + const fileService = accessor.get(IFileService); + const requestService = accessor.get(IRequestService); + const profileService = accessor.get(IWorkbenchProfileService); + const dialogService = accessor.get(IDialogService); + + if (!(await dialogService.confirm({ + title: localize('import profile title', "Import customizations from a Profile"), + message: localize('confiirmation message', "This will replace your current customizations. Are you sure you want to continue?"), + })).confirmed) { + return; + } + + const disposables = new DisposableStore(); + const quickPick = disposables.add(quickInputService.createQuickPick()); + const updateQuickPickItems = (value?: string) => { + const selectFromFileItem: IQuickPickItem = { label: localize('select from file', "Import from profile file") }; + quickPick.items = value ? [{ label: localize('select from url', "Import from URL"), description: quickPick.value }, selectFromFileItem] : [selectFromFileItem]; + }; + quickPick.title = localize('import profile quick pick title', "Import customizations from a Profile"); + quickPick.placeholder = localize('import profile placeholder', "Provide profile URL or select profile file to import"); + quickPick.ignoreFocusOut = true; + disposables.add(quickPick.onDidChangeValue(updateQuickPickItems)); + updateQuickPickItems(); + quickPick.matchOnLabel = false; + quickPick.matchOnDescription = false; + disposables.add(quickPick.onDidAccept(async () => { + quickPick.hide(); + const profile = quickPick.selectedItems[0].description ? await this.getProfileFromURL(quickPick.value, requestService) : await this.getProfileFromFileSystem(fileDialogService, fileService); + if (profile) { + await profileService.setProfile(profile); + } + })); + disposables.add(quickPick.onDidHide(() => disposables.dispose())); + quickPick.show(); + } + + private async getProfileFromFileSystem(fileDialogService: IFileDialogService, fileService: IFileService): Promise { + const profileLocation = await fileDialogService.showOpenDialog({ + canSelectFolders: false, + canSelectFiles: true, + canSelectMany: false, + filters: PROFILE_FILTER, + title: localize('import profile dialog', "Import Profile"), + }); + if (!profileLocation) { + return null; + } + const content = (await fileService.readFile(profileLocation[0])).value.toString(); + const parsed = JSON.parse(content); + return isProfile(parsed) ? parsed : null; + } + + private async getProfileFromURL(url: string, requestService: IRequestService): Promise { + const options = { type: 'GET', url }; + const context = await requestService.request(options, CancellationToken.None); + if (context.res.statusCode === 200) { + const result = await asJson(context); + return isProfile(result) ? result : null; + } else { + const message = await asText(context); + throw new Error(`Expected 200, got back ${context.res.statusCode} instead.\n\n${message}`); + } + } + +}); -- cgit v1.2.3 From ecb88fbc33020d1ce45846825b1ed8f9845bbd59 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 22 Apr 2022 12:20:07 -0700 Subject: Fix "Disconnect and Suspend" in attach configs #134412 And also fix the stop alt action precondition --- src/vs/workbench/contrib/debug/browser/debugToolBar.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index 4cf1809bb1a..bcc50927d22 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -346,7 +346,7 @@ MenuRegistry.onDidChangeMenu(e => { registerDebugToolBarItem(CONTINUE_ID, CONTINUE_LABEL, 10, icons.debugContinue, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); registerDebugToolBarItem(PAUSE_ID, PAUSE_LABEL, 10, icons.debugPause, CONTEXT_DEBUG_STATE.notEqualsTo('stopped'), CONTEXT_DEBUG_STATE.isEqualTo('running')); registerDebugToolBarItem(STOP_ID, STOP_LABEL, 70, icons.debugStop, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), undefined, { id: DISCONNECT_ID, title: DISCONNECT_LABEL, icon: icons.debugDisconnect, precondition: ContextKeyExpr.and(CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED), }); -registerDebugToolBarItem(DISCONNECT_ID, DISCONNECT_LABEL, 70, icons.debugDisconnect, CONTEXT_FOCUSED_SESSION_IS_ATTACH, undefined, { id: STOP_ID, title: STOP_LABEL, icon: icons.debugStop, precondition: ContextKeyExpr.and(CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED), }); +registerDebugToolBarItem(DISCONNECT_ID, DISCONNECT_LABEL, 70, icons.debugDisconnect, CONTEXT_FOCUSED_SESSION_IS_ATTACH, undefined, { id: STOP_ID, title: STOP_LABEL, icon: icons.debugStop, precondition: ContextKeyExpr.and(CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED), }); registerDebugToolBarItem(STEP_OVER_ID, STEP_OVER_LABEL, 20, icons.debugStepOver, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); registerDebugToolBarItem(STEP_INTO_ID, STEP_INTO_LABEL, 30, icons.debugStepInto, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); registerDebugToolBarItem(STEP_OUT_ID, STEP_OUT_LABEL, 40, icons.debugStepOut, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); @@ -379,7 +379,10 @@ MenuRegistry.appendMenuItem(MenuId.DebugToolBarStop, { MenuRegistry.appendMenuItem(MenuId.DebugToolBarStop, { group: 'navigation', - when: ContextKeyExpr.and(CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED), + when: ContextKeyExpr.or( + ContextKeyExpr.and(CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated(), CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED), + ContextKeyExpr.and(CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED), + ), order: 0, command: { id: DISCONNECT_AND_SUSPEND_ID, -- cgit v1.2.3 From ed06c9f3cf1fdbabd692df48d8c0dfd993b17434 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 22 Apr 2022 13:27:49 -0700 Subject: Don't give keybindingProvider to debugtoolbar stop menu #134412 --- .../contrib/debug/browser/debugToolBar.ts | 55 ++++++++++------------ 1 file changed, 25 insertions(+), 30 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index bcc50927d22..13d089466e4 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -3,40 +3,39 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import 'vs/css!./media/debugToolBar'; -import * as errors from 'vs/base/common/errors'; import * as browser from 'vs/base/browser/browser'; import * as dom from 'vs/base/browser/dom'; -import * as arrays from 'vs/base/common/arrays'; -import { localize } from 'vs/nls'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, Action } from 'vs/base/common/actions'; import { ActionBar, ActionsOrientation, IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IDebugConfiguration, IDebugService, State, CONTEXT_DEBUG_STATE, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_MULTI_SESSION_DEBUG, VIEWLET_ID, CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED } from 'vs/workbench/contrib/debug/common/debug'; -import { FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IThemeService, Themable, ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { contrastBorder, widgetShadow } from 'vs/platform/theme/common/colorRegistry'; -import { INotificationService } from 'vs/platform/notification/common/notification'; +import { Action, IAction, IRunEvent, WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions'; +import * as arrays from 'vs/base/common/arrays'; import { RunOnceScheduler } from 'vs/base/common/async'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { createActionViewItem, createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { IMenu, IMenuService, MenuId, MenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions'; -import { IContextKeyService, ContextKeyExpression, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle'; -import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; -import { debugToolBarBackground, debugToolBarBorder } from 'vs/workbench/contrib/debug/browser/debugColors'; +import * as errors from 'vs/base/common/errors'; +import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; -import { CONTINUE_LABEL, CONTINUE_ID, PAUSE_ID, STOP_ID, DISCONNECT_ID, STEP_OVER_ID, STEP_INTO_ID, RESTART_SESSION_ID, STEP_OUT_ID, STEP_BACK_ID, REVERSE_CONTINUE_ID, RESTART_LABEL, STEP_OUT_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, DISCONNECT_LABEL, STOP_LABEL, PAUSE_LABEL, FOCUS_SESSION_ID, FOCUS_SESSION_LABEL, DISCONNECT_AND_SUSPEND_ID, DISCONNECT_AND_SUSPEND_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import 'vs/css!./media/debugToolBar'; +import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; +import { localize } from 'vs/nls'; import { ICommandAction } from 'vs/platform/action/common/action'; import { DropdownWithPrimaryActionViewItem } from 'vs/platform/actions/browser/dropdownWithPrimaryActionViewItem'; +import { createActionViewItem, createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { IMenu, IMenuService, MenuId, MenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ContextKeyExpr, ContextKeyExpression, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { contrastBorder, widgetShadow } from 'vs/platform/theme/common/colorRegistry'; +import { IThemeService, Themable, ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; +import { FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems'; +import { debugToolBarBackground, debugToolBarBorder } from 'vs/workbench/contrib/debug/browser/debugColors'; +import { CONTINUE_ID, CONTINUE_LABEL, DISCONNECT_AND_SUSPEND_ID, DISCONNECT_AND_SUSPEND_LABEL, DISCONNECT_ID, DISCONNECT_LABEL, FOCUS_SESSION_ID, FOCUS_SESSION_LABEL, PAUSE_ID, PAUSE_LABEL, RESTART_LABEL, RESTART_SESSION_ID, REVERSE_CONTINUE_ID, STEP_BACK_ID, STEP_INTO_ID, STEP_INTO_LABEL, STEP_OUT_ID, STEP_OUT_LABEL, STEP_OVER_ID, STEP_OVER_LABEL, STOP_ID, STOP_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { CONTEXT_DEBUG_STATE, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_MULTI_SESSION_DEBUG, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED, IDebugConfiguration, IDebugService, State, VIEWLET_ID } from 'vs/workbench/contrib/debug/common/debug'; +import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; const DEBUG_TOOLBAR_POSITION_KEY = 'debug.actionswidgetposition'; const DEBUG_TOOLBAR_Y_KEY = 'debug.actionswidgety'; @@ -272,7 +271,6 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { export function createDisconnectMenuItemAction(action: MenuItemAction, disposables: DisposableStore, accessor: ServicesAccessor): IActionViewItem | undefined { const menuService = accessor.get(IMenuService); const contextKeyService = accessor.get(IContextKeyService); - const keybindingService = accessor.get(IKeybindingService); const instantiationService = accessor.get(IInstantiationService); const contextMenuService = accessor.get(IContextMenuService); @@ -285,16 +283,13 @@ export function createDisconnectMenuItemAction(action: MenuItemAction, disposabl } const dropdownAction = disposables.add(new Action('notebook.moreRunActions', localize('notebook.moreRunActionsLabel', "More..."), 'codicon-chevron-down', true)); - const keybindingProvider = (action: IAction) => keybindingService.lookupKeybinding(action.id, contextKeyService); const item = instantiationService.createInstance(DropdownWithPrimaryActionViewItem, action as MenuItemAction, dropdownAction, secondary, 'debug-stop-actions', contextMenuService, - { - getKeyBinding: keybindingProvider - }); + {}); return item; } -- cgit v1.2.3 From c4b149d15580f5b039ce53b7e981ea7ffe6306d9 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Fri, 22 Apr 2022 14:47:44 -0700 Subject: don't overwrite IFS in bash shell integration script (#147946) --- .../contrib/terminal/browser/media/shellIntegration-bash.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh index f50ca67b01d..fa3240dd5e1 100755 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh @@ -95,6 +95,9 @@ __vsc_preexec() { __vsc_update_prompt __vsc_prompt_cmd_original() { + if [[ ${IFS+set} ]]; then + __vsc_original_ifs="$IFS" + fi __vsc_status="$?" if [[ "$__vsc_original_prompt_command" =~ .+\;.+ ]]; then IFS=';' @@ -105,7 +108,11 @@ __vsc_prompt_cmd_original() { for ((i = 0; i < ${#ADDR[@]}; i++)); do builtin eval ${ADDR[i]} done - IFS='' + if [[ ${__vsc_original_ifs+set} ]]; then + IFS="$__vsc_original_ifs" + else + unset IFS + fi __vsc_precmd } -- cgit v1.2.3 From fc20be16b421c5b2cfefa60915b5ae78dc3e352a Mon Sep 17 00:00:00 2001 From: meganrogge Date: Fri, 22 Apr 2022 15:18:54 -0700 Subject: unset var after use in bash integration script #147946 --- src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh | 1 + 1 file changed, 1 insertion(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh index fa3240dd5e1..9ece742ca99 100755 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh @@ -110,6 +110,7 @@ __vsc_prompt_cmd_original() { done if [[ ${__vsc_original_ifs+set} ]]; then IFS="$__vsc_original_ifs" + unset __vsc_original_ifs else unset IFS fi -- cgit v1.2.3 From 118da3fc5d69cf66266bfc43204b236613023b4a Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Fri, 22 Apr 2022 15:53:44 -0700 Subject: fix #147952 (#147953) --- .../workbench/contrib/terminal/browser/media/shellIntegration-bash.sh | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh index 9ece742ca99..cda92578a5d 100755 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh @@ -10,6 +10,10 @@ if [ -z "$VSCODE_SHELL_LOGIN" ]; then else # Imitate -l because --init-file doesn't support it: # run the first of these files that exists + if [ -f /etc/bash_profile ]; then + . /etc/bash_profile + fi + # exceute the first that exists if [ -f ~/.bash_profile ]; then . ~/.bash_profile elif [ -f ~/.bash_login ]; then -- cgit v1.2.3 From 7135a30a635810e6745c33a97af2d3164d6f05bd Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 22 Apr 2022 16:20:39 -0700 Subject: Open the notebook editor find widget when opening a notebook from search results #95275 --- .../browser/contrib/find/findController.ts | 452 --------------------- .../notebook/browser/contrib/find/findModel.ts | 18 +- .../notebook/browser/contrib/find/notebookFind.ts | 135 ++++++ .../contrib/find/notebookFindReplaceWidget.ts | 6 +- .../browser/contrib/find/notebookFindWidget.ts | 353 ++++++++++++++++ .../notebook/browser/notebook.contribution.ts | 2 +- .../notebook/test/browser/contrib/find.test.ts | 38 +- .../workbench/contrib/search/browser/searchView.ts | 45 +- 8 files changed, 554 insertions(+), 495 deletions(-) delete mode 100644 src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts create mode 100644 src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts create mode 100644 src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts deleted file mode 100644 index 662b1929a2e..00000000000 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts +++ /dev/null @@ -1,452 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import 'vs/css!./media/notebookFind'; -import { alert as alertFn } from 'vs/base/browser/ui/aria/aria'; -import * as strings from 'vs/base/common/strings'; -import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { IContextKeyService, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; -import { INotebookEditor, CellEditState, INotebookEditorContribution, getNotebookEditorFromEditorPane } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { Range } from 'vs/editor/common/core/range'; -import { MATCHES_LIMIT } from 'vs/editor/contrib/find/browser/findModel'; -import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; -import * as DOM from 'vs/base/browser/dom'; -import { registerNotebookContribution } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions'; -import { registerAction2, Action2, IMenuService } from 'vs/platform/actions/common/actions'; -import { localize } from 'vs/nls'; -import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { FindReplaceState } from 'vs/editor/contrib/find/browser/findState'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { StartFindAction, StartFindReplaceAction } from 'vs/editor/contrib/find/browser/findController'; -import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { NLS_MATCHES_LOCATION, NLS_NO_RESULTS } from 'vs/editor/contrib/find/browser/findWidget'; -import { FindModel } from 'vs/workbench/contrib/notebook/browser/contrib/find/findModel'; -import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { FindMatch, ITextModel } from 'vs/editor/common/model'; -import { SimpleFindReplaceWidget } from 'vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget'; -import { NotebookFindFilters } from 'vs/workbench/contrib/notebook/browser/contrib/find/findFilters'; -import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; -import { Schemas } from 'vs/base/common/network'; -import { CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { URI } from 'vs/base/common/uri'; -import { isEqual } from 'vs/base/common/resources'; - -const FIND_HIDE_TRANSITION = 'find-hide-transition'; -const FIND_SHOW_TRANSITION = 'find-show-transition'; -let MAX_MATCHES_COUNT_WIDTH = 69; -const PROGRESS_BAR_DELAY = 200; // show progress for at least 200ms - -export class NotebookFindWidget extends SimpleFindReplaceWidget implements INotebookEditorContribution { - static id: string = 'workbench.notebook.find'; - protected _findWidgetFocused: IContextKey; - private _showTimeout: number | null = null; - private _hideTimeout: number | null = null; - private _previousFocusElement?: HTMLElement; - private _findModel: FindModel; - - constructor( - private readonly _notebookEditor: INotebookEditor, - @IContextViewService contextViewService: IContextViewService, - @IContextKeyService contextKeyService: IContextKeyService, - @IThemeService themeService: IThemeService, - @IConfigurationService configurationService: IConfigurationService, - @IContextMenuService contextMenuService: IContextMenuService, - @IMenuService menuService: IMenuService, - @IInstantiationService instantiationService: IInstantiationService, - ) { - super(contextViewService, contextKeyService, themeService, configurationService, menuService, contextMenuService, instantiationService, new FindReplaceState()); - this._findModel = new FindModel(this._notebookEditor, this._state, this._configurationService); - - DOM.append(this._notebookEditor.getDomNode(), this.getDomNode()); - this._findWidgetFocused = KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED.bindTo(contextKeyService); - this._register(this._findInput.onKeyDown((e) => this._onFindInputKeyDown(e))); - this.updateTheme(themeService.getColorTheme()); - this._register(themeService.onDidColorThemeChange(() => { - this.updateTheme(themeService.getColorTheme()); - })); - - this._register(this._state.onFindReplaceStateChange((e) => { - this.onInputChanged(); - - if (e.isSearching) { - if (this._state.isSearching) { - this._progressBar.infinite().show(PROGRESS_BAR_DELAY); - } else { - this._progressBar.stop().hide(); - } - } - - if (this._findModel.currentMatch >= 0) { - const currentMatch = this._findModel.getCurrentMatch(); - this._replaceBtn.setEnabled(currentMatch.isModelMatch); - } - - const matches = this._findModel.findMatches; - this._replaceAllBtn.setEnabled(matches.length > 0 && matches.find(match => match.modelMatchCount < match.matches.length) === undefined); - - if (e.filters) { - this._findInput.updateFilterState((this._state.filters?.markupPreview ?? false) || (this._state.filters?.codeOutput ?? false)); - } - })); - - this._register(DOM.addDisposableListener(this.getDomNode(), DOM.EventType.FOCUS, e => { - this._previousFocusElement = e.relatedTarget instanceof HTMLElement ? e.relatedTarget : undefined; - }, true)); - } - - - private _onFindInputKeyDown(e: IKeyboardEvent): void { - if (e.equals(KeyCode.Enter)) { - this._findModel.find(false); - e.preventDefault(); - return; - } else if (e.equals(KeyMod.Shift | KeyCode.Enter)) { - this.find(true); - e.preventDefault(); - return; - } - } - - protected onInputChanged(): boolean { - this._state.change({ searchString: this.inputValue }, false); - // this._findModel.research(); - const findMatches = this._findModel.findMatches; - if (findMatches && findMatches.length) { - return true; - } - - return false; - } - - protected find(previous: boolean): void { - this._findModel.find(previous); - } - - protected replaceOne() { - if (!this._notebookEditor.hasModel()) { - return; - } - - if (!this._findModel.findMatches.length) { - return; - } - - this._findModel.ensureFindMatches(); - - if (this._findModel.currentMatch < 0) { - this._findModel.find(false); - } - - const currentMatch = this._findModel.getCurrentMatch(); - const cell = currentMatch.cell; - if (currentMatch.isModelMatch) { - const match = currentMatch.match as FindMatch; - - this._progressBar.infinite().show(PROGRESS_BAR_DELAY); - - const replacePattern = this.replacePattern; - const replaceString = replacePattern.buildReplaceString(match.matches, this._state.preserveCase); - - const viewModel = this._notebookEditor._getViewModel(); - viewModel.replaceOne(cell, match.range, replaceString).then(() => { - this._progressBar.stop(); - }); - } else { - // this should not work - console.error('Replace does not work for output match'); - } - } - - protected replaceAll() { - if (!this._notebookEditor.hasModel()) { - return; - } - - this._progressBar.infinite().show(PROGRESS_BAR_DELAY); - - const replacePattern = this.replacePattern; - - const cellFindMatches = this._findModel.findMatches; - const replaceStrings: string[] = []; - cellFindMatches.forEach(cellFindMatch => { - const findMatches = cellFindMatch.matches; - findMatches.forEach((findMatch, index) => { - if (index < cellFindMatch.modelMatchCount) { - const match = findMatch as FindMatch; - const matches = match.matches; - replaceStrings.push(replacePattern.buildReplaceString(matches, this._state.preserveCase)); - } - }); - }); - - const viewModel = this._notebookEditor._getViewModel(); - viewModel.replaceAll(this._findModel.findMatches, replaceStrings).then(() => { - this._progressBar.stop(); - }); - } - - protected findFirst(): void { } - - protected onFocusTrackerFocus() { - this._findWidgetFocused.set(true); - } - - protected onFocusTrackerBlur() { - this._previousFocusElement = undefined; - this._findWidgetFocused.reset(); - } - - protected onReplaceInputFocusTrackerFocus(): void { - // throw new Error('Method not implemented.'); - } - protected onReplaceInputFocusTrackerBlur(): void { - // throw new Error('Method not implemented.'); - } - - protected onFindInputFocusTrackerFocus(): void { } - protected onFindInputFocusTrackerBlur(): void { } - - override show(initialInput?: string): void { - super.show(initialInput); - this._state.change({ searchString: initialInput ?? '', isRevealed: true }, false); - this._findInput.select(); - - if (this._showTimeout === null) { - if (this._hideTimeout !== null) { - window.clearTimeout(this._hideTimeout); - this._hideTimeout = null; - this._notebookEditor.removeClassName(FIND_HIDE_TRANSITION); - } - - this._notebookEditor.addClassName(FIND_SHOW_TRANSITION); - this._showTimeout = window.setTimeout(() => { - this._notebookEditor.removeClassName(FIND_SHOW_TRANSITION); - this._showTimeout = null; - }, 200); - } else { - // no op - } - } - - replace(initialFindInput?: string, initialReplaceInput?: string) { - super.showWithReplace(initialFindInput, initialReplaceInput); - this._state.change({ searchString: initialFindInput ?? '', replaceString: initialReplaceInput ?? '', isRevealed: true }, false); - this._replaceInput.select(); - - if (this._showTimeout === null) { - if (this._hideTimeout !== null) { - window.clearTimeout(this._hideTimeout); - this._hideTimeout = null; - this._notebookEditor.removeClassName(FIND_HIDE_TRANSITION); - } - - this._notebookEditor.addClassName(FIND_SHOW_TRANSITION); - this._showTimeout = window.setTimeout(() => { - this._notebookEditor.removeClassName(FIND_SHOW_TRANSITION); - this._showTimeout = null; - }, 200); - } else { - // no op - } - } - - override hide() { - super.hide(); - this._state.change({ isRevealed: false }, false); - this._findModel.clear(); - this._notebookEditor.findStop(); - this._progressBar.stop(); - - if (this._hideTimeout === null) { - if (this._showTimeout !== null) { - window.clearTimeout(this._showTimeout); - this._showTimeout = null; - this._notebookEditor.removeClassName(FIND_SHOW_TRANSITION); - } - this._notebookEditor.addClassName(FIND_HIDE_TRANSITION); - this._hideTimeout = window.setTimeout(() => { - this._notebookEditor.removeClassName(FIND_HIDE_TRANSITION); - }, 200); - } else { - // no op - } - - if (this._previousFocusElement && this._previousFocusElement.offsetParent) { - this._previousFocusElement.focus(); - this._previousFocusElement = undefined; - } - - if (this._notebookEditor.hasModel()) { - for (let i = 0; i < this._notebookEditor.getLength(); i++) { - const cell = this._notebookEditor.cellAt(i); - - if (cell.getEditState() === CellEditState.Editing && cell.editStateSource === 'find') { - cell.updateEditState(CellEditState.Preview, 'find'); - } - } - } - } - - override _updateMatchesCount(): void { - if (!this._findModel || !this._findModel.findMatches) { - return; - } - - this._matchesCount.style.minWidth = MAX_MATCHES_COUNT_WIDTH + 'px'; - this._matchesCount.title = ''; - - // remove previous content - if (this._matchesCount.firstChild) { - this._matchesCount.removeChild(this._matchesCount.firstChild); - } - - let label: string; - - if (this._state.matchesCount > 0) { - let matchesCount: string = String(this._state.matchesCount); - if (this._state.matchesCount >= MATCHES_LIMIT) { - matchesCount += '+'; - } - const matchesPosition: string = this._findModel.currentMatch < 0 ? '?' : String((this._findModel.currentMatch + 1)); - label = strings.format(NLS_MATCHES_LOCATION, matchesPosition, matchesCount); - } else { - label = NLS_NO_RESULTS; - } - - this._matchesCount.appendChild(document.createTextNode(label)); - - alertFn(this._getAriaLabel(label, this._state.currentMatch, this._state.searchString)); - MAX_MATCHES_COUNT_WIDTH = Math.max(MAX_MATCHES_COUNT_WIDTH, this._matchesCount.clientWidth); - } - - private _getAriaLabel(label: string, currentMatch: Range | null, searchString: string): string { - if (label === NLS_NO_RESULTS) { - return searchString === '' - ? localize('ariaSearchNoResultEmpty', "{0} found", label) - : localize('ariaSearchNoResult', "{0} found for '{1}'", label, searchString); - } - - // TODO@rebornix, aria for `cell ${index}, line {line}` - return localize('ariaSearchNoResultWithLineNumNoCurrentMatch', "{0} found for '{1}'", label, searchString); - } - override dispose() { - this._notebookEditor?.removeClassName(FIND_SHOW_TRANSITION); - this._notebookEditor?.removeClassName(FIND_HIDE_TRANSITION); - this._findModel.dispose(); - super.dispose(); - } -} - -registerNotebookContribution(NotebookFindWidget.id, NotebookFindWidget); - -registerAction2(class extends Action2 { - constructor() { - super({ - id: 'notebook.hideFind', - title: { value: localize('notebookActions.hideFind', "Hide Find in Notebook"), original: 'Hide Find in Notebook' }, - keybinding: { - when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED), - primary: KeyCode.Escape, - weight: KeybindingWeight.WorkbenchContrib - } - }); - } - - async run(accessor: ServicesAccessor): Promise { - const editorService = accessor.get(IEditorService); - const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); - - if (!editor) { - return; - } - - const controller = editor.getContribution(NotebookFindWidget.id); - controller.hide(); - editor.focus(); - } -}); - -registerAction2(class extends Action2 { - constructor() { - super({ - id: 'notebook.find', - title: { value: localize('notebookActions.findInNotebook', "Find in Notebook"), original: 'Find in Notebook' }, - keybinding: { - when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR, EditorContextKeys.focus.toNegated()), - primary: KeyCode.KeyF | KeyMod.CtrlCmd, - weight: KeybindingWeight.WorkbenchContrib - } - }); - } - - async run(accessor: ServicesAccessor): Promise { - const editorService = accessor.get(IEditorService); - const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); - - if (!editor) { - return; - } - - const controller = editor.getContribution(NotebookFindWidget.id); - controller.show(); - } -}); - -function notebookContainsTextModel(uri: URI, textModel: ITextModel) { - if (textModel.uri.scheme === Schemas.vscodeNotebookCell) { - const cellUri = CellUri.parse(textModel.uri); - if (cellUri && isEqual(cellUri.notebook, uri)) { - return true; - } - } - - return false; -} - -StartFindAction.addImplementation(100, (accessor: ServicesAccessor, codeEditor: ICodeEditor, args: any) => { - const editorService = accessor.get(IEditorService); - const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); - - if (!editor) { - return false; - } - - if (!editor.hasEditorFocus() && !editor.hasWebviewFocus()) { - const codeEditorService = accessor.get(ICodeEditorService); - // check if the active pane contains the active text editor - const textEditor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor(); - if (editor.hasModel() && textEditor && textEditor.hasModel() && notebookContainsTextModel(editor.textModel.uri, textEditor.getModel())) { - // the active text editor is in notebook editor - } else { - return false; - } - } - - const controller = editor.getContribution(NotebookFindWidget.id); - controller.show(); - return true; -}); - -StartFindReplaceAction.addImplementation(100, (accessor: ServicesAccessor, codeEditor: ICodeEditor, args: any) => { - const editorService = accessor.get(IEditorService); - const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); - - if (!editor) { - return false; - } - - const controller = editor.getContribution(NotebookFindWidget.id); - if (controller) { - controller.replace(); - return true; - } - - return false; -}); diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts index f1b0150286c..2f5d35ba93f 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts @@ -88,7 +88,7 @@ export class FindModel extends Disposable { }; } - find(previous: boolean) { + find(option: { previous: boolean } | { index: number }) { if (!this.findMatches.length) { return; } @@ -96,14 +96,20 @@ export class FindModel extends Disposable { // let currCell; if (!this._findMatchesStarts) { this.set(this._findMatches, true); + if ('index' in option) { + this._currentMatch = option.index; + } } else { // const currIndex = this._findMatchesStarts!.getIndexOf(this._currentMatch); // currCell = this._findMatches[currIndex.index].cell; const totalVal = this._findMatchesStarts.getTotalSum(); - if (this._currentMatch === -1) { - this._currentMatch = previous ? totalVal - 1 : 0; + if ('index' in option) { + this._currentMatch = option.index; + } + else if (this._currentMatch === -1) { + this._currentMatch = option.previous ? totalVal - 1 : 0; } else { - const nextVal = (this._currentMatch + (previous ? -1 : 1) + totalVal) % totalVal; + const nextVal = (this._currentMatch + (option.previous ? -1 : 1) + totalVal) % totalVal; this._currentMatch = nextVal; } } @@ -157,8 +163,8 @@ export class FindModel extends Disposable { } async research() { - this._throttledDelayer.trigger(() => { - this._research(); + return this._throttledDelayer.trigger(() => { + return this._research(); }); } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts new file mode 100644 index 00000000000..f1ff2386aa7 --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts @@ -0,0 +1,135 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import 'vs/css!./media/notebookFind'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { Schemas } from 'vs/base/common/network'; +import { isEqual } from 'vs/base/common/resources'; +import { URI } from 'vs/base/common/uri'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; +import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; +import { ITextModel } from 'vs/editor/common/model'; +import { StartFindAction, StartFindReplaceAction } from 'vs/editor/contrib/find/browser/findController'; +import { localize } from 'vs/nls'; +import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { NotebookFindWidget } from 'vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget'; +import { getNotebookEditorFromEditorPane } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { registerNotebookContribution } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions'; +import { CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; + +registerNotebookContribution(NotebookFindWidget.id, NotebookFindWidget); + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'notebook.hideFind', + title: { value: localize('notebookActions.hideFind', "Hide Find in Notebook"), original: 'Hide Find in Notebook' }, + keybinding: { + when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED), + primary: KeyCode.Escape, + weight: KeybindingWeight.WorkbenchContrib + } + }); + } + + async run(accessor: ServicesAccessor): Promise { + const editorService = accessor.get(IEditorService); + const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); + + if (!editor) { + return; + } + + const controller = editor.getContribution(NotebookFindWidget.id); + controller.hide(); + editor.focus(); + } +}); + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'notebook.find', + title: { value: localize('notebookActions.findInNotebook', "Find in Notebook"), original: 'Find in Notebook' }, + keybinding: { + when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR, EditorContextKeys.focus.toNegated()), + primary: KeyCode.KeyF | KeyMod.CtrlCmd, + weight: KeybindingWeight.WorkbenchContrib + } + }); + } + + async run(accessor: ServicesAccessor): Promise { + const editorService = accessor.get(IEditorService); + const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); + + if (!editor) { + return; + } + + const controller = editor.getContribution(NotebookFindWidget.id); + controller.show(); + } +}); + +function notebookContainsTextModel(uri: URI, textModel: ITextModel) { + if (textModel.uri.scheme === Schemas.vscodeNotebookCell) { + const cellUri = CellUri.parse(textModel.uri); + if (cellUri && isEqual(cellUri.notebook, uri)) { + return true; + } + } + + return false; +} + + +StartFindAction.addImplementation(100, (accessor: ServicesAccessor, codeEditor: ICodeEditor, args: any) => { + const editorService = accessor.get(IEditorService); + const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); + + if (!editor) { + return false; + } + + if (!editor.hasEditorFocus() && !editor.hasWebviewFocus()) { + const codeEditorService = accessor.get(ICodeEditorService); + // check if the active pane contains the active text editor + const textEditor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor(); + if (editor.hasModel() && textEditor && textEditor.hasModel() && notebookContainsTextModel(editor.textModel.uri, textEditor.getModel())) { + // the active text editor is in notebook editor + } else { + return false; + } + } + + const controller = editor.getContribution(NotebookFindWidget.id); + controller.show(); + return true; +}); + +StartFindReplaceAction.addImplementation(100, (accessor: ServicesAccessor, codeEditor: ICodeEditor, args: any) => { + const editorService = accessor.get(IEditorService); + const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); + + if (!editor) { + return false; + } + + const controller = editor.getContribution(NotebookFindWidget.id); + if (controller) { + controller.replace(); + return true; + } + + return false; +}); + diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts index 9e7e660b6b0..329490a8431 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts @@ -614,7 +614,7 @@ export abstract class SimpleFindReplaceWidget extends Widget { this._findInput.focus(); } - public show(initialInput?: string): void { + public show(initialInput?: string, options?: { focus?: boolean }): void { if (initialInput && !this._isVisible) { this._findInput.setValue(initialInput); } @@ -625,7 +625,9 @@ export abstract class SimpleFindReplaceWidget extends Widget { this._domNode.classList.add('visible', 'visible-transition'); this._domNode.setAttribute('aria-hidden', 'false'); - this.focus(); + if (options?.focus ?? true) { + this.focus(); + } }, 0); } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts new file mode 100644 index 00000000000..c027d8137d4 --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts @@ -0,0 +1,353 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as DOM from 'vs/base/browser/dom'; +import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { alert as alertFn } from 'vs/base/browser/ui/aria/aria'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import * as strings from 'vs/base/common/strings'; +import { Range } from 'vs/editor/common/core/range'; +import { FindMatch } from 'vs/editor/common/model'; +import { MATCHES_LIMIT } from 'vs/editor/contrib/find/browser/findModel'; +import { FindReplaceState } from 'vs/editor/contrib/find/browser/findState'; +import { NLS_MATCHES_LOCATION, NLS_NO_RESULTS } from 'vs/editor/contrib/find/browser/findWidget'; +import { localize } from 'vs/nls'; +import { IMenuService } from 'vs/platform/actions/common/actions'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { NotebookFindFilters } from 'vs/workbench/contrib/notebook/browser/contrib/find/findFilters'; +import { FindModel } from 'vs/workbench/contrib/notebook/browser/contrib/find/findModel'; +import { SimpleFindReplaceWidget } from 'vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget'; +import { CellEditState, INotebookEditor, INotebookEditorContribution } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; + +const FIND_HIDE_TRANSITION = 'find-hide-transition'; +const FIND_SHOW_TRANSITION = 'find-show-transition'; +let MAX_MATCHES_COUNT_WIDTH = 69; +const PROGRESS_BAR_DELAY = 200; // show progress for at least 200ms + +export interface IShowNotebookFindWidgetOptions { + isRegex?: boolean; + wholeWord?: boolean; + matchCase?: boolean; + matchIndex?: number; + focus?: boolean; +} + +export class NotebookFindWidget extends SimpleFindReplaceWidget implements INotebookEditorContribution { + static id: string = 'workbench.notebook.find'; + protected _findWidgetFocused: IContextKey; + private _showTimeout: number | null = null; + private _hideTimeout: number | null = null; + private _previousFocusElement?: HTMLElement; + private _findModel: FindModel; + + constructor( + private readonly _notebookEditor: INotebookEditor, + @IContextViewService contextViewService: IContextViewService, + @IContextKeyService contextKeyService: IContextKeyService, + @IThemeService themeService: IThemeService, + @IConfigurationService configurationService: IConfigurationService, + @IContextMenuService contextMenuService: IContextMenuService, + @IMenuService menuService: IMenuService, + @IInstantiationService instantiationService: IInstantiationService, + ) { + super(contextViewService, contextKeyService, themeService, configurationService, menuService, contextMenuService, instantiationService, new FindReplaceState()); + this._findModel = new FindModel(this._notebookEditor, this._state, this._configurationService); + + DOM.append(this._notebookEditor.getDomNode(), this.getDomNode()); + this._findWidgetFocused = KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED.bindTo(contextKeyService); + this._register(this._findInput.onKeyDown((e) => this._onFindInputKeyDown(e))); + this.updateTheme(themeService.getColorTheme()); + this._register(themeService.onDidColorThemeChange(() => { + this.updateTheme(themeService.getColorTheme()); + })); + + this._register(this._state.onFindReplaceStateChange((e) => { + this.onInputChanged(); + + if (e.isSearching) { + if (this._state.isSearching) { + this._progressBar.infinite().show(PROGRESS_BAR_DELAY); + } else { + this._progressBar.stop().hide(); + } + } + + if (this._findModel.currentMatch >= 0) { + const currentMatch = this._findModel.getCurrentMatch(); + this._replaceBtn.setEnabled(currentMatch.isModelMatch); + } + + const matches = this._findModel.findMatches; + this._replaceAllBtn.setEnabled(matches.length > 0 && matches.find(match => match.modelMatchCount < match.matches.length) === undefined); + + if (e.filters) { + this._findInput.updateFilterState((this._state.filters?.markupPreview ?? false) || (this._state.filters?.codeOutput ?? false)); + } + })); + + this._register(DOM.addDisposableListener(this.getDomNode(), DOM.EventType.FOCUS, e => { + this._previousFocusElement = e.relatedTarget instanceof HTMLElement ? e.relatedTarget : undefined; + }, true)); + } + + + private _onFindInputKeyDown(e: IKeyboardEvent): void { + if (e.equals(KeyCode.Enter)) { + this.find(false); + e.preventDefault(); + return; + } else if (e.equals(KeyMod.Shift | KeyCode.Enter)) { + this.find(true); + e.preventDefault(); + return; + } + } + + protected onInputChanged(): boolean { + this._state.change({ searchString: this.inputValue }, false); + // this._findModel.research(); + const findMatches = this._findModel.findMatches; + if (findMatches && findMatches.length) { + return true; + } + + return false; + } + + private findIndex(index: number): void { + this._findModel.find({ index }); + } + + protected find(previous: boolean): void { + this._findModel.find({ previous }); + } + + protected replaceOne() { + if (!this._notebookEditor.hasModel()) { + return; + } + + if (!this._findModel.findMatches.length) { + return; + } + + this._findModel.ensureFindMatches(); + + if (this._findModel.currentMatch < 0) { + this._findModel.find({ previous: false }); + } + + const currentMatch = this._findModel.getCurrentMatch(); + const cell = currentMatch.cell; + if (currentMatch.isModelMatch) { + const match = currentMatch.match as FindMatch; + + this._progressBar.infinite().show(PROGRESS_BAR_DELAY); + + const replacePattern = this.replacePattern; + const replaceString = replacePattern.buildReplaceString(match.matches, this._state.preserveCase); + + const viewModel = this._notebookEditor._getViewModel(); + viewModel.replaceOne(cell, match.range, replaceString).then(() => { + this._progressBar.stop(); + }); + } else { + // this should not work + console.error('Replace does not work for output match'); + } + } + + protected replaceAll() { + if (!this._notebookEditor.hasModel()) { + return; + } + + this._progressBar.infinite().show(PROGRESS_BAR_DELAY); + + const replacePattern = this.replacePattern; + + const cellFindMatches = this._findModel.findMatches; + const replaceStrings: string[] = []; + cellFindMatches.forEach(cellFindMatch => { + const findMatches = cellFindMatch.matches; + findMatches.forEach((findMatch, index) => { + if (index < cellFindMatch.modelMatchCount) { + const match = findMatch as FindMatch; + const matches = match.matches; + replaceStrings.push(replacePattern.buildReplaceString(matches, this._state.preserveCase)); + } + }); + }); + + const viewModel = this._notebookEditor._getViewModel(); + viewModel.replaceAll(this._findModel.findMatches, replaceStrings).then(() => { + this._progressBar.stop(); + }); + } + + protected findFirst(): void { } + + protected onFocusTrackerFocus() { + this._findWidgetFocused.set(true); + } + + protected onFocusTrackerBlur() { + this._previousFocusElement = undefined; + this._findWidgetFocused.reset(); + } + + protected onReplaceInputFocusTrackerFocus(): void { + // throw new Error('Method not implemented.'); + } + protected onReplaceInputFocusTrackerBlur(): void { + // throw new Error('Method not implemented.'); + } + + protected onFindInputFocusTrackerFocus(): void { } + protected onFindInputFocusTrackerBlur(): void { } + + override async show(initialInput?: string, options?: IShowNotebookFindWidgetOptions): Promise { + super.show(initialInput, options); + this._state.change({ searchString: initialInput ?? '', isRevealed: true }, false); + + if (typeof options?.matchIndex === 'number') { + if (!this._findModel.findMatches.length) { + await this._findModel.research(); + } + this.findIndex(options.matchIndex); + } else { + this._findInput.select(); + } + + if (this._showTimeout === null) { + if (this._hideTimeout !== null) { + window.clearTimeout(this._hideTimeout); + this._hideTimeout = null; + this._notebookEditor.removeClassName(FIND_HIDE_TRANSITION); + } + + this._notebookEditor.addClassName(FIND_SHOW_TRANSITION); + this._showTimeout = window.setTimeout(() => { + this._notebookEditor.removeClassName(FIND_SHOW_TRANSITION); + this._showTimeout = null; + }, 200); + } else { + // no op + } + } + + replace(initialFindInput?: string, initialReplaceInput?: string) { + super.showWithReplace(initialFindInput, initialReplaceInput); + this._state.change({ searchString: initialFindInput ?? '', replaceString: initialReplaceInput ?? '', isRevealed: true }, false); + this._replaceInput.select(); + + if (this._showTimeout === null) { + if (this._hideTimeout !== null) { + window.clearTimeout(this._hideTimeout); + this._hideTimeout = null; + this._notebookEditor.removeClassName(FIND_HIDE_TRANSITION); + } + + this._notebookEditor.addClassName(FIND_SHOW_TRANSITION); + this._showTimeout = window.setTimeout(() => { + this._notebookEditor.removeClassName(FIND_SHOW_TRANSITION); + this._showTimeout = null; + }, 200); + } else { + // no op + } + } + + override hide() { + super.hide(); + this._state.change({ isRevealed: false }, false); + this._findModel.clear(); + this._notebookEditor.findStop(); + this._progressBar.stop(); + + if (this._hideTimeout === null) { + if (this._showTimeout !== null) { + window.clearTimeout(this._showTimeout); + this._showTimeout = null; + this._notebookEditor.removeClassName(FIND_SHOW_TRANSITION); + } + this._notebookEditor.addClassName(FIND_HIDE_TRANSITION); + this._hideTimeout = window.setTimeout(() => { + this._notebookEditor.removeClassName(FIND_HIDE_TRANSITION); + }, 200); + } else { + // no op + } + + if (this._previousFocusElement && this._previousFocusElement.offsetParent) { + this._previousFocusElement.focus(); + this._previousFocusElement = undefined; + } + + if (this._notebookEditor.hasModel()) { + for (let i = 0; i < this._notebookEditor.getLength(); i++) { + const cell = this._notebookEditor.cellAt(i); + + if (cell.getEditState() === CellEditState.Editing && cell.editStateSource === 'find') { + cell.updateEditState(CellEditState.Preview, 'find'); + } + } + } + } + + override _updateMatchesCount(): void { + if (!this._findModel || !this._findModel.findMatches) { + return; + } + + this._matchesCount.style.minWidth = MAX_MATCHES_COUNT_WIDTH + 'px'; + this._matchesCount.title = ''; + + // remove previous content + if (this._matchesCount.firstChild) { + this._matchesCount.removeChild(this._matchesCount.firstChild); + } + + let label: string; + + if (this._state.matchesCount > 0) { + let matchesCount: string = String(this._state.matchesCount); + if (this._state.matchesCount >= MATCHES_LIMIT) { + matchesCount += '+'; + } + const matchesPosition: string = this._findModel.currentMatch < 0 ? '?' : String((this._findModel.currentMatch + 1)); + label = strings.format(NLS_MATCHES_LOCATION, matchesPosition, matchesCount); + } else { + label = NLS_NO_RESULTS; + } + + this._matchesCount.appendChild(document.createTextNode(label)); + + alertFn(this._getAriaLabel(label, this._state.currentMatch, this._state.searchString)); + MAX_MATCHES_COUNT_WIDTH = Math.max(MAX_MATCHES_COUNT_WIDTH, this._matchesCount.clientWidth); + } + + private _getAriaLabel(label: string, currentMatch: Range | null, searchString: string): string { + if (label === NLS_NO_RESULTS) { + return searchString === '' + ? localize('ariaSearchNoResultEmpty', "{0} found", label) + : localize('ariaSearchNoResult', "{0} found for '{1}'", label, searchString); + } + + // TODO@rebornix, aria for `cell ${index}, line {line}` + return localize('ariaSearchNoResultWithLineNumNoCurrentMatch', "{0} found for '{1}'", label, searchString); + } + override dispose() { + this._notebookEditor?.removeClassName(FIND_SHOW_TRANSITION); + this._notebookEditor?.removeClassName(FIND_HIDE_TRANSITION); + this._findModel.dispose(); + super.dispose(); + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index b96059530d4..466fd1bf565 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -70,7 +70,7 @@ import 'vs/workbench/contrib/notebook/browser/controller/foldingController'; // Editor Contribution import 'vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard'; -import 'vs/workbench/contrib/notebook/browser/contrib/find/findController'; +import 'vs/workbench/contrib/notebook/browser/contrib/find/notebookFind'; import 'vs/workbench/contrib/notebook/browser/contrib/format/formatting'; import 'vs/workbench/contrib/notebook/browser/contrib/gettingStarted/notebookGettingStarted'; import 'vs/workbench/contrib/notebook/browser/contrib/layout/layoutActions'; diff --git a/src/vs/workbench/contrib/notebook/test/browser/contrib/find.test.ts b/src/vs/workbench/contrib/notebook/test/browser/contrib/find.test.ts index b9822f87393..6b1282d9afb 100644 --- a/src/vs/workbench/contrib/notebook/test/browser/contrib/find.test.ts +++ b/src/vs/workbench/contrib/notebook/test/browser/contrib/find.test.ts @@ -68,11 +68,11 @@ suite('Notebook Find', () => { await found; assert.strictEqual(model.findMatches.length, 2); assert.strictEqual(model.currentMatch, -1); - model.find(false); + model.find({ previous: false }); assert.strictEqual(model.currentMatch, 0); - model.find(false); + model.find({ previous: false }); assert.strictEqual(model.currentMatch, 1); - model.find(false); + model.find({ previous: false }); assert.strictEqual(model.currentMatch, 0); assert.strictEqual(editor.textModel.length, 3); @@ -115,11 +115,11 @@ suite('Notebook Find', () => { // find matches is not necessarily find results assert.strictEqual(model.findMatches.length, 4); assert.strictEqual(model.currentMatch, -1); - model.find(false); + model.find({ previous: false }); assert.strictEqual(model.currentMatch, 0); - model.find(false); + model.find({ previous: false }); assert.strictEqual(model.currentMatch, 1); - model.find(false); + model.find({ previous: false }); assert.strictEqual(model.currentMatch, 2); const found2 = new Promise(resolve => state.onFindReplaceStateChange(e => { @@ -132,13 +132,13 @@ suite('Notebook Find', () => { assert.strictEqual(model.findMatches.length, 3); assert.strictEqual(model.currentMatch, 2); - model.find(true); + model.find({ previous: true }); assert.strictEqual(model.currentMatch, 1); - model.find(false); + model.find({ previous: false }); assert.strictEqual(model.currentMatch, 2); - model.find(false); + model.find({ previous: false }); assert.strictEqual(model.currentMatch, 3); - model.find(false); + model.find({ previous: false }); assert.strictEqual(model.currentMatch, 0); }); }); @@ -166,7 +166,7 @@ suite('Notebook Find', () => { // find matches is not necessarily find results assert.strictEqual(model.findMatches.length, 4); assert.strictEqual(model.currentMatch, -1); - model.find(true); + model.find({ previous: true }); assert.strictEqual(model.currentMatch, 4); const found2 = new Promise(resolve => state.onFindReplaceStateChange(e => { @@ -178,9 +178,9 @@ suite('Notebook Find', () => { await found2; assert.strictEqual(model.findMatches.length, 3); assert.strictEqual(model.currentMatch, 0); - model.find(true); + model.find({ previous: true }); assert.strictEqual(model.currentMatch, 3); - model.find(true); + model.find({ previous: true }); assert.strictEqual(model.currentMatch, 2); }); }); @@ -208,9 +208,9 @@ suite('Notebook Find', () => { // find matches is not necessarily find results assert.strictEqual(model.findMatches.length, 4); assert.strictEqual(model.currentMatch, -1); - model.find(false); - model.find(false); - model.find(false); + model.find({ previous: false }); + model.find({ previous: false }); + model.find({ previous: false }); assert.strictEqual(model.currentMatch, 2); const found2 = new Promise(resolve => state.onFindReplaceStateChange(e => { if (e.matchesCount) { resolve(true); } @@ -244,11 +244,11 @@ suite('Notebook Find', () => { await found; assert.strictEqual(model.findMatches.length, 2); assert.strictEqual(model.currentMatch, -1); - model.find(false); + model.find({ previous: false }); assert.strictEqual(model.currentMatch, 0); - model.find(false); + model.find({ previous: false }); assert.strictEqual(model.currentMatch, 1); - model.find(false); + model.find({ previous: false }); assert.strictEqual(model.currentMatch, 0); assert.strictEqual(editor.textModel.length, 3); diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index a587b74597b..17baf536043 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -44,20 +44,24 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { getSelectionKeyboardEvent, WorkbenchObjectTree } from 'vs/platform/list/browser/listService'; -import { INotificationService, } from 'vs/platform/notification/common/notification'; +import { INotificationService } from 'vs/platform/notification/common/notification'; import { IOpenerService, withSelection } from 'vs/platform/opener/common/opener'; import { IProgress, IProgressService, IProgressStep } from 'vs/platform/progress/common/progress'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { diffInserted, diffInsertedOutline, diffRemoved, diffRemovedOutline, editorFindMatchHighlight, editorFindMatchHighlightBorder, foreground, listActiveSelectionForeground, textLinkActiveForeground, textLinkForeground, toolbarActiveBackground, toolbarHoverBackground } from 'vs/platform/theme/common/colorRegistry'; +import { isHighContrast } from 'vs/platform/theme/common/theme'; import { IColorTheme, ICssStyleCollector, IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { OpenFileFolderAction, OpenFolderAction } from 'vs/workbench/browser/actions/workspaceActions'; +import { ResourceListDnDHandler } from 'vs/workbench/browser/dnd'; import { ResourceLabels } from 'vs/workbench/browser/labels'; import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IEditorPane } from 'vs/workbench/common/editor'; import { Memento, MementoObject } from 'vs/workbench/common/memento'; import { IViewDescriptorService } from 'vs/workbench/common/views'; +import { NotebookFindWidget } from 'vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget'; +import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEditor'; import { ExcludePatternInputWidget, IncludePatternInputWidget } from 'vs/workbench/contrib/search/browser/patternInputWidget'; import { appendKeyBindingLabel, IFindInFilesArgs } from 'vs/workbench/contrib/search/browser/searchActions'; import { searchDetailsIcon } from 'vs/workbench/contrib/search/browser/searchIcons'; @@ -65,7 +69,6 @@ import { renderSearchMessage } from 'vs/workbench/contrib/search/browser/searchM import { FileMatchRenderer, FolderMatchRenderer, MatchRenderer, SearchAccessibilityProvider, SearchDelegate } from 'vs/workbench/contrib/search/browser/searchResultsView'; import { ISearchWidgetOptions, SearchWidget } from 'vs/workbench/contrib/search/browser/searchWidget'; import * as Constants from 'vs/workbench/contrib/search/common/constants'; -import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/services/search/common/queryBuilder'; import { IReplaceService } from 'vs/workbench/contrib/search/common/replace'; import { getOutOfWorkspaceEditorResources, SearchStateKey, SearchUIState } from 'vs/workbench/contrib/search/common/search'; import { ISearchHistoryService, ISearchHistoryValues } from 'vs/workbench/contrib/search/common/searchHistoryService'; @@ -73,11 +76,10 @@ import { FileMatch, FileMatchOrMatch, FolderMatch, FolderMatchWithResource, ICha import { createEditorFromSearchResult } from 'vs/workbench/contrib/searchEditor/browser/searchEditorActions'; import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IPreferencesService, ISettingsEditorOptions } from 'vs/workbench/services/preferences/common/preferences'; +import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/services/search/common/queryBuilder'; import { IPatternInfo, ISearchComplete, ISearchConfiguration, ISearchConfigurationProperties, ITextQuery, SearchCompletionExitCode, SearchSortOrder, TextSearchCompleteMessageType } from 'vs/workbench/services/search/common/search'; import { TextSearchCompleteMessage } from 'vs/workbench/services/search/common/searchExtTypes'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { ResourceListDnDHandler } from 'vs/workbench/browser/dnd'; -import { isHighContrast } from 'vs/platform/theme/common/theme'; const $ = dom.$; @@ -1712,18 +1714,22 @@ export class SearchView extends ViewPane { this.open(lineMatch, preserveFocus, sideBySide, pinned); } - open(element: FileMatchOrMatch, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise { + async open(element: FileMatchOrMatch, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise { const selection = this.getSelectionFrom(element); const resource = element instanceof Match ? element.parent().resource : (element).resource; - return this.editorService.openEditor({ - resource: resource, - options: { - preserveFocus, - pinned, - selection, - revealIfVisible: true - } - }, sideBySide ? SIDE_GROUP : ACTIVE_GROUP).then(editor => { + + let editor: IEditorPane | undefined; + try { + editor = await this.editorService.openEditor({ + resource: resource, + options: { + preserveFocus, + pinned, + selection, + revealIfVisible: true + } + }, sideBySide ? SIDE_GROUP : ACTIVE_GROUP); + const editorControl = editor?.getControl(); if (element instanceof Match && preserveFocus && isCodeEditor(editorControl)) { this.viewModel.searchResult.rangeHighlightDecorations.highlightRange( @@ -1733,7 +1739,16 @@ export class SearchView extends ViewPane { } else { this.viewModel.searchResult.rangeHighlightDecorations.removeHighlightRange(); } - }, errors.onUnexpectedError); + } catch (err) { + errors.onUnexpectedError(err); + return; + } + + if (editor instanceof NotebookEditor) { + const controller = editor.getControl()?.getContribution(NotebookFindWidget.id); + const matchIndex = element instanceof Match ? element.parent().matches().findIndex(e => e.id() === element.id()) : undefined; + controller?.show(this.searchWidget.searchInput.getValue(), { matchIndex, focus: false }); + } } openEditorWithMultiCursor(element: FileMatchOrMatch): Promise { -- cgit v1.2.3 From 310108c376cb6274eeed8adeff9be32de946d8ad Mon Sep 17 00:00:00 2001 From: Johannes Date: Mon, 25 Apr 2022 09:40:57 +0200 Subject: fix https://github.com/microsoft/vscode/issues/144555 --- .../contrib/themes/test/electron-browser/colorRegistry.releaseTest.ts | 4 ++-- src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/themes/test/electron-browser/colorRegistry.releaseTest.ts b/src/vs/workbench/contrib/themes/test/electron-browser/colorRegistry.releaseTest.ts index 397ecffdb59..76104ae81f2 100644 --- a/src/vs/workbench/contrib/themes/test/electron-browser/colorRegistry.releaseTest.ts +++ b/src/vs/workbench/contrib/themes/test/electron-browser/colorRegistry.releaseTest.ts @@ -5,7 +5,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IColorRegistry, Extensions, ColorContribution } from 'vs/platform/theme/common/colorRegistry'; -import { asText } from 'vs/platform/request/common/request'; +import { asTextOrError } from 'vs/platform/request/common/request'; import * as pfs from 'vs/base/node/pfs'; import * as path from 'vs/base/common/path'; import * as assert from 'assert'; @@ -39,7 +39,7 @@ suite('Color Registry', function () { const environmentService = new class extends mock() { override args = { _: [] }; }; const reqContext = await new RequestService(new TestConfigurationService(), environmentService, new NullLogService()).request({ url: 'https://raw.githubusercontent.com/microsoft/vscode-docs/vnext/api/references/theme-color.md' }, CancellationToken.None); - const content = (await asText(reqContext))!; + const content = (await asTextOrError(reqContext))!; const expression = /-\s*\`([\w\.]+)\`: (.*)/g; diff --git a/src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts b/src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts index f7379a4d721..df20df258da 100644 --- a/src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts +++ b/src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts @@ -21,7 +21,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IProductService } from 'vs/platform/product/common/productService'; -import { asText, IRequestService } from 'vs/platform/request/common/request'; +import { asTextOrError, IRequestService } from 'vs/platform/request/common/request'; import { DEFAULT_MARKDOWN_STYLES, renderMarkdownDocument } from 'vs/workbench/contrib/markdown/browser/markdownDocumentRenderer'; import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput'; import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService'; @@ -163,7 +163,7 @@ export class ReleaseNotesManager { const fetchReleaseNotes = async () => { let text; try { - text = await asText(await this._requestService.request({ url }, CancellationToken.None)); + text = await asTextOrError(await this._requestService.request({ url }, CancellationToken.None)); } catch { throw new Error('Failed to fetch release notes'); } -- cgit v1.2.3 From 522d784b28326601bafb052c18fdf2fd4dc50b72 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 25 Apr 2022 16:29:46 +0530 Subject: - fix layering issue - remove id - fix namings --- src/vs/workbench/contrib/profiles/common/profiles.ts | 10 ---------- .../contrib/profiles/common/profilesActions.ts | 19 +++++++++---------- 2 files changed, 9 insertions(+), 20 deletions(-) delete mode 100644 src/vs/workbench/contrib/profiles/common/profiles.ts (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/profiles/common/profiles.ts b/src/vs/workbench/contrib/profiles/common/profiles.ts deleted file mode 100644 index 46db3b23829..00000000000 --- a/src/vs/workbench/contrib/profiles/common/profiles.ts +++ /dev/null @@ -1,10 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { localize } from 'vs/nls'; - -export const PROFILES_CATEGORY = localize('profiles', "Profiles"); -export const PROFILE_EXTENSION = 'code-profile'; -export const PROFILE_FILTER = [{ name: localize('profile', "Code Profile"), extensions: [PROFILE_EXTENSION] }]; diff --git a/src/vs/workbench/contrib/profiles/common/profilesActions.ts b/src/vs/workbench/contrib/profiles/common/profilesActions.ts index 5c24616eaa4..2ab0e5462ce 100644 --- a/src/vs/workbench/contrib/profiles/common/profilesActions.ts +++ b/src/vs/workbench/contrib/profiles/common/profilesActions.ts @@ -14,8 +14,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { INotificationService } from 'vs/platform/notification/common/notification'; import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { asJson, asText, IRequestService } from 'vs/platform/request/common/request'; -import { PROFILES_CATEGORY, PROFILE_EXTENSION, PROFILE_FILTER } from 'vs/workbench/contrib/profiles/common/profiles'; -import { IProfile, isProfile, IWorkbenchProfileService } from 'vs/workbench/services/profiles/common/profile'; +import { IProfile, isProfile, IWorkbenchProfileService, PROFILES_CATEGORY, PROFILE_EXTENSION, PROFILE_FILTER } from 'vs/workbench/services/profiles/common/profile'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; registerAction2(class ExportProfileAction extends Action2 { @@ -23,8 +22,8 @@ registerAction2(class ExportProfileAction extends Action2 { super({ id: 'workbench.profiles.actions.exportProfile', title: { - value: localize('export profile', "Export customizations as a Profile..."), - original: 'Export customizations as a Profile...' + value: localize('export profile', "Export Settings as a Profile..."), + original: 'Export Settings as a Profile...' }, category: PROFILES_CATEGORY, f1: true @@ -50,7 +49,7 @@ registerAction2(class ExportProfileAction extends Action2 { const profile = await profileService.createProfile({ skipComments: true }); await textFileService.create([{ resource: profileLocation, value: JSON.stringify(profile), options: { overwrite: true } }]); - notificationService.info(localize('export success', "Profile successfully exported.")); + notificationService.info(localize('export success', "{0}: Exported successfully.", PROFILES_CATEGORY)); } }); @@ -59,8 +58,8 @@ registerAction2(class ImportProfileAction extends Action2 { super({ id: 'workbench.profiles.actions.importProfile', title: { - value: localize('import profile', "Import customizations from a Profile..."), - original: 'Import customizations from a Profile...' + value: localize('import profile', "Import Settings from a Profile..."), + original: 'Import Settings from a Profile...' }, category: PROFILES_CATEGORY, f1: true @@ -76,8 +75,8 @@ registerAction2(class ImportProfileAction extends Action2 { const dialogService = accessor.get(IDialogService); if (!(await dialogService.confirm({ - title: localize('import profile title', "Import customizations from a Profile"), - message: localize('confiirmation message', "This will replace your current customizations. Are you sure you want to continue?"), + title: localize('import profile title', "Import Settings from a Profile"), + message: localize('confiirmation message', "This will replace your current settings. Are you sure you want to continue?"), })).confirmed) { return; } @@ -88,7 +87,7 @@ registerAction2(class ImportProfileAction extends Action2 { const selectFromFileItem: IQuickPickItem = { label: localize('select from file', "Import from profile file") }; quickPick.items = value ? [{ label: localize('select from url', "Import from URL"), description: quickPick.value }, selectFromFileItem] : [selectFromFileItem]; }; - quickPick.title = localize('import profile quick pick title', "Import customizations from a Profile"); + quickPick.title = localize('import profile quick pick title', "Import Settings from a Profile"); quickPick.placeholder = localize('import profile placeholder', "Provide profile URL or select profile file to import"); quickPick.ignoreFocusOut = true; disposables.add(quickPick.onDidChangeValue(updateQuickPickItems)); -- cgit v1.2.3 From 12a14de6a67ac0dcabc77fde2f24b352b5f0f9a6 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 25 Apr 2022 15:05:02 +0200 Subject: increase default audioCues volume to 70 fyi @hediet --- src/vs/workbench/contrib/audioCues/browser/audioCues.contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/audioCues/browser/audioCues.contribution.ts b/src/vs/workbench/contrib/audioCues/browser/audioCues.contribution.ts index 4122bc5a7dd..ef9e3d8358a 100644 --- a/src/vs/workbench/contrib/audioCues/browser/audioCues.contribution.ts +++ b/src/vs/workbench/contrib/audioCues/browser/audioCues.contribution.ts @@ -41,7 +41,7 @@ Registry.as(ConfigurationExtensions.Configuration).regis 'type': 'number', 'minimum': 0, 'maximum': 100, - 'default': 50 + 'default': 70 }, 'audioCues.lineHasBreakpoint': { 'description': localize('audioCues.lineHasBreakpoint', "Plays a sound when the active line has a breakpoint."), -- cgit v1.2.3 From e1abd2a799d843b37c2bc378e7b0bdb5bf78f469 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 25 Apr 2022 16:11:48 +0200 Subject: Fix descriptions for comment thread range colors --- src/vs/workbench/contrib/comments/browser/commentColors.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentColors.ts b/src/vs/workbench/contrib/comments/browser/commentColors.ts index 78555e0e9e3..127c30c86f8 100644 --- a/src/vs/workbench/contrib/comments/browser/commentColors.ts +++ b/src/vs/workbench/contrib/comments/browser/commentColors.ts @@ -13,9 +13,9 @@ import { IColorTheme } from 'vs/platform/theme/common/themeService'; const resolvedCommentBorder = registerColor('editorCommentsWidget.resolvedBorder', { dark: disabledForeground, light: disabledForeground, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('resolvedCommentBorder', 'Color of borders and arrow for resolved comments.')); const unresolvedCommentBorder = registerColor('editorCommentsWidget.unresolvedBorder', { dark: peekViewBorder, light: peekViewBorder, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('unresolvedCommentBorder', 'Color of borders and arrow for unresolved comments.')); export const commentThreadRangeBackground = registerColor('editorCommentsWidget.rangeBackground', { dark: transparent(unresolvedCommentBorder, .1), light: transparent(unresolvedCommentBorder, .1), hcDark: transparent(unresolvedCommentBorder, .1), hcLight: transparent(unresolvedCommentBorder, .1) }, nls.localize('commentThreadRangeBackground', 'Color of background for comment ranges.')); -export const commentThreadRangeBorder = registerColor('editorCommentsWidget.rangeBorder', { dark: transparent(unresolvedCommentBorder, .4), light: transparent(unresolvedCommentBorder, .4), hcDark: transparent(unresolvedCommentBorder, .4), hcLight: transparent(unresolvedCommentBorder, .4) }, nls.localize('commentThreadRangeBackground', 'Color of background for comment ranges.')); -export const commentThreadRangeActiveBackground = registerColor('editorCommentsWidget.rangeActiveBackground', { dark: transparent(unresolvedCommentBorder, .1), light: transparent(unresolvedCommentBorder, .1), hcDark: transparent(unresolvedCommentBorder, .1), hcLight: transparent(unresolvedCommentBorder, .1) }, nls.localize('commentThreadRangeBackground', 'Color of background for comment ranges.')); -export const commentThreadRangeActiveBorder = registerColor('editorCommentsWidget.rangeActiveBorder', { dark: transparent(unresolvedCommentBorder, .4), light: transparent(unresolvedCommentBorder, .4), hcDark: transparent(unresolvedCommentBorder, .4), hcLight: transparent(unresolvedCommentBorder, .2) }, nls.localize('commentThreadRangeBackground', 'Color of background for comment ranges.')); +export const commentThreadRangeBorder = registerColor('editorCommentsWidget.rangeBorder', { dark: transparent(unresolvedCommentBorder, .4), light: transparent(unresolvedCommentBorder, .4), hcDark: transparent(unresolvedCommentBorder, .4), hcLight: transparent(unresolvedCommentBorder, .4) }, nls.localize('commentThreadRangeBorder', 'Color of border for comment ranges.')); +export const commentThreadRangeActiveBackground = registerColor('editorCommentsWidget.rangeActiveBackground', { dark: transparent(unresolvedCommentBorder, .1), light: transparent(unresolvedCommentBorder, .1), hcDark: transparent(unresolvedCommentBorder, .1), hcLight: transparent(unresolvedCommentBorder, .1) }, nls.localize('commentThreadActiveRangeBackground', 'Color of background for currently selected or hovered comment range.')); +export const commentThreadRangeActiveBorder = registerColor('editorCommentsWidget.rangeActiveBorder', { dark: transparent(unresolvedCommentBorder, .4), light: transparent(unresolvedCommentBorder, .4), hcDark: transparent(unresolvedCommentBorder, .4), hcLight: transparent(unresolvedCommentBorder, .2) }, nls.localize('commentThreadActiveRangeBorder', 'Color of border for currently selected or hovered comment range.')); const commentThreadStateColors = new Map([ [languages.CommentThreadState.Unresolved, unresolvedCommentBorder], -- cgit v1.2.3 From 4f9bad8775676e714da6d25d7514b3e30863f5b5 Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Mon, 25 Apr 2022 10:23:09 -0400 Subject: Fix #145378 --- src/vs/workbench/contrib/timeline/browser/timelinePane.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index 6c2233986e1..b2ee02b8923 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -352,7 +352,7 @@ export class TimelinePane extends ViewPane { } private onActiveEditorChanged() { - if (!this.followActiveEditor) { + if (!this.followActiveEditor || !this.isExpanded()) { return; } -- cgit v1.2.3 From 22592e3c7546bf162544db2725364ea5f5d43a17 Mon Sep 17 00:00:00 2001 From: SteVen Batten <6561887+sbatten@users.noreply.github.com> Date: Mon, 25 Apr 2022 07:58:56 -0700 Subject: better handling of uris when remote is windows (#147803) --- .../workspace/browser/workspaceTrustEditor.ts | 31 +++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts b/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts index 5aae1567d83..68e9e88bcd4 100644 --- a/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts +++ b/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts @@ -50,7 +50,8 @@ import { WorkspaceTrustEditorInput } from 'vs/workbench/services/workspaces/brow import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { getExtensionDependencies } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { EnablementState, IWorkbenchExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; -import { posix } from 'vs/base/common/path'; +import { posix, win32 } from 'vs/base/common/path'; +import { hasDriveLetter, toSlashes } from 'vs/base/common/extpath'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { IProductService } from 'vs/platform/product/common/productService'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; @@ -530,8 +531,10 @@ class TrustedUriPathColumnRenderer implements ITableRenderer { hideInputBox(); - const uri = item.uri.with({ path: templateData.pathInput.value }); - templateData.pathLabel.innerText = templateData.pathInput.value; + + const pathToUse = templateData.pathInput.value; + const uri = hasDriveLetter(pathToUse) ? item.uri.with({ path: posix.sep + toSlashes(pathToUse) }) : item.uri.with({ path: pathToUse }); + templateData.pathLabel.innerText = this.formatPath(uri); if (uri) { this.table.acceptEdit(item, uri); @@ -563,12 +566,10 @@ class TrustedUriPathColumnRenderer implements ITableRenderer C:\user\directory + if (uri.path.startsWith(posix.sep)) { + const pathWithoutLeadingSeparator = uri.path.substring(1); + const isWindowsPath = hasDriveLetter(pathWithoutLeadingSeparator, true); + if (isWindowsPath) { + return win32.normalize(pathWithoutLeadingSeparator); + } + } + + return uri.path; + } + } -- cgit v1.2.3 From 5dad501a0388550a8cda924c12d68fe721b75cd7 Mon Sep 17 00:00:00 2001 From: Johannes Date: Mon, 25 Apr 2022 17:24:12 +0200 Subject: add formatter conflict information (and ask to configure default) as language status item, https://github.com/microsoft/vscode/issues/148053 --- .../format/browser/formatActionsMultiple.ts | 109 +++++++++++++++------ 1 file changed, 80 insertions(+), 29 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts b/src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts index 3481452d194..1f9d18be26c 100644 --- a/src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts +++ b/src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts @@ -3,15 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { EditorAction, registerEditorAction, ServicesAccessor } from 'vs/editor/browser/editorExtensions'; +import { getCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { EditorAction, registerEditorAction } from 'vs/editor/browser/editorExtensions'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { DocumentFormattingEditProvider, DocumentRangeFormattingEditProvider } from 'vs/editor/common/languages'; import * as nls from 'vs/nls'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; -import { CancellationToken } from 'vs/base/common/cancellation'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { formatDocumentRangesWithProvider, formatDocumentWithProvider, getRealAndSyntheticDocumentFormattersOrdered, FormattingConflicts, FormattingMode } from 'vs/editor/contrib/format/browser/format'; import { Range } from 'vs/editor/common/core/range'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -21,7 +21,7 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'v import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry, IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { IExtensionService, toExtension } from 'vs/workbench/services/extensions/common/extensions'; -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ITextModel } from 'vs/editor/common/model'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; @@ -30,6 +30,10 @@ import { IWorkbenchExtensionEnablementService } from 'vs/workbench/services/exte import { editorConfigurationBaseNode } from 'vs/editor/common/config/editorConfigurationSchema'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; +import { ILanguageStatusService } from 'vs/workbench/services/languageStatus/common/languageStatusService'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { CommandsRegistry } from 'vs/platform/commands/common/commands'; +import { generateUuid } from 'vs/base/common/uuid'; type FormattingEditProvider = DocumentFormattingEditProvider | DocumentRangeFormattingEditProvider; @@ -41,6 +45,8 @@ class DefaultFormatter extends Disposable implements IWorkbenchContribution { static extensionItemLabels: string[] = []; static extensionDescriptions: string[] = []; + private readonly _languageStatusStore = this._store.add(new DisposableStore()); + constructor( @IExtensionService private readonly _extensionService: IExtensionService, @IWorkbenchExtensionEnablementService private readonly _extensionEnablementService: IWorkbenchExtensionEnablementService, @@ -49,10 +55,16 @@ class DefaultFormatter extends Disposable implements IWorkbenchContribution { @IDialogService private readonly _dialogService: IDialogService, @IQuickInputService private readonly _quickInputService: IQuickInputService, @ILanguageService private readonly _languageService: ILanguageService, + @ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService, + @ILanguageStatusService private readonly _languageStatusService: ILanguageStatusService, + @IEditorService private readonly _editorService: IEditorService, ) { super(); - this._register(this._extensionService.onDidChangeExtensions(this._updateConfigValues, this)); - this._register(FormattingConflicts.setFormatterSelector((formatter, document, mode) => this._selectFormatter(formatter, document, mode))); + this._store.add(this._extensionService.onDidChangeExtensions(this._updateConfigValues, this)); + this._store.add(FormattingConflicts.setFormatterSelector((formatter, document, mode) => this._selectFormatter(formatter, document, mode))); + this._store.add(_editorService.onDidActiveEditorChange(this._updateStatus, this)); + this._store.add(_languageFeaturesService.documentFormattingEditProvider.onDidChange(this._updateStatus, this)); + this._store.add(_languageFeaturesService.documentRangeFormattingEditProvider.onDidChange(this._updateStatus, this)); this._updateConfigValues(); } @@ -93,8 +105,7 @@ class DefaultFormatter extends Disposable implements IWorkbenchContribution { return s.match(/\s/) ? `'${s}'` : s; } - private async _selectFormatter(formatter: T[], document: ITextModel, mode: FormattingMode): Promise { - + private async _analyzeFormatter(formatter: T[], document: ITextModel): Promise { const defaultFormatterId = this._configService.getValue(DefaultFormatter.configName, { resource: document.uri, overrideIdentifier: document.getLanguageId() @@ -114,23 +125,9 @@ class DefaultFormatter extends Disposable implements IWorkbenchContribution { // formatter does not target this file const langName = this._languageService.getLanguageName(document.getLanguageId()) || document.getLanguageId(); const detail = nls.localize('miss', "Extension '{0}' is configured as formatter but it cannot format '{1}'-files", extension.displayName || extension.name, langName); - if (mode === FormattingMode.Silent) { - this._notificationService.status(detail, { hideAfter: 4000 }); - return undefined; - } else { - const result = await this._dialogService.confirm({ - message: nls.localize('miss.1', "Change Default Formatter"), - detail, - primaryButton: nls.localize('do.config', "Configure..."), - secondaryButton: nls.localize('cancel', "Cancel") - }); - if (result.confirmed) { - return this._pickAndPersistDefaultFormatter(formatter, document); - } else { - return undefined; - } - } + return detail; } + } else if (formatter.length === 1) { // ok -> nothing configured but only one formatter available return formatter[0]; @@ -138,26 +135,35 @@ class DefaultFormatter extends Disposable implements IWorkbenchContribution { const langName = this._languageService.getLanguageName(document.getLanguageId()) || document.getLanguageId(); const message = !defaultFormatterId - ? nls.localize('config.needed', "There are multiple formatters for '{0}' files. Select a default formatter to continue.", DefaultFormatter._maybeQuotes(langName)) + ? nls.localize('config.needed', "There are multiple formatters for '{0}' files. One of them should be configured as default formatter.", DefaultFormatter._maybeQuotes(langName)) : nls.localize('config.bad', "Extension '{0}' is configured as formatter but not available. Select a different default formatter to continue.", defaultFormatterId); + return message; + } + + private async _selectFormatter(formatter: T[], document: ITextModel, mode: FormattingMode): Promise { + const formatterOrMessage = await this._analyzeFormatter(formatter, document); + if (typeof formatterOrMessage !== 'string') { + return formatterOrMessage; + } + if (mode !== FormattingMode.Silent) { // running from a user action -> show modal dialog so that users configure // a default formatter const result = await this._dialogService.confirm({ - message, + message: nls.localize('miss.1', "Configure Default Formatter"), + detail: formatterOrMessage, primaryButton: nls.localize('do.config', "Configure..."), secondaryButton: nls.localize('cancel', "Cancel") }); if (result.confirmed) { return this._pickAndPersistDefaultFormatter(formatter, document); } - } else { // no user action -> show a silent notification and proceed this._notificationService.prompt( Severity.Info, - message, + formatterOrMessage, [{ label: nls.localize('do.config', "Configure..."), run: () => this._pickAndPersistDefaultFormatter(formatter, document) }], { silent: true } ); @@ -184,6 +190,51 @@ class DefaultFormatter extends Disposable implements IWorkbenchContribution { }); return formatter[pick.index]; } + + // --- status item + + private _updateStatus() { + this._languageStatusStore.clear(); + + const editor = getCodeEditor(this._editorService.activeTextEditorControl); + if (!editor || !editor.hasModel()) { + return; + } + + + const document = editor.getModel(); + const formatter = getRealAndSyntheticDocumentFormattersOrdered(this._languageFeaturesService.documentFormattingEditProvider, this._languageFeaturesService.documentRangeFormattingEditProvider, document); + + if (formatter.length === 0) { + return; + } + + const cts = new CancellationTokenSource(); + this._languageStatusStore.add(toDisposable(() => cts.dispose(true))); + + this._analyzeFormatter(formatter, document).then(result => { + if (cts.token.isCancellationRequested) { + return; + } + if (typeof result !== 'string') { + return; + } + const command = { id: `formatter/configure/dfl/${generateUuid()}`, title: nls.localize('do.config', "Configure...") }; + this._languageStatusStore.add(CommandsRegistry.registerCommand(command.id, () => this._pickAndPersistDefaultFormatter(formatter, document))); + this._languageStatusStore.add(this._languageStatusService.addStatus({ + id: 'formatter.conflict', + name: nls.localize('summary', "Formatter Conflicts"), + selector: { language: document.getLanguageId(), pattern: document.uri.fsPath }, + severity: Severity.Error, + label: nls.localize('formatter', "Formatting"), + detail: result, + busy: false, + source: '', + command, + accessibilityInfo: undefined + })); + }); + } } Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution( -- cgit v1.2.3 From f07b19f5ac4ac4f5df5e67d72a82ccd834cefcae Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 25 Apr 2022 10:24:53 -0700 Subject: Fix #148009 --- .../contrib/languageDetection/browser/languageDetection.contribution.ts | 2 +- src/vs/workbench/contrib/notebook/browser/controller/editActions.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/languageDetection/browser/languageDetection.contribution.ts b/src/vs/workbench/contrib/languageDetection/browser/languageDetection.contribution.ts index 3df19dec7a5..8e046511962 100644 --- a/src/vs/workbench/contrib/languageDetection/browser/languageDetection.contribution.ts +++ b/src/vs/workbench/contrib/languageDetection/browser/languageDetection.contribution.ts @@ -126,7 +126,7 @@ registerAction2(class extends Action2 { title: localize('detectlang', 'Detect Language from Content'), f1: true, precondition: ContextKeyExpr.and(NOTEBOOK_EDITOR_EDITABLE.toNegated(), EditorContextKeys.editorTextFocus), - keybinding: { primary: KeyCode.KeyE | KeyMod.CtrlCmd, weight: KeybindingWeight.WorkbenchContrib } + keybinding: { primary: KeyCode.KeyD | KeyMod.Alt, weight: KeybindingWeight.WorkbenchContrib } }); } diff --git a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts index 27a1c5b7c21..34cc0e18f85 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts @@ -471,7 +471,7 @@ registerAction2(class DetectCellLanguageAction extends NotebookCellAction { title: localize('detectLanguage', 'Accept Detected Language for Cell'), f1: true, precondition: ContextKeyExpr.and(NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_CELL_EDITABLE), - keybinding: { primary: KeyCode.KeyE | KeyMod.CtrlCmd, weight: KeybindingWeight.WorkbenchContrib } + keybinding: { primary: KeyCode.KeyD | KeyMod.Alt, weight: KeybindingWeight.WorkbenchContrib } }); } -- cgit v1.2.3 From 89a3042eac46ec92255861599b41e01a505598d8 Mon Sep 17 00:00:00 2001 From: Suven-p Date: Mon, 25 Apr 2022 23:12:50 +0545 Subject: testing: add action to unhide all tests (#148003) --- .../contrib/testing/browser/testExplorerActions.ts | 16 ++++++++++++++++ src/vs/workbench/contrib/testing/common/constants.ts | 1 + 2 files changed, 17 insertions(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts index 9382f47bc67..db687ec08b6 100644 --- a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts +++ b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts @@ -111,6 +111,21 @@ export class UnhideTestAction extends Action2 { } } +export class UnhideAllTestsAction extends Action2 { + constructor() { + super({ + id: TestCommandId.UnhideAllTestsAction, + title: localize('unhideAllTests', 'Unhide All Tests'), + }); + } + + public override run(accessor: ServicesAccessor) { + const service = accessor.get(ITestService); + service.excluded.clear(); + return Promise.resolve(); + } +} + const testItemInlineAndInContext = (order: ActionOrder, when?: ContextKeyExpression) => [ { id: MenuId.TestItem, @@ -1190,4 +1205,5 @@ export const allTestActions = [ TestingViewAsTreeAction, ToggleInlineTestOutput, UnhideTestAction, + UnhideAllTestsAction, ]; diff --git a/src/vs/workbench/contrib/testing/common/constants.ts b/src/vs/workbench/contrib/testing/common/constants.ts index c8fc457be2d..224cbd48e90 100644 --- a/src/vs/workbench/contrib/testing/common/constants.ts +++ b/src/vs/workbench/contrib/testing/common/constants.ts @@ -89,4 +89,5 @@ export const enum TestCommandId { ToggleAutoRun = 'testing.toggleautoRun', ToggleInlineTestOutput = 'testing.toggleInlineTestOutput', UnhideTestAction = 'testing.unhideTest', + UnhideAllTestsAction = 'testing.unhideAllTests', } -- cgit v1.2.3 From c2299548a4d2ba69048069d6f84c92d915ad94d0 Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Mon, 25 Apr 2022 14:05:53 -0700 Subject: Add suggestions for ext filter (#148076) --- .../contrib/preferences/browser/settingsEditor2.ts | 16 +++++++++++++++- .../contrib/preferences/browser/settingsSearchMenu.ts | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 3afedd34c39..38f92fa0f10 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -59,6 +59,8 @@ import { Orientation, Sizing, SplitView } from 'vs/base/browser/ui/splitview/spl import { Color } from 'vs/base/common/color'; import { ILanguageService } from 'vs/editor/common/languages/language'; import { SettingsSearchFilterDropdownMenuActionViewItem } from 'vs/workbench/contrib/preferences/browser/settingsSearchMenu'; +import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ExtensionType } from 'vs/platform/extensions/common/extensions'; export const enum SettingsFocusContext { Search, @@ -202,6 +204,8 @@ export class SettingsEditor2 extends EditorPane { private settingsTreeScrollTop = 0; private dimension!: DOM.Dimension; + private installedExtensionIds: string[] = []; + constructor( @ITelemetryService telemetryService: ITelemetryService, @IWorkbenchConfigurationService private readonly configurationService: IWorkbenchConfigurationService, @@ -218,7 +222,8 @@ export class SettingsEditor2 extends EditorPane { @IUserDataSyncEnablementService private readonly userDataSyncEnablementService: IUserDataSyncEnablementService, @IWorkspaceTrustManagementService private readonly workspaceTrustManagementService: IWorkspaceTrustManagementService, @IExtensionService private readonly extensionService: IExtensionService, - @ILanguageService private readonly languageService: ILanguageService + @ILanguageService private readonly languageService: ILanguageService, + @IExtensionManagementService extensionManagementService: IExtensionManagementService ) { super(SettingsEditor2.ID, telemetryService, themeService, storageService); this.delayedFilterLogging = new Delayer(1000); @@ -269,6 +274,10 @@ export class SettingsEditor2 extends EditorPane { if (ENABLE_LANGUAGE_FILTER && !SettingsEditor2.SUGGESTIONS.includes(`@${LANGUAGE_SETTING_TAG}`)) { SettingsEditor2.SUGGESTIONS.push(`@${LANGUAGE_SETTING_TAG}`); } + + extensionManagementService.getInstalled(ExtensionType.System).then(extensions => { + this.installedExtensionIds = extensions.map(extension => extension.identifier.id); + }); } override get minimumWidth(): number { return SettingsEditor2.EDITOR_MIN_WIDTH; } @@ -538,6 +547,11 @@ export class SettingsEditor2 extends EditorPane { return `@${LANGUAGE_SETTING_TAG}${languageId} `; }).sort(); return sortedLanguages.filter(langFilter => !query.includes(langFilter)); + } else if (queryParts[queryParts.length - 1].startsWith(`@${EXTENSION_SETTING_TAG}`)) { + const installedExtensionsTags = this.installedExtensionIds.map(extensionId => { + return `@${EXTENSION_SETTING_TAG}${extensionId} `; + }).sort(); + return installedExtensionsTags.filter(extFilter => !query.includes(extFilter)); } else if (queryParts[queryParts.length - 1].startsWith('@')) { return SettingsEditor2.SUGGESTIONS.filter(tag => !query.includes(tag)).map(tag => tag.endsWith(':') ? tag : tag + ' '); } diff --git a/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts b/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts index 333d179f818..e39d23eb58e 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsSearchMenu.ts @@ -107,7 +107,7 @@ export class SettingsSearchFilterDropdownMenuActionViewItem extends DropdownMenu localize('extSettingsSearch', "Extension ID..."), localize('extSettingsSearchTooltip', "Add extension ID filter"), `@${EXTENSION_SETTING_TAG}`, - false + true ), this.createAction( 'featuresSettingsSearch', -- cgit v1.2.3 From d6313c09c9407ddbe220cad014c1374d661982dc Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 25 Apr 2022 16:36:36 -0700 Subject: Fix #148057 --- src/vs/workbench/contrib/webview/browser/pre/main.js | 6 +++++- src/vs/workbench/contrib/webview/browser/themeing.ts | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/webview/browser/pre/main.js b/src/vs/workbench/contrib/webview/browser/pre/main.js index d2c57f4aa10..60b8c5f777a 100644 --- a/src/vs/workbench/contrib/webview/browser/pre/main.js +++ b/src/vs/workbench/contrib/webview/browser/pre/main.js @@ -459,9 +459,13 @@ const applyStyles = (document, body) => { } if (body) { - body.classList.remove('vscode-light', 'vscode-dark', 'vscode-high-contrast', 'vscode-reduce-motion', 'vscode-using-screen-reader'); + body.classList.remove('vscode-light', 'vscode-dark', 'vscode-high-contrast', 'vscode-high-contrast-light', 'vscode-reduce-motion', 'vscode-using-screen-reader'); if (initData.activeTheme) { body.classList.add(initData.activeTheme); + if (initData.activeTheme === 'vscode-high-contrast-light') { + // backwards compatibility + body.classList.add('vscode-high-contrast'); + } } if (initData.reduceMotion) { diff --git a/src/vs/workbench/contrib/webview/browser/themeing.ts b/src/vs/workbench/contrib/webview/browser/themeing.ts index 815dba525eb..525958584ee 100644 --- a/src/vs/workbench/contrib/webview/browser/themeing.ts +++ b/src/vs/workbench/contrib/webview/browser/themeing.ts @@ -90,7 +90,8 @@ export class WebviewThemeDataProvider extends Disposable { enum ApiThemeClassName { light = 'vscode-light', dark = 'vscode-dark', - highContrast = 'vscode-high-contrast' + highContrast = 'vscode-high-contrast', + highContrastLight = 'vscode-high-contrast-light', } namespace ApiThemeClassName { @@ -98,7 +99,8 @@ namespace ApiThemeClassName { switch (theme.type) { case ColorScheme.LIGHT: return ApiThemeClassName.light; case ColorScheme.DARK: return ApiThemeClassName.dark; - default: return ApiThemeClassName.highContrast; + case ColorScheme.HIGH_CONTRAST_DARK: return ApiThemeClassName.highContrast; + default: return ApiThemeClassName.highContrastLight; } } } -- cgit v1.2.3 From 6c94e91d1a855c6bfd6d207df9cf79f288af10f8 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 25 Apr 2022 16:37:15 -0700 Subject: Revert "Fix #148057" This reverts commit d6313c09c9407ddbe220cad014c1374d661982dc. --- src/vs/workbench/contrib/webview/browser/pre/main.js | 6 +----- src/vs/workbench/contrib/webview/browser/themeing.ts | 6 ++---- 2 files changed, 3 insertions(+), 9 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/webview/browser/pre/main.js b/src/vs/workbench/contrib/webview/browser/pre/main.js index 60b8c5f777a..d2c57f4aa10 100644 --- a/src/vs/workbench/contrib/webview/browser/pre/main.js +++ b/src/vs/workbench/contrib/webview/browser/pre/main.js @@ -459,13 +459,9 @@ const applyStyles = (document, body) => { } if (body) { - body.classList.remove('vscode-light', 'vscode-dark', 'vscode-high-contrast', 'vscode-high-contrast-light', 'vscode-reduce-motion', 'vscode-using-screen-reader'); + body.classList.remove('vscode-light', 'vscode-dark', 'vscode-high-contrast', 'vscode-reduce-motion', 'vscode-using-screen-reader'); if (initData.activeTheme) { body.classList.add(initData.activeTheme); - if (initData.activeTheme === 'vscode-high-contrast-light') { - // backwards compatibility - body.classList.add('vscode-high-contrast'); - } } if (initData.reduceMotion) { diff --git a/src/vs/workbench/contrib/webview/browser/themeing.ts b/src/vs/workbench/contrib/webview/browser/themeing.ts index 525958584ee..815dba525eb 100644 --- a/src/vs/workbench/contrib/webview/browser/themeing.ts +++ b/src/vs/workbench/contrib/webview/browser/themeing.ts @@ -90,8 +90,7 @@ export class WebviewThemeDataProvider extends Disposable { enum ApiThemeClassName { light = 'vscode-light', dark = 'vscode-dark', - highContrast = 'vscode-high-contrast', - highContrastLight = 'vscode-high-contrast-light', + highContrast = 'vscode-high-contrast' } namespace ApiThemeClassName { @@ -99,8 +98,7 @@ namespace ApiThemeClassName { switch (theme.type) { case ColorScheme.LIGHT: return ApiThemeClassName.light; case ColorScheme.DARK: return ApiThemeClassName.dark; - case ColorScheme.HIGH_CONTRAST_DARK: return ApiThemeClassName.highContrast; - default: return ApiThemeClassName.highContrastLight; + default: return ApiThemeClassName.highContrast; } } } -- cgit v1.2.3 From 872a78f6e9cbabce6ca54ffa20023be6531e451c Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 25 Apr 2022 16:53:52 -0700 Subject: Close #148090 --- .../contrib/files/browser/explorerService.ts | 2 +- .../contrib/files/browser/files.contribution.ts | 24 +++++++++++----------- .../contrib/files/browser/views/explorerView.ts | 4 ++-- .../contrib/files/common/explorerModel.ts | 4 ++-- src/vs/workbench/contrib/files/common/files.ts | 8 +++++--- 5 files changed, 22 insertions(+), 20 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/browser/explorerService.ts b/src/vs/workbench/contrib/files/browser/explorerService.ts index 5293c2640ca..5adeb8e0ac6 100644 --- a/src/vs/workbench/contrib/files/browser/explorerService.ts +++ b/src/vs/workbench/contrib/files/browser/explorerService.ts @@ -393,7 +393,7 @@ export class ExplorerService implements IExplorerService { private async onConfigurationUpdated(configuration: IFilesConfiguration, event?: IConfigurationChangeEvent): Promise { let shouldRefresh = false; - if (event?.affectedKeys.some(x => x.startsWith('explorer.experimental.fileNesting.'))) { + if (event?.affectedKeys.some(x => x.startsWith('explorer.fileNesting.'))) { shouldRefresh = true; } diff --git a/src/vs/workbench/contrib/files/browser/files.contribution.ts b/src/vs/workbench/contrib/files/browser/files.contribution.ts index c113c495f27..9452991360b 100644 --- a/src/vs/workbench/contrib/files/browser/files.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/files.contribution.ts @@ -417,7 +417,7 @@ configurationRegistry.registerConfiguration({ nls.localize('sortOrder.modified', 'Files and folders are sorted by last modified date in descending order. Folders are displayed before files.'), nls.localize('sortOrder.foldersNestsFiles', 'Files and folders are sorted by their names. Folders are displayed before files. Files with nested children are displayed before other files.') ], - 'markdownDescription': nls.localize('sortOrder', "Controls the property-based sorting of files and folders in the explorer. When `#explorer.experimental.fileNesting.enabled#` is enabled, also controls sorting of nested files.") + 'markdownDescription': nls.localize('sortOrder', "Controls the property-based sorting of files and folders in the explorer. When `#explorer.fileNesting.enabled#` is enabled, also controls sorting of nested files.") }, 'explorer.sortOrderLexicographicOptions': { 'type': 'string', @@ -471,23 +471,18 @@ configurationRegistry.registerConfiguration({ 'description': nls.localize('copyRelativePathSeparator', "The path separation character used when copying relative file paths."), 'default': 'auto' }, - 'explorer.experimental.fileNesting.enabled': { + 'explorer.fileNesting.enabled': { 'type': 'boolean', scope: ConfigurationScope.RESOURCE, - 'markdownDescription': nls.localize('fileNestingEnabled', "Experimental. Controls whether file nesting is enabled in the explorer. File nesting allows for related files in a directory to be visually grouped together under a single parent file."), + 'markdownDescription': nls.localize('fileNestingEnabled', "Controls whether file nesting is enabled in the explorer. File nesting allows for related files in a directory to be visually grouped together under a single parent file."), 'default': false, }, - 'explorer.experimental.fileNesting.expand': { + 'explorer.fileNesting.expand': { 'type': 'boolean', - 'markdownDescription': nls.localize('fileNestingExpand', "Experimental. Controls whether file nests are automatically expanded. `#explorer.experimental.fileNesting.enabled#` must be set for this to take effect."), + 'markdownDescription': nls.localize('fileNestingExpand', "Controls whether file nests are automatically expanded. `#explorer.fileNesting.enabled#` must be set for this to take effect."), 'default': true, }, - 'explorer.experimental.fileNesting.operateAsGroup': { - 'type': 'boolean', - 'markdownDescription': nls.localize('operateAsGroup', "Controls whether file nests are treated as a group for clipboard operations, file deletions, and during drag and drop."), - 'default': true, - }, - 'explorer.experimental.fileNesting.patterns': { + 'explorer.fileNesting.patterns': { 'type': 'object', scope: ConfigurationScope.RESOURCE, 'markdownDescription': nls.localize('fileNestingPatterns', "Controls nesting of files in the explorer. Each __Item__ represents a parent pattern and may contain a single `*` character that matches any string. Each __Value__ represents a comma separated list of the child patterns that should be shown nested under a given parent. Child patterns may contain several special tokens:\n- `${capture}`: Matches the resolved value of the `*` from the parent pattern\n- `${basename}`: Matches the parent file's basename, the `file` in `file.ts`\n- `${extname}`: Matches the parent file's extension, the `ts` in `file.ts`\n- `${dirname}`: Matches the parent file's directory name, the `src` in `src/file.ts`\n- `*`: Matches any string, may only be used once per child pattern"), @@ -507,7 +502,12 @@ configurationRegistry.registerConfiguration({ 'tsconfig.json': 'tsconfig.*.json', 'package.json': 'package-lock.json, yarn.lock', } - } + }, + 'explorer.experimental.fileNesting.operateAsGroup': { + 'type': 'boolean', + 'markdownDescription': nls.localize('operateAsGroup', "Experimental. Controls whether file nests are treated as a group for clipboard operations, file deletions, and during drag and drop."), + 'default': true, + }, } }); diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index c82cc35150a..cbed9078f22 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -384,7 +384,7 @@ export class ExplorerView extends ViewPane implements IExplorerView { const isCompressionEnabled = () => this.configurationService.getValue('explorer.compactFolders'); - const getFileNestingSettings = (item?: ExplorerItem) => this.configurationService.getValue({ resource: item?.root.resource }).explorer.experimental.fileNesting; + const getFileNestingSettings = (item?: ExplorerItem) => this.configurationService.getValue({ resource: item?.root.resource }).explorer.fileNesting; this.tree = >this.instantiationService.createInstance(WorkbenchCompressibleAsyncDataTree, 'FileExplorer', container, new ExplorerDelegate(), new ExplorerCompressionDelegate(), [this.renderer], this.instantiationService.createInstance(ExplorerDataSource), { @@ -625,7 +625,7 @@ export class ExplorerView extends ViewPane implements IExplorerView { } const toRefresh = item || this.tree.getInput(); - if (this.configurationService.getValue({ resource: item?.root.resource }).explorer.experimental.fileNesting.enabled) { + if (this.configurationService.getValue({ resource: item?.root.resource }).explorer.fileNesting.enabled) { return (async () => { try { await this.tree.updateChildren(toRefresh, recursive, false, { diff --git a/src/vs/workbench/contrib/files/common/explorerModel.ts b/src/vs/workbench/contrib/files/common/explorerModel.ts index b0ae19eedba..5e6f1ba8e31 100644 --- a/src/vs/workbench/contrib/files/common/explorerModel.ts +++ b/src/vs/workbench/contrib/files/common/explorerModel.ts @@ -298,7 +298,7 @@ export class ExplorerItem { } fetchChildren(sortOrder: SortOrder): ExplorerItem[] | Promise { - const nestingConfig = this.configService.getValue({ resource: this.root.resource }).explorer.experimental.fileNesting; + const nestingConfig = this.configService.getValue({ resource: this.root.resource }).explorer.fileNesting; // fast path when the children can be resolved sync if (nestingConfig.enabled && this.nestedChildren) { @@ -369,7 +369,7 @@ export class ExplorerItem { private _fileNester: ExplorerFileNestingTrie | undefined; private get fileNester(): ExplorerFileNestingTrie { if (!this.root._fileNester) { - const nestingConfig = this.configService.getValue({ resource: this.root.resource }).explorer.experimental.fileNesting; + const nestingConfig = this.configService.getValue({ resource: this.root.resource }).explorer.fileNesting; const patterns = Object.entries(nestingConfig.patterns) .filter(entry => typeof (entry[0]) === 'string' && typeof (entry[1]) === 'string' && entry[0] && entry[1]) diff --git a/src/vs/workbench/contrib/files/common/files.ts b/src/vs/workbench/contrib/files/common/files.ts index aff70bc0e8b..00284027740 100644 --- a/src/vs/workbench/contrib/files/common/files.ts +++ b/src/vs/workbench/contrib/files/common/files.ts @@ -98,12 +98,14 @@ export interface IFilesConfiguration extends PlatformIFilesConfiguration, IWorkb badges: boolean; }; incrementalNaming: 'simple' | 'smart'; + fileNesting: { + enabled: boolean; + expand: boolean; + patterns: { [parent: string]: string }; + }; experimental: { fileNesting: { - enabled: boolean; operateAsGroup: boolean; - expand: boolean; - patterns: { [parent: string]: string }; }; }; }; -- cgit v1.2.3 From bab5c223e4be43578b082492a12344b41551baac Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 25 Apr 2022 16:57:24 -0700 Subject: Use Alt+Shift+D ref #148009 --- .../contrib/languageDetection/browser/languageDetection.contribution.ts | 2 +- src/vs/workbench/contrib/notebook/browser/controller/editActions.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/languageDetection/browser/languageDetection.contribution.ts b/src/vs/workbench/contrib/languageDetection/browser/languageDetection.contribution.ts index 8e046511962..94f1e9af9bd 100644 --- a/src/vs/workbench/contrib/languageDetection/browser/languageDetection.contribution.ts +++ b/src/vs/workbench/contrib/languageDetection/browser/languageDetection.contribution.ts @@ -126,7 +126,7 @@ registerAction2(class extends Action2 { title: localize('detectlang', 'Detect Language from Content'), f1: true, precondition: ContextKeyExpr.and(NOTEBOOK_EDITOR_EDITABLE.toNegated(), EditorContextKeys.editorTextFocus), - keybinding: { primary: KeyCode.KeyD | KeyMod.Alt, weight: KeybindingWeight.WorkbenchContrib } + keybinding: { primary: KeyCode.KeyD | KeyMod.Alt | KeyMod.Shift, weight: KeybindingWeight.WorkbenchContrib } }); } diff --git a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts index 34cc0e18f85..d684e721add 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts @@ -471,7 +471,7 @@ registerAction2(class DetectCellLanguageAction extends NotebookCellAction { title: localize('detectLanguage', 'Accept Detected Language for Cell'), f1: true, precondition: ContextKeyExpr.and(NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_CELL_EDITABLE), - keybinding: { primary: KeyCode.KeyD | KeyMod.Alt, weight: KeybindingWeight.WorkbenchContrib } + keybinding: { primary: KeyCode.KeyD | KeyMod.Alt | KeyMod.Shift, weight: KeybindingWeight.WorkbenchContrib } }); } -- cgit v1.2.3 From ab86e0229d6b4d0cb49cfd6747c92cafcd2bd4af Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Mon, 25 Apr 2022 18:01:26 -0700 Subject: updating untitled text again --- .../codeEditor/browser/untitledTextEditorHint.ts | 35 +++++++++++++--------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts index 353965fd9fa..14c97806e09 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts @@ -107,19 +107,6 @@ class UntitledTextEditorHintContentWidget implements IContentWidget { this.domNode = $('.untitled-hint'); this.domNode.style.width = 'max-content'; - const editorType = $('a.editor-type'); - editorType.style.cursor = 'pointer'; - editorType.innerText = localize('notLookingForTextEditor', "Not looking for a text editor?"); - const selectEditorTypeKeyBinding = this.keybindingService.lookupKeybinding('welcome.showNewFileEntries'); - const selectEditorTypeKeybindingLabel = selectEditorTypeKeyBinding?.getLabel(); - if (selectEditorTypeKeybindingLabel) { - editorType.title = localize('keyboardBindingTooltip', "{0}", selectEditorTypeKeybindingLabel); - } - this.domNode.appendChild(editorType); - - this.domNode.appendChild($('br')); - this.domNode.appendChild($('br')); - const language = $('a.language-mode'); language.style.cursor = 'pointer'; language.innerText = localize('selectAlanguage2', "Select a language"); @@ -130,10 +117,30 @@ class UntitledTextEditorHintContentWidget implements IContentWidget { } this.domNode.appendChild(language); + const or = $('span'); + or.innerText = localize('or', " or ",); + this.domNode.appendChild(or); + + const editorType = $('a.editor-type'); + editorType.style.cursor = 'pointer'; + editorType.innerText = localize('openADifferentEditor', "open a different editor"); + const selectEditorTypeKeyBinding = this.keybindingService.lookupKeybinding('welcome.showNewFileEntries'); + const selectEditorTypeKeybindingLabel = selectEditorTypeKeyBinding?.getLabel(); + if (selectEditorTypeKeybindingLabel) { + editorType.title = localize('keyboardBindingTooltip', "{0}", selectEditorTypeKeybindingLabel); + } + this.domNode.appendChild(editorType); + const toGetStarted = $('span'); - toGetStarted.innerText = localize('toGetStarted', " to get started. Start typing to dismiss, or ",); + toGetStarted.innerText = localize('toGetStarted', " to get started."); this.domNode.appendChild(toGetStarted); + this.domNode.appendChild($('br')); + + const startTyping = $('span'); + startTyping.innerText = localize('startTyping', "Start typing to dismiss or "); + this.domNode.appendChild(startTyping); + const dontShow = $('a'); dontShow.style.cursor = 'pointer'; dontShow.innerText = localize('dontshow', "don't show"); -- cgit v1.2.3 From 28cb0264ed35bee2a724baedc9da6e27040d087d Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 26 Apr 2022 11:54:42 +0530 Subject: split log web and native contributions --- .../contrib/logs/browser/logs.contribution.ts | 34 +++++++++++ .../contrib/logs/common/logs.contribution.ts | 66 +++------------------- .../logs/electron-sandbox/logs.contribution.ts | 36 ++++++++++++ 3 files changed, 78 insertions(+), 58 deletions(-) create mode 100644 src/vs/workbench/contrib/logs/browser/logs.contribution.ts (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/logs/browser/logs.contribution.ts b/src/vs/workbench/contrib/logs/browser/logs.contribution.ts new file mode 100644 index 00000000000..d78954e856e --- /dev/null +++ b/src/vs/workbench/contrib/logs/browser/logs.contribution.ts @@ -0,0 +1,34 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Registry } from 'vs/platform/registry/common/platform'; +import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions, CATEGORIES } from 'vs/workbench/common/actions'; +import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; +import { OpenWindowSessionLogFileAction } from 'vs/workbench/contrib/logs/common/logsActions'; +import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { LogsDataCleaner } from 'vs/workbench/contrib/logs/common/logsDataCleaner'; + +class WebLogOutputChannels extends Disposable implements IWorkbenchContribution { + + constructor( + @IInstantiationService private readonly instantiationService: IInstantiationService, + ) { + super(); + this.registerWebContributions(); + } + + private registerWebContributions(): void { + this.instantiationService.createInstance(LogsDataCleaner); + + const workbenchActionsRegistry = Registry.as(WorkbenchActionExtensions.WorkbenchActions); + workbenchActionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(OpenWindowSessionLogFileAction), 'Developer: Open Window Log File (Session)...', CATEGORIES.Developer.value); + } + +} + +Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(WebLogOutputChannels, LifecyclePhase.Restored); diff --git a/src/vs/workbench/contrib/logs/common/logs.contribution.ts b/src/vs/workbench/contrib/logs/common/logs.contribution.ts index 9485c762876..5e533149305 100644 --- a/src/vs/workbench/contrib/logs/common/logs.contribution.ts +++ b/src/vs/workbench/contrib/logs/common/logs.contribution.ts @@ -4,28 +4,22 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { join } from 'vs/base/common/path'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions, CATEGORIES } from 'vs/workbench/common/actions'; import { Action2, registerAction2, SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { SetLogLevelAction, OpenWindowSessionLogFileAction } from 'vs/workbench/contrib/logs/common/logsActions'; +import { SetLogLevelAction } from 'vs/workbench/contrib/logs/common/logsActions'; import * as Constants from 'vs/workbench/contrib/logs/common/logConstants'; import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { IFileService, whenProviderRegistered } from 'vs/platform/files/common/files'; -import { URI } from 'vs/base/common/uri'; -import { IOutputChannelRegistry, Extensions as OutputExt, IOutputService } from 'vs/workbench/services/output/common/output'; +import { IFileService } from 'vs/platform/files/common/files'; +import { IOutputService, registerLogChannel } from 'vs/workbench/services/output/common/output'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { ILogService, LogLevel } from 'vs/platform/log/common/log'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { isWeb } from 'vs/base/common/platform'; -import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { LogsDataCleaner } from 'vs/workbench/contrib/logs/common/logsDataCleaner'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils'; import { IProductService } from 'vs/platform/product/common/productService'; -import { createCancelablePromise, timeout } from 'vs/base/common/async'; -import { canceled, getErrorMessage, isCancellationError } from 'vs/base/common/errors'; -import { CancellationToken } from 'vs/base/common/cancellation'; +import { URI } from 'vs/base/common/uri'; const workbenchActionsRegistry = Registry.as(WorkbenchActionExtensions.WorkbenchActions); workbenchActionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(SetLogLevelAction), 'Developer: Set Log Level...', CATEGORIES.Developer.value); @@ -37,15 +31,9 @@ class LogOutputChannels extends Disposable implements IWorkbenchContribution { @IProductService private readonly productService: IProductService, @ILogService private readonly logService: ILogService, @IFileService private readonly fileService: IFileService, - @IInstantiationService private readonly instantiationService: IInstantiationService, ) { super(); this.registerCommonContributions(); - if (isWeb) { - this.registerWebContributions(); - } else { - this.registerNativeContributions(); - } } private registerCommonContributions(): void { @@ -83,47 +71,9 @@ class LogOutputChannels extends Disposable implements IWorkbenchContribution { }); } - private registerWebContributions(): void { - this.instantiationService.createInstance(LogsDataCleaner); - - const workbenchActionsRegistry = Registry.as(WorkbenchActionExtensions.WorkbenchActions); - workbenchActionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(OpenWindowSessionLogFileAction), 'Developer: Open Window Log File (Session)...', CATEGORIES.Developer.value); - } - - private registerNativeContributions(): void { - this.registerLogChannel(Constants.mainLogChannelId, nls.localize('mainLog', "Main"), URI.file(join(this.environmentService.logsPath, `main.log`))); - this.registerLogChannel(Constants.sharedLogChannelId, nls.localize('sharedLog', "Shared"), URI.file(join(this.environmentService.logsPath, `sharedprocess.log`))); - } - - private async registerLogChannel(id: string, label: string, file: URI): Promise { - await whenProviderRegistered(file, this.fileService); - const outputChannelRegistry = Registry.as(OutputExt.OutputChannels); - try { - const promise = createCancelablePromise(token => this.whenFileExists(file, 1, token)); - this._register(toDisposable(() => promise.cancel())); - await promise; - outputChannelRegistry.registerChannel({ id, label, file, log: true }); - } catch (error) { - if (!isCancellationError(error)) { - this.logService.error('Error while registering log channel', file.toString(), getErrorMessage(error)); - } - } - } - - private async whenFileExists(file: URI, trial: number, token: CancellationToken): Promise { - const exists = await this.fileService.exists(file); - if (exists) { - return; - } - if (token.isCancellationRequested) { - throw canceled(); - } - if (trial > 10) { - throw new Error(`Timed out while waiting for file to be created`); - } - this.logService.debug(`[Registering Log Channel] File does not exist. Waiting for 1s to retry.`, file.toString()); - await timeout(1000, token); - await this.whenFileExists(file, trial + 1, token); + private registerLogChannel(id: string, label: string, file: URI): void { + const promise = registerLogChannel(id, label, file, this.fileService, this.logService); + this._register(toDisposable(() => promise.cancel())); } } diff --git a/src/vs/workbench/contrib/logs/electron-sandbox/logs.contribution.ts b/src/vs/workbench/contrib/logs/electron-sandbox/logs.contribution.ts index 34b8d2ff3fa..022c66402f2 100644 --- a/src/vs/workbench/contrib/logs/electron-sandbox/logs.contribution.ts +++ b/src/vs/workbench/contrib/logs/electron-sandbox/logs.contribution.ts @@ -3,10 +3,46 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions, CATEGORIES } from 'vs/workbench/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { OpenLogsFolderAction, OpenExtensionLogsFolderAction } from 'vs/workbench/contrib/logs/electron-sandbox/logsActions'; +import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; +import * as Constants from 'vs/workbench/contrib/logs/common/logConstants'; +import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; +import { IFileService } from 'vs/platform/files/common/files'; +import { ILogService } from 'vs/platform/log/common/log'; +import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { URI } from 'vs/base/common/uri'; +import { join } from 'vs/base/common/path'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { registerLogChannel } from 'vs/workbench/services/output/common/output'; + +class NativeLogOutputChannels extends Disposable implements IWorkbenchContribution { + + constructor( + @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, + @ILogService private readonly logService: ILogService, + @IFileService private readonly fileService: IFileService, + ) { + super(); + this.registerNativeContributions(); + } + + private registerNativeContributions(): void { + this.registerLogChannel(Constants.mainLogChannelId, nls.localize('mainLog', "Main"), URI.file(join(this.environmentService.logsPath, `main.log`))); + this.registerLogChannel(Constants.sharedLogChannelId, nls.localize('sharedLog', "Shared"), URI.file(join(this.environmentService.logsPath, `sharedprocess.log`))); + } + + private registerLogChannel(id: string, label: string, file: URI): void { + const promise = registerLogChannel(id, label, file, this.fileService, this.logService); + this._register(toDisposable(() => promise.cancel())); + } + +} + +Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(NativeLogOutputChannels, LifecyclePhase.Restored); const workbenchActionsRegistry = Registry.as(WorkbenchActionExtensions.WorkbenchActions); workbenchActionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(OpenLogsFolderAction), 'Developer: Open Logs Folder', CATEGORIES.Developer.value); -- cgit v1.2.3 From 404a525a83a588d828e0b1781a0362e2c7e0ad78 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Tue, 26 Apr 2022 13:24:32 +0200 Subject: Fix #148111 --- src/vs/workbench/contrib/scm/common/scmService.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/scm/common/scmService.ts b/src/vs/workbench/contrib/scm/common/scmService.ts index 8fbe71b55e8..a4670d7aff9 100644 --- a/src/vs/workbench/contrib/scm/common/scmService.ts +++ b/src/vs/workbench/contrib/scm/common/scmService.ts @@ -175,10 +175,10 @@ class SCMInput implements ISCMInput { const history = [...this.historyNavigator].map(s => s ?? ''); if (history.length === 0 || (history.length === 1 && history[0] === '')) { - return; + storageService.remove(key, StorageScope.GLOBAL); + } else { + storageService.store(key, JSON.stringify({ timestamp: new Date().getTime(), history }), StorageScope.GLOBAL, StorageTarget.MACHINE); } - - storageService.store(key, JSON.stringify({ timestamp: new Date().getTime(), history }), StorageScope.GLOBAL, StorageTarget.MACHINE); this.didChangeHistory = false; }); } -- cgit v1.2.3 From a5f1bd19c6567aeb533b29e384b38f5cc36fabdc Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 26 Apr 2022 14:45:31 +0200 Subject: Add line height to comment snippet in view Fixes #148054 --- src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts | 1 + 1 file changed, 1 insertion(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts b/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts index 940de2d18d7..3166fd47195 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts @@ -201,6 +201,7 @@ export class CommentNodeRenderer implements IListRenderer const originalComment = node.element; templateData.threadMetadata.commentPreview.innerText = ''; + templateData.threadMetadata.commentPreview.style.height = '22px'; if (typeof originalComment.comment.body === 'string') { templateData.threadMetadata.commentPreview.innerText = originalComment.comment.body; } else { -- cgit v1.2.3 From 8a39cb93047294ff10960f3313ac169aa2fcf5ac Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 26 Apr 2022 18:09:01 +0200 Subject: labels - make `getPathLabel` aware of remote OS --- src/vs/workbench/contrib/terminal/test/browser/terminalService.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalService.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalService.test.ts index 9ab2dc7f95f..10ffee5b9d0 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/terminalService.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/terminalService.test.ts @@ -12,7 +12,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { TestEditorService, TestLifecycleService, TestTerminalEditorService, TestTerminalGroupService, TestTerminalInstanceService, TestTerminalProfileService } from 'vs/workbench/test/browser/workbenchTestServices'; +import { TestEditorService, TestLifecycleService, TestRemoteAgentService, TestTerminalEditorService, TestTerminalGroupService, TestTerminalInstanceService, TestTerminalProfileService } from 'vs/workbench/test/browser/workbenchTestServices'; import { ITerminalEditorService, ITerminalGroupService, ITerminalInstance, ITerminalInstanceService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -22,7 +22,6 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; -import { TestRemoteAgentService } from 'vs/workbench/services/remote/test/common/testServices'; suite('Workbench - TerminalService', () => { let instantiationService: TestInstantiationService; -- cgit v1.2.3 From e629ad1150db84d1c9513155969b1194b7423f59 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 26 Apr 2022 09:45:11 -0700 Subject: Remove more traces of nesting experimentalism --- .../contrib/files/browser/views/explorerView.ts | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index cbed9078f22..98e9f79568c 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -56,7 +56,6 @@ import { Codicon } from 'vs/base/common/codicons'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IEditorResolverService } from 'vs/workbench/services/editor/common/editorResolverService'; import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; -import { INotificationService } from 'vs/platform/notification/common/notification'; import { EditorOpenSource } from 'vs/platform/editor/common/editor'; import { ResourceMap } from 'vs/base/common/map'; @@ -188,7 +187,6 @@ export class ExplorerView extends ViewPane implements IExplorerView { @IMenuService private readonly menuService: IMenuService, @ITelemetryService telemetryService: ITelemetryService, @IExplorerService private readonly explorerService: IExplorerService, - @INotificationService private readonly notificationService: INotificationService, @IStorageService private readonly storageService: IStorageService, @IClipboardService private clipboardService: IClipboardService, @IFileService private readonly fileService: IFileService, @@ -625,23 +623,9 @@ export class ExplorerView extends ViewPane implements IExplorerView { } const toRefresh = item || this.tree.getInput(); - if (this.configurationService.getValue({ resource: item?.root.resource }).explorer.fileNesting.enabled) { - return (async () => { - try { - await this.tree.updateChildren(toRefresh, recursive, false, { - diffIdentityProvider: identityProvider - }); - } catch (e) { - this.notificationService.error('Internal error in file explorer. This may be due to experimental file nesting.'); - console.error('Unepxected error', e, 'in refreshing explorer. This may be due to experimental file nesting.'); - return; - } - })(); - } else { - return this.tree.updateChildren(toRefresh, recursive, false, { - diffIdentityProvider: identityProvider - }); - } + return this.tree.updateChildren(toRefresh, recursive, false, { + diffIdentityProvider: identityProvider + }); } override getOptimalWidth(): number { -- cgit v1.2.3 From ce82e3595e1b04c8a39717206c5f88ac8e601176 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 26 Apr 2022 10:00:58 -0700 Subject: Fix #141430 --- src/vs/workbench/contrib/files/browser/views/explorerView.ts | 2 +- src/vs/workbench/contrib/files/browser/views/explorerViewer.ts | 4 +++- src/vs/workbench/contrib/files/common/explorerModel.ts | 9 +++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index 98e9f79568c..dd373320fbd 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -385,7 +385,7 @@ export class ExplorerView extends ViewPane implements IExplorerView { const getFileNestingSettings = (item?: ExplorerItem) => this.configurationService.getValue({ resource: item?.root.resource }).explorer.fileNesting; this.tree = >this.instantiationService.createInstance(WorkbenchCompressibleAsyncDataTree, 'FileExplorer', container, new ExplorerDelegate(), new ExplorerCompressionDelegate(), [this.renderer], - this.instantiationService.createInstance(ExplorerDataSource), { + this.instantiationService.createInstance(ExplorerDataSource, this.filter), { compressionEnabled: isCompressionEnabled(), accessibilityProvider: this.renderer, identityProvider, diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index f445df889f1..f2acc5fc722 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -75,6 +75,7 @@ export const explorerRootErrorEmitter = new Emitter(); export class ExplorerDataSource implements IAsyncDataSource { constructor( + private fileFilter: FilesFilter, @IProgressService private readonly progressService: IProgressService, @IConfigurationService private readonly configService: IConfigurationService, @INotificationService private readonly notificationService: INotificationService, @@ -85,7 +86,8 @@ export class ExplorerDataSource implements IAsyncDataSource this.fileFilter.filter(stat, TreeVisibility.Visible)); } getChildren(element: ExplorerItem | ExplorerItem[]): ExplorerItem[] | Promise { diff --git a/src/vs/workbench/contrib/files/common/explorerModel.ts b/src/vs/workbench/contrib/files/common/explorerModel.ts index 5e6f1ba8e31..4cc8fb51bd1 100644 --- a/src/vs/workbench/contrib/files/common/explorerModel.ts +++ b/src/vs/workbench/contrib/files/common/explorerModel.ts @@ -120,8 +120,13 @@ export class ExplorerItem { this._isExcluded = value; } - get hasChildren() { - return this.isDirectory || this.hasNests; + hasChildren(filter: (stat: ExplorerItem) => boolean): boolean { + if (this.hasNests) { + console.log(this, this.hasNests, this.nestedChildren?.filter(c => filter(c))); + return this.nestedChildren?.some(c => filter(c)) ?? false; + } else { + return this.isDirectory; + } } get hasNests() { -- cgit v1.2.3 From cf264c89b07b3a86801b43f8e8f1535aa3f7950a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 26 Apr 2022 20:22:45 +0200 Subject: fixes #148162 (#148172) --- .../contrib/scm/browser/scmRepositoriesViewPane.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts index e66a0f24fd5..3772fac9387 100644 --- a/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts @@ -23,6 +23,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { RepositoryRenderer } from 'vs/workbench/contrib/scm/browser/scmRepositoryRenderer'; import { collectContextMenuActions, getActionViewItemProvider } from 'vs/workbench/contrib/scm/browser/util'; import { Orientation } from 'vs/base/browser/ui/sash/sash'; +import { Iterable } from 'vs/base/common/iterator'; class ListDelegate implements IListVirtualDelegate { @@ -155,23 +156,28 @@ export class SCMRepositoriesViewPane extends ViewPane { } private updateListSelection(): void { - const set = new Set(); + const oldSelection = this.list.getSelection(); + const oldSet = new Set(Iterable.map(oldSelection, i => this.list.element(i))); + const set = new Set(this.scmViewService.visibleRepositories); + const added = new Set(Iterable.filter(set, r => !oldSet.has(r))); + const removed = new Set(Iterable.filter(oldSet, r => !set.has(r))); - for (const repository of this.scmViewService.visibleRepositories) { - set.add(repository); + if (added.size === 0 && removed.size === 0) { + return; } - const selection: number[] = []; + const selection = oldSelection + .filter(i => !removed.has(this.list.element(i))); for (let i = 0; i < this.list.length; i++) { - if (set.has(this.list.element(i))) { + if (added.has(this.list.element(i))) { selection.push(i); } } this.list.setSelection(selection); - if (selection.length > 0) { + if (selection.length > 0 && selection.indexOf(this.list.getFocus()[0]) === -1) { this.list.setAnchor(selection[0]); this.list.setFocus([selection[0]]); } -- cgit v1.2.3 From 7d9b1c37f8e5ae3772782ba3b09d827eb3fdd833 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Tue, 26 Apr 2022 13:01:03 -0700 Subject: add plain text type to fix copy as html (#148205) --- src/vs/workbench/contrib/terminal/browser/terminalInstance.ts | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 0adfa2cee9d..c3c037859a7 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -1153,6 +1153,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { if (asHtml) { const textAsHtml = await xterm.getSelectionAsHtml(command); function listener(e: any) { + if (!e.clipboardData.types.includes('text/plain')) { + e.clipboardData.setData('text/plain', command?.getOutput()); + } e.clipboardData.setData('text/html', textAsHtml); e.preventDefault(); } -- cgit v1.2.3 From e70161f75d08e0abc6226cbd4e324c239621d42c Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 26 Apr 2022 14:36:45 -0700 Subject: Allow language guessing to work with suggested kernels in addition to selected --- .../notebook/browser/contrib/cellStatusBar/statusBarProviders.ts | 6 +++--- src/vs/workbench/contrib/notebook/browser/controller/editActions.ts | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts b/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts index 3747a011ae7..3700db63aa5 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts @@ -88,12 +88,12 @@ class CellStatusBarLanguageDetectionProvider implements INotebookCellStatusBarIt 'markdown' : (this._languageService.getLanguageIdByLanguageName(cell.language) || cell.language); - const kernel = this._notebookKernelService.getMatchingKernel(doc); + const kernel = this._notebookKernelService.getSelectedOrSuggestedKernel(doc); const items: INotebookCellStatusBarItem[] = []; - if (kernel.selected) { + if (kernel) { const availableLangs = []; - availableLangs.push(...kernel.selected.supportedLanguages, 'markdown'); + availableLangs.push(...kernel.supportedLanguages, 'markdown'); const detectedLanguageId = await this._languageDetectionService.detectLanguage(cell.uri, availableLangs); if (detectedLanguageId && currentLanguageId !== detectedLanguageId) { diff --git a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts index d684e721add..8d253828d2e 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts @@ -28,6 +28,7 @@ import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; import { ILanguageDetectionService } from 'vs/workbench/services/languageDetection/common/languageDetectionWorkerService'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; const CLEAR_ALL_CELLS_OUTPUTS_COMMAND_ID = 'notebook.clearAllCellsOutputs'; const EDIT_CELL_COMMAND_ID = 'notebook.cell.edit'; @@ -478,7 +479,9 @@ registerAction2(class DetectCellLanguageAction extends NotebookCellAction { async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { const languageDetectionService = accessor.get(ILanguageDetectionService); const notificationService = accessor.get(INotificationService); - const providerLanguages = [...context.notebookEditor.activeKernel?.supportedLanguages ?? []]; + const kernelService = accessor.get(INotebookKernelService); + const kernel = kernelService.getSelectedOrSuggestedKernel(context.notebookEditor.textModel); + const providerLanguages = [...kernel?.supportedLanguages ?? []]; providerLanguages.push('markdown'); const detection = await languageDetectionService.detectLanguage(context.cell.uri, providerLanguages); if (detection) { -- cgit v1.2.3 From 06f498c78360733f947aef94034fddf9dd7e22d1 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 26 Apr 2022 15:56:43 -0700 Subject: remove log --- src/vs/workbench/contrib/files/common/explorerModel.ts | 1 - 1 file changed, 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/common/explorerModel.ts b/src/vs/workbench/contrib/files/common/explorerModel.ts index 4cc8fb51bd1..4b7b2c6eace 100644 --- a/src/vs/workbench/contrib/files/common/explorerModel.ts +++ b/src/vs/workbench/contrib/files/common/explorerModel.ts @@ -122,7 +122,6 @@ export class ExplorerItem { hasChildren(filter: (stat: ExplorerItem) => boolean): boolean { if (this.hasNests) { - console.log(this, this.hasNests, this.nestedChildren?.filter(c => filter(c))); return this.nestedChildren?.some(c => filter(c)) ?? false; } else { return this.isDirectory; -- cgit v1.2.3 From ac3e081e0ecbee16961053cc2713489e70332650 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 26 Apr 2022 16:00:51 -0700 Subject: Improve debouncing logic to immediately react to language changes Fixes #148196 --- .../contrib/cellStatusBar/statusBarProviders.ts | 84 ++++++++++++---------- 1 file changed, 46 insertions(+), 38 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts b/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts index 3700db63aa5..750af12fdf4 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Delayer } from 'vs/base/common/async'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Disposable } from 'vs/base/common/lifecycle'; +import { ResourceMap } from 'vs/base/common/map'; import { URI } from 'vs/base/common/uri'; import { ILanguageService } from 'vs/editor/common/languages/language'; import { localize } from 'vs/nls'; @@ -59,7 +59,11 @@ class CellStatusBarLanguageDetectionProvider implements INotebookCellStatusBarIt readonly viewType = '*'; - private delayer = new Delayer(500); + private cache = new ResourceMap<{ + lastUpdate: number; + lastCellLang: string; + lastGuess?: string; + }>(); constructor( @INotebookService private readonly _notebookService: INotebookService, @@ -71,53 +75,57 @@ class CellStatusBarLanguageDetectionProvider implements INotebookCellStatusBarIt ) { } async provideCellStatusBarItems(uri: URI, index: number, token: CancellationToken): Promise { - return await this.delayer.trigger(async () => { - const doc = this._notebookService.getNotebookTextModel(uri); - const cell = doc?.cells[index]; - if (!cell || token.isCancellationRequested) { - return; - } + const doc = this._notebookService.getNotebookTextModel(uri); + const cell = doc?.cells[index]; + if (!cell) { return; } - const enablementConfig = this._configurationService.getValue('workbench.editor.languageDetectionHints'); - const enabled = enablementConfig === 'always' || enablementConfig === 'notebookEditors'; - if (!enabled) { - return; - } + const enablementConfig = this._configurationService.getValue('workbench.editor.languageDetectionHints'); + const enabled = enablementConfig === 'always' || enablementConfig === 'notebookEditors'; + if (!enabled) { + return; + } - const currentLanguageId = cell.cellKind === CellKind.Markup ? - 'markdown' : - (this._languageService.getLanguageIdByLanguageName(cell.language) || cell.language); + const currentLanguageId = cell.cellKind === CellKind.Markup ? + 'markdown' : + (this._languageService.getLanguageIdByLanguageName(cell.language) || cell.language); + + if (!this.cache.has(uri)) { + this.cache.set(uri, { lastCellLang: currentLanguageId, lastUpdate: 0 }); + } + + const cached = this.cache.get(uri)!; + if (cached.lastUpdate < Date.now() - 1000 || cached.lastCellLang !== currentLanguageId) { + cached.lastUpdate = Date.now(); + cached.lastCellLang = currentLanguageId; const kernel = this._notebookKernelService.getSelectedOrSuggestedKernel(doc); - const items: INotebookCellStatusBarItem[] = []; if (kernel) { const availableLangs = []; availableLangs.push(...kernel.supportedLanguages, 'markdown'); - const detectedLanguageId = await this._languageDetectionService.detectLanguage(cell.uri, availableLangs); - - if (detectedLanguageId && currentLanguageId !== detectedLanguageId) { - const detectedName = this._languageService.getLanguageName(detectedLanguageId) || detectedLanguageId; - let tooltip = localize('notebook.cell.status.autoDetectLanguage', "Accept Detected Language: {0}", detectedName); - const keybinding = this._keybindingService.lookupKeybinding(DETECT_CELL_LANGUAGE); - const label = keybinding?.getLabel(); - if (label) { - tooltip += ` (${label})`; - } - - items.push({ - text: '$(lightbulb-autofix)', - command: DETECT_CELL_LANGUAGE, - tooltip, - alignment: CellStatusbarAlignment.Right, - priority: -Number.MAX_SAFE_INTEGER + 1 - }); - } + cached.lastGuess = await this._languageDetectionService.detectLanguage(cell.uri, availableLangs); } + } - return { items }; - }); + const items: INotebookCellStatusBarItem[] = []; + if (cached.lastGuess && currentLanguageId !== cached.lastGuess) { + const detectedName = this._languageService.getLanguageName(cached.lastGuess) || cached.lastGuess; + let tooltip = localize('notebook.cell.status.autoDetectLanguage', "Accept Detected Language: {0}", detectedName); + const keybinding = this._keybindingService.lookupKeybinding(DETECT_CELL_LANGUAGE); + const label = keybinding?.getLabel(); + if (label) { + tooltip += ` (${label})`; + } + items.push({ + text: '$(lightbulb-autofix)', + command: DETECT_CELL_LANGUAGE, + tooltip, + alignment: CellStatusbarAlignment.Right, + priority: -Number.MAX_SAFE_INTEGER + 1 + }); + } + return { items }; } } -- cgit v1.2.3 From 410fe0fc7890ef563830bb86cbcd763995bfc65f Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Tue, 26 Apr 2022 16:39:20 -0700 Subject: fix terminal find bugs (#148222) --- .../contrib/codeEditor/browser/find/simpleFindWidget.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts index f49139355d7..02f42a4e844 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts @@ -308,14 +308,17 @@ export abstract class SimpleFindWidget extends Widget { this._matchesCount.className = 'matchesCount'; } this._matchesCount.innerText = ''; - let label; - if (count?.resultCount === -1) { - label = ''; - } else { - label = count === undefined || count.resultCount === 0 ? NLS_NO_RESULTS : strings.format(NLS_MATCHES_LOCATION, count.resultIndex + 1, count?.resultCount); + let label = ''; + this._matchesCount.classList.toggle('no-results', false); + if (count?.resultCount && count?.resultCount <= 0) { + label = NLS_NO_RESULTS; + if (!!this.inputValue) { + this._matchesCount.classList.toggle('no-results', true); + } + } else if (count?.resultCount) { + label = strings.format(NLS_MATCHES_LOCATION, count.resultIndex + 1, count?.resultCount); } this._matchesCount.appendChild(document.createTextNode(label)); - this._matchesCount.classList.toggle('no-results', !count || count.resultCount === 0); this._findInput?.domNode.insertAdjacentElement('afterend', this._matchesCount); this._foundMatch = !!count && count.resultCount > 0; } -- cgit v1.2.3 From 4c427c825845f35f8be08e618378690cfbfdf168 Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 27 Apr 2022 11:02:13 +0200 Subject: fix https://github.com/microsoft/vscode/issues/148234 --- src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts | 1 + 1 file changed, 1 insertion(+) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts b/src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts index 1f9d18be26c..aba0c2eed69 100644 --- a/src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts +++ b/src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts @@ -65,6 +65,7 @@ class DefaultFormatter extends Disposable implements IWorkbenchContribution { this._store.add(_editorService.onDidActiveEditorChange(this._updateStatus, this)); this._store.add(_languageFeaturesService.documentFormattingEditProvider.onDidChange(this._updateStatus, this)); this._store.add(_languageFeaturesService.documentRangeFormattingEditProvider.onDidChange(this._updateStatus, this)); + this._store.add(_configService.onDidChangeConfiguration(e => e.affectsConfiguration(DefaultFormatter.configName) && this._updateStatus())); this._updateConfigValues(); } -- cgit v1.2.3 From 8624c1125c9e05e95845c8dc45bb8f8e7290b934 Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 27 Apr 2022 11:53:59 +0200 Subject: fix https://github.com/microsoft/vscode/issues/148232 --- .../workbench/contrib/languageStatus/browser/media/languageStatus.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css b/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css index 55ef5b103df..c31cfe44a49 100644 --- a/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css +++ b/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css @@ -25,7 +25,7 @@ } } -.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus A>SPAN.codicon.wiggle { +.monaco-workbench .statusbar DIV#status\.languageStatus A>SPAN.codicon.wiggle { animation-duration: .8s; animation-iteration-count: 1; animation-name: wiggle; @@ -45,7 +45,7 @@ } } -.monaco-workbench.enable-motion .statusbar DIV#status\.languageStatus.flash { +.monaco-workbench .statusbar DIV#status\.languageStatus.flash { animation-duration: .8s; animation-iteration-count: 1; animation-name: flash; -- cgit v1.2.3 From eccf3433eaf4201812fcd9b539b2cf7790f3bd0b Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 27 Apr 2022 12:09:13 +0200 Subject: Fix comments view not always opening on first file Fixes #148208 --- .../workbench/contrib/comments/browser/commentsEditorContribution.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index 5d80b0e5dfd..3a6c877b2fa 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -633,9 +633,7 @@ export class CommentController implements IEditorContribution { this._commentThreadRangeDecorator.update(this.editor, commentInfo); })); - this.beginCompute().then(() => { - return this.openCommentsView(); - }); + this.beginCompute(); } private async openCommentsView() { @@ -656,6 +654,7 @@ export class CommentController implements IEditorContribution { const zoneWidget = this.instantiationService.createInstance(ReviewZoneWidget, this.editor, owner, thread, pendingComment); zoneWidget.display(thread.range.endLineNumber); this._commentWidgets.push(zoneWidget); + this.openCommentsView(); } private onEditorMouseDown(e: IEditorMouseEvent): void { -- cgit v1.2.3 From 12c8a19dd534d0d3fca87c2b623c6a5eea61f373 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 27 Apr 2022 12:34:53 +0200 Subject: Fix add comment range decorator showing after changing files Fixes #148212 --- .../contrib/comments/browser/commentsEditorContribution.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index 3a6c877b2fa..829eb7dacac 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -168,7 +168,7 @@ class CommentingRangeDecorator { this._lastHover = hoverLine ?? -1; } - public updateSelection(cursorLine: number, range: Range) { + public updateSelection(cursorLine: number, range: Range = new Range(0, 0, 0, 0)) { this._lastSelection = range.isEmpty() ? undefined : range; this._lastSelectionCursor = range.isEmpty() ? undefined : cursorLine; // Some scenarios: @@ -370,6 +370,7 @@ export class CommentController implements IEditorContribution { this._editorDisposables.push(this.editor.onDidChangeCursorPosition(e => this.onEditorChangeCursorPosition(e.position))); this._editorDisposables.push(this.editor.onDidFocusEditorWidget(() => this.onEditorChangeCursorPosition(this.editor.getPosition()))); this._editorDisposables.push(this.editor.onDidChangeCursorSelection(e => this.onEditorChangeCursorSelection(e))); + this._editorDisposables.push(this.editor.onDidBlurEditorWidget(() => this.onEditorChangeCursorSelection())); } private clearEditorListeners() { @@ -381,10 +382,10 @@ export class CommentController implements IEditorContribution { this._commentingRangeDecorator.updateHover(e.target.position?.lineNumber); } - private onEditorChangeCursorSelection(e: ICursorSelectionChangedEvent): void { + private onEditorChangeCursorSelection(e?: ICursorSelectionChangedEvent): void { const position = this.editor.getPosition()?.lineNumber; if (position) { - this._commentingRangeDecorator.updateSelection(position, e.selection); + this._commentingRangeDecorator.updateSelection(position, e?.selection); } } -- cgit v1.2.3 From 55e06cd29a7f1daa63582210dbc1746a74a6284f Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 27 Apr 2022 16:37:25 +0200 Subject: Update current comment thread on widget dispose Fixes #148216 --- src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts index 92b06773800..5759d2f3783 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts @@ -196,7 +196,10 @@ export class CommentThreadWidget extends this._onDidResize.fire(dimension); } - + override dispose() { + super.dispose(); + this.updateCurrentThread(false, false); + } private _bindCommentThreadListeners() { this._commentThreadDisposables.push(this._commentThread.onDidChangeCanReply(() => { -- cgit v1.2.3 From 15fe71b121ca93887fd565cbea3cec2616cc1fe7 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 27 Apr 2022 17:04:22 +0200 Subject: Fix single line comment ranges Fixes #148268 --- src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index 829eb7dacac..dd4fa30d7ff 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -675,7 +675,7 @@ export class CommentController implements IEditorContribution { // Check for selection at line number. let range: Range = new Range(lineNumber, 1, lineNumber, 1); const selection = this.editor.getSelection(); - if (selection?.containsRange(range)) { + if (selection && (selection.startLineNumber <= lineNumber) && (lineNumber <= selection.endLineNumber)) { range = selection; this.editor.setSelection(new Range(selection.endLineNumber, 1, selection.endLineNumber, 1)); } -- cgit v1.2.3 From 25f57061a3fab1692b8e3a4d156157f7ac39df39 Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 27 Apr 2022 17:41:03 +0200 Subject: missing part #148232 --- .../contrib/languageStatus/browser/languageStatus.contribution.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts index 1068901ce24..0372c278593 100644 --- a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts +++ b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts @@ -204,8 +204,8 @@ class EditorStatusContribution implements IWorkbenchContribution { // animate the status bar icon whenever language status changes, repeat animation // when severity is warning or error, don't show animation when showing progress/busy const userHasInteractedWithStatus = this._interactionCounter.value >= 3; - const node = document.querySelector('.monaco-workbench.enable-motion .statusbar DIV#status\\.languageStatus A>SPAN.codicon'); - const container = document.querySelector('.monaco-workbench.enable-motion .statusbar DIV#status\\.languageStatus'); + const node = document.querySelector('.monaco-workbench .statusbar DIV#status\\.languageStatus A>SPAN.codicon'); + const container = document.querySelector('.monaco-workbench .statusbar DIV#status\\.languageStatus'); if (node instanceof HTMLElement && container) { const _wiggle = 'wiggle'; const _flash = 'flash'; -- cgit v1.2.3 From f1b624488915949ee7b040704bbe3f376d130633 Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Wed, 27 Apr 2022 14:59:34 -0700 Subject: Source extensions properly, fixes #148192 (#148239) --- src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 38f92fa0f10..abdaa391f5a 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -60,7 +60,6 @@ import { Color } from 'vs/base/common/color'; import { ILanguageService } from 'vs/editor/common/languages/language'; import { SettingsSearchFilterDropdownMenuActionViewItem } from 'vs/workbench/contrib/preferences/browser/settingsSearchMenu'; import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { ExtensionType } from 'vs/platform/extensions/common/extensions'; export const enum SettingsFocusContext { Search, @@ -275,8 +274,10 @@ export class SettingsEditor2 extends EditorPane { SettingsEditor2.SUGGESTIONS.push(`@${LANGUAGE_SETTING_TAG}`); } - extensionManagementService.getInstalled(ExtensionType.System).then(extensions => { - this.installedExtensionIds = extensions.map(extension => extension.identifier.id); + extensionManagementService.getInstalled().then(extensions => { + this.installedExtensionIds = extensions + .filter(ext => ext.manifest && ext.manifest.contributes && ext.manifest.contributes.configuration) + .map(ext => ext.identifier.id); }); } -- cgit v1.2.3 From 19457f35121b6d15f706c9f261f3ba18c32edf55 Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Wed, 27 Apr 2022 15:52:51 -0700 Subject: refs #147748 - move os file command to always be first --- src/vs/workbench/contrib/files/browser/fileActions.contribution.ts | 7 ++++--- .../contrib/files/electron-sandbox/fileActions.contribution.ts | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts index 71422933855..57bb796dfc4 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts @@ -154,15 +154,16 @@ const copyRelativePathCommand = { // Editor Title Context Menu appendEditorTitleContextMenuItem(COPY_PATH_COMMAND_ID, copyPathCommand.title, ResourceContextKey.IsFileSystemResource, '1_cutcopypaste'); appendEditorTitleContextMenuItem(COPY_RELATIVE_PATH_COMMAND_ID, copyRelativePathCommand.title, ResourceContextKey.IsFileSystemResource, '1_cutcopypaste'); -appendEditorTitleContextMenuItem(REVEAL_IN_EXPLORER_COMMAND_ID, nls.localize('revealInSideBar', "Reveal in Explorer View"), ResourceContextKey.IsFileSystemResource); +appendEditorTitleContextMenuItem(REVEAL_IN_EXPLORER_COMMAND_ID, nls.localize('revealInSideBar', "Reveal in Explorer View"), ResourceContextKey.IsFileSystemResource, '2_files', 1); -export function appendEditorTitleContextMenuItem(id: string, title: string, when: ContextKeyExpression | undefined, group?: string): void { +export function appendEditorTitleContextMenuItem(id: string, title: string, when: ContextKeyExpression | undefined, group: string, order?: number): void { // Menu MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id, title }, when, - group: group || '2_files' + group, + order }); } diff --git a/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts b/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts index 7e5450675c1..6473ad59136 100644 --- a/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts @@ -57,7 +57,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ } }); -appendEditorTitleContextMenuItem(REVEAL_IN_OS_COMMAND_ID, REVEAL_IN_OS_LABEL, REVEAL_IN_OS_WHEN_CONTEXT); +appendEditorTitleContextMenuItem(REVEAL_IN_OS_COMMAND_ID, REVEAL_IN_OS_LABEL, REVEAL_IN_OS_WHEN_CONTEXT, '2_files', 0); // Menu registration - open editors -- cgit v1.2.3 From af1152f20096763cd3350f81001bcf7b8e6b8c99 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Wed, 27 Apr 2022 16:00:13 -0700 Subject: improve consistency of terminal find with editor find (#148306) --- .../codeEditor/browser/find/simpleFindWidget.css | 12 +++++- .../codeEditor/browser/find/simpleFindWidget.ts | 45 ++++++++++++++++++++-- .../contrib/terminal/browser/terminalFindWidget.ts | 4 +- 3 files changed, 54 insertions(+), 7 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.css b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.css index bdd496042ce..46b11d7eedf 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.css +++ b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.css @@ -15,6 +15,10 @@ padding: 0 10px 10px; } +.simple-find-part .monaco-inputbox > .ibwrapper > input { + text-overflow: clip; +} + .monaco-workbench .simple-find-part { visibility: hidden; /* Use visibility to maintain flex layout while hidden otherwise interferes with transition */ z-index: 10; @@ -57,7 +61,11 @@ cursor: pointer; } -.monaco-workbench .simple-find-part .button.disabled { - opacity: 0.3; +.monaco-workbench div.simple-find-part div.button.disabled { + opacity: 0.3 !important; cursor: default; } + +div.simple-find-part-wrapper div.button { + border-radius: 5px; +} diff --git a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts index 02f42a4e844..514a9c59c4c 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts @@ -15,14 +15,16 @@ import { IMessage as InputBoxMessage } from 'vs/base/browser/ui/inputbox/inputBo import { SimpleButton, findPreviousMatchIcon, findNextMatchIcon, NLS_NO_RESULTS, NLS_MATCHES_LOCATION } from 'vs/editor/contrib/find/browser/findWidget'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { editorWidgetBackground, inputActiveOptionBorder, inputActiveOptionBackground, inputActiveOptionForeground, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationWarningForeground, widgetShadow, editorWidgetForeground, errorForeground } from 'vs/platform/theme/common/colorRegistry'; +import { editorWidgetBackground, inputActiveOptionBorder, inputActiveOptionBackground, inputActiveOptionForeground, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationWarningForeground, widgetShadow, editorWidgetForeground, errorForeground, toolbarHoverBackground, toolbarHoverOutline } from 'vs/platform/theme/common/colorRegistry'; import { IColorTheme, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { ContextScopedFindInput } from 'vs/platform/history/browser/contextScopedHistoryWidget'; import { widgetClose } from 'vs/platform/theme/common/iconRegistry'; import * as strings from 'vs/base/common/strings'; +import { TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; const NLS_FIND_INPUT_LABEL = nls.localize('label.find', "Find"); -const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find"); +const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find (\u21C5 for history)"); const NLS_PREVIOUS_MATCH_BTN_LABEL = nls.localize('label.previousMatchButton', "Previous Match"); const NLS_NEXT_MATCH_BTN_LABEL = nls.localize('label.nextMatchButton', "Next Match"); const NLS_CLOSE_BTN_LABEL = nls.localize('label.closeButton', "Close"); @@ -31,6 +33,10 @@ interface IFindOptions { showOptionButtons?: boolean; checkImeCompletionState?: boolean; showResultCount?: boolean; + appendCaseSensitiveLabel?: string; + appendRegexLabel?: string; + appendWholeWordsLabel?: string; + type?: 'Terminal' | 'Webview'; } export abstract class SimpleFindWidget extends Widget { @@ -51,7 +57,8 @@ export abstract class SimpleFindWidget extends Widget { @IContextViewService private readonly _contextViewService: IContextViewService, @IContextKeyService contextKeyService: IContextKeyService, private readonly _state: FindReplaceState = new FindReplaceState(), - private readonly _options: IFindOptions + private readonly _options: IFindOptions, + private readonly _keybindingService?: IKeybindingService ) { super(); @@ -70,7 +77,10 @@ export abstract class SimpleFindWidget extends Widget { this.updateButtons(this._foundMatch); return { content: e.message }; } - } + }, + appendCaseSensitiveLabel: _options.appendCaseSensitiveLabel && _options.type === 'Terminal' ? this._getKeybinding(TerminalCommandId.ToggleFindCaseSensitive) : undefined, + appendRegexLabel: _options.appendRegexLabel && _options.type === 'Terminal' ? this._getKeybinding(TerminalCommandId.ToggleFindRegex) : undefined, + appendWholeWordsLabel: _options.appendWholeWordsLabel && _options.type === 'Terminal' ? this._getKeybinding(TerminalCommandId.ToggleFindWholeWord) : undefined }, contextKeyService, _options.showOptionButtons)); // Find History with update delayer @@ -210,6 +220,14 @@ export abstract class SimpleFindWidget extends Widget { this._findInput.style(inputStyles); } + private _getKeybinding(actionId: string): string { + let kb = this._keybindingService?.lookupKeybinding(actionId); + if (!kb) { + return ''; + } + return ` (${kb.getLabel()})`; + } + override dispose() { super.dispose(); @@ -345,4 +363,23 @@ registerThemingParticipant((theme, collector) => { if (error) { collector.addRule(`.no-results.matchesCount { color: ${error}; }`); } + + const toolbarHoverBackgroundColor = theme.getColor(toolbarHoverBackground); + if (toolbarHoverBackgroundColor) { + collector.addRule(` + div.simple-find-part-wrapper div.button:hover:not(.disabled) { + background-color: ${toolbarHoverBackgroundColor}; + } + `); + } + + const toolbarHoverOutlineColor = theme.getColor(toolbarHoverOutline); + if (toolbarHoverOutlineColor) { + collector.addRule(` + div.simple-find-part-wrapper div.button:hover:not(.disabled) { + outline: 1px dashed ${toolbarHoverOutlineColor}; + outline-offset: -1px; + } + `); + } }); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts b/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts index ffd839a6c18..a12db0f881b 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts @@ -12,6 +12,7 @@ import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/termin import { TerminalLocation } from 'vs/platform/terminal/common/terminal'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; export class TerminalFindWidget extends SimpleFindWidget { protected _findInputFocused: IContextKey; @@ -21,13 +22,14 @@ export class TerminalFindWidget extends SimpleFindWidget { constructor( findState: FindReplaceState, @IContextViewService _contextViewService: IContextViewService, + @IKeybindingService keybindingService: IKeybindingService, @IContextKeyService private readonly _contextKeyService: IContextKeyService, @ITerminalService private readonly _terminalService: ITerminalService, @ITerminalGroupService private readonly _terminalGroupService: ITerminalGroupService, @IThemeService private readonly _themeService: IThemeService, @IConfigurationService private readonly _configurationService: IConfigurationService ) { - super(_contextViewService, _contextKeyService, findState, { showOptionButtons: true, showResultCount: true }); + super(_contextViewService, _contextKeyService, findState, { showOptionButtons: true, showResultCount: true, type: 'Terminal' }, keybindingService); this._register(findState.onFindReplaceStateChange(() => { this.show(); -- cgit v1.2.3 From c4e1f19aac0ef025ec208bc5d6500df5e5e36600 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 27 Apr 2022 16:52:06 -0700 Subject: Fix #148255 --- src/vs/workbench/contrib/debug/browser/baseDebugView.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/debug/browser/baseDebugView.ts b/src/vs/workbench/contrib/debug/browser/baseDebugView.ts index e97efddd569..19b1e114ac0 100644 --- a/src/vs/workbench/contrib/debug/browser/baseDebugView.ts +++ b/src/vs/workbench/contrib/debug/browser/baseDebugView.ts @@ -14,6 +14,7 @@ import { createMatches, FuzzyScore } from 'vs/base/common/filters'; import { once } from 'vs/base/common/functional'; import { KeyCode } from 'vs/base/common/keyCodes'; import { DisposableStore, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { localize } from 'vs/nls'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -113,7 +114,6 @@ export function renderVariable(variable: Variable, data: IVariableTemplateData, } data.expression.classList.toggle('lazy', !!variable.presentationHint?.lazy); - data.lazyButton.title = variable.presentationHint?.lazy ? variable.value : ''; renderExpressionValue(variable, data.value, { showChanged, maxValueLength: MAX_VALUE_RENDER_LENGTH_IN_VIEWLET, @@ -159,6 +159,7 @@ export abstract class AbstractExpressionsRenderer implements ITreeRenderer Date: Wed, 27 Apr 2022 18:19:44 -0700 Subject: Fix #148218 --- .../contrib/files/browser/explorerService.ts | 41 ++++++++++++---------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/browser/explorerService.ts b/src/vs/workbench/contrib/files/browser/explorerService.ts index 5adeb8e0ac6..c45f45aed9a 100644 --- a/src/vs/workbench/contrib/files/browser/explorerService.ts +++ b/src/vs/workbench/contrib/files/browser/explorerService.ts @@ -33,8 +33,7 @@ export class ExplorerService implements IExplorerService { private readonly disposables = new DisposableStore(); private editable: { stat: ExplorerItem; data: IEditableData } | undefined; - private _sortOrder: SortOrder; - private _lexicographicOptions: LexicographicOptions; + private config: IFilesConfiguration['explorer']; private cutItems: ExplorerItem[] | undefined; private view: IExplorerView | undefined; private model: ExplorerModel; @@ -52,8 +51,7 @@ export class ExplorerService implements IExplorerService { @IProgressService private readonly progressService: IProgressService, @IHostService hostService: IHostService ) { - this._sortOrder = this.configurationService.getValue('explorer.sortOrder'); - this._lexicographicOptions = this.configurationService.getValue('explorer.sortOrderLexicographicOptions'); + this.config = this.configurationService.getValue('explorer'); this.model = new ExplorerModel(this.contextService, this.uriIdentityService, this.fileService, this.configurationService); this.disposables.add(this.model); @@ -65,7 +63,7 @@ export class ExplorerService implements IExplorerService { // Filter to the ones we care const types = [FileChangeType.DELETED]; - if (this._sortOrder === SortOrder.Modified) { + if (this.config.sortOrder === SortOrder.Modified) { types.push(FileChangeType.UPDATED); } @@ -142,8 +140,8 @@ export class ExplorerService implements IExplorerService { get sortOrderConfiguration(): ISortOrderConfiguration { return { - sortOrder: this._sortOrder, - lexicographicOptions: this._lexicographicOptions, + sortOrder: this.config.sortOrder, + lexicographicOptions: this.config.sortOrderLexicographicOptions, }; } @@ -261,7 +259,7 @@ export class ExplorerService implements IExplorerService { } // Stat needs to be resolved first and then revealed - const options: IResolveFileOptions = { resolveTo: [resource], resolveMetadata: this._sortOrder === SortOrder.Modified }; + const options: IResolveFileOptions = { resolveTo: [resource], resolveMetadata: this.config.sortOrder === SortOrder.Modified }; const root = this.findClosestRoot(resource); if (!root) { return undefined; @@ -302,6 +300,11 @@ export class ExplorerService implements IExplorerService { // File events private async onDidRunOperation(e: FileOperationEvent): Promise { + // When nesting, changes to one file in a folder may impact the rendered structure + // of all the folder's immediate children, thus a recursive refresh is needed. + // Ideally the tree would be able to recusively refresh just one level but that does not yet exist. + const shouldDeepRefresh = this.config.fileNesting.enabled; + // Add if (e.isOperation(FileOperation.CREATE) || e.isOperation(FileOperation.COPY)) { const addedElement = e.target; @@ -313,7 +316,7 @@ export class ExplorerService implements IExplorerService { // Add the new file to its parent (Model) await Promise.all(parents.map(async p => { // We have to check if the parent is resolved #29177 - const resolveMetadata = this._sortOrder === `modified`; + const resolveMetadata = this.config.sortOrder === `modified`; if (!p.isDirectoryResolved) { const stat = await this.fileService.resolve(p.resource, { resolveMetadata }); if (stat) { @@ -327,7 +330,7 @@ export class ExplorerService implements IExplorerService { p.removeChild(childElement); p.addChild(childElement); // Refresh the Parent (View) - await this.view?.refresh(false, p); + await this.view?.refresh(shouldDeepRefresh, p); })); } } @@ -346,7 +349,7 @@ export class ExplorerService implements IExplorerService { await Promise.all(modelElements.map(async modelElement => { // Rename File (Model) modelElement.rename(newElement); - await this.view?.refresh(false, modelElement.parent); + await this.view?.refresh(shouldDeepRefresh, modelElement.parent); })); } @@ -363,7 +366,7 @@ export class ExplorerService implements IExplorerService { await this.view?.refresh(false, oldNestedParent); } await this.view?.refresh(false, oldParent); - await this.view?.refresh(false, newParents[index]); + await this.view?.refresh(shouldDeepRefresh, newParents[index]); })); } } @@ -384,7 +387,7 @@ export class ExplorerService implements IExplorerService { await this.view?.refresh(false, oldNestedParent); } // Refresh Parent (View) - await this.view?.refresh(false, parent); + await this.view?.refresh(shouldDeepRefresh, parent); } })); } @@ -398,17 +401,17 @@ export class ExplorerService implements IExplorerService { } const configSortOrder = configuration?.explorer?.sortOrder || SortOrder.Default; - if (this._sortOrder !== configSortOrder) { - shouldRefresh = this._sortOrder !== undefined; - this._sortOrder = configSortOrder; + if (this.config.sortOrder !== configSortOrder) { + shouldRefresh = this.config.sortOrder !== undefined; } const configLexicographicOptions = configuration?.explorer?.sortOrderLexicographicOptions || LexicographicOptions.Default; - if (this._lexicographicOptions !== configLexicographicOptions) { - shouldRefresh = shouldRefresh || this._lexicographicOptions !== undefined; - this._lexicographicOptions = configLexicographicOptions; + if (this.config.sortOrderLexicographicOptions !== configLexicographicOptions) { + shouldRefresh = shouldRefresh || this.config.sortOrderLexicographicOptions !== undefined; } + this.config = configuration.explorer; + if (shouldRefresh) { await this.refresh(); } -- cgit v1.2.3 From 7fc8af4e2d8f50a3950b809b9beab86fa5135f29 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 27 Apr 2022 18:47:31 -0700 Subject: Fix #145665 --- .../workbench/contrib/files/browser/explorerService.ts | 16 +++++++--------- src/vs/workbench/contrib/files/browser/fileActions.ts | 16 ++++------------ .../contrib/files/browser/files.contribution.ts | 7 +------ src/vs/workbench/contrib/files/browser/files.ts | 1 + .../contrib/files/browser/views/explorerView.ts | 6 +++++- .../contrib/files/browser/views/explorerViewer.ts | 6 ++++-- src/vs/workbench/contrib/files/common/files.ts | 5 ----- 7 files changed, 22 insertions(+), 35 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/browser/explorerService.ts b/src/vs/workbench/contrib/files/browser/explorerService.ts index c45f45aed9a..a1d5910f284 100644 --- a/src/vs/workbench/contrib/files/browser/explorerService.ts +++ b/src/vs/workbench/contrib/files/browser/explorerService.ts @@ -149,21 +149,19 @@ export class ExplorerService implements IExplorerService { this.view = contextProvider; } - getContext(respectMultiSelection: boolean, includeNestedChildren = false): ExplorerItem[] { + getContext(respectMultiSelection: boolean): ExplorerItem[] { if (!this.view) { return []; } const items = new Set(this.view.getContext(respectMultiSelection)); - if (includeNestedChildren) { - items.forEach(item => { - if (item.nestedChildren) { - for (const child of item.nestedChildren) { - items.add(child); - } + items.forEach(item => { + if (this.view?.isItemCollapsed(item) && item.nestedChildren) { + for (const child of item.nestedChildren) { + items.add(child); } - }); - } + } + }); return [...items]; } diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index d3100d24946..56160c6d47d 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -906,9 +906,7 @@ export const renameHandler = async (accessor: ServicesAccessor) => { export const moveFileToTrashHandler = async (accessor: ServicesAccessor) => { const explorerService = accessor.get(IExplorerService); - const configurationService = accessor.get(IConfigurationService); - const groupNests = configurationService.getValue().explorer.experimental.fileNesting.operateAsGroup; - const stats = explorerService.getContext(true, groupNests).filter(s => !s.isRoot); + const stats = explorerService.getContext(true).filter(s => !s.isRoot); if (stats.length) { await deleteFiles(accessor.get(IExplorerService), accessor.get(IWorkingCopyFileService), accessor.get(IDialogService), accessor.get(IConfigurationService), stats, true); } @@ -916,9 +914,7 @@ export const moveFileToTrashHandler = async (accessor: ServicesAccessor) => { export const deleteFileHandler = async (accessor: ServicesAccessor) => { const explorerService = accessor.get(IExplorerService); - const configurationService = accessor.get(IConfigurationService); - const groupNests = configurationService.getValue().explorer.experimental.fileNesting.operateAsGroup; - const stats = explorerService.getContext(true, groupNests).filter(s => !s.isRoot); + const stats = explorerService.getContext(true).filter(s => !s.isRoot); if (stats.length) { await deleteFiles(accessor.get(IExplorerService), accessor.get(IWorkingCopyFileService), accessor.get(IDialogService), accessor.get(IConfigurationService), stats, false); @@ -928,9 +924,7 @@ export const deleteFileHandler = async (accessor: ServicesAccessor) => { let pasteShouldMove = false; export const copyFileHandler = async (accessor: ServicesAccessor) => { const explorerService = accessor.get(IExplorerService); - const configurationService = accessor.get(IConfigurationService); - const groupNests = configurationService.getValue().explorer.experimental.fileNesting.operateAsGroup; - const stats = explorerService.getContext(true, groupNests); + const stats = explorerService.getContext(true); if (stats.length > 0) { await explorerService.setToCopy(stats, false); pasteShouldMove = false; @@ -939,9 +933,7 @@ export const copyFileHandler = async (accessor: ServicesAccessor) => { export const cutFileHandler = async (accessor: ServicesAccessor) => { const explorerService = accessor.get(IExplorerService); - const configurationService = accessor.get(IConfigurationService); - const groupNests = configurationService.getValue().explorer.experimental.fileNesting.operateAsGroup; - const stats = explorerService.getContext(true, groupNests); + const stats = explorerService.getContext(true); if (stats.length > 0) { await explorerService.setToCopy(stats, true); pasteShouldMove = true; diff --git a/src/vs/workbench/contrib/files/browser/files.contribution.ts b/src/vs/workbench/contrib/files/browser/files.contribution.ts index 9452991360b..258dbbf35d6 100644 --- a/src/vs/workbench/contrib/files/browser/files.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/files.contribution.ts @@ -502,12 +502,7 @@ configurationRegistry.registerConfiguration({ 'tsconfig.json': 'tsconfig.*.json', 'package.json': 'package-lock.json, yarn.lock', } - }, - 'explorer.experimental.fileNesting.operateAsGroup': { - 'type': 'boolean', - 'markdownDescription': nls.localize('operateAsGroup', "Experimental. Controls whether file nests are treated as a group for clipboard operations, file deletions, and during drag and drop."), - 'default': true, - }, + } } }); diff --git a/src/vs/workbench/contrib/files/browser/files.ts b/src/vs/workbench/contrib/files/browser/files.ts index 3c034c4e388..b4b01687527 100644 --- a/src/vs/workbench/contrib/files/browser/files.ts +++ b/src/vs/workbench/contrib/files/browser/files.ts @@ -56,6 +56,7 @@ export interface IExplorerView { itemsCopied(tats: ExplorerItem[], cut: boolean, previousCut: ExplorerItem[] | undefined): void; setEditable(stat: ExplorerItem, isEditing: boolean): Promise; isItemVisible(item: ExplorerItem): boolean; + isItemCollapsed(item: ExplorerItem): boolean; hasFocus(): boolean; } diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index dd373320fbd..1ba98e190c7 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -323,6 +323,10 @@ export class ExplorerView extends ViewPane implements IExplorerView { return this.filter.filter(item, TreeVisibility.Visible); } + isItemCollapsed(item: ExplorerItem): boolean { + return this.tree.isCollapsed(item); + } + async setEditable(stat: ExplorerItem, isEditing: boolean): Promise { if (isEditing) { this.horizontalScrolling = this.tree.options.horizontalScrolling; @@ -408,7 +412,7 @@ export class ExplorerView extends ViewPane implements IExplorerView { multipleSelectionSupport: true, filter: this.filter, sorter: this.instantiationService.createInstance(FileSorter), - dnd: this.instantiationService.createInstance(FileDragAndDrop), + dnd: this.instantiationService.createInstance(FileDragAndDrop, (item) => this.isItemCollapsed(item)), collapseByDefault: (e) => { if (e instanceof ExplorerItem) { if (e.hasNests && getFileNestingSettings(e).expand) { diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index f2acc5fc722..1181f9867c4 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -851,6 +851,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { private dropEnabled = false; constructor( + private isCollapsed: (item: ExplorerItem) => boolean, @IExplorerService private explorerService: IExplorerService, @IEditorService private editorService: IEditorService, @IDialogService private dialogService: IDialogService, @@ -1084,8 +1085,8 @@ export class FileDragAndDrop implements ITreeDragAndDrop { const elementsData = FileDragAndDrop.getStatsFromDragAndDropData(data); const distinctItems = new Set(elementsData); - if (this.configurationService.getValue().explorer.experimental.fileNesting.operateAsGroup) { - for (const item of distinctItems) { + for (const item of distinctItems) { + if (this.isCollapsed(item)) { const nestedChildren = item.nestedChildren; if (nestedChildren) { for (const child of nestedChildren) { @@ -1094,6 +1095,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { } } } + const items = distinctParents([...distinctItems], s => s.resource); const isCopy = (originalEvent.ctrlKey && !isMacintosh) || (originalEvent.altKey && isMacintosh); diff --git a/src/vs/workbench/contrib/files/common/files.ts b/src/vs/workbench/contrib/files/common/files.ts index 00284027740..5f10b350de4 100644 --- a/src/vs/workbench/contrib/files/common/files.ts +++ b/src/vs/workbench/contrib/files/common/files.ts @@ -103,11 +103,6 @@ export interface IFilesConfiguration extends PlatformIFilesConfiguration, IWorkb expand: boolean; patterns: { [parent: string]: string }; }; - experimental: { - fileNesting: { - operateAsGroup: boolean; - }; - }; }; editor: IEditorOptions; } -- cgit v1.2.3 From 6fadb2d2be32d883043f7919955e81d031121b35 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 28 Apr 2022 11:48:51 +0530 Subject: fix #148272 --- .../contrib/extensions/browser/extensionEditor.ts | 5 ++-- .../extensions/browser/extensionsWidgets.ts | 6 +++- .../browser/extensionsWorkbenchService.ts | 34 ++++++++++++---------- 3 files changed, 27 insertions(+), 18 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts index cb560efaaa3..8e2d1a5badd 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts @@ -71,6 +71,7 @@ import { MarkdownString } from 'vs/base/common/htmlContent'; import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; import { ViewContainerLocation } from 'vs/workbench/common/views'; import { IExtensionGalleryService, IGalleryExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; +import semver = require('vs/base/common/semver/semver'); class NavBar extends Disposable { @@ -183,10 +184,10 @@ class VersionWidget extends ExtensionWithDifferentGalleryVersionWidget { this.render(); } render(): void { - if (!this.extension) { + if (!this.extension || !semver.valid(this.extension.version)) { return; } - this.element.textContent = `v${this.gallery ? this.gallery.version : this.extension.version}`; + this.element.textContent = `v${this.gallery?.version ?? this.extension.version}`; } } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts index 522cc6346be..76d062f4c5a 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/extensionsWidgets'; +import * as semver from 'vs/base/common/semver/semver'; import { Disposable, toDisposable, DisposableStore, MutableDisposable, IDisposable } from 'vs/base/common/lifecycle'; import { IExtension, IExtensionsWorkbenchService, IExtensionContainer, ExtensionState, ExtensionEditorTab } from 'vs/workbench/contrib/extensions/common/extensions'; import { append, $ } from 'vs/base/browser/dom'; @@ -480,7 +481,10 @@ export class ExtensionHoverWidget extends ExtensionWidget { } const markdown = new MarkdownString('', { isTrusted: true, supportThemeIcons: true }); - markdown.appendMarkdown(`**${this.extension.displayName}** ** _v${this.extension.version}_** `); + markdown.appendMarkdown(`**${this.extension.displayName}**`); + if (semver.valid(this.extension.version)) { + markdown.appendMarkdown(` ** _v${this.extension.version}_** `); + } if (this.extension.state === ExtensionState.Installed ? this.extension.local?.isPreReleaseVersion : this.extension.gallery?.properties.isPreReleaseVersion) { const extensionPreReleaseIcon = this.themeService.getColorTheme().getColor(extensionPreReleaseIconColor); markdown.appendMarkdown(`** **  $(${preReleaseIcon.id}) ${localize('pre-release-label', "Pre-Release")} `); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index 701473fe624..57acb10a415 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -203,21 +203,25 @@ export class Extension implements IExtension { } get outdated(): boolean { - if (!this.gallery || !this.local) { - return false; - } - // Do not allow updating system extensions in stable - if (this.type === ExtensionType.System && this.productService.quality === 'stable') { - return false; - } - if (!this.local.preRelease && this.gallery.properties.isPreReleaseVersion) { - return false; - } - if (semver.gt(this.latestVersion, this.version)) { - return true; - } - if (this.outdatedTargetPlatform) { - return true; + try { + if (!this.gallery || !this.local) { + return false; + } + // Do not allow updating system extensions in stable + if (this.type === ExtensionType.System && this.productService.quality === 'stable') { + return false; + } + if (!this.local.preRelease && this.gallery.properties.isPreReleaseVersion) { + return false; + } + if (semver.gt(this.latestVersion, this.version)) { + return true; + } + if (this.outdatedTargetPlatform) { + return true; + } + } catch (error) { + /* Ignore */ } return false; } -- cgit v1.2.3 From adb03b8e8d49329b211bc37569fcd7d048a9f984 Mon Sep 17 00:00:00 2001 From: Johannes Date: Thu, 28 Apr 2022 11:14:29 +0200 Subject: fix https://github.com/microsoft/vscode/issues/147940 --- .../workbench/contrib/languageStatus/browser/media/languageStatus.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css b/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css index c31cfe44a49..1fc68790f97 100644 --- a/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css +++ b/src/vs/workbench/contrib/languageStatus/browser/media/languageStatus.css @@ -45,7 +45,7 @@ } } -.monaco-workbench .statusbar DIV#status\.languageStatus.flash { +.monaco-workbench .statusbar DIV#status\.languageStatus.flash A { animation-duration: .8s; animation-iteration-count: 1; animation-name: flash; -- cgit v1.2.3 From a1bfe13ab6e7d68a5d8d93593d84aaff8746f84c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 28 Apr 2022 13:08:44 +0200 Subject: watcher - improve JSDoc and settings description --- src/vs/workbench/contrib/files/browser/files.contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/browser/files.contribution.ts b/src/vs/workbench/contrib/files/browser/files.contribution.ts index 258dbbf35d6..b162ad2ead5 100644 --- a/src/vs/workbench/contrib/files/browser/files.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/files.contribution.ts @@ -246,7 +246,7 @@ configurationRegistry.registerConfiguration({ 'files.watcherExclude': { 'type': 'object', 'default': { '**/.git/objects/**': true, '**/.git/subtree-cache/**': true, '**/node_modules/*/**': true, '**/.hg/store/**': true }, - 'markdownDescription': nls.localize('watcherExclude', "Configure paths or glob patterns to exclude from file watching. Paths that are relative (for example `build/output`) will be resolved to an absolute path using the currently opened workspace. Glob patterns must match on absolute paths (i.e. prefix with `**/` or the full path and suffix with `/**` to match files within a path) to match properly (for example `**/build/output/**` or `/Users/name/workspaces/project/build/output/**`). When you experience the file watcher process consuming a lot of CPU, make sure to exclude large folders that are of less interest (such as build output folders)."), + 'markdownDescription': nls.localize('watcherExclude', "Configure paths or glob patterns to exclude from file watching. Paths or basic glob patterns that are relative (for example `build/output` or `*.js`) will be resolved to an absolute path using the currently opened workspace. Complex glob patterns must match on absolute paths (i.e. prefix with `**/` or the full path and suffix with `/**` to match files within a path) to match properly (for example `**/build/output/**` or `/Users/name/workspaces/project/build/output/**`). When you experience the file watcher process consuming a lot of CPU, make sure to exclude large folders that are of less interest (such as build output folders)."), 'scope': ConfigurationScope.RESOURCE }, 'files.watcherInclude': { -- cgit v1.2.3 From aea5b8cea0f12227e7623989a43d4bf4920c623e Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 28 Apr 2022 17:34:42 +0200 Subject: Fix comment actions not showing Fixes #148279 --- src/vs/workbench/contrib/comments/browser/commentNode.ts | 7 ++++--- src/vs/workbench/contrib/comments/browser/media/review.css | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentNode.ts b/src/vs/workbench/contrib/comments/browser/commentNode.ts index d99f9c41a0b..db768308374 100644 --- a/src/vs/workbench/contrib/comments/browser/commentNode.ts +++ b/src/vs/workbench/contrib/comments/browser/commentNode.ts @@ -165,10 +165,11 @@ export class CommentNode extends Disposable { private createHeader(commentDetailsContainer: HTMLElement): void { const header = dom.append(commentDetailsContainer, dom.$(`div.comment-title.${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`)); - const author = dom.append(header, dom.$('strong.author')); + const infoContainer = dom.append(header, dom.$('comment-header-info')); + const author = dom.append(infoContainer, dom.$('strong.author')); author.innerText = this.comment.userName; - this.createTimestamp(header); - this._isPendingLabel = dom.append(header, dom.$('span.isPending')); + this.createTimestamp(infoContainer); + this._isPendingLabel = dom.append(infoContainer, dom.$('span.isPending')); if (this.comment.label) { this._isPendingLabel.innerText = this.comment.label; diff --git a/src/vs/workbench/contrib/comments/browser/media/review.css b/src/vs/workbench/contrib/comments/browser/media/review.css index b87a2db8b42..f30e7d7109b 100644 --- a/src/vs/workbench/contrib/comments/browser/media/review.css +++ b/src/vs/workbench/contrib/comments/browser/media/review.css @@ -29,6 +29,11 @@ height: 21px; } +.review-widget .body .review-comment .comment-title .comment-header-info { + overflow: hidden; + text-overflow: ellipsis; +} + .review-widget .body .review-comment .comment-title { display: flex; width: 100%; -- cgit v1.2.3 From 8632e9c4096eab5773958b9fb3f45f92efba74a8 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 28 Apr 2022 16:04:03 -0700 Subject: fix #148258. --- .../contrib/notebook/browser/notebookEditorWidget.ts | 5 +++++ .../contrib/notebook/browser/view/cellParts/codeCell.ts | 13 +++++++++++-- .../contrib/notebook/browser/view/cellParts/markdownCell.ts | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 942f49772ca..5f76bc5718f 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1824,6 +1824,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD const focusRange = this.viewModel.getFocus(); const element = this.viewModel.cellAt(focusRange.start); + // The notebook editor doesn't have focus yet + if (!this.hasEditorFocus()) { + this.focusContainer(); + } + if (element && element.focusMode === CellFocusMode.Editor) { element.updateEditState(CellEditState.Editing, 'editorWidget.focus'); element.focusMode = CellFocusMode.Editor; diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts index 3f2df96e305..6cd5d2c242d 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts @@ -316,8 +316,17 @@ export class CodeCell extends Disposable { })); } + private shouldUpdateDOMFocus() { + // The DOM focus needs to be adjusted: + // when a cell editor should be focused + // the document active element is inside the notebook editor or the document body (cell editor being disposed previously) + return this.notebookEditor.getActiveCell() === this.viewCell + && this.viewCell.focusMode === CellFocusMode.Editor + && (this.notebookEditor.hasEditorFocus() || document.activeElement === document.body); + } + private updateEditorForFocusModeChange() { - if (this.viewCell.focusMode === CellFocusMode.Editor && this.notebookEditor.getActiveCell() === this.viewCell) { + if (this.shouldUpdateDOMFocus()) { this.templateData.editor?.focus(); } @@ -479,7 +488,7 @@ export class CodeCell extends Disposable { this._isDisposed = true; // move focus back to the cell list otherwise the focus goes to body - if (this.notebookEditor.getActiveCell() === this.viewCell && this.viewCell.focusMode === CellFocusMode.Editor) { + if (this.shouldUpdateDOMFocus()) { this.notebookEditor.focusContainer(); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts index b7652ba37ca..82e710ed494 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts @@ -221,7 +221,7 @@ export class StatefulMarkdownCell extends Disposable { override dispose() { // move focus back to the cell list otherwise the focus goes to body - if (this.notebookEditor.getActiveCell() === this.viewCell && this.viewCell.focusMode === CellFocusMode.Editor) { + if (this.notebookEditor.getActiveCell() === this.viewCell && this.viewCell.focusMode === CellFocusMode.Editor && (this.notebookEditor.hasEditorFocus() || document.activeElement === document.body)) { this.notebookEditor.focusContainer(); } -- cgit v1.2.3 From 5b7ed788d7f6c7f89a7a08e9e67abdcba8b3d1b6 Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Fri, 29 Apr 2022 13:30:51 -0400 Subject: Fix #96784 --- src/vs/workbench/contrib/timeline/browser/timelinePane.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index b2ee02b8923..65b9d91beca 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -888,7 +888,7 @@ export class TimelinePane extends ViewPane { if (isLoadMoreCommand(element)) { return element.ariaLabel; } - return element.accessibilityInformation ? element.accessibilityInformation.label : localize('timeline.aria.item', "{0}: {1}", element.relativeTime ?? '', element.label); + return element.accessibilityInformation ? element.accessibilityInformation.label : localize('timeline.aria.item', "{0}: {1}", element.relativeTimeFullWord ?? '', element.label); }, getRole(element: TreeElement): string { if (isLoadMoreCommand(element)) { -- cgit v1.2.3 From 975e88c01a551aeb34c44b4d1ca07aa6f4b3f9ff Mon Sep 17 00:00:00 2001 From: meganrogge Date: Fri, 29 Apr 2022 14:25:44 -0700 Subject: fix #148446 --- .../workbench/contrib/terminal/browser/media/shellIntegration-env.zsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-env.zsh b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-env.zsh index 26ab335881a..f676a0308bd 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-env.zsh +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-env.zsh @@ -3,6 +3,6 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # --------------------------------------------------------------------------------------------- -if [[ $options[norcs] = off && -o "login" && -f ~/.zshenv ]]; then +if [[ -f ~/.zshenv ]]; then . ~/.zshenv fi -- cgit v1.2.3 From 3f4cf3d89c50912d383aa9eab80c9d2dfde669b6 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Fri, 29 Apr 2022 15:47:28 -0700 Subject: fix #147952 (#148463) Co-authored-by: Jackson Kearl --- .../workbench/contrib/terminal/browser/media/shellIntegration-bash.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh index cda92578a5d..80d528804c0 100755 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh @@ -10,8 +10,8 @@ if [ -z "$VSCODE_SHELL_LOGIN" ]; then else # Imitate -l because --init-file doesn't support it: # run the first of these files that exists - if [ -f /etc/bash_profile ]; then - . /etc/bash_profile + if [ -f /etc/profile ]; then + . /etc/profile fi # exceute the first that exists if [ -f ~/.bash_profile ]; then -- cgit v1.2.3 From 5a13636bde7c6bbb4bbb471f1f8142289bda106b Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Fri, 29 Apr 2022 14:40:14 +0200 Subject: Fix #148187 --- src/vs/workbench/contrib/scm/browser/scmViewPane.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 3eb672f06c5..fd1a31c8767 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -1642,19 +1642,19 @@ abstract class SetSortKeyAction extends ViewAction { class SetSortByNameAction extends SetSortKeyAction { constructor() { - super(ViewModelSortKey.Name, localize('sortByName', "Sort by Name")); + super(ViewModelSortKey.Name, localize('sortChangesByName', "Sort Changes by Name")); } } class SetSortByPathAction extends SetSortKeyAction { constructor() { - super(ViewModelSortKey.Path, localize('sortByPath', "Sort by Path")); + super(ViewModelSortKey.Path, localize('sortChangesByPath', "Sort Changes by Path")); } } class SetSortByStatusAction extends SetSortKeyAction { constructor() { - super(ViewModelSortKey.Status, localize('sortByStatus', "Sort by Status")); + super(ViewModelSortKey.Status, localize('sortChangesByStatus', "Sort Changes by Status")); } } -- cgit v1.2.3 From ca936dcc94fba1f8d6c6de2b5984827571e24eaa Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 2 May 2022 09:25:36 +0200 Subject: Remember target directory when downloading files (fix #140358) --- .../contrib/files/browser/fileImportExport.ts | 31 ++++++++++++++++------ .../contrib/profiles/common/profilesActions.ts | 2 +- .../workspace/browser/workspaceTrustEditor.ts | 1 - 3 files changed, 24 insertions(+), 10 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/files/browser/fileImportExport.ts b/src/vs/workbench/contrib/files/browser/fileImportExport.ts index 08fdd59d803..71eda39201c 100644 --- a/src/vs/workbench/contrib/files/browser/fileImportExport.ts +++ b/src/vs/workbench/contrib/files/browser/fileImportExport.ts @@ -14,7 +14,7 @@ import { IFilesConfiguration, UndoConfirmLevel, VIEW_ID } from 'vs/workbench/con import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { Limiter, Promises, RunOnceWorker } from 'vs/base/common/async'; import { newWriteableBufferStream, VSBuffer } from 'vs/base/common/buffer'; -import { basename, joinPath } from 'vs/base/common/resources'; +import { basename, dirname, joinPath } from 'vs/base/common/resources'; import { ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService'; import { ExplorerItem } from 'vs/workbench/contrib/files/common/explorerModel'; import { URI } from 'vs/base/common/uri'; @@ -35,6 +35,7 @@ import { canceled } from 'vs/base/common/errors'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; //#region Browser File Upload (drag and drop, input element) @@ -574,12 +575,15 @@ interface IDownloadOperation { export class FileDownload { + private static readonly LAST_USED_DOWNLOAD_PATH_STORAGE_KEY = 'workbench.explorer.downloadPath'; + constructor( @IFileService private readonly fileService: IFileService, @IExplorerService private readonly explorerService: IExplorerService, @IProgressService private readonly progressService: IProgressService, @ILogService private readonly logService: ILogService, - @IFileDialogService private readonly fileDialogService: IFileDialogService + @IFileDialogService private readonly fileDialogService: IFileDialogService, + @IStorageService private readonly storageService: IStorageService ) { } @@ -791,12 +795,18 @@ export class FileDownload { private async doDownloadNative(explorerItem: ExplorerItem, progress: IProgress, cts: CancellationTokenSource): Promise { progress.report({ message: explorerItem.name }); - const defaultUri = joinPath( - explorerItem.isDirectory ? - await this.fileDialogService.defaultFolderPath(Schemas.file) : - await this.fileDialogService.defaultFilePath(Schemas.file), - explorerItem.name - ); + let defaultUri: URI; + const lastUsedDownloadPath = this.storageService.get(FileDownload.LAST_USED_DOWNLOAD_PATH_STORAGE_KEY, StorageScope.GLOBAL); + if (lastUsedDownloadPath) { + defaultUri = joinPath(URI.file(lastUsedDownloadPath), explorerItem.name); + } else { + defaultUri = joinPath( + explorerItem.isDirectory ? + await this.fileDialogService.defaultFolderPath(Schemas.file) : + await this.fileDialogService.defaultFilePath(Schemas.file), + explorerItem.name + ); + } const destination = await this.fileDialogService.showSaveDialog({ availableFileSystems: [Schemas.file], @@ -806,6 +816,11 @@ export class FileDownload { }); if (destination) { + + // Remember as last used download folder + this.storageService.store(FileDownload.LAST_USED_DOWNLOAD_PATH_STORAGE_KEY, dirname(destination).fsPath, StorageScope.GLOBAL, StorageTarget.MACHINE); + + // Perform download await this.explorerService.applyBulkEdit([new ResourceFileEdit(explorerItem.resource, destination, { overwrite: true, copy: true })], { undoLabel: localize('downloadBulkEdit', "Download {0}", explorerItem.name), progressLabel: localize('downloadingBulkEdit', "Downloading {0}", explorerItem.name), diff --git a/src/vs/workbench/contrib/profiles/common/profilesActions.ts b/src/vs/workbench/contrib/profiles/common/profilesActions.ts index 2ab0e5462ce..bae901d966d 100644 --- a/src/vs/workbench/contrib/profiles/common/profilesActions.ts +++ b/src/vs/workbench/contrib/profiles/common/profilesActions.ts @@ -39,7 +39,7 @@ registerAction2(class ExportProfileAction extends Action2 { const profileLocation = await fileDialogService.showSaveDialog({ title: localize('export profile dialog', "Save Profile"), filters: PROFILE_FILTER, - defaultUri: joinPath(await fileDialogService.defaultFilePath(undefined), `profile.${PROFILE_EXTENSION}`), + defaultUri: joinPath(await fileDialogService.defaultFilePath(), `profile.${PROFILE_EXTENSION}`), }); if (!profileLocation) { diff --git a/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts b/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts index 68e9e88bcd4..679be9104d5 100644 --- a/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts +++ b/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts @@ -353,7 +353,6 @@ class WorkspaceTrustedUrisTable extends Disposable { canSelectMany: false, defaultUri: item.uri, openLabel: localize('trustUri', "Trust Folder"), - title: localize('selectTrustedUri', "Select Folder To Trust") }); -- cgit v1.2.3 From d6f55b65e981c6470b70b1dc7028c4350d497c65 Mon Sep 17 00:00:00 2001 From: Johannes Date: Mon, 2 May 2022 10:18:30 +0200 Subject: use `fsPath` instead of `path` --- src/vs/workbench/contrib/snippets/browser/tabCompletion.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts b/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts index 0ed0cc9470b..1f4afaa0a94 100644 --- a/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts +++ b/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts @@ -147,7 +147,7 @@ export class TabCompletionController implements IEditorContribution { } }; const registration = this._languageFeaturesService.completionProvider.register( - { language: model.getLanguageId(), pattern: model.uri.path, scheme: model.uri.scheme }, + { language: model.getLanguageId(), pattern: model.uri.fsPath, scheme: model.uri.scheme }, this._completionProvider ); } -- cgit v1.2.3 From b96fd041fd83a43bed90585901e83ef6577dabf4 Mon Sep 17 00:00:00 2001 From: Johannes Date: Mon, 2 May 2022 13:30:40 +0200 Subject: Add title menu quick pick as submenu and use special rendering for that, add some global and local commands and remeber the last picked --- .../codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts | 7 +++++-- .../workbench/contrib/quickaccess/browser/commandsQuickAccess.ts | 6 +++++- src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts | 8 ++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts index 0680340ed33..2510900a42e 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts @@ -270,11 +270,14 @@ registerAction2(class GotoSymbolAction extends Action2 { weight: KeybindingWeight.WorkbenchContrib, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyO }, - menu: { + menu: [{ id: MenuId.MenubarGoMenu, group: '4_symbol_nav', order: 1 - } + }, { + id: MenuId.TitleMenuQuickPick, + group: '2/localQuickPick' + }] }); } diff --git a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts index 755c6fa307c..7f42b5c647f 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts @@ -160,12 +160,16 @@ export class ShowAllCommandsAction extends Action2 { super({ id: ShowAllCommandsAction.ID, title: { value: localize('showTriggerActions', "Show All Commands"), original: 'Show All Commands' }, - f1: true, keybinding: { weight: KeybindingWeight.WorkbenchContrib, when: undefined, primary: !isFirefox ? (KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyP) : undefined, secondary: [KeyCode.F1] + }, + f1: true, + menu: { + id: MenuId.TitleMenuQuickPick, + group: '1/globalQuickPick' } }); } diff --git a/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts b/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts index 4a278af2146..195fb79a57a 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts @@ -15,7 +15,7 @@ import { matchesFuzzy } from 'vs/base/common/filters'; import { fuzzyContains } from 'vs/base/common/strings'; import { withNullAsUndefined } from 'vs/base/common/types'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { Action2 } from 'vs/platform/actions/common/actions'; +import { Action2, MenuId } from 'vs/platform/actions/common/actions'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -217,7 +217,11 @@ export class OpenViewPickerAction extends Action2 { id: OpenViewPickerAction.ID, title: { value: localize('openView', "Open View"), original: 'Open View' }, category: CATEGORIES.View, - f1: true + f1: true, + menu: { + id: MenuId.TitleMenuQuickPick, + group: '1/globalQuickPick' + } }); } -- cgit v1.2.3 From ab13b068b55f468ba2d1914ea4a13bcb88ec8f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 2 May 2022 14:47:04 +0200 Subject: Remove SCMRepository instances from context service (#148047) * have SCMService expose iterable repositories list * remove SCMRepository instances from context service Related-to: #147926 --- src/vs/workbench/contrib/scm/browser/activity.ts | 16 ++++++----- .../contrib/scm/browser/dirtydiffDecorator.ts | 11 ++++---- .../contrib/scm/browser/scm.contribution.ts | 24 ++++++++++++---- .../workbench/contrib/scm/browser/scmViewPane.ts | 14 ++++----- src/vs/workbench/contrib/scm/common/scm.ts | 5 +++- src/vs/workbench/contrib/scm/common/scmService.ts | 33 +++++++++------------- 6 files changed, 58 insertions(+), 45 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/scm/browser/activity.ts b/src/vs/workbench/contrib/scm/browser/activity.ts index 399e48dcce8..91629caa98b 100644 --- a/src/vs/workbench/contrib/scm/browser/activity.ts +++ b/src/vs/workbench/contrib/scm/browser/activity.ts @@ -18,6 +18,7 @@ import { EditorResourceAccessor } from 'vs/workbench/common/editor'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; import { stripIcons } from 'vs/base/common/iconLabels'; import { Schemas } from 'vs/base/common/network'; +import { Iterable } from 'vs/base/common/iterator'; function getCount(repository: ISCMRepository): number { if (typeof repository.provider.count === 'number') { @@ -116,7 +117,7 @@ export class SCMStatusController implements IWorkbenchContribution { return; } - this.focusRepository(this.scmService.repositories[0]); + this.focusRepository(Iterable.first(this.scmService.repositories)); } private focusRepository(repository: ISCMRepository | undefined): void { @@ -172,7 +173,7 @@ export class SCMStatusController implements IWorkbenchContribution { let count = 0; if (countBadgeType === 'all') { - count = this.scmService.repositories.reduce((r, repository) => r + getCount(repository), 0); + count = Iterable.reduce(this.scmService.repositories, (r, repository) => r + getCount(repository), 0); } else if (countBadgeType === 'focused' && this.focusedRepository) { count = getCount(this.focusedRepository); } @@ -198,7 +199,7 @@ export class SCMStatusController implements IWorkbenchContribution { export class SCMActiveResourceContextKeyController implements IWorkbenchContribution { private activeResourceHasChangesContextKey: IContextKey; - private activeResourceRepositoryContextKey: IContextKey; + private activeResourceRepositoryContextKey: IContextKey; private disposables = new DisposableStore(); private repositoryDisposables = new Set(); @@ -239,11 +240,12 @@ export class SCMActiveResourceContextKeyController implements IWorkbenchContribu const activeResource = EditorResourceAccessor.getOriginalUri(this.editorService.activeEditor); if (activeResource?.scheme === Schemas.file || activeResource?.scheme === Schemas.vscodeRemote) { - const activeResourceRepository = this.scmService.repositories - .find(r => r.provider.rootUri && - this.uriIdentityService.extUri.isEqualOrParent(activeResource, r.provider.rootUri)); + const activeResourceRepository = Iterable.find( + this.scmService.repositories, + r => Boolean(r.provider.rootUri && this.uriIdentityService.extUri.isEqualOrParent(activeResource, r.provider.rootUri)) + ); - this.activeResourceRepositoryContextKey.set(activeResourceRepository); + this.activeResourceRepositoryContextKey.set(activeResourceRepository?.id); for (const resourceGroup of activeResourceRepository?.provider.groups.elements ?? []) { if (resourceGroup.elements diff --git a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts index 8bae9fbc794..0457fde2584 100644 --- a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts +++ b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts @@ -53,6 +53,7 @@ import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/ import { IChange } from 'vs/editor/common/diff/diffComputer'; import { Color } from 'vs/base/common/color'; import { editorGutter } from 'vs/editor/common/core/editorColorRegistry'; +import { Iterable } from 'vs/base/common/iterator'; class DiffActionRunner extends ActionRunner { @@ -1079,8 +1080,8 @@ export function createProviderComparer(uri: URI): (a: ISCMProvider, b: ISCMProvi } export async function getOriginalResource(scmService: ISCMService, uri: URI): Promise { - const providers = scmService.repositories.map(r => r.provider); - const rootedProviders = providers.filter(p => !!p.rootUri); + const providers = Iterable.map(scmService.repositories, r => r.provider); + const rootedProviders = Iterable.collect(Iterable.filter(providers, p => !!p.rootUri)); rootedProviders.sort(createProviderComparer(uri)); @@ -1090,8 +1091,8 @@ export async function getOriginalResource(scmService: ISCMService, uri: URI): Pr return result; } - const nonRootedProviders = providers.filter(p => !p.rootUri); - return first(nonRootedProviders.map(p => () => p.getOriginalResource(uri))); + const nonRootedProviders = Iterable.filter(providers, p => !p.rootUri); + return first(Iterable.collect(Iterable.map(nonRootedProviders, p => () => p.getOriginalResource(uri)))); } export class DirtyDiffModel extends Disposable { @@ -1132,7 +1133,7 @@ export class DirtyDiffModel extends Disposable { )(this.triggerDiff, this) ); this._register(scmService.onDidAddRepository(this.onDidAddRepository, this)); - scmService.repositories.forEach(r => this.onDidAddRepository(r)); + Iterable.forEach(scmService.repositories, r => this.onDidAddRepository(r)); this._register(this._model.onDidChangeEncoding(() => { this.diffDelayer.cancel(); diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index 89b85c7ecae..956e867a21f 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { DirtyDiffWorkbenchController } from './dirtydiffDecorator'; -import { VIEWLET_ID, ISCMRepository, ISCMService, VIEW_PANE_ID, ISCMProvider, ISCMViewService, REPOSITORIES_VIEW_PANE_ID } from 'vs/workbench/contrib/scm/common/scm'; +import { VIEWLET_ID, ISCMService, VIEW_PANE_ID, ISCMProvider, ISCMViewService, REPOSITORIES_VIEW_PANE_ID } from 'vs/workbench/contrib/scm/common/scm'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { SCMActiveResourceContextKeyController, SCMStatusController } from './activity'; @@ -292,15 +292,23 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ handler: accessor => { const contextKeyService = accessor.get(IContextKeyService); const context = contextKeyService.getContext(document.activeElement); - const repository = context.getValue('scmRepository'); + const repositoryId = context.getValue('scmRepository'); - if (!repository || !repository.provider.acceptInputCommand) { + if (!repositoryId) { return Promise.resolve(null); } + + const scmService = accessor.get(ISCMService); + const repository = scmService.getRepository(repositoryId); + + if (!repository?.provider.acceptInputCommand) { + return Promise.resolve(null); + } + const id = repository.provider.acceptInputCommand.id; const args = repository.provider.acceptInputCommand.arguments; - const commandService = accessor.get(ICommandService); + return commandService.executeCommand(id, ...(args || [])); } }); @@ -310,8 +318,10 @@ const viewNextCommitCommand = { weight: KeybindingWeight.WorkbenchContrib, handler: (accessor: ServicesAccessor) => { const contextKeyService = accessor.get(IContextKeyService); + const scmService = accessor.get(ISCMService); const context = contextKeyService.getContext(document.activeElement); - const repository = context.getValue('scmRepository'); + const repositoryId = context.getValue('scmRepository'); + const repository = repositoryId ? scmService.getRepository(repositoryId) : undefined; repository?.input.showNextHistoryValue(); } }; @@ -321,8 +331,10 @@ const viewPreviousCommitCommand = { weight: KeybindingWeight.WorkbenchContrib, handler: (accessor: ServicesAccessor) => { const contextKeyService = accessor.get(IContextKeyService); + const scmService = accessor.get(ISCMService); const context = contextKeyService.getContext(document.activeElement); - const repository = context.getValue('scmRepository'); + const repositoryId = context.getValue('scmRepository'); + const repository = repositoryId ? scmService.getRepository(repositoryId) : undefined; repository?.input.showPreviousHistoryValue(); } }; diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index fd1a31c8767..7e87c10e0fc 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -1724,7 +1724,7 @@ class SCMInputWidget extends Disposable { private inputEditor: CodeEditorWidget; private model: { readonly input: ISCMInput; readonly textModel: ITextModel } | undefined; - private repositoryContextKey: IContextKey; + private repositoryIdContextKey: IContextKey; private repositoryDisposables = new DisposableStore(); private validation: IInputValidation | undefined; @@ -1753,7 +1753,7 @@ class SCMInputWidget extends Disposable { this.repositoryDisposables.dispose(); this.repositoryDisposables = new DisposableStore(); - this.repositoryContextKey.set(input?.repository); + this.repositoryIdContextKey.set(input?.repository.id); if (!input) { this.model?.textModel.dispose(); @@ -1919,7 +1919,7 @@ class SCMInputWidget extends Disposable { this.setPlaceholderFontStyles(fontFamily, fontSize, lineHeight); const contextKeyService2 = contextKeyService.createScoped(this.element); - this.repositoryContextKey = contextKeyService2.createKey('scmRepository', undefined); + this.repositoryIdContextKey = contextKeyService2.createKey('scmRepository', undefined); const editorOptions: IEditorConstructionOptions = { ...getSimpleEditorOptions(), @@ -2326,14 +2326,14 @@ export class SCMViewPane extends ViewPane { return; } else if (isSCMResourceGroup(e.element)) { const provider = e.element.provider; - const repository = this.scmService.repositories.find(r => r.provider === provider); + const repository = Iterable.find(this.scmService.repositories, r => r.provider === provider); if (repository) { this.scmViewService.focus(repository); } return; } else if (ResourceTree.isResourceNode(e.element)) { const provider = e.element.context.provider; - const repository = this.scmService.repositories.find(r => r.provider === provider); + const repository = Iterable.find(this.scmService.repositories, r => r.provider === provider); if (repository) { this.scmViewService.focus(repository); } @@ -2376,7 +2376,7 @@ export class SCMViewPane extends ViewPane { } const provider = e.element.resourceGroup.provider; - const repository = this.scmService.repositories.find(r => r.provider === provider); + const repository = Iterable.find(this.scmService.repositories, r => r.provider === provider); if (repository) { this.scmViewService.focus(repository); @@ -2451,7 +2451,7 @@ export class SCMViewPane extends ViewPane { } override shouldShowWelcome(): boolean { - return this.scmService.repositories.length === 0; + return this.scmService.repositoryCount === 0; } override getActionsContext(): unknown { diff --git a/src/vs/workbench/contrib/scm/common/scm.ts b/src/vs/workbench/contrib/scm/common/scm.ts index a70726447a1..e180e8e9d3c 100644 --- a/src/vs/workbench/contrib/scm/common/scm.ts +++ b/src/vs/workbench/contrib/scm/common/scm.ts @@ -135,6 +135,7 @@ export interface ISCMInput { } export interface ISCMRepository extends IDisposable { + readonly id: string; readonly provider: ISCMProvider; readonly input: ISCMInput; } @@ -144,9 +145,11 @@ export interface ISCMService { readonly _serviceBrand: undefined; readonly onDidAddRepository: Event; readonly onDidRemoveRepository: Event; - readonly repositories: ISCMRepository[]; + readonly repositories: Iterable; + readonly repositoryCount: number; registerSCMProvider(provider: ISCMProvider): ISCMRepository; + getRepository(id: string): ISCMRepository | undefined; } export interface ISCMTitleMenu { diff --git a/src/vs/workbench/contrib/scm/common/scmService.ts b/src/vs/workbench/contrib/scm/common/scmService.ts index a4670d7aff9..7877ba1d34e 100644 --- a/src/vs/workbench/contrib/scm/common/scmService.ts +++ b/src/vs/workbench/contrib/scm/common/scmService.ts @@ -242,6 +242,7 @@ class SCMRepository implements ISCMRepository { readonly input: ISCMInput = new SCMInput(this, this.storageService); constructor( + public readonly id: string, public readonly provider: ISCMProvider, private disposable: IDisposable, @IStorageService private storageService: IStorageService @@ -266,9 +267,9 @@ export class SCMService implements ISCMService { declare readonly _serviceBrand: undefined; - private _providerIds = new Set(); - private _repositories: ISCMRepository[] = []; - get repositories(): ISCMRepository[] { return [...this._repositories]; } + private _repositories = new Map(); + get repositories(): Iterable { return this._repositories.values(); } + get repositoryCount(): number { return this._repositories.size; } private providerCount: IContextKey; @@ -289,31 +290,25 @@ export class SCMService implements ISCMService { registerSCMProvider(provider: ISCMProvider): ISCMRepository { this.logService.trace('SCMService#registerSCMProvider'); - if (this._providerIds.has(provider.id)) { + if (this._repositories.has(provider.id)) { throw new Error(`SCM Provider ${provider.id} already exists.`); } - this._providerIds.add(provider.id); - const disposable = toDisposable(() => { - const index = this._repositories.indexOf(repository); - - if (index < 0) { - return; - } - - this._providerIds.delete(provider.id); - this._repositories.splice(index, 1); + this._repositories.delete(provider.id); this._onDidRemoveProvider.fire(repository); - - this.providerCount.set(this._repositories.length); + this.providerCount.set(this._repositories.size); }); - const repository = new SCMRepository(provider, disposable, this.storageService); - this._repositories.push(repository); + const repository = new SCMRepository(provider.id, provider, disposable, this.storageService); + this._repositories.set(provider.id, repository); this._onDidAddProvider.fire(repository); - this.providerCount.set(this._repositories.length); + this.providerCount.set(this._repositories.size); return repository; } + + getRepository(id: string): ISCMRepository | undefined { + return this._repositories.get(id); + } } -- cgit v1.2.3 From e4a5ddae87a68bc37a16540f9223f62906b50c84 Mon Sep 17 00:00:00 2001 From: Johannes Date: Mon, 2 May 2022 15:18:19 +0200 Subject: add "go to symbol in workspace", ordering, set title to window title --- .../browser/quickaccess/gotoLineQuickAccess.ts | 7 ++++- .../browser/quickaccess/gotoSymbolQuickAccess.ts | 3 +- .../quickaccess/browser/commandsQuickAccess.ts | 3 +- .../contrib/quickaccess/browser/viewQuickAccess.ts | 8 ++---- .../contrib/search/browser/search.contribution.ts | 32 ++++++++++++++-------- 5 files changed, 33 insertions(+), 20 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts index cec3c9c01f8..d2b4f005a8b 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts @@ -12,7 +12,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IQuickAccessRegistry, Extensions as QuickaccesExtensions } from 'vs/platform/quickinput/common/quickAccess'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; -import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; +import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -85,6 +85,11 @@ class GotoLineAction extends Action2 { when: null, primary: KeyMod.CtrlCmd | KeyCode.KeyG, mac: { primary: KeyMod.WinCtrl | KeyCode.KeyG } + }, + menu: { + id: MenuId.TitleMenuQuickPick, + group: '3/editorNav', + order: 2 } }); } diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts index 2510900a42e..a8b90ea7be3 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts @@ -276,7 +276,8 @@ registerAction2(class GotoSymbolAction extends Action2 { order: 1 }, { id: MenuId.TitleMenuQuickPick, - group: '2/localQuickPick' + group: '3/editorNav', + order: 1 }] }); } diff --git a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts index 7f42b5c647f..0f8b4edc30d 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts @@ -169,7 +169,8 @@ export class ShowAllCommandsAction extends Action2 { f1: true, menu: { id: MenuId.TitleMenuQuickPick, - group: '1/globalQuickPick' + group: '1/workspaceNav', + order: 3 } }); } diff --git a/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts b/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts index 195fb79a57a..4a278af2146 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts @@ -15,7 +15,7 @@ import { matchesFuzzy } from 'vs/base/common/filters'; import { fuzzyContains } from 'vs/base/common/strings'; import { withNullAsUndefined } from 'vs/base/common/types'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { Action2, MenuId } from 'vs/platform/actions/common/actions'; +import { Action2 } from 'vs/platform/actions/common/actions'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -217,11 +217,7 @@ export class OpenViewPickerAction extends Action2 { id: OpenViewPickerAction.ID, title: { value: localize('openView', "Open View"), original: 'Open View' }, category: CATEGORIES.View, - f1: true, - menu: { - id: MenuId.TitleMenuQuickPick, - group: '1/globalQuickPick' - } + f1: true }); } diff --git a/src/vs/workbench/contrib/search/browser/search.contribution.ts b/src/vs/workbench/contrib/search/browser/search.contribution.ts index 4ed1c60a5ca..fb3d698f583 100644 --- a/src/vs/workbench/contrib/search/browser/search.contribution.ts +++ b/src/vs/workbench/contrib/search/browser/search.contribution.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Action } from 'vs/base/common/actions'; import { onUnexpectedError } from 'vs/base/common/errors'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import * as platform from 'vs/base/common/platform'; @@ -594,25 +593,37 @@ MenuRegistry.appendMenuItem(MenuId.ExplorerContext, { when: ContextKeyExpr.and(ExplorerRootContext, ExplorerFolderContext.toNegated()) }); - -class ShowAllSymbolsAction extends Action { +registerAction2(class ShowAllSymbolsAction extends Action2 { static readonly ID = 'workbench.action.showAllSymbols'; static readonly LABEL = nls.localize('showTriggerActions', "Go to Symbol in Workspace..."); static readonly ALL_SYMBOLS_PREFIX = '#'; constructor( - actionId: string, - actionLabel: string, - @IQuickInputService private readonly quickInputService: IQuickInputService ) { - super(actionId, actionLabel); + super({ + id: 'workbench.action.showAllSymbols', + title: { + value: nls.localize('showTriggerActions', "Go to Symbol in Workspace..."), + original: 'Go to Symbol in Workspace...' + }, + f1: true, + menu: { + id: MenuId.TitleMenuQuickPick, + group: '1/workspaceNav', + order: 2 + }, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyMod.CtrlCmd | KeyCode.KeyT + } + }); } - override async run(): Promise { - this.quickInputService.quickAccess.show(ShowAllSymbolsAction.ALL_SYMBOLS_PREFIX); + override async run(accessor: ServicesAccessor): Promise { + accessor.get(IQuickInputService).quickAccess.show(ShowAllSymbolsAction.ALL_SYMBOLS_PREFIX); } -} +}); const SEARCH_MODE_CONFIG = 'search.mode'; @@ -793,7 +804,6 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ } }); -registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowAllSymbolsAction, { primary: KeyMod.CtrlCmd | KeyCode.KeyT }), 'Go to Symbol in Workspace...'); registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleSearchOnTypeAction), 'Search: Toggle Search on Type', category.value); // Register Quick Access Handler -- cgit v1.2.3 From 83f9e8605b4acdd1aaa503c6657a9911d041de6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 2 May 2022 15:54:04 +0200 Subject: fixes #146360 cc @lszomoru --- src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts index 0457fde2584..c05f0b2f4be 100644 --- a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts +++ b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts @@ -610,7 +610,8 @@ export class DirtyDiffController extends Disposable implements IEditorContributi } .monaco-editor .margin-view-overlays .dirty-diff-glyph:hover::before { - width: 9px; + height: 100%; + width: 6px; left: -6px; } -- cgit v1.2.3 From b0a0e7ec37df52bf2dddbcb5b1892933ad707867 Mon Sep 17 00:00:00 2001 From: Johannes Date: Mon, 2 May 2022 15:51:11 +0200 Subject: debt - use Action2 instead of spread out calls to registries --- .../contrib/notebook/browser/controller/layoutActions.ts | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts index 27ce6ca5434..4f6a3e489c5 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts @@ -173,15 +173,6 @@ registerAction2(class ToggleBreadcrumbFromEditorTitle extends Action2 { } }); -MenuRegistry.appendMenuItem(MenuId.NotebookToolbar, { - command: { - id: 'breadcrumbs.toggle', - title: { value: localize('cmd.toggle', "Toggle Breadcrumbs"), original: 'Toggle Breadcrumbs' }, - }, - group: 'notebookLayout', - order: 2 -}); - registerAction2(class SaveMimeTypeDisplayOrder extends Action2 { constructor() { super({ -- cgit v1.2.3 From 634785196338961dbec92e5b67543019e6f151fe Mon Sep 17 00:00:00 2001 From: Johannes Date: Mon, 2 May 2022 16:01:26 +0200 Subject: debt - more registerAction2 --- .../contrib/snippets/browser/configureSnippets.ts | 144 ++++++++++----------- 1 file changed, 70 insertions(+), 74 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/snippets/browser/configureSnippets.ts b/src/vs/workbench/contrib/snippets/browser/configureSnippets.ts index bbee0e94ef5..9b5871c2e89 100644 --- a/src/vs/workbench/contrib/snippets/browser/configureSnippets.ts +++ b/src/vs/workbench/contrib/snippets/browser/configureSnippets.ts @@ -4,11 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ILanguageService } from 'vs/editor/common/languages/language'; import { extname } from 'vs/base/common/path'; -import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; +import { MenuId, registerAction2, Action2 } from 'vs/platform/actions/common/actions'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { URI } from 'vs/base/common/uri'; import { ISnippetsService } from 'vs/workbench/contrib/snippets/browser/snippets.contribution'; @@ -19,8 +18,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { isValidBasename } from 'vs/base/common/extpath'; import { joinPath, basename } from 'vs/base/common/resources'; - -const id = 'workbench.action.openSnippets'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; namespace ISnippetPick { export function is(thing: object | undefined): thing is ISnippetPick { @@ -201,82 +199,80 @@ async function createLanguageSnippetFile(pick: ISnippetPick, fileService: IFileS await textFileService.write(pick.filepath, contents); } -CommandsRegistry.registerCommand(id, async (accessor): Promise => { - - const snippetService = accessor.get(ISnippetsService); - const quickInputService = accessor.get(IQuickInputService); - const opener = accessor.get(IOpenerService); - const languageService = accessor.get(ILanguageService); - const envService = accessor.get(IEnvironmentService); - const workspaceService = accessor.get(IWorkspaceContextService); - const fileService = accessor.get(IFileService); - const textFileService = accessor.get(ITextFileService); - - const picks = await computePicks(snippetService, envService, languageService); - const existing: QuickPickInput[] = picks.existing; - - type SnippetPick = IQuickPickItem & { uri: URI } & { scope: string }; - const globalSnippetPicks: SnippetPick[] = [{ - scope: nls.localize('new.global_scope', 'global'), - label: nls.localize('new.global', "New Global Snippets file..."), - uri: envService.snippetsHome - }]; - - const workspaceSnippetPicks: SnippetPick[] = []; - for (const folder of workspaceService.getWorkspace().folders) { - workspaceSnippetPicks.push({ - scope: nls.localize('new.workspace_scope', "{0} workspace", folder.name), - label: nls.localize('new.folder', "New Snippets file for '{0}'...", folder.name), - uri: folder.toResource('.vscode') +registerAction2(class ConfigureSnippets extends Action2 { + + constructor() { + super({ + id: 'workbench.action.openSnippets', + title: { + value: nls.localize('openSnippet.label', "Configure User Snippets"), + original: 'Configure User Snippets' + }, + shortTitle: { + value: nls.localize('userSnippets', "User Snippets"), + mnemonicTitle: nls.localize({ key: 'miOpenSnippets', comment: ['&& denotes a mnemonic'] }, "User &&Snippets"), + original: 'User Snippets' + }, + menu: [ + { id: MenuId.CommandPalette }, + { id: MenuId.MenubarPreferencesMenu, group: '3_snippets', order: 1 }, + { id: MenuId.GlobalActivity, group: '3_snippets', order: 1 }, + ] }); } - if (existing.length > 0) { - existing.unshift({ type: 'separator', label: nls.localize('group.global', "Existing Snippets") }); - existing.push({ type: 'separator', label: nls.localize('new.global.sep', "New Snippets") }); - } else { - existing.push({ type: 'separator', label: nls.localize('new.global.sep', "New Snippets") }); - } - - const pick = await quickInputService.pick(([] as QuickPickInput[]).concat(existing, globalSnippetPicks, workspaceSnippetPicks, picks.future), { - placeHolder: nls.localize('openSnippet.pickLanguage', "Select Snippets File or Create Snippets"), - matchOnDescription: true - }); + async run(accessor: ServicesAccessor, ...args: any[]): Promise { + + const snippetService = accessor.get(ISnippetsService); + const quickInputService = accessor.get(IQuickInputService); + const opener = accessor.get(IOpenerService); + const languageService = accessor.get(ILanguageService); + const envService = accessor.get(IEnvironmentService); + const workspaceService = accessor.get(IWorkspaceContextService); + const fileService = accessor.get(IFileService); + const textFileService = accessor.get(ITextFileService); + + const picks = await computePicks(snippetService, envService, languageService); + const existing: QuickPickInput[] = picks.existing; + + type SnippetPick = IQuickPickItem & { uri: URI } & { scope: string }; + const globalSnippetPicks: SnippetPick[] = [{ + scope: nls.localize('new.global_scope', 'global'), + label: nls.localize('new.global', "New Global Snippets file..."), + uri: envService.snippetsHome + }]; + + const workspaceSnippetPicks: SnippetPick[] = []; + for (const folder of workspaceService.getWorkspace().folders) { + workspaceSnippetPicks.push({ + scope: nls.localize('new.workspace_scope', "{0} workspace", folder.name), + label: nls.localize('new.folder', "New Snippets file for '{0}'...", folder.name), + uri: folder.toResource('.vscode') + }); + } - if (globalSnippetPicks.indexOf(pick as SnippetPick) >= 0) { - return createSnippetFile((pick as SnippetPick).scope, (pick as SnippetPick).uri, quickInputService, fileService, textFileService, opener); - } else if (workspaceSnippetPicks.indexOf(pick as SnippetPick) >= 0) { - return createSnippetFile((pick as SnippetPick).scope, (pick as SnippetPick).uri, quickInputService, fileService, textFileService, opener); - } else if (ISnippetPick.is(pick)) { - if (pick.hint) { - await createLanguageSnippetFile(pick, fileService, textFileService); + if (existing.length > 0) { + existing.unshift({ type: 'separator', label: nls.localize('group.global', "Existing Snippets") }); + existing.push({ type: 'separator', label: nls.localize('new.global.sep', "New Snippets") }); + } else { + existing.push({ type: 'separator', label: nls.localize('new.global.sep', "New Snippets") }); } - return opener.open(pick.filepath); - } -}); -MenuRegistry.appendMenuItem(MenuId.CommandPalette, { - command: { - id, - title: { value: nls.localize('openSnippet.label', "Configure User Snippets"), original: 'Configure User Snippets' }, - category: { value: nls.localize('preferences', "Preferences"), original: 'Preferences' } - } -}); + const pick = await quickInputService.pick(([] as QuickPickInput[]).concat(existing, globalSnippetPicks, workspaceSnippetPicks, picks.future), { + placeHolder: nls.localize('openSnippet.pickLanguage', "Select Snippets File or Create Snippets"), + matchOnDescription: true + }); -MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, { - group: '3_snippets', - command: { - id, - title: nls.localize({ key: 'miOpenSnippets', comment: ['&& denotes a mnemonic'] }, "User &&Snippets") - }, - order: 1 -}); + if (globalSnippetPicks.indexOf(pick as SnippetPick) >= 0) { + return createSnippetFile((pick as SnippetPick).scope, (pick as SnippetPick).uri, quickInputService, fileService, textFileService, opener); + } else if (workspaceSnippetPicks.indexOf(pick as SnippetPick) >= 0) { + return createSnippetFile((pick as SnippetPick).scope, (pick as SnippetPick).uri, quickInputService, fileService, textFileService, opener); + } else if (ISnippetPick.is(pick)) { + if (pick.hint) { + await createLanguageSnippetFile(pick, fileService, textFileService); + } + return opener.open(pick.filepath); + } -MenuRegistry.appendMenuItem(MenuId.GlobalActivity, { - group: '3_snippets', - command: { - id, - title: nls.localize('userSnippets', "User Snippets") - }, - order: 1 + } }); -- cgit v1.2.3 From 2337d8b5dca7d0cea1a0fe70d3dee0d75ecb4858 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 2 May 2022 16:40:25 +0200 Subject: fix #146749 --- src/vs/workbench/contrib/extensions/browser/extensionsActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index ad81be89e2b..dd69b73511d 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -601,7 +601,7 @@ export abstract class InstallInOtherServerAction extends ExtensionAction { this.extensionsWorkbenchService.open(this.extension); alert(localize('installExtensionStart', "Installing extension {0} started. An editor is now open with more details on this extension", this.extension.displayName)); if (this.extension.gallery) { - await this.server.extensionManagementService.installFromGallery(this.extension.gallery); + await this.server.extensionManagementService.installFromGallery(this.extension.gallery, { installPreReleaseVersion: this.extension.local?.preRelease }); } else { const vsix = await this.extension.server!.extensionManagementService.zip(this.extension.local!); await this.server.extensionManagementService.install(vsix); -- cgit v1.2.3 From 2785ac4f7117d8cd3086ffd5ac13628963d712c7 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Mon, 2 May 2022 10:07:25 -0700 Subject: fix #147603. Enable selecting line on line number. (#148459) --- src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts | 1 - 1 file changed, 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 5f76bc5718f..20ea78a5058 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -101,7 +101,6 @@ export class BaseCellEditorOptions extends Disposable implements IBaseCellEditor }, renderLineHighlightOnlyWhenFocus: true, overviewRulerLanes: 0, - selectOnLineNumbers: false, lineNumbers: 'off', lineDecorationsWidth: 0, folding: true, -- cgit v1.2.3 From b033e551c50f32a116199d9b942e8724225785a6 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Mon, 2 May 2022 21:25:18 +0200 Subject: Fix #147036 --- src/vs/workbench/contrib/scm/browser/activity.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/scm/browser/activity.ts b/src/vs/workbench/contrib/scm/browser/activity.ts index 91629caa98b..38a53b72c60 100644 --- a/src/vs/workbench/contrib/scm/browser/activity.ts +++ b/src/vs/workbench/contrib/scm/browser/activity.ts @@ -149,7 +149,8 @@ export class SCMStatusController implements IWorkbenchContribution { : repository.provider.label; const disposables = new DisposableStore(); - for (const command of commands) { + for (let index = 0; index < commands.length; index++) { + const command = commands[index]; const tooltip = `${label}${command.tooltip ? ` - ${command.tooltip}` : ''}`; let ariaLabel = stripIcons(command.title).trim(); @@ -161,7 +162,7 @@ export class SCMStatusController implements IWorkbenchContribution { ariaLabel: `${ariaLabel}${command.tooltip ? ` - ${command.tooltip}` : ''}`, tooltip, command: command.id ? command : undefined - }, 'status.scm', MainThreadStatusBarAlignment.LEFT, 10000)); + }, `status.scm.${index}`, MainThreadStatusBarAlignment.LEFT, 10000)); } this.statusBarDisposable = disposables; -- cgit v1.2.3 From 57479a5f6be520ada8517ecbbca6a982b1f80ff3 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Mon, 2 May 2022 12:34:13 -0700 Subject: Always suggest the only preferred kernel. (#148576) --- .../contrib/notebook/browser/notebookKernelServiceImpl.ts | 11 ++++++++++- .../browser/viewParts/notebookKernelActionViewItem.ts | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts index 1f2e2e72032..3a14f27d0ff 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts @@ -196,7 +196,16 @@ export class NotebookKernelService extends Disposable implements INotebookKernel getSelectedOrSuggestedKernel(notebook: INotebookTextModel): INotebookKernel | undefined { const info = this.getMatchingKernel(notebook); - return info.selected ?? (info.all.length === 1 ? info.all[0] : undefined); + if (info.selected) { + return info.selected; + } + + const preferred = info.all.filter(kernel => this._kernels.get(kernel.id)?.notebookPriorities.get(notebook.uri) === 2 /* vscode.NotebookControllerPriority.Preferred */); + if (preferred.length === 1) { + return preferred[0]; + } + + return info.all.length === 1 ? info.all[0] : undefined; } // default kernel for notebookType diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts index ed9098ad49d..e5814ce98ec 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts @@ -68,7 +68,7 @@ export class NotebooKernelActionViewItem extends ActionViewItem { private _updateActionFromKernelInfo(info: INotebookKernelMatchResult): void { this._kernelDisposable.clear(); this._action.enabled = true; - const selectedOrSuggested = info.selected ?? ((info.all.length === 1 && info.suggestions.length === 1 && info.suggestions[0].type === NotebookKernelType.Resolved) ? info.suggestions[0] : undefined); + const selectedOrSuggested = info.selected ?? ((info.suggestions.length === 1 && info.suggestions[0].type === NotebookKernelType.Resolved) ? info.suggestions[0] : undefined); if (selectedOrSuggested) { // selected or suggested kernel this._action.label = selectedOrSuggested.label; -- cgit v1.2.3 From 52ff0231ad4895a7948a5c180826c7509dcc3d74 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Mon, 2 May 2022 14:10:45 -0700 Subject: use ?? (#148577) --- src/vs/workbench/contrib/terminal/browser/terminalInstance.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index c3c037859a7..3a72c0e81b7 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -1154,7 +1154,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { const textAsHtml = await xterm.getSelectionAsHtml(command); function listener(e: any) { if (!e.clipboardData.types.includes('text/plain')) { - e.clipboardData.setData('text/plain', command?.getOutput()); + e.clipboardData.setData('text/plain', command?.getOutput() ?? ''); } e.clipboardData.setData('text/html', textAsHtml); e.preventDefault(); -- cgit v1.2.3 From c0f7f2af791cfad34fd01c00ff5abd85d6f03954 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Mon, 2 May 2022 14:23:36 -0700 Subject: clean up simple find widget (#148575) --- .../codeEditor/browser/find/simpleFindWidget.ts | 42 +++++++++++----------- .../contrib/terminal/browser/terminalFindWidget.ts | 2 +- .../contrib/webview/browser/webviewFindWidget.ts | 6 ++-- 3 files changed, 26 insertions(+), 24 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts index 514a9c59c4c..8d08748fbd8 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts @@ -54,15 +54,15 @@ export abstract class SimpleFindWidget extends Widget { private _foundMatch: boolean = false; constructor( - @IContextViewService private readonly _contextViewService: IContextViewService, - @IContextKeyService contextKeyService: IContextKeyService, - private readonly _state: FindReplaceState = new FindReplaceState(), - private readonly _options: IFindOptions, - private readonly _keybindingService?: IKeybindingService + readonly state: FindReplaceState = new FindReplaceState(), + options: IFindOptions, + contextViewService: IContextViewService, + contextKeyService: IContextKeyService, + private readonly _keybindingService: IKeybindingService ) { super(); - this._findInput = this._register(new ContextScopedFindInput(null, this._contextViewService, { + this._findInput = this._register(new ContextScopedFindInput(null, contextViewService, { label: NLS_FIND_INPUT_LABEL, placeholder: NLS_FIND_INPUT_PLACEHOLDER, validation: (value: string): InputBoxMessage | null => { @@ -78,18 +78,18 @@ export abstract class SimpleFindWidget extends Widget { return { content: e.message }; } }, - appendCaseSensitiveLabel: _options.appendCaseSensitiveLabel && _options.type === 'Terminal' ? this._getKeybinding(TerminalCommandId.ToggleFindCaseSensitive) : undefined, - appendRegexLabel: _options.appendRegexLabel && _options.type === 'Terminal' ? this._getKeybinding(TerminalCommandId.ToggleFindRegex) : undefined, - appendWholeWordsLabel: _options.appendWholeWordsLabel && _options.type === 'Terminal' ? this._getKeybinding(TerminalCommandId.ToggleFindWholeWord) : undefined - }, contextKeyService, _options.showOptionButtons)); + appendCaseSensitiveLabel: options.appendCaseSensitiveLabel && options.type === 'Terminal' ? this._getKeybinding(TerminalCommandId.ToggleFindCaseSensitive) : undefined, + appendRegexLabel: options.appendRegexLabel && options.type === 'Terminal' ? this._getKeybinding(TerminalCommandId.ToggleFindRegex) : undefined, + appendWholeWordsLabel: options.appendWholeWordsLabel && options.type === 'Terminal' ? this._getKeybinding(TerminalCommandId.ToggleFindWholeWord) : undefined + }, contextKeyService, options.showOptionButtons)); // Find History with update delayer this._updateHistoryDelayer = new Delayer(500); this._register(this._findInput.onInput(async (e) => { - if (!_options.checkImeCompletionState || !this._findInput.isImeSessionInProgress) { + if (!options.checkImeCompletionState || !this._findInput.isImeSessionInProgress) { this._foundMatch = this._onInputChanged(); - if (this._options.showResultCount) { + if (options.showResultCount) { await this.updateResultCount(); } this.updateButtons(this._foundMatch); @@ -98,22 +98,22 @@ export abstract class SimpleFindWidget extends Widget { } })); - this._findInput.setRegex(!!this._state.isRegex); - this._findInput.setCaseSensitive(!!this._state.matchCase); - this._findInput.setWholeWords(!!this._state.wholeWord); + this._findInput.setRegex(!!state.isRegex); + this._findInput.setCaseSensitive(!!state.matchCase); + this._findInput.setWholeWords(!!state.wholeWord); this._register(this._findInput.onDidOptionChange(() => { - this._state.change({ + state.change({ isRegex: this._findInput.getRegex(), wholeWord: this._findInput.getWholeWords(), matchCase: this._findInput.getCaseSensitive() }, true); })); - this._register(this._state.onFindReplaceStateChange(() => { - this._findInput.setRegex(this._state.isRegex); - this._findInput.setWholeWords(this._state.wholeWord); - this._findInput.setCaseSensitive(this._state.matchCase); + this._register(state.onFindReplaceStateChange(() => { + this._findInput.setRegex(state.isRegex); + this._findInput.setWholeWords(state.wholeWord); + this._findInput.setCaseSensitive(state.matchCase); this.findFirst(); })); @@ -173,7 +173,7 @@ export abstract class SimpleFindWidget extends Widget { event.stopPropagation(); })); - if (_options?.showResultCount) { + if (options?.showResultCount) { this._domNode.classList.add('result-count'); this._register(this._findInput.onDidChange(() => { this.updateResultCount(); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts b/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts index a12db0f881b..4ba93e51fb3 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts @@ -29,7 +29,7 @@ export class TerminalFindWidget extends SimpleFindWidget { @IThemeService private readonly _themeService: IThemeService, @IConfigurationService private readonly _configurationService: IConfigurationService ) { - super(_contextViewService, _contextKeyService, findState, { showOptionButtons: true, showResultCount: true, type: 'Terminal' }, keybindingService); + super(findState, { showOptionButtons: true, showResultCount: true, type: 'Terminal' }, _contextViewService, _contextKeyService, keybindingService); this._register(findState.onFindReplaceStateChange(() => { this.show(); diff --git a/src/vs/workbench/contrib/webview/browser/webviewFindWidget.ts b/src/vs/workbench/contrib/webview/browser/webviewFindWidget.ts index e7bad42e252..58841297621 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewFindWidget.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewFindWidget.ts @@ -6,6 +6,7 @@ import { Event } from 'vs/base/common/event'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { SimpleFindWidget } from 'vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget'; import { KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_FOCUSED } from 'vs/workbench/contrib/webview/browser/webview'; @@ -29,9 +30,10 @@ export class WebviewFindWidget extends SimpleFindWidget { constructor( private readonly _delegate: WebviewFindDelegate, @IContextViewService contextViewService: IContextViewService, - @IContextKeyService contextKeyService: IContextKeyService + @IContextKeyService contextKeyService: IContextKeyService, + @IKeybindingService keybindingService: IKeybindingService ) { - super(contextViewService, contextKeyService, undefined, { showOptionButtons: false, checkImeCompletionState: _delegate.checkImeCompletionState }); + super(undefined, { showOptionButtons: false, checkImeCompletionState: _delegate.checkImeCompletionState }, contextViewService, contextKeyService, keybindingService); this._findWidgetFocused = KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_FOCUSED.bindTo(contextKeyService); this._register(_delegate.hasFindResult(hasResult => { -- cgit v1.2.3 From a164020c9729eea04c2aa5006d4022ed4453ce2f Mon Sep 17 00:00:00 2001 From: SteVen Batten <6561887+sbatten@users.noreply.github.com> Date: Mon, 2 May 2022 16:14:34 -0700 Subject: adding gdpr comments for owned events (#148595) --- .../workspace/browser/workspace.contribution.ts | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts b/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts index 714d83dc166..1575fbf2118 100644 --- a/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts +++ b/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts @@ -761,7 +761,9 @@ class WorkspaceTrustTelemetryContribution extends Disposable implements IWorkben const disabledByCliFlag = this.environmentService.disableWorkspaceTrust; type WorkspaceTrustDisabledEventClassification = { - reason: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' }; + owner: 'sbatten'; + comment: 'Logged when workspace trust is disabled'; + reason: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The reason workspace trust is disabled. e.g. cli or setting' }; }; type WorkspaceTrustDisabledEvent = { @@ -775,7 +777,9 @@ class WorkspaceTrustTelemetryContribution extends Disposable implements IWorkben } type WorkspaceTrustInfoEventClassification = { - trustedFoldersCount: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true }; + owner: 'sbatten'; + comment: 'Information about the workspaces trusted on the machine'; + trustedFoldersCount: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'The number of trusted folders on the machine' }; }; type WorkspaceTrustInfoEvent = { @@ -798,8 +802,10 @@ class WorkspaceTrustTelemetryContribution extends Disposable implements IWorkben }; type WorkspaceTrustStateChangedEventClassification = { - workspaceId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' }; - isTrusted: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true }; + owner: 'sbatten'; + comment: 'Logged when the workspace transitions between trusted and restricted modes'; + workspaceId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'An id of the workspace' }; + isTrusted: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'true if the workspace is trusted' }; }; this.telemetryService.publicLog2('workspaceTrustStateChanged', { @@ -809,9 +815,11 @@ class WorkspaceTrustTelemetryContribution extends Disposable implements IWorkben if (isTrusted) { type WorkspaceTrustFolderInfoEventClassification = { - trustedFolderDepth: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true }; - workspaceFolderDepth: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true }; - delta: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true }; + owner: 'sbatten'; + comment: 'Some metrics on the trusted workspaces folder structure'; + trustedFolderDepth: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'The number of directories deep of the trusted path' }; + workspaceFolderDepth: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'The number of directories deep of the workspace path' }; + delta: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'The difference between the trusted path and the workspace path directories depth' }; }; type WorkspaceTrustFolderInfoEvent = { -- cgit v1.2.3 From e19f09713b6d674a200b293fb66fda0908e8a971 Mon Sep 17 00:00:00 2001 From: Jason Williams <936006+jasonwilliams@users.noreply.github.com> Date: Tue, 3 May 2022 08:56:24 +0100 Subject: Enable globs on tasks otherwise fallback to default - fixes #88106 (#141230) * use glob on tasks otherwise fallback to default * add support for test commands also * try to find one globbed task otherwise fallback to defaults * - get relativePath (but fallback to absolute if outside of workspace) - bring back json schema * Refactor and reduce duplicate code * remove glob, make isDefault a string or boolean * update taskConfig * - rebase - type updates - splitPerGroupType should check explicitly for true on isDefault - hygiene check * Remove task glob from API * Task group DTO updates * Make sure globs run ahead of default task if there's multiple globs matching * Style and name changes * More naming and code re-use * Glob doesn't work when only 1 glob match Co-authored-by: Alex Ross --- .../contrib/tasks/browser/abstractTaskService.ts | 195 ++++++++++++--------- .../contrib/tasks/common/jsonSchema_v2.ts | 4 +- .../contrib/tasks/common/taskConfiguration.ts | 6 +- src/vs/workbench/contrib/tasks/common/tasks.ts | 2 +- 4 files changed, 120 insertions(+), 87 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index 2e0f5f76e40..5c133362dcb 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -16,6 +16,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import * as Types from 'vs/base/common/types'; import { TerminateResponseCode } from 'vs/base/common/processes'; import { ValidationStatus, ValidationState } from 'vs/base/common/parsers'; +import * as glob from 'vs/base/common/glob'; import * as UUID from 'vs/base/common/uuid'; import * as Platform from 'vs/base/common/platform'; import { LRUCache, Touch } from 'vs/base/common/map'; @@ -69,7 +70,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { toFormattedString } from 'vs/base/common/jsonFormatter'; import { ITextModelService, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; -import { SaveReason } from 'vs/workbench/common/editor'; +import { EditorResourceAccessor, SaveReason } from 'vs/workbench/common/editor'; import { ITextEditorSelection, TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; @@ -2753,11 +2754,21 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer }); } - private splitPerGroupType(tasks: Task[]): { none: Task[]; defaults: Task[] } { + /** + * + * @param tasks - The tasks which need filtering from defaults and non-defaults + * @param defaultType - If there are globs want globs in the default list, otherwise only tasks with true + * @param taskGlobsInList - This tells splitPerGroupType to filter out globbed tasks (into default), otherwise fall back to boolean + * @returns + */ + private splitPerGroupType(tasks: Task[], taskGlobsInList: boolean = false): { none: Task[]; defaults: Task[] } { let none: Task[] = []; let defaults: Task[] = []; for (let task of tasks) { - if ((task.configurationProperties.group as TaskGroup).isDefault) { + // At this point (assuming taskGlobsInList is true) there are tasks with matching globs, so only put those in defaults + if (taskGlobsInList && typeof (task.configurationProperties.group as TaskGroup).isDefault === 'string') { + defaults.push(task); + } else if (!taskGlobsInList && (task.configurationProperties.group as TaskGroup).isDefault === true) { defaults.push(task); } else { none.push(task); @@ -2766,54 +2777,38 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer return { none, defaults }; } - private runBuildCommand(): void { + private runTaskGroupCommand(taskGroup: TaskGroup, strings: { + fetching: string; + select: string; + notFoundConfigure: string; + }, configure: () => void, legacyCommand: () => void): void { if (!this.canRunCommand()) { return; } if (this.schemaVersion === JsonSchemaVersion.V0_1_0) { - this.build(); + legacyCommand(); return; } let options: IProgressOptions = { location: ProgressLocation.Window, - title: nls.localize('TaskService.fetchingBuildTasks', 'Fetching build tasks...') + title: strings.fetching }; let promise = (async () => { - const buildTasks = await this._findWorkspaceTasksInGroup(TaskGroup.Build, false); - async function runSingleBuildTask(task: Task | undefined, problemMatcherOptions: ProblemMatcherRunOptions | undefined, that: AbstractTaskService) { + let taskGroupTasks: (Task | ConfiguringTask)[] = []; + + async function runSingleTask(task: Task | undefined, problemMatcherOptions: ProblemMatcherRunOptions | undefined, that: AbstractTaskService) { that.run(task, problemMatcherOptions, TaskRunSource.User).then(undefined, reason => { // eat the error, it has already been surfaced to the user and we don't care about it here }); } - if (buildTasks.length === 1) { - const buildTask = buildTasks[0]; - if (ConfiguringTask.is(buildTask)) { - return this.tryResolveTask(buildTask).then(resolvedTask => { - runSingleBuildTask(resolvedTask, undefined, this); - }); - } else { - runSingleBuildTask(buildTask, undefined, this); - return; - } - } - - return this.getTasksForGroup(TaskGroup.Build).then((tasks) => { - if (tasks.length > 0) { - let { none, defaults } = this.splitPerGroupType(tasks); - if (defaults.length === 1) { - runSingleBuildTask(defaults[0], undefined, this); - return; - } else if (defaults.length + none.length > 0) { - tasks = defaults.concat(none); - } - } + const chooseAndRunTask = (tasks: Task[]) => { this.showIgnoredFoldersMessage().then(() => { this.showQuickPick(tasks, - nls.localize('TaskService.pickBuildTask', 'Select the build task to run'), + strings.select, { - label: nls.localize('TaskService.noBuildTask', 'No build task to run found. Configure Build Task...'), + label: strings.notFoundConfigure, task: null }, true).then((entry) => { @@ -2822,66 +2817,104 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer return; } if (task === null) { - this.runConfigureDefaultBuildTask(); + configure(); return; } - runSingleBuildTask(task, { attachProblemMatcher: true }, this); + runSingleTask(task, { attachProblemMatcher: true }, this); }); }); - }); - })(); - this.progressService.withProgress(options, () => promise); - } + }; - private runTestCommand(): void { - if (!this.canRunCommand()) { - return; - } - if (this.schemaVersion === JsonSchemaVersion.V0_1_0) { - this.runTest(); - return; - } - let options: IProgressOptions = { - location: ProgressLocation.Window, - title: nls.localize('TaskService.fetchingTestTasks', 'Fetching test tasks...') - }; - let promise = this.getTasksForGroup(TaskGroup.Test).then((tasks) => { - if (tasks.length > 0) { - let { none, defaults } = this.splitPerGroupType(tasks); - if (defaults.length === 1) { - this.run(defaults[0], undefined, TaskRunSource.User).then(undefined, reason => { - // eat the error, it has already been surfaced to the user and we don't care about it here - }); - return; - } else if (defaults.length + none.length > 0) { - tasks = defaults.concat(none); - } - } - this.showIgnoredFoldersMessage().then(() => { - this.showQuickPick(tasks, - nls.localize('TaskService.pickTestTask', 'Select the test task to run'), - { - label: nls.localize('TaskService.noTestTaskTerminal', 'No test task to run found. Configure Tasks...'), - task: null - }, true - ).then((entry) => { - let task: Task | undefined | null = entry ? entry.task : undefined; - if (task === undefined) { - return; + // First check for globs before checking for the default tasks of the task group + const absoluteURI = EditorResourceAccessor.getOriginalUri(this.editorService.activeEditor); + if (absoluteURI) { + const workspaceFolder = this.contextService.getWorkspaceFolder(absoluteURI); + // fallback to absolute path of the file if it is not in a workspace or relative path cannot be found + const relativePath = workspaceFolder?.uri ? (resources.relativePath(workspaceFolder.uri, absoluteURI) ?? absoluteURI.path) : absoluteURI.path; + + taskGroupTasks = await this._findWorkspaceTasks((task) => { + const taskGroup = task.configurationProperties.group; + if (taskGroup && typeof taskGroup !== 'string' && typeof taskGroup.isDefault === 'string') { + return (taskGroup._id === taskGroup._id && glob.match(taskGroup.isDefault, relativePath)); } - if (task === null) { - this.runConfigureTasks(); - return; + + return false; + }); + } + + const handleMultipleTasks = (areGlobTasks: boolean) => { + return this.getTasksForGroup(taskGroup).then((tasks) => { + if (tasks.length > 0) { + // If we're dealing with tasks that were chosen because of a glob match, + // then put globs in the defaults and everything else in none + let { none, defaults } = this.splitPerGroupType(tasks, areGlobTasks); + if (defaults.length === 1) { + runSingleTask(defaults[0], undefined, this); + return; + } else if (defaults.length + none.length > 0) { + tasks = defaults.concat(none); + } } - this.run(task, undefined, TaskRunSource.User).then(undefined, reason => { - // eat the error, it has already been surfaced to the user and we don't care about it here - }); + + // At this this point there are multiple tasks. + chooseAndRunTask(tasks); }); - }); - }); + }; + + const resolveTaskAndRun = (taskGroupTask: Task | ConfiguringTask) => { + if (ConfiguringTask.is(taskGroupTask)) { + this.tryResolveTask(taskGroupTask).then(resolvedTask => { + runSingleTask(resolvedTask, undefined, this); + }); + } else { + runSingleTask(taskGroupTask, undefined, this); + } + }; + + // A single default glob task was returned, just run it directly + if (taskGroupTasks.length === 1) { + return resolveTaskAndRun(taskGroupTasks[0]); + } + + // If there's multiple globs that match we want to show the quick picker for those tasks + // We will need to call splitPerGroupType putting globs in defaults and the remaining tasks in none. + // We don't need to carry on after here + if (taskGroupTasks.length > 1) { + return handleMultipleTasks(true); + } + + // If no globs are found or matched fallback to checking for default tasks of the task group + if (!taskGroupTasks.length) { + taskGroupTasks = await this._findWorkspaceTasksInGroup(taskGroup, false); + } + + // A single default task was returned, just run it directly + if (taskGroupTasks.length === 1) { + return resolveTaskAndRun(taskGroupTasks[0]); + } + + // Multiple default tasks returned, show the quickPicker + return handleMultipleTasks(false); + })(); this.progressService.withProgress(options, () => promise); } + private runBuildCommand(): void { + return this.runTaskGroupCommand(TaskGroup.Build, { + fetching: nls.localize('TaskService.fetchingBuildTasks', 'Fetching build tasks...'), + select: nls.localize('TaskService.pickBuildTask', 'Select the build task to run'), + notFoundConfigure: nls.localize('TaskService.noBuildTask', 'No build task to run found. Configure Build Task...') + }, this.runConfigureDefaultBuildTask, this.build); + } + + private runTestCommand(): void { + return this.runTaskGroupCommand(TaskGroup.Test, { + fetching: nls.localize('TaskService.fetchingTestTasks', 'Fetching test tasks...'), + select: nls.localize('TaskService.pickTestTask', 'Select the test task to run'), + notFoundConfigure: nls.localize('TaskService.noTestTaskTerminal', 'No test task to run found. Configure Tasks...') + }, this.runConfigureDefaultTestTask, this.runTest); + } + private runTerminateCommand(arg?: any): void { if (!this.canRunCommand()) { return; diff --git a/src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts b/src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts index c3d81ff6df0..f0ba5e9fa63 100644 --- a/src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts +++ b/src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts @@ -192,9 +192,9 @@ const group: IJSONSchema = { properties: { kind: groupStrings, isDefault: { - type: 'boolean', + type: ['boolean', 'string'], default: false, - description: nls.localize('JsonSchema.tasks.group.isDefault', 'Defines if this task is the default task in the group.') + description: nls.localize('JsonSchema.tasks.group.isDefault', 'Defines if this task is the default task in the group, or a glob to match the file which should trigger this task.') } } }, diff --git a/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts b/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts index 7ab00229e89..9c6f0ba9e34 100644 --- a/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts +++ b/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts @@ -282,7 +282,7 @@ export interface CommandProperties extends BaseCommandProperties { export interface GroupKind { kind?: string; - isDefault?: boolean; + isDefault?: boolean | string; } export interface ConfigurationProperties { @@ -1245,7 +1245,7 @@ export namespace GroupKind { return { _id: external, isDefault: false }; } else if (Types.isString(external.kind) && Tasks.TaskGroup.is(external.kind)) { let group: string = external.kind; - let isDefault: boolean = !!external.isDefault; + let isDefault: boolean | string = Types.isUndefined(external.isDefault) ? false : external.isDefault; return { _id: group, isDefault }; } @@ -1260,7 +1260,7 @@ export namespace GroupKind { } return { kind: group._id, - isDefault: group.isDefault + isDefault: group.isDefault, }; } } diff --git a/src/vs/workbench/contrib/tasks/common/tasks.ts b/src/vs/workbench/contrib/tasks/common/tasks.ts index cb475cae0ee..1e7e42b6c81 100644 --- a/src/vs/workbench/contrib/tasks/common/tasks.ts +++ b/src/vs/workbench/contrib/tasks/common/tasks.ts @@ -393,7 +393,7 @@ export namespace TaskGroup { export interface TaskGroup { _id: string; - isDefault?: boolean; + isDefault?: boolean | string; } export const enum TaskScope { -- cgit v1.2.3 From b802077fea580c268944a27286b2a6ad4a63ef96 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 3 May 2022 15:45:56 +0200 Subject: Comment loss when clicking "Go to review" (#148630) Fixes #148629 --- src/vs/workbench/contrib/comments/browser/commentReply.ts | 1 - 1 file changed, 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/comments/browser/commentReply.ts b/src/vs/workbench/contrib/comments/browser/commentReply.ts index 6b9c90cc2ba..cf2e81a3bb9 100644 --- a/src/vs/workbench/contrib/comments/browser/commentReply.ts +++ b/src/vs/workbench/contrib/comments/browser/commentReply.ts @@ -275,7 +275,6 @@ export class CommentReply extends Disposable { } private hideReplyArea() { - this.commentEditor.setValue(''); this.commentEditor.getDomNode()!.style.outline = ''; this._pendingComment = ''; this.form.classList.remove('expand'); -- cgit v1.2.3 From e6b17bd4a636fe625c2f93ec4b1df438e95adcfd Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Tue, 3 May 2022 07:13:05 -0700 Subject: remove readonly (#148589) --- src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts index 8d08748fbd8..ff599441598 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts @@ -54,7 +54,7 @@ export abstract class SimpleFindWidget extends Widget { private _foundMatch: boolean = false; constructor( - readonly state: FindReplaceState = new FindReplaceState(), + state: FindReplaceState = new FindReplaceState(), options: IFindOptions, contextViewService: IContextViewService, contextKeyService: IContextKeyService, -- cgit v1.2.3 From 322ee9dc4119f48648b1951009db63eedfeb4495 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 3 May 2022 16:16:15 +0200 Subject: return untyped editor input from saveAs (#148614) --- .../workbench/contrib/notebook/common/notebookCommon.ts | 5 ++--- .../contrib/notebook/common/notebookEditorInput.ts | 4 ++-- .../contrib/notebook/common/notebookEditorModel.ts | 15 +++++---------- .../notebook/test/browser/notebookEditorModel.test.ts | 6 ++---- 4 files changed, 11 insertions(+), 19 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 5f70d558da1..40b6b6a2074 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -25,8 +25,7 @@ import { IEditorModel } from 'vs/platform/editor/common/editor'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; import { UndoRedoGroup } from 'vs/platform/undoRedo/common/undoRedo'; -import { IRevertOptions, ISaveOptions } from 'vs/workbench/common/editor'; -import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { IRevertOptions, ISaveOptions, IUntypedEditorInput } from 'vs/workbench/common/editor'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; import { IWorkingCopyBackupMeta, IWorkingCopySaveEvent } from 'vs/workbench/services/workingCopy/common/workingCopy'; @@ -780,7 +779,7 @@ export interface INotebookEditorModel extends IEditorModel { hasAssociatedFilePath(): boolean; load(options?: INotebookLoadOptions): Promise; save(options?: ISaveOptions): Promise; - saveAs(target: URI): Promise; + saveAs(target: URI): Promise; revert(options?: IRevertOptions): Promise; } diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts index 6e28efdd088..b8cbd4985d0 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts @@ -124,7 +124,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { return this._editorModelReference.object.isDirty(); } - override async save(group: GroupIdentifier, options?: ISaveOptions): Promise { + override async save(group: GroupIdentifier, options?: ISaveOptions): Promise { if (this._editorModelReference) { if (this.hasCapability(EditorInputCapabilities.Untitled)) { @@ -139,7 +139,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { return undefined; } - override async saveAs(group: GroupIdentifier, options?: ISaveOptions): Promise { + override async saveAs(group: GroupIdentifier, options?: ISaveOptions): Promise { if (!this._editorModelReference) { return undefined; } diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts index 8938cff2e80..7cd345036a7 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts @@ -4,8 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { IRevertOptions, ISaveOptions } from 'vs/workbench/common/editor'; -import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { IRevertOptions, ISaveOptions, IUntypedEditorInput } from 'vs/workbench/common/editor'; import { EditorModel } from 'vs/workbench/common/editor/editorModel'; import { Emitter, Event } from 'vs/base/common/event'; import { ICellDto2, INotebookEditorModel, INotebookLoadOptions, IResolvedNotebookEditorModel, NotebookCellsChangeType, NotebookData, NotebookDocumentBackupData } from 'vs/workbench/contrib/notebook/common/notebookCommon'; @@ -28,8 +27,6 @@ import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/commo import { StoredFileWorkingCopyState, IStoredFileWorkingCopy, IStoredFileWorkingCopyModel, IStoredFileWorkingCopyModelContentChangedEvent, IStoredFileWorkingCopyModelFactory, IStoredFileWorkingCopySaveEvent } from 'vs/workbench/services/workingCopy/common/storedFileWorkingCopy'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { CancellationError } from 'vs/base/common/errors'; -import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { filter } from 'vs/base/common/objects'; import { IFileWorkingCopyManager } from 'vs/workbench/services/workingCopy/common/fileWorkingCopyManager'; import { IUntitledFileWorkingCopy, IUntitledFileWorkingCopyModel, IUntitledFileWorkingCopyModelContentChangedEvent, IUntitledFileWorkingCopyModelFactory } from 'vs/workbench/services/workingCopy/common/untitledFileWorkingCopy'; @@ -59,7 +56,6 @@ export class ComplexNotebookEditorModel extends EditorModel implements INotebook readonly resource: URI, readonly viewType: string, private readonly _contentProvider: INotebookContentProvider, - @IInstantiationService private readonly _instantiationService: IInstantiationService, @INotebookService private readonly _notebookService: INotebookService, @IWorkingCopyService private readonly _workingCopyService: IWorkingCopyService, @IWorkingCopyBackupService private readonly _workingCopyBackupService: IWorkingCopyBackupService, @@ -393,7 +389,7 @@ export class ComplexNotebookEditorModel extends EditorModel implements INotebook }); } - async saveAs(targetResource: URI): Promise { + async saveAs(targetResource: URI): Promise { if (!this.isResolved()) { return undefined; @@ -419,7 +415,7 @@ export class ComplexNotebookEditorModel extends EditorModel implements INotebook } this.setDirty(false); this._onDidSave.fire({}); - return this._instantiationService.createInstance(NotebookEditorInput, targetResource, this.viewType, {}); + return { resource: targetResource }; } private async _resolveStats(resource: URI) { @@ -462,7 +458,6 @@ export class SimpleNotebookEditorModel extends EditorModel implements INotebookE private readonly _hasAssociatedFilePath: boolean, readonly viewType: string, private readonly _workingCopyManager: IFileWorkingCopyManager, - @IInstantiationService private readonly _instantiationService: IInstantiationService, @IFileService private readonly _fileService: IFileService ) { super(); @@ -547,14 +542,14 @@ export class SimpleNotebookEditorModel extends EditorModel implements INotebookE return this; } - async saveAs(target: URI): Promise { + async saveAs(target: URI): Promise { const newWorkingCopy = await this._workingCopyManager.saveAs(this.resource, target); if (!newWorkingCopy) { return undefined; } // this is a little hacky because we leave the new working copy alone. BUT // the newly created editor input will pick it up and claim ownership of it. - return this._instantiationService.createInstance(NotebookEditorInput, newWorkingCopy.resource, this.viewType, {}); + return { resource: newWorkingCopy.resource }; } private static _isStoredFileWorkingCopy(candidate?: IStoredFileWorkingCopy | IUntitledFileWorkingCopy): candidate is IStoredFileWorkingCopy { diff --git a/src/vs/workbench/contrib/notebook/test/browser/notebookEditorModel.test.ts b/src/vs/workbench/contrib/notebook/test/browser/notebookEditorModel.test.ts index d71a25076b3..124729d29b4 100644 --- a/src/vs/workbench/contrib/notebook/test/browser/notebookEditorModel.test.ts +++ b/src/vs/workbench/contrib/notebook/test/browser/notebookEditorModel.test.ts @@ -10,7 +10,6 @@ import { isEqual } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { mock } from 'vs/base/test/common/mock'; import { IFileService } from 'vs/platform/files/common/files'; -import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { ILabelService } from 'vs/platform/label/common/label'; import { NullLogService } from 'vs/platform/log/common/log'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -187,7 +186,6 @@ suite('NotebookFileWorkingCopyModel', function () { suite('ComplexNotebookEditorModel', function () { - const instaService = new InstantiationService(); const notebokService = new class extends mock() { }; const backupService = new class extends mock() { }; const notificationService = new class extends mock() { }; @@ -214,8 +212,8 @@ suite('ComplexNotebookEditorModel', function () { } }; - new ComplexNotebookEditorModel(r1, 'fff', notebookDataProvider, instaService, notebokService, workingCopyService, backupService, fileService, notificationService, new NullLogService(), untitledTextEditorService, labelService); - new ComplexNotebookEditorModel(r2, 'fff', notebookDataProvider, instaService, notebokService, workingCopyService, backupService, fileService, notificationService, new NullLogService(), untitledTextEditorService, labelService); + new ComplexNotebookEditorModel(r1, 'fff', notebookDataProvider, notebokService, workingCopyService, backupService, fileService, notificationService, new NullLogService(), untitledTextEditorService, labelService); + new ComplexNotebookEditorModel(r2, 'fff', notebookDataProvider, notebokService, workingCopyService, backupService, fileService, notificationService, new NullLogService(), untitledTextEditorService, labelService); assert.strictEqual(copies.length, 2); assert.strictEqual(!isEqual(copies[0].resource, copies[1].resource), true); -- cgit v1.2.3 From 7e9564a49e2f43439a1b3c92404b0e1bd7e96068 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Tue, 3 May 2022 10:51:01 -0700 Subject: testing: hide ANSI color codes in test peeks (#148594) * testing: hide ANSI color codes in test peeks Fixes #148397 * refactor: name test message type enum more appropriately --- .../contrib/testing/browser/testingOutputPeek.ts | 8 +++++--- src/vs/workbench/contrib/testing/browser/theme.ts | 2 +- src/vs/workbench/contrib/testing/common/testResult.ts | 2 +- src/vs/workbench/contrib/testing/common/testTypes.ts | 10 +++++----- .../contrib/testing/common/testingContentProvider.ts | 15 +++++++++------ 5 files changed, 21 insertions(+), 16 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts index 71b7930768c..979dc41d729 100644 --- a/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts +++ b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts @@ -25,7 +25,7 @@ import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { Lazy } from 'vs/base/common/lazy'; import { Disposable, DisposableStore, IDisposable, IReference, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { clamp } from 'vs/base/common/numbers'; -import { count } from 'vs/base/common/strings'; +import { count, removeAnsiEscapeCodes } from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; import { ICodeEditor, IDiffEditorConstructionOptions, isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorAction2 } from 'vs/editor/browser/editorExtensions'; @@ -1162,7 +1162,7 @@ class TestMessageElement implements ITreeElement { public readonly taskIndex: number, public readonly messageIndex: number, ) { - const { message, location } = test.tasks[taskIndex].messages[messageIndex]; + const { type, message, location } = test.tasks[taskIndex].messages[messageIndex]; this.location = location; this.uri = this.context = buildTestUri({ @@ -1175,7 +1175,9 @@ class TestMessageElement implements ITreeElement { this.id = this.uri.toString(); - const asPlaintext = renderStringAsPlaintext(message); + const asPlaintext = type === TestMessageType.Output + ? removeAnsiEscapeCodes(message) + : renderStringAsPlaintext(message); const lines = count(asPlaintext.trimRight(), '\n'); this.label = firstLine(asPlaintext); if (lines > 0) { diff --git a/src/vs/workbench/contrib/testing/browser/theme.ts b/src/vs/workbench/contrib/testing/browser/theme.ts index dcd6e2bb567..2a8d95b8665 100644 --- a/src/vs/workbench/contrib/testing/browser/theme.ts +++ b/src/vs/workbench/contrib/testing/browser/theme.ts @@ -91,7 +91,7 @@ export const testMessageSeverityColors: { localize('testing.message.error.marginBackground', 'Margin color beside error messages shown inline in the editor.') ), }, - [TestMessageType.Info]: { + [TestMessageType.Output]: { decorationForeground: registerColor( 'testing.message.info.decorationForeground', { dark: transparent(editorForeground, 0.5), light: transparent(editorForeground, 0.5), hcDark: transparent(editorForeground, 0.5), hcLight: transparent(editorForeground, 0.5) }, diff --git a/src/vs/workbench/contrib/testing/common/testResult.ts b/src/vs/workbench/contrib/testing/common/testResult.ts index dce023d7d60..368d43988d7 100644 --- a/src/vs/workbench/contrib/testing/common/testResult.ts +++ b/src/vs/workbench/contrib/testing/common/testResult.ts @@ -321,7 +321,7 @@ export class LiveTestResult implements ITestResult { location, message: output.toString(), offset: this.output.offset, - type: TestMessageType.Info, + type: TestMessageType.Output, }; const index = this.mustGetTaskIndex(taskId); diff --git a/src/vs/workbench/contrib/testing/common/testTypes.ts b/src/vs/workbench/contrib/testing/common/testTypes.ts index 6f3e639ef90..29ae1628071 100644 --- a/src/vs/workbench/contrib/testing/common/testTypes.ts +++ b/src/vs/workbench/contrib/testing/common/testTypes.ts @@ -117,7 +117,7 @@ export namespace IRichLocation { export const enum TestMessageType { Error, - Info + Output } export interface ITestErrorMessage { @@ -156,7 +156,7 @@ export namespace ITestErrorMessage { export interface ITestOutputMessage { message: string; - type: TestMessageType.Info; + type: TestMessageType.Output; offset: number; location: IRichLocation | undefined; } @@ -165,20 +165,20 @@ export namespace ITestOutputMessage { export interface Serialized { message: string; offset: number; - type: TestMessageType.Info; + type: TestMessageType.Output; location: IRichLocation.Serialize | undefined; } export const serialize = (message: ITestOutputMessage): Serialized => ({ message: message.message, - type: TestMessageType.Info, + type: TestMessageType.Output, offset: message.offset, location: message.location && IRichLocation.serialize(message.location), }); export const deserialize = (message: Serialized): ITestOutputMessage => ({ message: message.message, - type: TestMessageType.Info, + type: TestMessageType.Output, offset: message.offset, location: message.location && IRichLocation.deserialize(message.location), }); diff --git a/src/vs/workbench/contrib/testing/common/testingContentProvider.ts b/src/vs/workbench/contrib/testing/common/testingContentProvider.ts index c93c0968a07..4ce00913d35 100644 --- a/src/vs/workbench/contrib/testing/common/testingContentProvider.ts +++ b/src/vs/workbench/contrib/testing/common/testingContentProvider.ts @@ -12,6 +12,7 @@ import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { TestMessageType } from 'vs/workbench/contrib/testing/common/testTypes'; import { parseTestUri, TestUriType, TEST_DATA_SCHEME } from 'vs/workbench/contrib/testing/common/testingUri'; import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; +import { removeAnsiEscapeCodes } from 'vs/base/common/strings'; /** * A content provider that returns various outputs for tests. This is used @@ -61,12 +62,14 @@ export class TestingContentProvider implements IWorkbenchContribution, ITextMode break; } case TestUriType.ResultMessage: { - const message = test.tasks[parsed.taskIndex].messages[parsed.messageIndex]?.message; - if (typeof message === 'string') { - text = message; - } else if (message) { - text = message.value; - language = this.languageService.createById('markdown'); + const message = test.tasks[parsed.taskIndex].messages[parsed.messageIndex]; + if (message) { + if (typeof message.message === 'string') { + text = message.type === TestMessageType.Output ? removeAnsiEscapeCodes(message.message) : message.message; + } else { + text = message.message.value; + language = this.languageService.createById('markdown'); + } } break; } -- cgit v1.2.3 From 758af40b557d0c599b4ba21cb35a1464fd3b6492 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Tue, 3 May 2022 15:14:04 -0700 Subject: on focusout, reset terminal focus context key (#148659) --- .../contrib/terminal/browser/terminalInstance.ts | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 3a72c0e81b7..9414adfc86a 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -1097,16 +1097,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { setTimeout(() => this._refreshSelectionContextKey(), 0); })); - this._register(dom.addDisposableListener(xterm.raw.textarea, 'focus', () => { - this._terminalFocusContextKey.set(true); - this._onDidFocus.fire(this); - })); - - this._register(dom.addDisposableListener(xterm.raw.textarea, 'blur', () => { - this._terminalFocusContextKey.reset(); - this._onDidBlur.fire(this); - this._refreshSelectionContextKey(); - })); + this._register(dom.addDisposableListener(xterm.raw.textarea, 'focus', () => this._setFocus(true))); + this._register(dom.addDisposableListener(xterm.raw.textarea, 'blur', () => this._setFocus(false))); + this._register(dom.addDisposableListener(xterm.raw.textarea, 'focusout', () => this._setFocus(false))); this._initDragAndDrop(container); @@ -1132,6 +1125,17 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } + private _setFocus(focused?: boolean): void { + if (focused) { + this._terminalFocusContextKey.set(true); + this._onDidFocus.fire(this); + } else { + this._terminalFocusContextKey.reset(); + this._onDidBlur.fire(this); + this._refreshSelectionContextKey(); + } + } + private _initDragAndDrop(container: HTMLElement) { this._dndObserver?.dispose(); const dndController = this._instantiationService.createInstance(TerminalInstanceDragAndDropController, container); -- cgit v1.2.3 From bf33c14a186121fbc2fc4633f0297a18d0f26ad9 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Tue, 3 May 2022 15:55:13 -0700 Subject: fix #146377 (#148666) --- .../contrib/terminal/browser/media/shellIntegration-bash.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib') diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh index 80d528804c0..0c5d62458d5 100755 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh @@ -109,15 +109,16 @@ __vsc_prompt_cmd_original() { IFS=' ' fi builtin read -ra ADDR <<<"$__vsc_original_prompt_command" - for ((i = 0; i < ${#ADDR[@]}; i++)); do - builtin eval ${ADDR[i]} - done if [[ ${__vsc_original_ifs+set} ]]; then IFS="$__vsc_original_ifs" unset __vsc_original_ifs else unset IFS fi + for ((i = 0; i < ${#ADDR[@]}; i++)); do + # unset IFS + builtin eval ${ADDR[i]} + done __vsc_precmd } -- cgit v1.2.3