mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-13 15:35:20 +01:00
Merge branch 'main' into tyriar/xterm_240715
This commit is contained in:
@@ -835,6 +835,8 @@
|
||||
"--vscode-editorStickyScroll-scrollableWidth",
|
||||
"--vscode-editorStickyScroll-foldingOpacityTransition",
|
||||
"--window-border-color",
|
||||
"--vscode-parameterHintsWidget-editorFontFamily",
|
||||
"--vscode-parameterHintsWidget-editorFontFamilyDefault",
|
||||
"--workspace-trust-check-color",
|
||||
"--workspace-trust-selected-color",
|
||||
"--workspace-trust-unselected-color",
|
||||
|
||||
@@ -7,6 +7,7 @@ import { ExtensionContext, Uri, l10n } from 'vscode';
|
||||
import { BaseLanguageClient, LanguageClientOptions } from 'vscode-languageclient';
|
||||
import { startClient, LanguageClientConstructor } from '../cssClient';
|
||||
import { LanguageClient } from 'vscode-languageclient/browser';
|
||||
import { registerDropOrPasteResourceSupport } from '../dropOrPaste/dropOrPasteResource';
|
||||
|
||||
let client: BaseLanguageClient | undefined;
|
||||
|
||||
@@ -23,6 +24,7 @@ export async function activate(context: ExtensionContext) {
|
||||
|
||||
client = await startClient(context, newLanguageClient, { TextDecoder });
|
||||
|
||||
context.subscriptions.push(registerDropOrPasteResourceSupport({ language: 'css', scheme: '*' }));
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import { getDocumentDir, Mimes, Schemes } from './shared';
|
||||
import { UriList } from './uriList';
|
||||
|
||||
class DropOrPasteResourceProvider implements vscode.DocumentDropEditProvider, vscode.DocumentPasteEditProvider {
|
||||
readonly kind = vscode.DocumentDropOrPasteEditKind.Empty.append('css', 'url');
|
||||
|
||||
async provideDocumentDropEdits(
|
||||
document: vscode.TextDocument,
|
||||
position: vscode.Position,
|
||||
dataTransfer: vscode.DataTransfer,
|
||||
token: vscode.CancellationToken,
|
||||
): Promise<vscode.DocumentDropEdit | undefined> {
|
||||
const uriList = await this.getUriList(dataTransfer);
|
||||
if (!uriList.entries.length || token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
const snippet = await this.createUriListSnippet(uriList);
|
||||
if (!snippet || token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
kind: this.kind,
|
||||
title: snippet.label,
|
||||
insertText: snippet.snippet.value,
|
||||
yieldTo: this.pasteAsCssUrlByDefault(document, position) ? [] : [vscode.DocumentDropOrPasteEditKind.Empty.append('uri')]
|
||||
};
|
||||
}
|
||||
|
||||
async provideDocumentPasteEdits(
|
||||
document: vscode.TextDocument,
|
||||
ranges: readonly vscode.Range[],
|
||||
dataTransfer: vscode.DataTransfer,
|
||||
_context: vscode.DocumentPasteEditContext,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.DocumentPasteEdit[] | undefined> {
|
||||
const uriList = await this.getUriList(dataTransfer);
|
||||
if (!uriList.entries.length || token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
const snippet = await this.createUriListSnippet(uriList);
|
||||
if (!snippet || token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
return [{
|
||||
kind: this.kind,
|
||||
title: snippet.label,
|
||||
insertText: snippet.snippet.value,
|
||||
yieldTo: this.pasteAsCssUrlByDefault(document, ranges[0].start) ? [] : [vscode.DocumentDropOrPasteEditKind.Empty.append('uri')]
|
||||
}];
|
||||
}
|
||||
|
||||
private async getUriList(dataTransfer: vscode.DataTransfer): Promise<UriList> {
|
||||
const urlList = await dataTransfer.get(Mimes.uriList)?.asString();
|
||||
if (urlList) {
|
||||
return UriList.from(urlList);
|
||||
}
|
||||
|
||||
// Find file entries
|
||||
const uris: vscode.Uri[] = [];
|
||||
for (const [_, entry] of dataTransfer) {
|
||||
const file = entry.asFile();
|
||||
if (file?.uri) {
|
||||
uris.push(file.uri);
|
||||
}
|
||||
}
|
||||
|
||||
return new UriList(uris.map(uri => ({ uri, str: uri.toString(true) })));
|
||||
}
|
||||
|
||||
private async createUriListSnippet(uriList: UriList): Promise<{ readonly snippet: vscode.SnippetString; readonly label: string } | undefined> {
|
||||
if (!uriList.entries.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const snippet = new vscode.SnippetString();
|
||||
for (let i = 0; i < uriList.entries.length; i++) {
|
||||
const uri = uriList.entries[i];
|
||||
const relativePath = getRelativePath(uri.uri);
|
||||
const urlText = relativePath ?? uri.str;
|
||||
|
||||
snippet.appendText(`url(${urlText})`);
|
||||
if (i !== uriList.entries.length - 1) {
|
||||
snippet.appendText(' ');
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
snippet,
|
||||
label: uriList.entries.length > 1
|
||||
? vscode.l10n.t('Insert url() Functions')
|
||||
: vscode.l10n.t('Insert url() Function')
|
||||
};
|
||||
}
|
||||
|
||||
private pasteAsCssUrlByDefault(document: vscode.TextDocument, position: vscode.Position): boolean {
|
||||
const regex = /url\(.+?\)/gi;
|
||||
for (const match of Array.from(document.lineAt(position.line).text.matchAll(regex))) {
|
||||
if (position.character > match.index && position.character < match.index + match[0].length) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function getRelativePath(file: vscode.Uri): string | undefined {
|
||||
const dir = getDocumentDir(file);
|
||||
if (dir && dir.scheme === file.scheme && dir.authority === file.authority) {
|
||||
if (file.scheme === Schemes.file) {
|
||||
// On windows, we must use the native `path.relative` to generate the relative path
|
||||
// so that drive-letters are resolved cast insensitively. However we then want to
|
||||
// convert back to a posix path to insert in to the document
|
||||
const relativePath = path.relative(dir.fsPath, file.fsPath);
|
||||
return path.posix.normalize(relativePath.split(path.sep).join(path.posix.sep));
|
||||
}
|
||||
|
||||
return path.posix.relative(dir.path, file.path);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function registerDropOrPasteResourceSupport(selector: vscode.DocumentSelector): vscode.Disposable {
|
||||
const provider = new DropOrPasteResourceProvider();
|
||||
|
||||
return vscode.Disposable.from(
|
||||
vscode.languages.registerDocumentDropEditProvider(selector, provider, {
|
||||
providedDropEditKinds: [provider.kind],
|
||||
dropMimeTypes: [
|
||||
Mimes.uriList,
|
||||
'files'
|
||||
]
|
||||
}),
|
||||
vscode.languages.registerDocumentPasteEditProvider(selector, provider, {
|
||||
providedPasteEditKinds: [provider.kind],
|
||||
pasteMimeTypes: [
|
||||
Mimes.uriList,
|
||||
'files'
|
||||
]
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { Utils } from 'vscode-uri';
|
||||
|
||||
export const Schemes = Object.freeze({
|
||||
file: 'file',
|
||||
notebookCell: 'vscode-notebook-cell',
|
||||
untitled: 'untitled',
|
||||
});
|
||||
|
||||
export const Mimes = Object.freeze({
|
||||
plain: 'text/plain',
|
||||
uriList: 'text/uri-list',
|
||||
});
|
||||
|
||||
|
||||
export function getDocumentDir(uri: vscode.Uri): vscode.Uri | undefined {
|
||||
const docUri = getParentDocumentUri(uri);
|
||||
if (docUri.scheme === Schemes.untitled) {
|
||||
return vscode.workspace.workspaceFolders?.[0]?.uri;
|
||||
}
|
||||
return Utils.dirname(docUri);
|
||||
}
|
||||
|
||||
function getParentDocumentUri(uri: vscode.Uri): vscode.Uri {
|
||||
if (uri.scheme === Schemes.notebookCell) {
|
||||
// is notebook documents necessary?
|
||||
for (const notebook of vscode.workspace.notebookDocuments) {
|
||||
for (const cell of notebook.getCells()) {
|
||||
if (cell.document.uri.toString() === uri.toString()) {
|
||||
return notebook.uri;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
function splitUriList(str: string): string[] {
|
||||
return str.split('\r\n');
|
||||
}
|
||||
|
||||
function parseUriList(str: string): string[] {
|
||||
return splitUriList(str)
|
||||
.filter(value => !value.startsWith('#')) // Remove comments
|
||||
.map(value => value.trim());
|
||||
}
|
||||
|
||||
export class UriList {
|
||||
|
||||
static from(str: string): UriList {
|
||||
return new UriList(coalesce(parseUriList(str).map(line => {
|
||||
try {
|
||||
return { uri: vscode.Uri.parse(line), str: line };
|
||||
} catch {
|
||||
// Uri parse failure
|
||||
return undefined;
|
||||
}
|
||||
})));
|
||||
}
|
||||
|
||||
constructor(
|
||||
public readonly entries: ReadonlyArray<{ readonly uri: vscode.Uri; readonly str: string }>
|
||||
) { }
|
||||
}
|
||||
|
||||
function coalesce<T>(array: ReadonlyArray<T | undefined | null>): T[] {
|
||||
return <T[]>array.filter(e => !!e);
|
||||
}
|
||||
@@ -3,12 +3,12 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { getNodeFSRequestService } from './nodeFs';
|
||||
import { ExtensionContext, extensions, l10n } from 'vscode';
|
||||
import { startClient, LanguageClientConstructor } from '../cssClient';
|
||||
import { ServerOptions, TransportKind, LanguageClientOptions, LanguageClient, BaseLanguageClient } from 'vscode-languageclient/node';
|
||||
import { TextDecoder } from 'util';
|
||||
|
||||
import { ExtensionContext, extensions, l10n } from 'vscode';
|
||||
import { BaseLanguageClient, LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node';
|
||||
import { LanguageClientConstructor, startClient } from '../cssClient';
|
||||
import { getNodeFSRequestService } from './nodeFs';
|
||||
import { registerDropOrPasteResourceSupport } from '../dropOrPaste/dropOrPasteResource';
|
||||
|
||||
let client: BaseLanguageClient | undefined;
|
||||
|
||||
@@ -37,6 +37,8 @@ export async function activate(context: ExtensionContext) {
|
||||
process.env['VSCODE_L10N_BUNDLE_LOCATION'] = l10n.uri?.toString() ?? '';
|
||||
|
||||
client = await startClient(context, newLanguageClient, { fs: getNodeFSRequestService(), TextDecoder });
|
||||
|
||||
context.subscriptions.push(registerDropOrPasteResourceSupport({ language: 'css', scheme: '*' }));
|
||||
}
|
||||
|
||||
export async function deactivate(): Promise<void> {
|
||||
@@ -45,3 +47,4 @@ export async function deactivate(): Promise<void> {
|
||||
client = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"../../../src/vscode-dts/vscode.d.ts"
|
||||
"../../../src/vscode-dts/vscode.d.ts",
|
||||
"../../../src/vscode-dts/vscode.proposed.documentPaste.d.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
"supported": true
|
||||
}
|
||||
},
|
||||
"enabledApiProposals": [
|
||||
"documentPaste"
|
||||
],
|
||||
"scripts": {
|
||||
"compile": "npx gulp compile-extension:css-language-features-client compile-extension:css-language-features-server",
|
||||
"watch": "npx gulp watch-extension:css-language-features-client watch-extension:css-language-features-server",
|
||||
|
||||
@@ -313,7 +313,7 @@ export class MarkdownItEngine implements IMdParser {
|
||||
private _addNamedHeaders(md: MarkdownIt): void {
|
||||
const original = md.renderer.rules.heading_open;
|
||||
md.renderer.rules.heading_open = (tokens: Token[], idx: number, options, env, self) => {
|
||||
const title = tokens[idx + 1].children!.reduce<string>((acc, t) => acc + t.content, '');
|
||||
const title = this._tokenToPlainText(tokens[idx + 1]);
|
||||
let slug = this.slugifier.fromHeading(title);
|
||||
|
||||
if (this._slugCount.has(slug.value)) {
|
||||
@@ -334,6 +334,21 @@ export class MarkdownItEngine implements IMdParser {
|
||||
};
|
||||
}
|
||||
|
||||
private _tokenToPlainText(token: Token): string {
|
||||
if (token.children) {
|
||||
return token.children.map(x => this._tokenToPlainText(x)).join('');
|
||||
}
|
||||
|
||||
switch (token.type) {
|
||||
case 'text':
|
||||
case 'emoji':
|
||||
case 'code_inline':
|
||||
return token.content;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
private _addLinkRenderer(md: MarkdownIt): void {
|
||||
const original = md.renderer.rules.link_open;
|
||||
|
||||
@@ -441,4 +456,4 @@ function normalizeHighlightLang(lang: string | undefined) {
|
||||
default:
|
||||
return lang;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,8 @@ module.exports = withBrowserDefaults({
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'./node/crypto': path.resolve(__dirname, 'src/browser/crypto'),
|
||||
'./node/authServer': path.resolve(__dirname, 'src/browser/authServer'),
|
||||
'./node/buffer': path.resolve(__dirname, 'src/browser/buffer'),
|
||||
'./node/fetch': path.resolve(__dirname, 'src/browser/fetch'),
|
||||
'./node/buffer': path.resolve(__dirname, 'src/browser/buffer')
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -117,7 +117,6 @@
|
||||
"@types/uuid": "8.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"node-fetch": "2.6.7",
|
||||
"@azure/ms-rest-azure-env": "^2.0.0",
|
||||
"@vscode/extension-telemetry": "^0.9.0"
|
||||
},
|
||||
|
||||
@@ -11,7 +11,6 @@ import { generateCodeChallenge, generateCodeVerifier, randomUUID } from './crypt
|
||||
import { BetterTokenStorage, IDidChangeInOtherWindowEvent } from './betterSecretStorage';
|
||||
import { LoopbackAuthServer } from './node/authServer';
|
||||
import { base64Decode } from './node/buffer';
|
||||
import { fetching } from './node/fetch';
|
||||
import { UriEventHandler } from './UriEventHandler';
|
||||
import TelemetryReporter from '@vscode/extension-telemetry';
|
||||
import { Environment } from '@azure/ms-rest-azure-env';
|
||||
@@ -806,7 +805,7 @@ export class AzureActiveDirectoryService {
|
||||
let result;
|
||||
let errorMessage: string | undefined;
|
||||
try {
|
||||
result = await fetching(endpoint, {
|
||||
result = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export const crypto = globalThis.crypto;
|
||||
@@ -1,6 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export const fetching = fetch;
|
||||
@@ -3,7 +3,6 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { base64Encode } from './node/buffer';
|
||||
import { crypto } from './node/crypto';
|
||||
|
||||
export function randomUUID() {
|
||||
return crypto.randomUUID();
|
||||
|
||||
@@ -1,7 +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 * as nodeCrypto from 'crypto';
|
||||
|
||||
export const crypto: Crypto = nodeCrypto.webcrypto as any;
|
||||
@@ -1,7 +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 fetch from 'node-fetch';
|
||||
|
||||
export const fetching = fetch;
|
||||
@@ -186,32 +186,7 @@ mime-types@^2.1.12:
|
||||
dependencies:
|
||||
mime-db "1.44.0"
|
||||
|
||||
node-fetch@2.6.7:
|
||||
version "2.6.7"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
|
||||
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
tr46@~0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
|
||||
|
||||
undici-types@~5.26.4:
|
||||
version "5.26.5"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
||||
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||
|
||||
webidl-conversions@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||
integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
|
||||
|
||||
whatwg-url@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
|
||||
integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0=
|
||||
dependencies:
|
||||
tr46 "~0.0.3"
|
||||
webidl-conversions "^3.0.0"
|
||||
|
||||
+1
-1
@@ -208,7 +208,7 @@
|
||||
"ts-loader": "^9.4.2",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsec": "0.2.7",
|
||||
"typescript": "^5.6.0-dev.20240711",
|
||||
"typescript": "^5.6.0-dev.20240715",
|
||||
"util": "^0.12.4",
|
||||
"vscode-nls-dev": "^3.3.1",
|
||||
"webpack": "^5.91.0",
|
||||
|
||||
@@ -512,9 +512,7 @@ export class DecorationsOverviewRuler extends ViewPart {
|
||||
canvasCtx.strokeStyle = this._settings.borderColor;
|
||||
canvasCtx.moveTo(0, 0);
|
||||
canvasCtx.lineTo(0, canvasHeight);
|
||||
canvasCtx.stroke();
|
||||
|
||||
canvasCtx.moveTo(0, 0);
|
||||
canvasCtx.moveTo(1, 0);
|
||||
canvasCtx.lineTo(canvasWidth, 0);
|
||||
canvasCtx.stroke();
|
||||
}
|
||||
|
||||
@@ -23,8 +23,6 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { labelForHoverVerbosityAction } from 'vs/editor/contrib/hover/browser/markdownHoverParticipant';
|
||||
|
||||
namespace HoverAccessibilityHelpNLS {
|
||||
export const introHoverPart = localize('introHoverPart', 'The focused hover part content is the following:');
|
||||
export const introHoverFull = localize('introHoverFull', 'The full focused hover content is the following:');
|
||||
export const increaseVerbosity = localize('increaseVerbosity', '- The focused hover part verbosity level can be increased with the Increase Hover Verbosity command<keybinding:{0}>.', INCREASE_HOVER_VERBOSITY_ACTION_ID);
|
||||
export const decreaseVerbosity = localize('decreaseVerbosity', '- The focused hover part verbosity level can be decreased with the Decrease Hover Verbosity command<keybinding:{0}>.', DECREASE_HOVER_VERBOSITY_ACTION_ID);
|
||||
}
|
||||
@@ -123,7 +121,6 @@ abstract class BaseHoverAccessibleViewProvider extends Disposable implements IAc
|
||||
if (includeVerbosityActions) {
|
||||
contents.push(...this._descriptionsOfVerbosityActionsForIndex(focusedHoverIndex));
|
||||
}
|
||||
contents.push(HoverAccessibilityHelpNLS.introHoverPart);
|
||||
contents.push(accessibleContent);
|
||||
return contents.join('\n\n');
|
||||
} else {
|
||||
@@ -132,7 +129,6 @@ abstract class BaseHoverAccessibleViewProvider extends Disposable implements IAc
|
||||
return '';
|
||||
}
|
||||
const contents: string[] = [];
|
||||
contents.push(HoverAccessibilityHelpNLS.introHoverFull);
|
||||
contents.push(accessibleContent);
|
||||
return contents.join('\n\n');
|
||||
}
|
||||
|
||||
@@ -69,6 +69,10 @@
|
||||
border-bottom: 1px solid var(--vscode-editorHoverWidget-border);
|
||||
}
|
||||
|
||||
.monaco-editor .parameter-hints-widget .code {
|
||||
font-family: var(--vscode-parameterHintsWidget-editorFontFamily), var(--vscode-parameterHintsWidget-editorFontFamilyDefault);
|
||||
}
|
||||
|
||||
.monaco-editor .parameter-hints-widget .docs {
|
||||
padding: 0 10px 0 5px;
|
||||
white-space: pre-wrap;
|
||||
|
||||
@@ -14,7 +14,7 @@ import { escapeRegExpCharacters } from 'vs/base/common/strings';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import 'vs/css!./parameterHints';
|
||||
import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { EDITOR_FONT_DEFAULTS, EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import * as languages from 'vs/editor/common/languages';
|
||||
import { ILanguageService } from 'vs/editor/common/languages/language';
|
||||
import { IMarkdownRenderResult, MarkdownRenderer } from 'vs/editor/browser/widget/markdownRenderer/browser/markdownRenderer';
|
||||
@@ -126,9 +126,13 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget {
|
||||
if (!this.domNodes) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fontInfo = this.editor.getOption(EditorOption.fontInfo);
|
||||
this.domNodes.element.style.fontSize = `${fontInfo.fontSize}px`;
|
||||
this.domNodes.element.style.lineHeight = `${fontInfo.lineHeight / fontInfo.fontSize}`;
|
||||
const element = this.domNodes.element;
|
||||
element.style.fontSize = `${fontInfo.fontSize}px`;
|
||||
element.style.lineHeight = `${fontInfo.lineHeight / fontInfo.fontSize}`;
|
||||
element.style.setProperty('--vscode-parameterHintsWidget-editorFontFamily', fontInfo.fontFamily);
|
||||
element.style.setProperty('--vscode-parameterHintsWidget-editorFontFamilyDefault', EDITOR_FONT_DEFAULTS.fontFamily);
|
||||
};
|
||||
|
||||
updateFont();
|
||||
@@ -203,10 +207,6 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget {
|
||||
}
|
||||
|
||||
const code = dom.append(this.domNodes.signature, $('.code'));
|
||||
const fontInfo = this.editor.getOption(EditorOption.fontInfo);
|
||||
code.style.fontSize = `${fontInfo.fontSize}px`;
|
||||
code.style.fontFamily = fontInfo.fontFamily;
|
||||
|
||||
const hasParameters = signature.parameters.length > 0;
|
||||
const activeParameterIndex = signature.activeParameter ?? hints.activeParameter;
|
||||
|
||||
|
||||
@@ -69,6 +69,11 @@ export interface IAccessibleViewOptions {
|
||||
* Keybinding items to configure
|
||||
*/
|
||||
configureKeybindingItems?: IQuickPickItem[];
|
||||
|
||||
/**
|
||||
* Keybinding items that are already configured
|
||||
*/
|
||||
configuredKeybindingItems?: IQuickPickItem[];
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +128,7 @@ export interface IAccessibleViewService {
|
||||
*/
|
||||
getOpenAriaHint(verbositySettingKey: string): string | null;
|
||||
getCodeBlockContext(): ICodeBlockActionContext | undefined;
|
||||
configureKeybindings(): void;
|
||||
configureKeybindings(unassigned: boolean): void;
|
||||
openHelpLink(): void;
|
||||
}
|
||||
|
||||
|
||||
@@ -334,7 +334,10 @@ export class AccessibleView extends Disposable {
|
||||
this._instantiationService.createInstance(AccessibleViewSymbolQuickPick, this).show(this._currentProvider);
|
||||
}
|
||||
|
||||
calculateCodeBlocks(markdown: string): void {
|
||||
calculateCodeBlocks(markdown?: string): void {
|
||||
if (!markdown) {
|
||||
return;
|
||||
}
|
||||
if (this._currentProvider?.id !== AccessibleViewProviderId.Chat) {
|
||||
return;
|
||||
}
|
||||
@@ -391,10 +394,10 @@ export class AccessibleView extends Disposable {
|
||||
this._openerService.open(URI.parse(this._currentProvider.options.readMoreUrl));
|
||||
}
|
||||
|
||||
configureKeybindings(): void {
|
||||
configureKeybindings(unassigned: boolean): void {
|
||||
this._inQuickPick = true;
|
||||
const provider = this._updateLastProvider();
|
||||
const items = provider?.options?.configureKeybindingItems;
|
||||
const items = unassigned ? provider?.options?.configureKeybindingItems : provider?.options?.configuredKeybindingItems;
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
@@ -496,45 +499,39 @@ export class AccessibleView extends Disposable {
|
||||
this._accessibleViewGoToSymbolSupported.set(this._goToSymbolsSupported() ? this.getSymbols()?.length! > 0 : false);
|
||||
}
|
||||
|
||||
private _updateContent(provider: AccesibleViewContentProvider, updatedContent?: string): void {
|
||||
let content = updatedContent ?? provider.provideContent();
|
||||
if (provider.options.type === AccessibleViewType.View) {
|
||||
this._currentContent = content;
|
||||
return;
|
||||
}
|
||||
const readMoreLinkHint = this._readMoreHint(provider);
|
||||
const disableHelpHint = this._disableVerbosityHint(provider);
|
||||
const screenReaderModeHint = this._screenReaderModeHint(provider);
|
||||
const exitThisDialogHint = this._exitDialogHint(provider);
|
||||
let configureKbHint = '';
|
||||
let configureAssignedKbHint = '';
|
||||
const resolvedContent = resolveContentAndKeybindingItems(this._keybindingService, screenReaderModeHint + content + readMoreLinkHint + disableHelpHint + exitThisDialogHint);
|
||||
if (resolvedContent) {
|
||||
content = resolvedContent.content.value;
|
||||
if (resolvedContent.configureKeybindingItems) {
|
||||
provider.options.configureKeybindingItems = resolvedContent.configureKeybindingItems;
|
||||
configureKbHint = this._configureUnassignedKbHint();
|
||||
}
|
||||
if (resolvedContent.configuredKeybindingItems) {
|
||||
provider.options.configuredKeybindingItems = resolvedContent.configuredKeybindingItems;
|
||||
configureAssignedKbHint = this._configureAssignedKbHint();
|
||||
}
|
||||
}
|
||||
this._currentContent = content + configureKbHint + configureAssignedKbHint;
|
||||
}
|
||||
|
||||
private _render(provider: AccesibleViewContentProvider, container: HTMLElement, showAccessibleViewHelp?: boolean, updatedContent?: string): IDisposable {
|
||||
this._currentProvider = provider;
|
||||
this._accessibleViewCurrentProviderId.set(provider.id);
|
||||
const verbose = this._verbosityEnabled();
|
||||
const readMoreLink = provider.options.readMoreUrl ? localize("openDoc", "\n\nOpen a browser window with more information related to accessibility<keybinding:{0}>.", AccessibilityCommandId.AccessibilityHelpOpenHelpLink) : '';
|
||||
let disableHelpHint = '';
|
||||
if (provider instanceof AccessibleContentProvider && provider.options.type === AccessibleViewType.Help && verbose) {
|
||||
disableHelpHint = this._getDisableVerbosityHint();
|
||||
}
|
||||
const accessibilitySupport = this._accessibilityService.isScreenReaderOptimized();
|
||||
let message = '';
|
||||
if (provider.options.type === AccessibleViewType.Help) {
|
||||
const turnOnMessage = (
|
||||
isMacintosh
|
||||
? AccessibilityHelpNLS.changeConfigToOnMac
|
||||
: AccessibilityHelpNLS.changeConfigToOnWinLinux
|
||||
);
|
||||
if (accessibilitySupport && provider instanceof AccessibleContentProvider && provider.verbositySettingKey === AccessibilityVerbositySettingId.Editor) {
|
||||
message = AccessibilityHelpNLS.auto_on;
|
||||
message += '\n';
|
||||
} else if (!accessibilitySupport) {
|
||||
message = AccessibilityHelpNLS.auto_off + '\n' + turnOnMessage;
|
||||
message += '\n';
|
||||
}
|
||||
}
|
||||
const exitThisDialogHint = verbose && !provider.options.position ? localize('exit', '\n\nExit this dialog (Escape).') : '';
|
||||
let content = updatedContent ?? provider.provideContent();
|
||||
if (provider.options.type === AccessibleViewType.Help) {
|
||||
const resolvedContent = resolveContentAndKeybindingItems(this._keybindingService, content + readMoreLink + disableHelpHint + exitThisDialogHint);
|
||||
if (resolvedContent) {
|
||||
content = resolvedContent.content.value;
|
||||
if (resolvedContent.configureKeybindingItems) {
|
||||
provider.options.configureKeybindingItems = resolvedContent.configureKeybindingItems;
|
||||
}
|
||||
}
|
||||
}
|
||||
const newContent = message + content;
|
||||
this.calculateCodeBlocks(newContent);
|
||||
this._currentContent = newContent;
|
||||
this._updateContent(provider, updatedContent);
|
||||
this.calculateCodeBlocks(this._currentContent);
|
||||
this._updateContextKeys(provider, true);
|
||||
const widgetIsFocused = this._editorWidget.hasTextFocus() || this._editorWidget.hasWidgetFocus();
|
||||
this._getTextModel(URI.from({ path: `accessible-view-${provider.id}`, scheme: 'accessible-view', fragment: this._currentContent })).then((model) => {
|
||||
@@ -708,7 +705,7 @@ export class AccessibleView extends Disposable {
|
||||
accessibleViewHelpProvider = new AccessibleContentProvider(
|
||||
lastProvider.id as AccessibleViewProviderId,
|
||||
{ type: AccessibleViewType.Help },
|
||||
() => lastProvider.options.customHelp ? lastProvider?.options.customHelp() : this._getAccessibleViewHelpDialogContent(this._goToSymbolsSupported()),
|
||||
() => lastProvider.options.customHelp ? lastProvider?.options.customHelp() : this._accessibleViewHelpDialogContent(this._goToSymbolsSupported()),
|
||||
() => {
|
||||
this._contextViewService.hideContextView();
|
||||
// HACK: Delay to allow the context view to hide #207638
|
||||
@@ -720,7 +717,7 @@ export class AccessibleView extends Disposable {
|
||||
accessibleViewHelpProvider = new ExtensionContentProvider(
|
||||
lastProvider.id as AccessibleViewProviderId,
|
||||
{ type: AccessibleViewType.Help },
|
||||
() => lastProvider.options.customHelp ? lastProvider?.options.customHelp() : this._getAccessibleViewHelpDialogContent(this._goToSymbolsSupported()),
|
||||
() => lastProvider.options.customHelp ? lastProvider?.options.customHelp() : this._accessibleViewHelpDialogContent(this._goToSymbolsSupported()),
|
||||
() => {
|
||||
this._contextViewService.hideContextView();
|
||||
// HACK: Delay to allow the context view to hide #207638
|
||||
@@ -735,9 +732,9 @@ export class AccessibleView extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private _getAccessibleViewHelpDialogContent(providerHasSymbols?: boolean): string {
|
||||
const navigationHint = this._getNavigationHint();
|
||||
const goToSymbolHint = this._getGoToSymbolHint(providerHasSymbols);
|
||||
private _accessibleViewHelpDialogContent(providerHasSymbols?: boolean): string {
|
||||
const navigationHint = this._navigationHint();
|
||||
const goToSymbolHint = this._goToSymbolHint(providerHasSymbols);
|
||||
const toolbarHint = localize('toolbar', "Navigate to the toolbar (Shift+Tab).");
|
||||
const chatHints = this._getChatHints();
|
||||
|
||||
@@ -766,20 +763,61 @@ export class AccessibleView extends Disposable {
|
||||
localize('runInTerminal', " - Run the code block in the terminal<keybinding:'workbench.action.chat.runInTerminal>.\n")].join('\n');
|
||||
}
|
||||
|
||||
private _getNavigationHint(): string {
|
||||
private _navigationHint(): string {
|
||||
return localize('accessibleViewNextPreviousHint', "Show the next item<keybinding:{0}> or previous item<keybinding:{1}>.", AccessibilityCommandId.ShowNext, AccessibilityCommandId.ShowPrevious);
|
||||
}
|
||||
|
||||
private _getDisableVerbosityHint(): string {
|
||||
return localize('acessibleViewDisableHint', "\n\nDisable accessibility verbosity for this feature<keybinding:{0}>.", AccessibilityCommandId.DisableVerbosityHint);
|
||||
private _disableVerbosityHint(provider: AccesibleViewContentProvider): string {
|
||||
if (provider.options.type === AccessibleViewType.Help && this._verbosityEnabled()) {
|
||||
return localize('acessibleViewDisableHint', "\n\nDisable accessibility verbosity for this feature<keybinding:{0}>.", AccessibilityCommandId.DisableVerbosityHint);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
private _getGoToSymbolHint(providerHasSymbols?: boolean): string | undefined {
|
||||
private _goToSymbolHint(providerHasSymbols?: boolean): string | undefined {
|
||||
if (!providerHasSymbols) {
|
||||
return;
|
||||
}
|
||||
return localize('goToSymbolHint', 'Go to a symbol<keybinding:{0}>.', AccessibilityCommandId.GoToSymbol);
|
||||
}
|
||||
|
||||
private _configureUnassignedKbHint(): string {
|
||||
const configureKb = this._keybindingService.lookupKeybinding(AccessibilityCommandId.AccessibilityHelpConfigureKeybindings)?.getAriaLabel();
|
||||
const keybindingToConfigureQuickPick = configureKb ? '(' + configureKb + ')' : 'by assigning a keybinding to the command Accessibility Help Configure Keybindings.';
|
||||
return localize('configureKb', '\n\nConfigure keybindings for commands that lack them {0}.', keybindingToConfigureQuickPick);
|
||||
}
|
||||
|
||||
private _configureAssignedKbHint(): string {
|
||||
const configureKb = this._keybindingService.lookupKeybinding(AccessibilityCommandId.AccessibilityHelpConfigureAssignedKeybindings)?.getAriaLabel();
|
||||
const keybindingToConfigureQuickPick = configureKb ? '(' + configureKb + ')' : 'by assigning a keybinding to the command Accessibility Help Configure Assigned Keybindings.';
|
||||
return localize('configureKbAssigned', '\n\nConfigure keybindings for commands that already have assignments {0}.', keybindingToConfigureQuickPick);
|
||||
}
|
||||
|
||||
private _screenReaderModeHint(provider: AccesibleViewContentProvider): string {
|
||||
const accessibilitySupport = this._accessibilityService.isScreenReaderOptimized();
|
||||
let screenReaderModeHint = '';
|
||||
const turnOnMessage = (
|
||||
isMacintosh
|
||||
? AccessibilityHelpNLS.changeConfigToOnMac
|
||||
: AccessibilityHelpNLS.changeConfigToOnWinLinux
|
||||
);
|
||||
if (accessibilitySupport && provider.id === AccessibleViewProviderId.Editor) {
|
||||
screenReaderModeHint = AccessibilityHelpNLS.auto_on;
|
||||
screenReaderModeHint += '\n';
|
||||
} else if (!accessibilitySupport) {
|
||||
screenReaderModeHint = AccessibilityHelpNLS.auto_off + '\n' + turnOnMessage;
|
||||
screenReaderModeHint += '\n';
|
||||
}
|
||||
return screenReaderModeHint;
|
||||
}
|
||||
|
||||
private _exitDialogHint(provider: AccesibleViewContentProvider): string {
|
||||
return this._verbosityEnabled() && !provider.options.position ? localize('exit', '\n\nExit this dialog (Escape).') : '';
|
||||
}
|
||||
|
||||
private _readMoreHint(provider: AccesibleViewContentProvider): string {
|
||||
return provider.options.readMoreUrl ? localize("openDoc", "\n\nOpen a browser window with more information related to accessibility<keybinding:{0}>.", AccessibilityCommandId.AccessibilityHelpOpenHelpLink) : '';
|
||||
}
|
||||
}
|
||||
|
||||
export class AccessibleViewService extends Disposable implements IAccessibleViewService {
|
||||
@@ -800,8 +838,8 @@ export class AccessibleViewService extends Disposable implements IAccessibleView
|
||||
}
|
||||
this._accessibleView.show(provider, undefined, undefined, position);
|
||||
}
|
||||
configureKeybindings(): void {
|
||||
this._accessibleView?.configureKeybindings();
|
||||
configureKeybindings(unassigned: boolean): void {
|
||||
this._accessibleView?.configureKeybindings(unassigned);
|
||||
}
|
||||
openHelpLink(): void {
|
||||
this._accessibleView?.openHelpLink();
|
||||
|
||||
@@ -62,7 +62,6 @@ class AccessibleViewNextCodeBlockAction extends Action2 {
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.PageDown, },
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
},
|
||||
// to
|
||||
icon: Codicon.arrowRight,
|
||||
menu:
|
||||
{
|
||||
@@ -242,11 +241,29 @@ class AccessibilityHelpConfigureKeybindingsAction extends Action2 {
|
||||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor): Promise<void> {
|
||||
await accessor.get(IAccessibleViewService).configureKeybindings();
|
||||
await accessor.get(IAccessibleViewService).configureKeybindings(true);
|
||||
}
|
||||
}
|
||||
registerAction2(AccessibilityHelpConfigureKeybindingsAction);
|
||||
|
||||
class AccessibilityHelpConfigureAssignedKeybindingsAction extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: AccessibilityCommandId.AccessibilityHelpConfigureAssignedKeybindings,
|
||||
precondition: ContextKeyExpr.and(accessibilityHelpIsShown),
|
||||
keybinding: {
|
||||
primary: KeyMod.Alt | KeyCode.KeyA,
|
||||
weight: KeybindingWeight.WorkbenchContrib
|
||||
},
|
||||
title: localize('editor.action.accessibilityHelpConfigureAssignedKeybindings', "Accessibility Help Configure Assigned Keybindings")
|
||||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor): Promise<void> {
|
||||
await accessor.get(IAccessibleViewService).configureKeybindings(false);
|
||||
}
|
||||
}
|
||||
registerAction2(AccessibilityHelpConfigureAssignedKeybindingsAction);
|
||||
|
||||
|
||||
class AccessibilityHelpOpenHelpLinkAction extends Action2 {
|
||||
constructor() {
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
import { MarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IPickerQuickAccessItem } from 'vs/platform/quickinput/browser/pickerQuickAccess';
|
||||
import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands';
|
||||
|
||||
export function resolveContentAndKeybindingItems(keybindingService: IKeybindingService, value?: string): { content: MarkdownString; configureKeybindingItems: IPickerQuickAccessItem[] | undefined } | undefined {
|
||||
export function resolveContentAndKeybindingItems(keybindingService: IKeybindingService, value?: string): { content: MarkdownString; configureKeybindingItems: IPickerQuickAccessItem[] | undefined; configuredKeybindingItems: IPickerQuickAccessItem[] | undefined } | undefined {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
const configureKeybindingItems: IPickerQuickAccessItem[] = [];
|
||||
const configuredKeybindingItems: IPickerQuickAccessItem[] = [];
|
||||
const matches = value.matchAll(/\<keybinding:(?<commandId>.*)\>/gm);
|
||||
for (const match of [...matches]) {
|
||||
const commandId = match?.groups?.commandId;
|
||||
@@ -20,21 +20,23 @@ export function resolveContentAndKeybindingItems(keybindingService: IKeybindingS
|
||||
if (match?.length && commandId) {
|
||||
const keybinding = keybindingService.lookupKeybinding(commandId)?.getAriaLabel();
|
||||
if (!keybinding) {
|
||||
const configureKb = keybindingService.lookupKeybinding(AccessibilityCommandId.AccessibilityHelpConfigureKeybindings)?.getAriaLabel();
|
||||
const keybindingToConfigureQuickPick = configureKb ? '(' + configureKb + ')' : 'by assigning a keybinding to the command Accessibility Help Configure Keybindings.';
|
||||
kbLabel = `, configure a keybinding ` + keybindingToConfigureQuickPick;
|
||||
kbLabel = ` (unassigned keybinding)`;
|
||||
configureKeybindingItems.push({
|
||||
label: commandId,
|
||||
id: commandId
|
||||
});
|
||||
} else {
|
||||
kbLabel = ' (' + keybinding + ')';
|
||||
configuredKeybindingItems.push({
|
||||
label: commandId,
|
||||
id: commandId
|
||||
});
|
||||
}
|
||||
value = value.replace(match[0], kbLabel);
|
||||
}
|
||||
}
|
||||
const content = new MarkdownString(value);
|
||||
content.isTrusted = true;
|
||||
return { content, configureKeybindingItems: configureKeybindingItems.length ? configureKeybindingItems : undefined };
|
||||
return { content, configureKeybindingItems: configureKeybindingItems.length ? configureKeybindingItems : undefined, configuredKeybindingItems: configuredKeybindingItems.length ? configuredKeybindingItems : undefined };
|
||||
}
|
||||
|
||||
|
||||
@@ -14,5 +14,6 @@ export const enum AccessibilityCommandId {
|
||||
NextCodeBlock = 'editor.action.accessibleViewNextCodeBlock',
|
||||
PreviousCodeBlock = 'editor.action.accessibleViewPreviousCodeBlock',
|
||||
AccessibilityHelpConfigureKeybindings = 'editor.action.accessibilityHelpConfigureKeybindings',
|
||||
AccessibilityHelpConfigureAssignedKeybindings = 'editor.action.accessibilityHelpConfigureAssignedKeybindings',
|
||||
AccessibilityHelpOpenHelpLink = 'editor.action.accessibilityHelpOpenHelpLink',
|
||||
}
|
||||
|
||||
@@ -139,6 +139,7 @@ export interface IChatWidget {
|
||||
readonly onDidAcceptInput: Event<void>;
|
||||
readonly onDidHide: Event<void>;
|
||||
readonly onDidSubmitAgent: Event<{ agent: IChatAgentData; slashCommand?: IChatAgentCommand }>;
|
||||
readonly onDidChangeAgent: Event<{ agent: IChatAgentData; slashCommand?: IChatAgentCommand }>;
|
||||
readonly onDidChangeParsedInput: Event<void>;
|
||||
readonly onDidChangeContext: Event<{ removed?: IChatRequestVariableEntry[]; added?: IChatRequestVariableEntry[] }>;
|
||||
readonly location: ChatAgentLocation;
|
||||
|
||||
@@ -88,6 +88,9 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
private readonly _onDidSubmitAgent = this._register(new Emitter<{ agent: IChatAgentData; slashCommand?: IChatAgentCommand }>());
|
||||
public readonly onDidSubmitAgent = this._onDidSubmitAgent.event;
|
||||
|
||||
private _onDidChangeAgent = this._register(new Emitter<{ agent: IChatAgentData; slashCommand?: IChatAgentCommand }>());
|
||||
readonly onDidChangeAgent = this._onDidChangeAgent.event;
|
||||
|
||||
private _onDidFocus = this._register(new Emitter<void>());
|
||||
readonly onDidFocus = this._onDidFocus.event;
|
||||
|
||||
@@ -688,6 +691,11 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
c.setInputState(viewState.inputState?.[c.id]);
|
||||
}
|
||||
});
|
||||
this.viewModelDisposables.add(model.onDidChange((e) => {
|
||||
if (e.kind === 'setAgent') {
|
||||
this._onDidChangeAgent.fire({ agent: e.agent, slashCommand: e.command });
|
||||
}
|
||||
}));
|
||||
|
||||
if (this.tree) {
|
||||
this.onDidChangeItems();
|
||||
|
||||
@@ -242,12 +242,22 @@ class InputEditorSlashCommandMode extends Disposable {
|
||||
private readonly widget: IChatWidget
|
||||
) {
|
||||
super();
|
||||
this._register(this.widget.onDidChangeAgent(e => {
|
||||
if (e.slashCommand && e.slashCommand.isSticky || !e.slashCommand && e.agent.metadata.isSticky) {
|
||||
this.repopulateAgentCommand(e.agent, e.slashCommand);
|
||||
}
|
||||
}));
|
||||
this._register(this.widget.onDidSubmitAgent(e => {
|
||||
this.repopulateAgentCommand(e.agent, e.slashCommand);
|
||||
}));
|
||||
}
|
||||
|
||||
private async repopulateAgentCommand(agent: IChatAgentData, slashCommand: IChatAgentCommand | undefined) {
|
||||
// Make sure we don't repopulate if the user already has something in the input
|
||||
if (this.widget.inputEditor.getValue().trim()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let value: string | undefined;
|
||||
if (slashCommand && slashCommand.isSticky) {
|
||||
value = `${chatAgentLeader}${agent.name} ${chatSubcommandLeader}${slashCommand.name} `;
|
||||
|
||||
@@ -545,7 +545,8 @@ export function isSerializableSessionData(obj: unknown): obj is ISerializableCha
|
||||
export type IChatChangeEvent =
|
||||
| IChatInitEvent
|
||||
| IChatAddRequestEvent | IChatChangedRequestEvent | IChatRemoveRequestEvent
|
||||
| IChatAddResponseEvent;
|
||||
| IChatAddResponseEvent
|
||||
| IChatSetAgentEvent;
|
||||
|
||||
export interface IChatAddRequestEvent {
|
||||
kind: 'addRequest';
|
||||
@@ -586,6 +587,12 @@ export interface IChatRemoveRequestEvent {
|
||||
reason: ChatRequestRemovalReason;
|
||||
}
|
||||
|
||||
export interface IChatSetAgentEvent {
|
||||
kind: 'setAgent';
|
||||
agent: IChatAgentData;
|
||||
command?: IChatAgentCommand;
|
||||
}
|
||||
|
||||
export interface IChatInitEvent {
|
||||
kind: 'initialize';
|
||||
}
|
||||
@@ -892,6 +899,7 @@ export class ChatModel extends Disposable implements IChatModel {
|
||||
const agent = this.chatAgentService.getAgent(progress.agentId);
|
||||
if (agent) {
|
||||
request.response.setAgent(agent, progress.command);
|
||||
this._onDidChange.fire({ kind: 'setAgent', agent, command: progress.command });
|
||||
}
|
||||
} else {
|
||||
this.logService.error(`Couldn't handle progress: ${JSON.stringify(progress)}`);
|
||||
|
||||
@@ -11,7 +11,7 @@ import { CodeActionsExtensionPoint, codeActionsExtensionPointDescriptor } from '
|
||||
import { DocumentationExtensionPoint, documentationExtensionPointDescriptor } from 'vs/workbench/contrib/codeActions/common/documentationExtensionPoint';
|
||||
import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { CodeActionsContribution, editorConfiguration } from './codeActionsContribution';
|
||||
import { CodeActionsContribution, editorConfiguration, notebookEditorConfiguration } from './codeActionsContribution';
|
||||
import { CodeActionDocumentationContribution } from './documentationContribution';
|
||||
|
||||
const codeActionsExtensionPoint = ExtensionsRegistry.registerExtensionPoint<CodeActionsExtensionPoint[]>(codeActionsExtensionPointDescriptor);
|
||||
@@ -20,6 +20,9 @@ const documentationExtensionPoint = ExtensionsRegistry.registerExtensionPoint<Do
|
||||
Registry.as<IConfigurationRegistry>(Extensions.Configuration)
|
||||
.registerConfiguration(editorConfiguration);
|
||||
|
||||
Registry.as<IConfigurationRegistry>(Extensions.Configuration)
|
||||
.registerConfiguration(notebookEditorConfiguration);
|
||||
|
||||
class WorkbenchConfigurationContribution {
|
||||
constructor(
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
|
||||
@@ -35,6 +35,21 @@ const createCodeActionsAutoSave = (description: string): IJSONSchema => {
|
||||
};
|
||||
};
|
||||
|
||||
const createNotebookCodeActionsAutoSave = (description: string): IJSONSchema => {
|
||||
return {
|
||||
type: ['string', 'boolean'],
|
||||
enum: ['explicit', 'never', true, false],
|
||||
enumDescriptions: [
|
||||
nls.localize('explicit', 'Triggers Code Actions only when explicitly saved.'),
|
||||
nls.localize('never', 'Never triggers Code Actions on save.'),
|
||||
nls.localize('explicitBoolean', 'Triggers Code Actions only when explicitly saved. This value will be deprecated in favor of "explicit".'),
|
||||
nls.localize('neverBoolean', 'Triggers Code Actions only when explicitly saved. This value will be deprecated in favor of "never".')
|
||||
],
|
||||
default: 'explicit',
|
||||
description: description
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
const codeActionsOnSaveSchema: IConfigurationPropertySchema = {
|
||||
oneOf: [
|
||||
@@ -66,6 +81,37 @@ export const editorConfiguration = Object.freeze<IConfigurationNode>({
|
||||
}
|
||||
});
|
||||
|
||||
const notebookCodeActionsOnSaveSchema: IConfigurationPropertySchema = {
|
||||
oneOf: [
|
||||
{
|
||||
type: 'object',
|
||||
additionalProperties: {
|
||||
type: 'string'
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'array',
|
||||
items: { type: 'string' }
|
||||
}
|
||||
],
|
||||
markdownDescription: nls.localize('notebook.codeActionsOnSave', 'Run a series of Code Actions for a notebook on save. Code Actions must be specified, the file must not be saved after delay, and the editor must not be shutting down. Example: `"notebook.source.organizeImports": "explicit"`'),
|
||||
type: 'object',
|
||||
additionalProperties: {
|
||||
type: ['string', 'boolean'],
|
||||
enum: ['explicit', 'never', true, false],
|
||||
// enum: ['explicit', 'always', 'never'], -- autosave support needs to be built first
|
||||
// nls.localize('always', 'Always triggers Code Actions on save, including autosave, focus, and window change events.'),
|
||||
},
|
||||
default: {}
|
||||
};
|
||||
|
||||
export const notebookEditorConfiguration = Object.freeze<IConfigurationNode>({
|
||||
...editorConfigurationBaseNode,
|
||||
properties: {
|
||||
'notebook.codeActionsOnSave': notebookCodeActionsOnSaveSchema
|
||||
}
|
||||
});
|
||||
|
||||
export class CodeActionsContribution extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
private _contributedCodeActions: CodeActionsExtensionPoint[] = [];
|
||||
@@ -81,7 +127,6 @@ export class CodeActionsContribution extends Disposable implements IWorkbenchCon
|
||||
super();
|
||||
|
||||
// TODO: @justschen caching of code actions based on extensions loaded: https://github.com/microsoft/vscode/issues/216019
|
||||
|
||||
languageFeatures.codeActionProvider.onDidChange(() => {
|
||||
this.updateSettingsFromCodeActionProviders();
|
||||
this.updateConfigurationSchemaFromContribs();
|
||||
@@ -114,23 +159,29 @@ export class CodeActionsContribution extends Disposable implements IWorkbenchCon
|
||||
|
||||
private updateConfigurationSchema(codeActionContributions: readonly CodeActionsExtensionPoint[]) {
|
||||
const newProperties: IJSONSchemaMap = {};
|
||||
const newNotebookProperties: IJSONSchemaMap = {};
|
||||
for (const [sourceAction, props] of this.getSourceActions(codeActionContributions)) {
|
||||
this.settings.add(sourceAction);
|
||||
newProperties[sourceAction] = createCodeActionsAutoSave(nls.localize('codeActionsOnSave.generic', "Controls whether '{0}' actions should be run on file save.", props.title));
|
||||
newNotebookProperties[sourceAction] = createNotebookCodeActionsAutoSave(nls.localize('codeActionsOnSave.generic', "Controls whether '{0}' actions should be run on file save.", props.title));
|
||||
}
|
||||
codeActionsOnSaveSchema.properties = newProperties;
|
||||
notebookCodeActionsOnSaveSchema.properties = newNotebookProperties;
|
||||
Registry.as<IConfigurationRegistry>(Extensions.Configuration)
|
||||
.notifyConfigurationSchemaUpdated(editorConfiguration);
|
||||
}
|
||||
|
||||
private updateConfigurationSchemaFromContribs() {
|
||||
const properties: IJSONSchemaMap = { ...codeActionsOnSaveSchema.properties };
|
||||
const notebookProperties: IJSONSchemaMap = { ...notebookCodeActionsOnSaveSchema.properties };
|
||||
for (const codeActionKind of this.settings) {
|
||||
if (!properties[codeActionKind]) {
|
||||
properties[codeActionKind] = createCodeActionsAutoSave(nls.localize('codeActionsOnSave.generic', "Controls whether '{0}' actions should be run on file save.", codeActionKind));
|
||||
notebookProperties[codeActionKind] = createNotebookCodeActionsAutoSave(nls.localize('codeActionsOnSave.generic', "Controls whether '{0}' actions should be run on file save.", codeActionKind));
|
||||
}
|
||||
}
|
||||
codeActionsOnSaveSchema.properties = properties;
|
||||
notebookCodeActionsOnSaveSchema.properties = notebookProperties;
|
||||
Registry.as<IConfigurationRegistry>(Extensions.Configuration)
|
||||
.notifyConfigurationSchemaUpdated(editorConfiguration);
|
||||
}
|
||||
|
||||
@@ -628,7 +628,7 @@ configurationRegistry.registerConfiguration({
|
||||
nls.localize('debug.autoExpandLazyVariables.on', "Always automatically expand lazy variables."),
|
||||
nls.localize('debug.autoExpandLazyVariables.off', "Never automatically expand lazy variables.")
|
||||
],
|
||||
description: nls.localize('debug.autoExpandLazyVariables', "Controls if variables, such as getters, are automatically resolved and expanded by the debugger.")
|
||||
description: nls.localize('debug.autoExpandLazyVariables', "Controls whether variables that are lazily resolved, such as getters, are automatically resolved and expanded by the debugger.")
|
||||
},
|
||||
'debug.enableStatusBarColor': {
|
||||
type: 'boolean',
|
||||
|
||||
@@ -28,8 +28,7 @@ export class DebugExtensionHostAction extends Action {
|
||||
super(DebugExtensionHostAction.ID, DebugExtensionHostAction.LABEL, DebugExtensionHostAction.CSS_CLASS);
|
||||
}
|
||||
|
||||
override async run(): Promise<any> {
|
||||
|
||||
override async run(args: unknown): Promise<any> {
|
||||
const inspectPorts = await this._extensionService.getInspectPorts(ExtensionHostKind.LocalProcess, false);
|
||||
if (inspectPorts.length === 0) {
|
||||
const res = await this._dialogService.confirm({
|
||||
@@ -49,11 +48,15 @@ export class DebugExtensionHostAction extends Action {
|
||||
console.warn(`There are multiple extension hosts available for debugging. Picking the first one...`);
|
||||
}
|
||||
|
||||
return this._debugService.startDebugging(undefined, {
|
||||
type: 'node',
|
||||
name: nls.localize('debugExtensionHost.launch.name', "Attach Extension Host"),
|
||||
request: 'attach',
|
||||
port: inspectPorts[0].port,
|
||||
});
|
||||
if (args !== undefined && (args as any)[0].dryRun) {
|
||||
return { inspectPorts };
|
||||
} else {
|
||||
return this._debugService.startDebugging(undefined, {
|
||||
type: 'node',
|
||||
name: nls.localize('debugExtensionHost.launch.name', "Attach Extension Host"),
|
||||
request: 'attach',
|
||||
port: inspectPorts[0].port,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,9 +77,9 @@ workbenchRegistry.registerWorkbenchContribution(ExtensionsAutoProfiler, Lifecycl
|
||||
workbenchRegistry.registerWorkbenchContribution(RemoteExtensionsInitializerContribution, LifecyclePhase.Restored);
|
||||
// Register Commands
|
||||
|
||||
CommandsRegistry.registerCommand(DebugExtensionHostAction.ID, (accessor: ServicesAccessor) => {
|
||||
CommandsRegistry.registerCommand(DebugExtensionHostAction.ID, (accessor: ServicesAccessor, ...args) => {
|
||||
const instantiationService = accessor.get(IInstantiationService);
|
||||
instantiationService.createInstance(DebugExtensionHostAction).run();
|
||||
return instantiationService.createInstance(DebugExtensionHostAction).run(args);
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand(StartExtensionHostProfileAction.ID, (accessor: ServicesAccessor) => {
|
||||
|
||||
@@ -1004,18 +1004,6 @@ configurationRegistry.registerConfiguration({
|
||||
tags: ['notebookLayout'],
|
||||
default: false
|
||||
},
|
||||
[NotebookSetting.codeActionsOnSave]: {
|
||||
markdownDescription: nls.localize('notebook.codeActionsOnSave', 'Run a series of Code Actions for a notebook on save. Code Actions must be specified, the file must not be saved after delay, and the editor must not be shutting down. Example: `"notebook.source.organizeImports": "explicit"`'),
|
||||
type: 'object',
|
||||
additionalProperties: {
|
||||
type: ['string', 'boolean'],
|
||||
enum: ['explicit', 'never', true, false],
|
||||
// enum: ['explicit', 'always', 'never'], -- autosave support needs to be built first
|
||||
// nls.localize('always', 'Always triggers Code Actions on save, including autosave, focus, and window change events.'),
|
||||
enumDescriptions: [nls.localize('explicit', 'Triggers Code Actions only when explicitly saved.'), nls.localize('never', 'Never triggers Code Actions on save.'), nls.localize('explicitBoolean', 'Triggers Code Actions only when explicitly saved. This value will be deprecated in favor of "explicit".'), nls.localize('neverBoolean', 'Triggers Code Actions only when explicitly saved. This value will be deprecated in favor of "never".')],
|
||||
},
|
||||
default: {}
|
||||
},
|
||||
[NotebookSetting.formatOnCellExecution]: {
|
||||
markdownDescription: nls.localize('notebook.formatOnCellExecution', "Format a notebook cell upon execution. A formatter must be available."),
|
||||
type: 'boolean',
|
||||
|
||||
@@ -72,11 +72,11 @@ export class SCMActiveRepositoryController extends Disposable implements IWorkbe
|
||||
switch (this._countBadgeConfig.read(reader)) {
|
||||
case 'all': {
|
||||
const repositories = this._repositories.read(reader);
|
||||
return [...Iterable.map(repositories, r => ({ ...r.provider, resourceCount: this._getRepositoryResourceCount(r) }))];
|
||||
return [...Iterable.map(repositories, r => ({ provider: r.provider, resourceCount: this._getRepositoryResourceCount(r) }))];
|
||||
}
|
||||
case 'focused': {
|
||||
const repository = this._activeRepository.read(reader);
|
||||
return repository ? [{ ...repository.provider, resourceCount: this._getRepositoryResourceCount(repository) }] : [];
|
||||
return repository ? [{ provider: repository.provider, resourceCount: this._getRepositoryResourceCount(repository) }] : [];
|
||||
}
|
||||
case 'off':
|
||||
return [];
|
||||
@@ -89,7 +89,7 @@ export class SCMActiveRepositoryController extends Disposable implements IWorkbe
|
||||
let total = 0;
|
||||
|
||||
for (const repository of this._countBadgeRepositories.read(reader)) {
|
||||
const count = repository.count?.read(reader);
|
||||
const count = repository.provider.count?.read(reader);
|
||||
const resourceCount = repository.resourceCount.read(reader);
|
||||
|
||||
total = total + (count ?? resourceCount);
|
||||
|
||||
@@ -112,15 +112,15 @@ __vsc_escape_value() {
|
||||
fi
|
||||
|
||||
# Process text byte by byte, not by codepoint.
|
||||
local -r LC_ALL=C
|
||||
local -r str="${1}"
|
||||
local -ir len="${#str}"
|
||||
builtin local -r LC_ALL=C
|
||||
builtin local -r str="${1}"
|
||||
builtin local -ir len="${#str}"
|
||||
|
||||
local -i i
|
||||
local -i val
|
||||
local byte
|
||||
local token
|
||||
local out=''
|
||||
builtin local -i i
|
||||
builtin local -i val
|
||||
builtin local byte
|
||||
builtin local token
|
||||
builtin local out=''
|
||||
|
||||
for (( i=0; i < "${#str}"; ++i )); do
|
||||
# Escape backslashes, semi-colons specially, then special ASCII chars below space (0x20).
|
||||
@@ -326,7 +326,7 @@ __vsc_prompt_cmd_original() {
|
||||
__vsc_restore_exit_code "${__vsc_status}"
|
||||
# Evaluate the original PROMPT_COMMAND similarly to how bash would normally
|
||||
# See https://unix.stackexchange.com/a/672843 for technique
|
||||
local cmd
|
||||
builtin local cmd
|
||||
for cmd in "${__vsc_original_prompt_command[@]}"; do
|
||||
eval "${cmd:-}"
|
||||
done
|
||||
|
||||
@@ -159,7 +159,7 @@ __vsc_update_prompt() {
|
||||
}
|
||||
|
||||
__vsc_precmd() {
|
||||
local __vsc_status="$?"
|
||||
builtin local __vsc_status="$?"
|
||||
if [ -z "${__vsc_in_command_execution-}" ]; then
|
||||
# not in command execution
|
||||
__vsc_command_output_start
|
||||
|
||||
@@ -10,7 +10,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { ThemeIcon } from 'vs/base/common/themables';
|
||||
import { ITerminalGroupService, ITerminalInstance, ITerminalService, TerminalDataTransfers } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ITerminalConfigurationService, ITerminalGroupService, ITerminalInstance, ITerminalService, TerminalDataTransfers } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { localize } from 'vs/nls';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -52,6 +52,7 @@ import { getColorForSeverity } from 'vs/workbench/contrib/terminal/browser/termi
|
||||
import { TerminalContextActionRunner } from 'vs/workbench/contrib/terminal/browser/terminalContextMenu';
|
||||
import type { IHoverAction } from 'vs/base/browser/ui/hover/hover';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { HoverPosition } from 'vs/base/browser/ui/hover/hoverWidget';
|
||||
|
||||
const $ = DOM.$;
|
||||
|
||||
@@ -250,6 +251,7 @@ class TerminalTabsRenderer implements IListRenderer<ITerminalInstance, ITerminal
|
||||
private readonly _labels: ResourceLabels,
|
||||
private readonly _getSelection: () => ITerminalInstance[],
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@ITerminalConfigurationService private readonly _terminalConfigurationService: ITerminalConfigurationService,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService,
|
||||
@ITerminalGroupService private readonly _terminalGroupService: ITerminalGroupService,
|
||||
@IHoverService private readonly _hoverService: IHoverService,
|
||||
@@ -274,8 +276,15 @@ class TerminalTabsRenderer implements IListRenderer<ITerminalInstance, ITerminal
|
||||
return this._hoverService.showHover({
|
||||
...options,
|
||||
actions: context.hoverActions,
|
||||
target: element,
|
||||
persistence: {
|
||||
hideOnHover: true
|
||||
},
|
||||
appearance: {
|
||||
showPointer: true
|
||||
},
|
||||
position: {
|
||||
hoverPosition: this._terminalConfigurationService.config.tabs.location === 'left' ? HoverPosition.RIGHT : HoverPosition.LEFT
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10300,10 +10300,10 @@ typescript@^4.7.4:
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6"
|
||||
integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==
|
||||
|
||||
typescript@^5.6.0-dev.20240711:
|
||||
version "5.6.0-dev.20240711"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.0-dev.20240711.tgz#2190141012fd1f3a535c13c7d4ba258c13ab4d74"
|
||||
integrity sha512-7P96lBbF9T4qBB2IseUQBz/IakXa9a0zLOywLmWTZQB6EFbRnRMlwa7103Q44mwI8tfvdXRmed3ICuxHxSNUwA==
|
||||
typescript@^5.6.0-dev.20240715:
|
||||
version "5.6.0-dev.20240715"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.0-dev.20240715.tgz#18b9e994f99916b90917943d5de8e78f781d1d70"
|
||||
integrity sha512-CLF8WFoqLgHgxQqjklkEOw3gT99Y2YNU4+TfkJurX5bfejAUYpb2jBjiYOn5Rq9HCew6ceZlRaG7Q++6/fBvVA==
|
||||
|
||||
typical@^4.0.0:
|
||||
version "4.0.0"
|
||||
|
||||
Reference in New Issue
Block a user