-
Notifications
You must be signed in to change notification settings - Fork 29.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow Extensions To Contribute Language Specific Settings #26707
Comments
It'd be really neat if the flow worked the other way: if the extension didn't need to know about what language is currently being used, but instead vscode simply changed the setting appropriately for the extension when a file of a different type was opened. That would mean that things like |
@mjbvz You can contribute default language specific settings as follows
Above should work. Regarding API, agreed that we need better support there. |
@mjbvz Ignore my earlier comment, I misunderstood with configuration defaults. |
I don't think this would work very well as you can have multiple files open side-by-side (there may also be side effects of firing config change events frequently if extensions currently only expect them to happen infrequently). I think it'd be much better to design something sane and have cooperation of extensions than try to make it work transparently. |
On a side note, it might be good to add something to the doc. Took me a while to understand how to allow per language customization for my extension. Thanks to @mjbvz for this useful example. Json validation/intellisense might be hard to solve (I am not familiar with Json schema), but adding a |
Something that I would love the most for extensions would be "files.associations": {
"**/templates/*.html": "django-html",
"**/templates/*": "django-txt",
"**/requirements{/**,*}.{txt,in}": "pip-requirements"
}, |
@batisteo How is your comment is related to this feature request? |
@sandy081 I was maybe confused with your comment, so if this feature request has nothing to do with |
@batisteo So you want |
An additional specific use-case: I want to disable GitLens's per-line blame annotations when working on Haskell files, because I have other plugins that show type information there. So I'd like to be able to put in my config something like: "gitlens.currentLine.enabled": true,
"[haskell]": {
"gitlens.currentLine.enabled": false,
}, |
I'm also looking for a way to do something like this. If anyone has an idea on how to accomplish that for arbitrary extension setting let me know! 😁 |
@eamodio I am still unsure about your use case to access settings only with the language. Can you please elaborate how are you accessing such settings and applying them. |
@sandy081 In GitLens I have 2 settings that control the scopes for where code lens should be rendered: So when I am providing code lens for a document, I look up the config for the current document uri and check So ideally I'd remove So for the reading side -- I think the current proposal works for my usage, but where it gets challenging if the inspection/updating part. I also currently only support configuring But if Does that make sense? |
@eamodio Thanks for the summary. If I understand correctly, In short your use case is to allow display/configuring a setting per language in Gitlens Settings UI. It means given a setting you want to know, which languages it is being overridden? Re writing, current API (by making resource optional in the scope) supports writing a setting under a language or not. /**
* Read language configuration.
*/
const textDocumentConfiguration = vscode.workspace.getConfiguration('sample', {languageId});
textDocumentConfiguration.get('languageSetting');
/**
* Write configuration
*/
textDocumentConfiguration.update('languageSetting', false, ConfigurationTarget.Global);
/**
* Write configuration under language
*/
textDocumentConfiguration.update('languageSetting', false, ConfigurationTarget.Global, true); |
@sandy081 would calling |
It will, if the setting is already overridden by the language in the given configuration target.
I do not think there is a way to do that even now. You can only remove the setting given the target. Now you can do the same for the language.
Is this for building the UI to show the value for a given setting for languages? |
Yeah, or at least signaling in the UI that the current setting might not always take effect (because I doubt I'll build the full UI for that). Also the inspect would be needed, if I wanted to force-ably reset a setting -- because I'd need to know all the language overrides and then |
Makes sense. How about having |
I was more thinking something like: inspect<T>(section: string): {
key: string;
defaultValue?: T;
globalValue?: T;
workspaceValue?: T,
workspaceFolderValue?: T,
languages?: {
languageId: string;
defaultValue?: T;
globalValue?: T;
workspaceValue?: T,
workspaceFolderValue?: T,
}[];
} | undefined; or inspect<T>(section: string): {
key: string;
defaultValue?: T;
globalValue?: T;
workspaceValue?: T,
workspaceFolderValue?: T,
languages?: {
[languageId: string]: {
defaultValue?: T;
globalValue?: T;
workspaceValue?: T,
workspaceFolderValue?: T,
}
}
} | undefined; |
I think above proposal makes sense if inspect<T>(section: string): {
key: string;
defaultValue?: T;
globalValue?: T;
workspaceValue?: T,
workspaceFolderValue?: T,
defaultLanguageValue?: T;
userLanguageValue?: T;
workspaceLanguageValue?: T;
workspaceFolderLanguageValue?: T;
languages?: string[];
} | undefined; This is consistent with inspecting resource scope. Inspect result provides all languages in which the key is configured at. One can get the language values by scoping |
After writing doc, preferred to have slim Final SolutionIntroduced APIexport type ConfigurationScope = Uri | TextDocument | WorkspaceFolder | { uri?: Uri, languageId: string };
/**
* An event describing the change in Configuration
*/
export interface ConfigurationChangeEvent {
/**
* Returns `true` if the given section is affected in the provided scope.
*
* @param section Configuration name, supports _dotted_ names.
* @param scope A scope in which to check.
* @return `true` if the given section is affected in the provided scope.
*/
affectsConfiguration(section: string, scope?: ConfigurationScope): boolean;
}
export namespace workspace {
/**
* Get a workspace configuration object.
*
* When a section-identifier is provided only that part of the configuration
* is returned. Dots in the section-identifier are interpreted as child-access,
* like `{ myExt: { setting: { doIt: true }}}` and `getConfiguration('myExt.setting').get('doIt') === true`.
*
* When a scope is provided configuraiton confined to that scope is returned. Scope can be a resource or a language identifier or both.
*
* @param section A dot-separated identifier.
* @return The full configuration or a subset.
*/
export function getConfiguration(section?: string | undefined, scope?: ConfigurationScope | null): WorkspaceConfiguration;
}
/**
* Represents the configuration. It is a merged view of
*
* - *Default Settings*
* - *Global (User) Settings*
* - *Workspace settings*
* - *Workspace Folder settings* - From one of the [Workspace Folders](#workspace.workspaceFolders) under which requested resource belongs to.
* - *Language settings* - Settings defined under requested language.
*
* The *effective* value (returned by [`get`](#WorkspaceConfiguration.get)) is computed by overriding or merging the values in the following order.
*
* ```
* `defaultValue`
* `globalValue` (if defined)
* `workspaceValue` (if defined)
* `workspaceFolderValue` (if defined)
* `defaultLanguageValue` (if defined)
* `globalLanguageValue` (if defined)
* `workspaceLanguageValue` (if defined)
* `workspaceLanguageValue` (if defined)
* ```
* **Note:** Only `object` value types are merged and all other value types are overridden.
*
* Example 1: Overriding
*
* ```ts
* defaultValue = 'on';
* globalValue = 'relative'
* workspaceFolderValue = 'off'
* value = 'off'
* ```
*
* Example 2: Language Values
*
* ```ts
* defaultValue = 'on';
* globalValue = 'relative'
* workspaceFolderValue = 'off'
* globalLanguageValue = 'on'
* value = 'on'
* ```
*
* Example 3: Object Values
*
* ```ts
* defaultValue = { "a": 1, "b": 2 };
* globalValue = { "b": 3, "c": 4 };
* value = { "a": 1, "b": 3, "c": 4 };
* ```
*
* *Note:* Workspace and Workspace Folder configurations contains `launch` and `tasks` settings. Their basename will be
* part of the section identifier. The following snippets shows how to retrieve all configurations
* from `launch.json`:
*
* ```ts
* // launch.json configuration
* const config = workspace.getConfiguration('launch', vscode.workspace.workspaceFolders[0].uri);
*
* // retrieve values
* const values = config.get('configurations');
* ```
*
* Refer to [Settings](https://code.visualstudio.com/docs/getstarted/settings) for more information.
*/
export interface WorkspaceConfiguration {
/**
* Return a value from this configuration.
*
* @param section Configuration name, supports _dotted_ names.
* @return The value `section` denotes or `undefined`.
*/
get<T>(section: string): T | undefined;
/**
* Return a value from this configuration.
*
* @param section Configuration name, supports _dotted_ names.
* @param defaultValue A value should be returned when no value could be found, is `undefined`.
* @return The value `section` denotes or the default.
*/
get<T>(section: string, defaultValue: T): T;
/**
* Check if this configuration has a certain value.
*
* @param section Configuration name, supports _dotted_ names.
* @return `true` if the section doesn't resolve to `undefined`.
*/
has(section: string): boolean;
/**
* Retrieve all information about a configuration setting. A configuration value
* often consists of a *default* value, a global or installation-wide value,
* a workspace-specific value, folder-specific value
* and language-specific values (if [WorkspaceConfiguration](#WorkspaceConfiguration) is scoped to a language).
*
* Also provides all language ids under which the given configuration setting is defined.
*
* *Note:* The configuration name must denote a leaf in the configuration tree
* (`editor.fontSize` vs `editor`) otherwise no result is returned.
*
* @param section Configuration name, supports _dotted_ names.
* @return Information about a configuration setting or `undefined`.
*/
inspect<T>(section: string): {
key: string;
defaultValue?: T;
globalValue?: T;
workspaceValue?: T,
workspaceFolderValue?: T,
defaultLanguageValue?: T;
userLanguageValue?: T;
workspaceLanguageValue?: T;
workspaceFolderLanguageValue?: T;
languageIds?: string[];
} | undefined;
/**
* Update a configuration value. The updated configuration values are persisted.
*
* A value can be changed in
*
* - [Global settings](#ConfigurationTarget.Global): Changes the value for all instances of the editor.
* - [Workspace settings](#ConfigurationTarget.Workspace): Changes the value for current workspace, if available.
* - [Workspace folder settings](#ConfigurationTarget.WorkspaceFolder): Changes the value for settings from one of the [Workspace Folders](#workspace.workspaceFolders) under which the requested resource belongs to.
* - Language settings: Changes the value for the requested languageId.
*
* *Note:* To remove a configuration value use `undefined`, like so: `config.update('somekey', undefined)`
*
* @param section Configuration name, supports _dotted_ names.
* @param value The new value.
* @param configurationTarget The [configuration target](#ConfigurationTarget) or a boolean value.
* - If `true` updates [Global settings](#ConfigurationTarget.Global).
* - If `false` updates [Workspace settings](#ConfigurationTarget.Workspace).
* - If `undefined` or `null` updates to [Workspace folder settings](#ConfigurationTarget.WorkspaceFolder) if configuration is resource specific,
* otherwise to [Workspace settings](#ConfigurationTarget.Workspace).
* @param scopeToLanguage Whether to update the value in the scope of requested languageId or not.
* - If `true` updates the value under the requested languageId.
* - If `undefined` updates the value under the requested languageId only if the configuration is defined for the language.
* @throws error while updating
* - configuration which is not registered.
* - window configuration to workspace folder
* - configuration to workspace or workspace folder when no workspace is opened.
* - configuration to workspace folder when there is no workspace folder settings.
* - configuration to workspace folder when [WorkspaceConfiguration](#WorkspaceConfiguration) is not scoped to a resource.
*/
update(section: string, value: any, configurationTarget?: ConfigurationTarget | boolean, scopeToLanguage?: boolean): Thenable<void>;
/**
* Readable dictionary that backs this configuration.
*/
readonly [key: string]: any;
} Example "configuration": {
"title": "sample",
"properties": {
"sample.languageSetting": {
"type": "boolean",
"scope": "language-overridable"
}
}
} /**
* Read language configuration.
*/
const textDocumentConfiguration = vscode.workspace.getConfiguration('sample', {resource, languageId});
textDocumentConfiguration.get('languageSetting');
/**
* Write configuration
*/
textDocumentConfiguration.update('languageSetting', false, ConfigurationTarget.Global);
/**
* Write configuration under language
*/
textDocumentConfiguration.update('languageSetting', false, ConfigurationTarget.Global, true);
/**
* Listen for configuration
*/
workspace.onDidChangeConfiguration(e => {
if(e.affectsConfiguration('sample.languageSetting') {
}
if(e.affectsConfiguration('sample.languageSetting', {resource, languageId}) {
}
}); |
@sandy081, is this currently in nightly builds (v1.42.0)? |
Yes and will be available in next stable (v1.42.0) |
@sandy081, ok thanks! const settingValue = vscode.workspace.getConfiguration('segment1', null).get('settingName', false); and this doesn't work and read only the global one. |
Please refer to sample here - https://github.com/microsoft/vscode-extension-samples/tree/master/configuration-sample |
@sandy081, sorry, but nothing worked for language-specific configuration.
The code is simple: . . .
private _onWillSaveTextDocument(event: TextDocumentWillSaveEvent): void {
const config = workspace.getConfiguration('', event.document);
const value = config.get<boolean>('value', false);
. . . |
My bad it is still under proposed API check. |
This doesn't work yet. See microsoft/vscode#26707
Problem
To my knowledge, there is no well supported way for an extension to contribute language specific settings, like so:
This actually works, but has some major issues:
Proposals
The text was updated successfully, but these errors were encountered: