diff --git a/build/yarn.lock b/build/yarn.lock index d0c7960a11e..d99ceffaadf 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -848,11 +848,11 @@ brace-expansion@^1.1.7: concat-map "0.0.1" braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" buffer-alloc-unsafe@^1.1.0: version "1.1.0" @@ -1371,10 +1371,10 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" diff --git a/cli/src/async_pipe.rs b/cli/src/async_pipe.rs index e9b710c1d68..78aed6fe3e7 100644 --- a/cli/src/async_pipe.rs +++ b/cli/src/async_pipe.rs @@ -227,7 +227,7 @@ impl hyper::server::accept::Accept for PollableAsyncListener { } } -/// Gets a random name for a pipe/socket on the paltform +/// Gets a random name for a pipe/socket on the platform pub fn get_socket_name() -> PathBuf { cfg_if::cfg_if! { if #[cfg(unix)] { diff --git a/cli/src/auth.rs b/cli/src/auth.rs index 67f1bfa6bc7..2d9162c5483 100644 --- a/cli/src/auth.rs +++ b/cli/src/auth.rs @@ -287,7 +287,7 @@ impl StorageImplementation for ThreadKeyringStorage { #[derive(Default)] struct KeyringStorage { - // keywring storage can be split into multiple entries due to entry length limits + // keyring storage can be split into multiple entries due to entry length limits // on Windows https://github.com/microsoft/vscode-cli/issues/358 entries: Vec, } diff --git a/cli/src/commands/args.rs b/cli/src/commands/args.rs index 79c4d3767a1..05e22e0cfb3 100644 --- a/cli/src/commands/args.rs +++ b/cli/src/commands/args.rs @@ -64,7 +64,7 @@ pub struct IntegratedCli { pub core: CliCore, } -/// Common CLI shared between intergated and standalone interfaces. +/// Common CLI shared between integrated and standalone interfaces. #[derive(Args, Debug, Default, Clone)] pub struct CliCore { /// One or more files, folders, or URIs to open. @@ -619,7 +619,7 @@ pub enum OutputFormat { #[derive(Args, Clone, Debug, Default)] pub struct ExistingTunnelArgs { /// Name you'd like to assign preexisting tunnel to use to connect the tunnel - /// Old option, new code sohuld just use `--name`. + /// Old option, new code should just use `--name`. #[clap(long, hide = true)] pub tunnel_name: Option, diff --git a/cli/src/constants.rs b/cli/src/constants.rs index 6f604e8876e..1e277a89d6a 100644 --- a/cli/src/constants.rs +++ b/cli/src/constants.rs @@ -13,7 +13,7 @@ use crate::options::Quality; pub const CONTROL_PORT: u16 = 31545; -/// Protocol version sent to clients. This can be used to indiciate new or +/// Protocol version sent to clients. This can be used to indicate new or /// changed capabilities that clients may wish to leverage. /// 1 - Initial protocol version /// 2 - Addition of `serve.compressed` property to control whether servermsg's diff --git a/package.json b/package.json index 49c83a768b7..ae706deebbc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.91.0", - "distro": "9cef7f933867933892cb3b591231ed071fe861a8", + "distro": "a08799837ca498c02f445ca7a896f446419af238", "author": { "name": "Microsoft Corporation" }, diff --git a/product.json b/product.json index d2d3bf7a361..27ae53fe16b 100644 --- a/product.json +++ b/product.json @@ -50,8 +50,8 @@ }, { "name": "ms-vscode.js-debug", - "version": "1.90.0", - "sha256": "1317dd7d1ac50641c1534a3e957ecbc94349f4fbd897acb916da11eea3208a66", + "version": "1.91.0", + "sha256": "53b99146c7fa280f00c74414e09721530c622bf3e5eac2c967ddfb9906b51c80", "repo": "https://github.com/microsoft/vscode-js-debug", "metadata": { "id": "25629058-ddac-4e17-abba-74678e126c5d", diff --git a/src/vs/base/browser/markdownRenderer.ts b/src/vs/base/browser/markdownRenderer.ts index 61e10f19359..265a57113f7 100644 --- a/src/vs/base/browser/markdownRenderer.ts +++ b/src/vs/base/browser/markdownRenderer.ts @@ -636,7 +636,7 @@ const plainTextRenderer = new Lazy((withCodeBlocks?: boolean) = const plainTextWithCodeBlocksRenderer = new Lazy(() => { const renderer = createRenderer(); renderer.code = (code: string): string => { - return '\n' + '```' + '\n' + code + '```' + '\n'; + return `\n\`\`\`\n${code}\n\`\`\`\n`; }; return renderer; }); @@ -768,8 +768,8 @@ function completeListItemPattern(list: marked.Tokens.List): marked.Tokens.List | const previousListItemsText = mergeRawTokenText(list.items.slice(0, -1)); - // Grabbing the `- ` or `1. ` off the list item because I can't find a better way to do this - const lastListItemLead = lastListItem.raw.match(/^(\s*(-|\d+\.) +)/)?.[0]; + // Grabbing the `- ` or `1. ` or `* ` off the list item because I can't find a better way to do this + const lastListItemLead = lastListItem.raw.match(/^(\s*(-|\d+\.|\*) +)/)?.[0]; if (!lastListItemLead) { // Is badly formatted return; diff --git a/src/vs/base/test/browser/markdownRenderer.test.ts b/src/vs/base/test/browser/markdownRenderer.test.ts index 81abf8c9c9e..4ea38c815c3 100644 --- a/src/vs/base/test/browser/markdownRenderer.test.ts +++ b/src/vs/base/test/browser/markdownRenderer.test.ts @@ -607,6 +607,15 @@ const y = 2; assert.deepStrictEqual(newTokens, completeTokens); }); + test(`incomplete ${name} in asterisk list`, () => { + const text = `* list item one\n* list item two and ${delimiter}text`; + const tokens = marked.lexer(text); + const newTokens = fillInIncompleteTokens(tokens); + + const completeTokens = marked.lexer(text + delimiter); + assert.deepStrictEqual(newTokens, completeTokens); + }); + test(`incomplete ${name} in numbered list`, () => { const text = `1. list item one\n2. list item two and ${delimiter}text`; const tokens = marked.lexer(text); diff --git a/src/vs/workbench/api/browser/mainThreadChatAgents2.ts b/src/vs/workbench/api/browser/mainThreadChatAgents2.ts index 0d63847dae5..35126b7998d 100644 --- a/src/vs/workbench/api/browser/mainThreadChatAgents2.ts +++ b/src/vs/workbench/api/browser/mainThreadChatAgents2.ts @@ -199,7 +199,8 @@ export class MainThreadChatAgents2 extends Disposable implements MainThreadChatA $updateAgent(handle: number, metadataUpdate: IExtensionChatAgentMetadata): void { const data = this._agents.get(handle); if (!data) { - throw new Error(`No agent with handle ${handle} registered`); + this._logService.error(`MainThreadChatAgents2#$updateAgent: No agent with handle ${handle} registered`); + return; } data.hasFollowups = metadataUpdate.hasFollowups; this._chatAgentService.updateAgent(data.id, revive(metadataUpdate)); diff --git a/src/vs/workbench/api/browser/mainThreadComments.ts b/src/vs/workbench/api/browser/mainThreadComments.ts index 2e342290e96..6bbeb159248 100644 --- a/src/vs/workbench/api/browser/mainThreadComments.ts +++ b/src/vs/workbench/api/browser/mainThreadComments.ts @@ -185,6 +185,7 @@ export class MainThreadCommentThread implements languages.CommentThread { public threadId: string, public resource: string, private _range: T | undefined, + comments: languages.Comment[] | undefined, private _canReply: boolean, private _isTemplate: boolean, public editorId?: string @@ -192,6 +193,8 @@ export class MainThreadCommentThread implements languages.CommentThread { this._isDisposed = false; if (_isTemplate) { this.comments = []; + } else if (comments) { + this._comments = comments; } } @@ -298,6 +301,7 @@ export class MainThreadCommentController implements ICommentController { threadId: string, resource: UriComponents, range: IRange | ICellRange | undefined, + comments: languages.Comment[], isTemplate: boolean, editorId?: string ): languages.CommentThread { @@ -308,6 +312,7 @@ export class MainThreadCommentController implements ICommentController { threadId, URI.revive(resource).toString(), range, + comments, true, isTemplate, editorId @@ -590,6 +595,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments threadId: string, resource: UriComponents, range: IRange | ICellRange | undefined, + comments: languages.Comment[], extensionId: ExtensionIdentifier, isTemplate: boolean, editorId?: string @@ -600,7 +606,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments return undefined; } - return provider.createCommentThread(extensionId.value, commentThreadHandle, threadId, resource, range, isTemplate, editorId); + return provider.createCommentThread(extensionId.value, commentThreadHandle, threadId, resource, range, comments, isTemplate, editorId); } $updateCommentThread(handle: number, diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 5785393c0e1..d810c7b892d 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -144,7 +144,7 @@ export interface MainThreadCommentsShape extends IDisposable { $registerCommentController(handle: number, id: string, label: string, extensionId: string): void; $unregisterCommentController(handle: number): void; $updateCommentControllerFeatures(handle: number, features: CommentProviderFeatures): void; - $createCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange | ICellRange | undefined, extensionId: ExtensionIdentifier, isTemplate: boolean, editorId?: string): languages.CommentThread | undefined; + $createCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange | ICellRange | undefined, comments: languages.Comment[], extensionId: ExtensionIdentifier, isTemplate: boolean, editorId?: string): languages.CommentThread | undefined; $updateCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, changes: CommentThreadChanges): void; $deleteCommentThread(handle: number, commentThreadHandle: number): void; $updateCommentingRanges(handle: number, resourceHints?: languages.CommentingRangeResourceHint): void; diff --git a/src/vs/workbench/api/common/extHostComments.ts b/src/vs/workbench/api/common/extHostComments.ts index 53b5176c25b..c84fb4782f9 100644 --- a/src/vs/workbench/api/common/extHostComments.ts +++ b/src/vs/workbench/api/common/extHostComments.ts @@ -424,6 +424,7 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo this._id, this._uri, extHostTypeConverter.Range.from(this._range), + this._comments.map(cmt => convertToDTOComment(this, cmt, this._commentsMap, this.extensionDescription)), extensionDescription.identifier, this._isTemplate, editorId @@ -436,9 +437,6 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo this.eventuallyUpdateCommentThread(); })); - // set up comments after ctor to batch update events. - this.comments = _comments; - this._localDisposables.push({ dispose: () => { proxy.$deleteCommentThread( diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts index 5a6574db112..b7d76a5a227 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts @@ -161,6 +161,7 @@ export class CancelAction extends Action2 { keybinding: { weight: KeybindingWeight.WorkbenchContrib, primary: KeyMod.CtrlCmd | KeyCode.Escape, + win: { primary: KeyMod.Alt | KeyCode.Backspace }, } }); } diff --git a/src/vs/workbench/contrib/codeEditor/browser/emptyTextEditorHint/emptyTextEditorHint.ts b/src/vs/workbench/contrib/codeEditor/browser/emptyTextEditorHint/emptyTextEditorHint.ts index c8a1443ab1e..327554fd781 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/emptyTextEditorHint/emptyTextEditorHint.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/emptyTextEditorHint/emptyTextEditorHint.ts @@ -34,6 +34,8 @@ import { SEARCH_RESULT_LANGUAGE_ID } from 'vs/workbench/services/search/common/s import { getDefaultHoverDelegate } from 'vs/base/browser/ui/hover/hoverDelegateFactory'; import { IHoverService } from 'vs/platform/hover/browser/hover'; import { ChatAgentLocation, IChatAgent, IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; const $ = dom.$; @@ -60,6 +62,7 @@ export class EmptyTextEditorHintContribution implements IEditorContribution { @IChatAgentService private readonly chatAgentService: IChatAgentService, @ITelemetryService private readonly telemetryService: ITelemetryService, @IProductService protected readonly productService: IProductService, + @IContextMenuService private readonly contextMenuService: IContextMenuService ) { this.toDispose = []; this.toDispose.push(this.editor.onDidChangeModel(() => this.update())); @@ -145,7 +148,8 @@ export class EmptyTextEditorHintContribution implements IEditorContribution { this.keybindingService, this.chatAgentService, this.telemetryService, - this.productService + this.productService, + this.contextMenuService ); } else if (!shouldRenderHint && this.textHintContentWidget) { this.textHintContentWidget.dispose(); @@ -178,7 +182,8 @@ class EmptyTextEditorHintContentWidget implements IContentWidget { private readonly keybindingService: IKeybindingService, private readonly chatAgentService: IChatAgentService, private readonly telemetryService: ITelemetryService, - private readonly productService: IProductService + private readonly productService: IProductService, + private readonly contextMenuService: IContextMenuService, ) { this.toDispose = new DisposableStore(); this.toDispose.add(this.editor.onDidChangeConfiguration((e: ConfigurationChangedEvent) => { @@ -199,10 +204,34 @@ class EmptyTextEditorHintContentWidget implements IContentWidget { return EmptyTextEditorHintContentWidget.ID; } - private _disableHint() { - this.configurationService.updateValue(emptyTextEditorHintSetting, 'hidden'); - this.dispose(); - this.editor.focus(); + private _disableHint(e?: MouseEvent) { + const disableHint = () => { + this.configurationService.updateValue(emptyTextEditorHintSetting, 'hidden'); + this.dispose(); + this.editor.focus(); + }; + + if (!e) { + disableHint(); + return; + } + + this.contextMenuService.showContextMenu({ + getAnchor: () => { return new StandardMouseEvent(dom.getActiveWindow(), e); }, + getActions: () => { + return [{ + id: 'workench.action.disableEmptyEditorHint', + label: localize('disableEditorEmptyHint', "Disable Empty Editor Hint"), + tooltip: localize('disableEditorEmptyHint', "Disable Empty Editor Hint"), + enabled: true, + class: undefined, + run: () => { + disableHint(); + } + } + ]; + } + }); } private _getHintInlineChat(providers: IChatAgent[]) { @@ -244,7 +273,7 @@ class EmptyTextEditorHintContentWidget implements IContentWidget { const hintPart = $('a', undefined, fragment); hintPart.style.fontStyle = 'italic'; hintPart.style.cursor = 'pointer'; - this.toDispose.add(dom.addDisposableListener(hintPart, dom.EventType.CONTEXT_MENU, () => this._disableHint())); + this.toDispose.add(dom.addDisposableListener(hintPart, dom.EventType.CONTEXT_MENU, (e) => this._disableHint(e))); this.toDispose.add(dom.addDisposableListener(hintPart, dom.EventType.CLICK, handleClick)); return hintPart; } else { @@ -263,7 +292,7 @@ class EmptyTextEditorHintContentWidget implements IContentWidget { if (this.options.clickable) { label.element.style.cursor = 'pointer'; - this.toDispose.add(dom.addDisposableListener(label.element, dom.EventType.CONTEXT_MENU, () => this._disableHint())); + this.toDispose.add(dom.addDisposableListener(label.element, dom.EventType.CONTEXT_MENU, (e) => this._disableHint(e))); this.toDispose.add(dom.addDisposableListener(label.element, dom.EventType.CLICK, handleClick)); } diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index c9ec64206bd..41f1a55b557 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -51,9 +51,9 @@ export const CONTEXT_IN_DEBUG_REPL = new RawContextKey('inDebugRepl', f export const CONTEXT_BREAKPOINT_WIDGET_VISIBLE = new RawContextKey('breakpointWidgetVisible', false, { type: 'boolean', description: nls.localize('breakpointWidgetVisibile', "True when breakpoint editor zone widget is visible, false otherwise.") }); export const CONTEXT_IN_BREAKPOINT_WIDGET = new RawContextKey('inBreakpointWidget', false, { type: 'boolean', description: nls.localize('inBreakpointWidget', "True when focus is in the breakpoint editor zone widget, false otherwise.") }); export const CONTEXT_BREAKPOINTS_FOCUSED = new RawContextKey('breakpointsFocused', true, { type: 'boolean', description: nls.localize('breakpointsFocused', "True when the BREAKPOINTS view is focused, false otherwise.") }); -export const CONTEXT_WATCH_EXPRESSIONS_FOCUSED = new RawContextKey('watchExpressionsFocused', true, { type: 'boolean', description: nls.localize('watchExpressionsFocused', "True when the WATCH view is focused, false otherwsie.") }); +export const CONTEXT_WATCH_EXPRESSIONS_FOCUSED = new RawContextKey('watchExpressionsFocused', true, { type: 'boolean', description: nls.localize('watchExpressionsFocused', "True when the WATCH view is focused, false otherwise.") }); export const CONTEXT_WATCH_EXPRESSIONS_EXIST = new RawContextKey('watchExpressionsExist', false, { type: 'boolean', description: nls.localize('watchExpressionsExist', "True when at least one watch expression exists, false otherwise.") }); -export const CONTEXT_VARIABLES_FOCUSED = new RawContextKey('variablesFocused', true, { type: 'boolean', description: nls.localize('variablesFocused', "True when the VARIABLES views is focused, false otherwsie") }); +export const CONTEXT_VARIABLES_FOCUSED = new RawContextKey('variablesFocused', true, { type: 'boolean', description: nls.localize('variablesFocused', "True when the VARIABLES views is focused, false otherwise") }); export const CONTEXT_EXPRESSION_SELECTED = new RawContextKey('expressionSelected', false, { type: 'boolean', description: nls.localize('expressionSelected', "True when an expression input box is open in either the WATCH or the VARIABLES view, false otherwise.") }); export const CONTEXT_BREAKPOINT_INPUT_FOCUSED = new RawContextKey('breakpointInputFocused', false, { type: 'boolean', description: nls.localize('breakpointInputFocused', "True when the input box has focus in the BREAKPOINTS view.") }); export const CONTEXT_CALLSTACK_ITEM_TYPE = new RawContextKey('callStackItemType', undefined, { type: 'string', description: nls.localize('callStackItemType', "Represents the item type of the focused element in the CALL STACK view. For example: 'session', 'thread', 'stackFrame'") }); @@ -72,7 +72,7 @@ export const CONTEXT_FOCUSED_SESSION_IS_ATTACH = new RawContextKey('foc export const CONTEXT_FOCUSED_SESSION_IS_NO_DEBUG = new RawContextKey('focusedSessionIsNoDebug', false, { type: 'boolean', description: nls.localize('focusedSessionIsNoDebug', "True when the focused session is run without debugging.") }); export const CONTEXT_STEP_BACK_SUPPORTED = new RawContextKey('stepBackSupported', false, { type: 'boolean', description: nls.localize('stepBackSupported', "True when the focused session supports 'stepBack' requests.") }); export const CONTEXT_RESTART_FRAME_SUPPORTED = new RawContextKey('restartFrameSupported', false, { type: 'boolean', description: nls.localize('restartFrameSupported', "True when the focused session supports 'restartFrame' requests.") }); -export const CONTEXT_STACK_FRAME_SUPPORTS_RESTART = new RawContextKey('stackFrameSupportsRestart', false, { type: 'boolean', description: nls.localize('stackFrameSupportsRestart', "True when the focused stack frame suppots 'restartFrame'.") }); +export const CONTEXT_STACK_FRAME_SUPPORTS_RESTART = new RawContextKey('stackFrameSupportsRestart', false, { type: 'boolean', description: nls.localize('stackFrameSupportsRestart', "True when the focused stack frame supports 'restartFrame'.") }); export const CONTEXT_JUMP_TO_CURSOR_SUPPORTED = new RawContextKey('jumpToCursorSupported', false, { type: 'boolean', description: nls.localize('jumpToCursorSupported', "True when the focused session supports 'jumpToCursor' request.") }); export const CONTEXT_STEP_INTO_TARGETS_SUPPORTED = new RawContextKey('stepIntoTargetsSupported', false, { type: 'boolean', description: nls.localize('stepIntoTargetsSupported', "True when the focused session supports 'stepIntoTargets' request.") }); export const CONTEXT_BREAKPOINTS_EXIST = new RawContextKey('breakpointsExist', false, { type: 'boolean', description: nls.localize('breakpointsExist', "True when at least one breakpoint exists.") }); diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index 55dfb610a32..33f961fc455 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -1493,7 +1493,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi menu: { id: MenuId.ExtensionContext, group: '0_install', - when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension'), CONTEXT_SYNC_ENABLEMENT), + when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.not('extensionDisallowInstall'), CONTEXT_SYNC_ENABLEMENT), order: 1 }, run: async (accessor: ServicesAccessor, extensionId: string) => { @@ -1516,7 +1516,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi menu: { id: MenuId.ExtensionContext, group: '0_install', - when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.has('extensionHasPreReleaseVersion'), CONTEXT_SYNC_ENABLEMENT), + when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.has('extensionHasPreReleaseVersion'), ContextKeyExpr.not('extensionDisallowInstall'), CONTEXT_SYNC_ENABLEMENT), order: 2 }, run: async (accessor: ServicesAccessor, extensionId: string) => { @@ -1540,7 +1540,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi menu: { id: MenuId.ExtensionContext, group: '0_install', - when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension')), + when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.not('extensionDisallowInstall')), order: 3 }, run: async (accessor: ServicesAccessor, extensionId: string) => { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 0b5323a75a0..fccbb361feb 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -1170,6 +1170,7 @@ async function getContextMenuActionsGroups(extension: IExtension | undefined | n cksOverlay.push(['galleryExtensionHasPreReleaseVersion', extension.gallery?.hasPreReleaseVersion]); cksOverlay.push(['extensionHasPreReleaseVersion', extension.hasPreReleaseVersion]); cksOverlay.push(['extensionHasReleaseVersion', extension.hasReleaseVersion]); + cksOverlay.push(['extensionDisallowInstall', !!extension.deprecationInfo?.disallowInstall]); const [colorThemes, fileIconThemes, productIconThemes] = await Promise.all([workbenchThemeService.getColorThemes(), workbenchThemeService.getFileIconThemes(), workbenchThemeService.getProductIconThemes()]); cksOverlay.push(['extensionHasColorThemes', colorThemes.some(theme => isThemeFromExtension(theme, extension))]); diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index a94926f1749..8811c5e8d14 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -50,6 +50,7 @@ import { generateUuid } from 'vs/base/common/uuid'; import { isEqual } from 'vs/base/common/resources'; import { ChatAgentLocation } from 'vs/workbench/contrib/chat/common/chatAgents'; import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService'; +import { escapeRegExpCharacters } from 'vs/base/common/strings'; export const enum State { CREATE_SESSION = 'CREATE_SESSION', @@ -463,7 +464,7 @@ export class InlineChatController implements IEditorContribution { })); // #region DEBT - // DEBT@jrieken + // DEBT@jrieken https://github.com/microsoft/vscode/issues/218819 // REMOVE when agents are adopted this._sessionStore.add(this._languageFeatureService.completionProvider.register({ scheme: ChatInputPart.INPUT_SCHEME, hasAccessToAllModels: true }, { _debugDisplayName: 'inline chat commands', @@ -486,7 +487,7 @@ export class InlineChatController implements IEditorContribution { result.suggestions.push({ label: { label: withSlash, description: command.description ?? '' }, kind: CompletionItemKind.Text, - insertText: withSlash, + insertText: `${withSlash} `, range: Range.fromPositions(new Position(1, 1), position), }); } @@ -501,16 +502,12 @@ export class InlineChatController implements IEditorContribution { for (const command of (this._session?.agent.slashCommands ?? []).sort((a, b) => b.name.length - a.name.length)) { const withSlash = `/${command.name}`; const firstLine = model.getLineContent(1); - if (firstLine.startsWith(withSlash)) { + if (firstLine.match(new RegExp(`^${escapeRegExpCharacters(withSlash)}(\\s|$)`))) { newDecorations.push({ range: new Range(1, 1, 1, withSlash.length + 1), options: { description: 'inline-chat-slash-command', inlineClassName: 'inline-chat-slash-command', - after: { - // Force some space between slash command and placeholder - content: ' ' - } } }); diff --git a/src/vs/workbench/contrib/interactive/browser/interactive.contribution.ts b/src/vs/workbench/contrib/interactive/browser/interactive.contribution.ts index 5705f2e7f3b..2109f7ef705 100644 --- a/src/vs/workbench/contrib/interactive/browser/interactive.contribution.ts +++ b/src/vs/workbench/contrib/interactive/browser/interactive.contribution.ts @@ -458,6 +458,11 @@ registerAction2(class extends Action2 { title: localize2('interactive.execute', 'Execute Code'), category: interactiveWindowCategory, keybinding: [{ + // when: NOTEBOOK_CELL_LIST_FOCUSED, + when: ContextKeyExpr.equals('activeEditor', 'workbench.editor.interactive'), + primary: KeyMod.CtrlCmd | KeyCode.Enter, + weight: NOTEBOOK_EDITOR_WIDGET_ACTION_WEIGHT + }, { when: ContextKeyExpr.and( ContextKeyExpr.equals('activeEditor', 'workbench.editor.interactive'), ContextKeyExpr.equals('config.interactiveWindow.executeWithShiftEnter', true) @@ -471,11 +476,6 @@ registerAction2(class extends Action2 { ), primary: KeyCode.Enter, weight: NOTEBOOK_EDITOR_WIDGET_ACTION_WEIGHT - }, { - // when: NOTEBOOK_CELL_LIST_FOCUSED, - when: ContextKeyExpr.equals('activeEditor', 'workbench.editor.interactive'), - primary: KeyMod.CtrlCmd | KeyCode.Enter, - weight: NOTEBOOK_EDITOR_WIDGET_ACTION_WEIGHT }], menu: [ { diff --git a/src/vs/workbench/contrib/interactive/browser/replInputHintContentWidget.ts b/src/vs/workbench/contrib/interactive/browser/replInputHintContentWidget.ts index b42ea604df8..6dc4644b71a 100644 --- a/src/vs/workbench/contrib/interactive/browser/replInputHintContentWidget.ts +++ b/src/vs/workbench/contrib/interactive/browser/replInputHintContentWidget.ts @@ -122,23 +122,25 @@ export class ReplInputHintContentWidget extends Disposable implements IContentWi private getKeybinding() { const keybindings = this.keybindingService.lookupKeybindings('interactive.execute'); const shiftEnterConfig = this.configurationService.getValue(InteractiveWindowSetting.executeWithShiftEnter); - const hasChord = (chord: string, kb: ResolvedKeybinding) => { + const hasEnterChord = (kb: ResolvedKeybinding, modifier: string = '') => { const chords = kb.getDispatchChords(); - return chords.length === 1 && chords[0] === chord; + const chord = modifier + 'Enter'; + const chordAlt = modifier + '[Enter]'; + return chords.length === 1 && (chords[0] === chord || chords[0] === chordAlt); }; if (shiftEnterConfig) { - const keybinding = keybindings.find(kb => hasChord('shift+Enter', kb)); + const keybinding = keybindings.find(kb => hasEnterChord(kb, 'shift+')); if (keybinding) { return keybinding; } } else { - let keybinding = keybindings.find(kb => hasChord('Enter', kb)); + let keybinding = keybindings.find(kb => hasEnterChord(kb)); if (keybinding) { return keybinding; } keybinding = this.keybindingService.lookupKeybindings('python.execInREPLEnter') - .find(kb => hasChord('Enter', kb)); + .find(kb => hasEnterChord(kb)); if (keybinding) { return keybinding; } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/editorHint/emptyCellEditorHint.ts b/src/vs/workbench/contrib/notebook/browser/contrib/editorHint/emptyCellEditorHint.ts index eeef10e64d2..205bce806e1 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/editorHint/emptyCellEditorHint.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/editorHint/emptyCellEditorHint.ts @@ -8,6 +8,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorContributionInstantiation, registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IHoverService } from 'vs/platform/hover/browser/hover'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IProductService } from 'vs/platform/product/common/productService'; @@ -32,7 +33,8 @@ export class EmptyCellEditorHintContribution extends EmptyTextEditorHintContribu @IInlineChatSessionService inlineChatSessionService: IInlineChatSessionService, @IChatAgentService chatAgentService: IChatAgentService, @ITelemetryService telemetryService: ITelemetryService, - @IProductService productService: IProductService + @IProductService productService: IProductService, + @IContextMenuService contextMenuService: IContextMenuService ) { super( editor, @@ -44,7 +46,8 @@ export class EmptyCellEditorHintContribution extends EmptyTextEditorHintContribu inlineChatSessionService, chatAgentService, telemetryService, - productService + productService, + contextMenuService ); const activeEditor = getNotebookEditorFromEditorPane(this._editorService.activeEditorPane); 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 e46d83c6bb1..06036fcbaae 100755 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh @@ -175,7 +175,9 @@ __vsc_stable="$VSCODE_STABLE" unset VSCODE_STABLE # Report continuation prompt -builtin printf "\e]633;P;ContinuationPrompt=$(echo "$PS2" | sed 's/\x1b/\\\\x1b/g')\a" +if [ "$__vsc_stable" = "0" ]; then + builtin printf "\e]633;P;ContinuationPrompt=$(echo "$PS2" | sed 's/\x1b/\\\\x1b/g')\a" +fi __vsc_report_prompt() { # Expand the original PS1 similarly to how bash would normally diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 index 53603022c29..6c92130ec95 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 @@ -98,7 +98,7 @@ function Global:Prompt() { # Prompt # OSC 633 ; = ST - if ($isStable -eq "1") { + if ($isStable -eq "0") { $Result += "$([char]0x1b)]633;P;Prompt=$(__VSCode-Escape-Value $OriginalPrompt)`a" } @@ -147,9 +147,11 @@ else { } # Set ContinuationPrompt property -$ContinuationPrompt = (Get-PSReadLineOption).ContinuationPrompt -if ($ContinuationPrompt) { - [Console]::Write("$([char]0x1b)]633;P;ContinuationPrompt=$(__VSCode-Escape-Value $ContinuationPrompt)`a") +if ($isStable -eq "0") { + $ContinuationPrompt = (Get-PSReadLineOption).ContinuationPrompt + if ($ContinuationPrompt) { + [Console]::Write("$([char]0x1b)]633;P;ContinuationPrompt=$(__VSCode-Escape-Value $ContinuationPrompt)`a") + } } # Set always on key handlers which map to default VS Code keybindings diff --git a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminal.initialHint.contribution.ts b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminal.initialHint.contribution.ts index 9bd955a1ab7..21d5f887145 100644 --- a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminal.initialHint.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminal.initialHint.contribution.ts @@ -261,6 +261,7 @@ class TerminalInitialHintWidget extends Disposable { }; this.toDispose.add(this.commandService.onDidExecuteCommand(e => { if (e.commandId === TerminalChatCommandId.Start) { + this._storageService.store(Constants.InitialHintHideStorageKey, true, StorageScope.APPLICATION, StorageTarget.USER); this.dispose(); } })); diff --git a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatWidget.ts b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatWidget.ts index c6808146699..33c01afbb63 100644 --- a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatWidget.ts +++ b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatWidget.ts @@ -96,11 +96,14 @@ export class TerminalChatWidget extends Disposable { this._container.appendChild(this._inlineChatWidget.domNode); this._focusTracker = this._register(trackFocus(this._container)); + this._register(this._focusTracker.onDidFocus(() => this._focusedContextKey.set(true))); this._register(this._focusTracker.onDidBlur(() => { + this._focusedContextKey.set(false); if (!this.inlineChatWidget.responseContent) { this.hide(); } })); + this.hide(); } @@ -150,7 +153,6 @@ export class TerminalChatWidget extends Disposable { reveal(): void { this._doLayout(this._inlineChatWidget.contentHeight); this._container.classList.remove('hide'); - this._focusedContextKey.set(true); this._visibleContextKey.set(true); this._inlineChatWidget.focus(); this._instance.scrollToBottom(); @@ -199,7 +201,6 @@ export class TerminalChatWidget extends Disposable { this._inlineChatWidget.updateChatMessage(undefined); this._inlineChatWidget.updateProgress(false); this._inlineChatWidget.updateToolbar(false); - this._focusedContextKey.set(false); this._visibleContextKey.set(false); this._inlineChatWidget.value = ''; this._instance.focus(); diff --git a/src/vs/workbench/contrib/userDataProfile/browser/userDataProfilesEditorModel.ts b/src/vs/workbench/contrib/userDataProfile/browser/userDataProfilesEditorModel.ts index 4b3d9947286..a2e56bc5c7b 100644 --- a/src/vs/workbench/contrib/userDataProfile/browser/userDataProfilesEditorModel.ts +++ b/src/vs/workbench/contrib/userDataProfile/browser/userDataProfilesEditorModel.ts @@ -716,14 +716,14 @@ export class UserDataProfilesEditorModel extends EditorModel { localize('active', "Use for Current Window"), ThemeIcon.asClassName(Codicon.check), true, - () => this.userDataProfileManagementService.switchProfile(profile) + () => this.userDataProfileManagementService.switchProfile(profileElement.profile) )); const copyFromProfileAction = disposables.add(new Action( 'userDataProfile.copyFromProfile', localize('copyFromProfile', "Duplicate..."), ThemeIcon.asClassName(Codicon.copy), - true, () => this.createNewProfile(profile) + true, () => this.createNewProfile(profileElement.profile) )); const exportAction = disposables.add(new Action( @@ -731,7 +731,7 @@ export class UserDataProfilesEditorModel extends EditorModel { localize('export', "Export..."), ThemeIcon.asClassName(Codicon.export), true, - () => this.exportProfile(profile) + () => this.exportProfile(profileElement.profile) )); const deleteAction = disposables.add(new Action( @@ -739,20 +739,20 @@ export class UserDataProfilesEditorModel extends EditorModel { localize('delete', "Delete"), ThemeIcon.asClassName(Codicon.trash), true, - () => this.removeProfile(profile) + () => this.removeProfile(profileElement.profile) )); const newWindowAction = disposables.add(new Action( 'userDataProfile.newWindow', - localize('open new window', "New Window"), + localize('open new window', "Open New Window with this Profile"), ThemeIcon.asClassName(Codicon.emptyWindow), true, - () => this.openWindow(profile) + () => this.openWindow(profileElement.profile) )); const useAsNewWindowProfileAction = disposables.add(new Action( 'userDataProfile.useAsNewWindowProfile', - localize('use as new window', "Use for New Windows", profile.name), + localize('use as new window', "Use for New Windows"), undefined, true, () => profileElement.toggleNewWindowProfile() @@ -788,9 +788,9 @@ export class UserDataProfilesEditorModel extends EditorModel { [primaryActions, secondaryActions] )); - activateAction.checked = this.userDataProfileService.currentProfile.id === profile.id; + activateAction.checked = this.userDataProfileService.currentProfile.id === profileElement.profile.id; disposables.add(this.userDataProfileService.onDidChangeCurrentProfile(() => - activateAction.checked = this.userDataProfileService.currentProfile.id === profile.id)); + activateAction.checked = this.userDataProfileService.currentProfile.id === profileElement.profile.id)); useAsNewWindowProfileAction.checked = profileElement.isNewWindowProfile; disposables.add(profileElement.onDidChange(e => { diff --git a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts index 5f3b9cbda7d..95be556e81a 100644 --- a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts +++ b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts @@ -832,7 +832,7 @@ export class SimpleFileDialog implements ISimpleFileDialog { } else if (!statDirname.isDirectory) { this.filePickBox.validationMessage = nls.localize('remoteFileDialog.validateNonexistentDir', 'Please enter a path that exists.'); return Promise.resolve(false); - } else if (statDirname.readonly || statDirname.locked) { + } else if (statDirname.readonly) { this.filePickBox.validationMessage = nls.localize('remoteFileDialog.validateReadonlyFolder', 'This folder cannot be used as a save destination. Please choose another folder'); return Promise.resolve(false); } diff --git a/src/vs/workbench/services/userDataProfile/common/userDataProfileIcons.ts b/src/vs/workbench/services/userDataProfile/common/userDataProfileIcons.ts index 93251b9b1c3..6e0e28a0347 100644 --- a/src/vs/workbench/services/userDataProfile/common/userDataProfileIcons.ts +++ b/src/vs/workbench/services/userDataProfile/common/userDataProfileIcons.ts @@ -71,7 +71,7 @@ export const ICONS = [ Codicon.pulse, Codicon.radioTower, Codicon.smiley, - Codicon.symbolEvent, + Codicon.zap, Codicon.squirrel, Codicon.symbolColor, Codicon.mail,