需要一种更好的方法以编程方式清除和设置 vscode 中的用户设置
Need a better way to programmatically clear and set user settings in vscode
所以我正在为配置文件用户设置和已安装的扩展编写 vscode 配置文件管理扩展,但遇到了一些障碍。
对于我的扩展,我需要清除用户 settings.json 文件中当前设置的设置,但据我所知,无法通过扩展 API 获得settings.json 文件中键的精确表示,需要用 WorkspaceConfiguration.update("key", undefinded, ConfigurationTarget.Global)
函数删除设置。为此,我编写了这个函数:
/**
* Clears out the Global (user) settings.json of all values.
*/
public async clearGlobalConfig() {
// Due to limitations on updating configuration values, all possible
// paths must be attempted for an update, from most specific to least
const fullConfigPaths = mapObjectPaths(this.getGlobalConfig());
// WorkspaceConfig object for doing config update operations
const workspaceConfig = workspace.getConfiguration();
// Iterate over all possible config paths
for (const key of fullConfigPaths) {
// Attempt to unset the value (will not unset till it matches the
// exact path as it matches in the settings.json file)
await workspaceConfig.update(key, undefined, ConfigurationTarget.Global);
}
}
但是 运行 需要大约 10 - 20 秒,至少在我当前的设置下,并且每次删除设置时 window 都会闪烁。
下一个问题是从 settings.json 中获取设置以保存在配置文件配置中。当您执行 workspace.getConfguration().inspect("")?.globalValue
时,返回的对象不是带有 settings.json 的 1:1,所有带点符号的键都将被删除,对象将被展开。这很糟糕,因为现在,我再次不知道需要与 WorkspaceConfiguration.update()
一起使用的正确键来设置加载配置文件时的设置。
所以我编写了这个函数来尝试从 workspace.getConfiguration()...
调用中探测返回的对象,以获取 settings.json 文件的 1:1 表示以保存在配置文件配置中:
/**
* Attempts to get an object that matches the contents of the user's
* settings.json file exactly.
*
* @returns An object that should match the contents of the user
* settings.json
*/
public async getGlobalSettingsFileContents(): Promise<Dictionary> {
// Get the current user settings (minus this extension's settings)
const runningConfig = this.getGlobalConfig();
// Get all the possible full dot notated paths in the config object (from
// most specific to least specific)
const configPaths = mapObjectPaths(runningConfig);
// Grab the WorkSpaceConfiguration object update function for reuse
const updateFunction = workspace.getConfiguration().update;
// The settings object with the proper settings.json keys to store in the
// profile
let actualSettings: Dictionary = {};
// Previously checked config object path
let previousPath = "";
// Iterate over all the possible configuration object's dot paths
for (const configPath of configPaths) {
// If the previous path was a valid settings key AND the current path
// is just a less specific object path
if (has(actualSettings, previousPath) && startsWith(previousPath, configPath)) {
continue;
}
// Get the current value before testing
const currentValue = get(runningConfig, configPath);
// Attempt to see if unsetting the settings value at this object path
// works
await updateFunction(configPath, undefined, ConfigurationTarget.Global);
// Get the new value after the attempted unset
const newValue = get(this.getGlobalConfig(), configPath);
// If the value has changed (newValue probably being undefined)
if (!isEqual(currentValue, newValue)) {
// Then this was a valid settings key, save it
actualSettings[configPath] = currentValue;
}
// Save path for checking against the next path
previousPath = configPath;
}
// Get the actual settings keys that were just probed
const actualConfigKeys = keys(actualSettings);
// Iterate over the settings keys
for (const configKey of actualConfigKeys) {
// Attempt to re-add all the settings that were removed in the probing
// process
// WILL FAIL IF THERE ISN'T AN EXTENSION THAT CORRESPONDS TO THE SETTING
await updateFunction(configKey, actualSettings[configKey], ConfigurationTarget.Global);
}
// Return what should be in the actual settings.json file
return actualSettings;
}
但现在的问题是,在删除设置后,然后尝试在删除它们的确切密钥处重新添加它们,如果未安装相应的扩展程序,则会抛出错误:
所以现在我的问题是,是否有更好的方式以编程方式编辑用户 settings.json,最好是在 vscode API 内并且不需要直接执行文件系统操作?
Link 到项目:https://github.com/SLGShark6/vscode-profile-manager/tree/development
有点俗气,但我发现在 vscode 生态系统中编辑 settings.json 文件足够安全。
(注:Dictionary
类型只是我自己定义的类型,大部分等同于object
)
import * as JSONC from 'jsonc-parser';
import {
commands,
window,
Range,
Position
} from 'vscode';
/**
* Gets the settings object directly from the settings.json file.
*
* @returns Parsed object from the user settings.json file
*/
async function getSettingsJSON(): Promise<Dictionary> {
// Open the user settings.json file in a new editor
await commands.executeCommand("workbench.action.openSettingsJson");
// Grab the new active editor from the window (should be the one we just
// opened)
const activeEditor = window.activeTextEditor!;
// Get the open document from the active editor (should be the
// settings.json file)
const settingsDocument = activeEditor.document;
// Get all of the text contained in the file
const documentText = settingsDocument.getText();
// Close the active settings.json editor
await commands.executeCommand("workbench.action.closeActiveEditor");
// Return the document parsed to a proper object
return JSONC.parse(documentText);
}
/**
* Writes a passed settings object directly to the user settings.json file,
* overwriting the contents.
*
* @param settings Settings object to overwrite the settings.json file with
*/
async function setSettingsJSON(settings: Dictionary) {
// Open the user settings.json file in a new editor
await commands.executeCommand("workbench.action.openSettingsJson");
// Grab the new active editor from the window (should be the one we just
// opened)
const activeEditor = window.activeTextEditor!;
// Get the open document from the active editor (should be the
// settings.json file)
const settingsDocument = activeEditor.document;
// Open an edit operation to update the settings document
activeEditor.edit((editBuilder) => {
// Make a range from start to end of the document
const startPosition = new Position(0,0);
const endPosition = settingsDocument.lineAt(settingsDocument.lineCount - 1).rangeIncludingLineBreak.end;
const range = new Range(startPosition, endPosition);
// Replace everything with the new settings object
editBuilder.replace(range, JSON.stringify(settings));
});
// Save the changed settings.json file
await settingsDocument.save();
// Close the active settings.json editor
await commands.executeCommand("workbench.action.closeActiveEditor");
}
所以我正在为配置文件用户设置和已安装的扩展编写 vscode 配置文件管理扩展,但遇到了一些障碍。
对于我的扩展,我需要清除用户 settings.json 文件中当前设置的设置,但据我所知,无法通过扩展 API 获得settings.json 文件中键的精确表示,需要用 WorkspaceConfiguration.update("key", undefinded, ConfigurationTarget.Global)
函数删除设置。为此,我编写了这个函数:
/**
* Clears out the Global (user) settings.json of all values.
*/
public async clearGlobalConfig() {
// Due to limitations on updating configuration values, all possible
// paths must be attempted for an update, from most specific to least
const fullConfigPaths = mapObjectPaths(this.getGlobalConfig());
// WorkspaceConfig object for doing config update operations
const workspaceConfig = workspace.getConfiguration();
// Iterate over all possible config paths
for (const key of fullConfigPaths) {
// Attempt to unset the value (will not unset till it matches the
// exact path as it matches in the settings.json file)
await workspaceConfig.update(key, undefined, ConfigurationTarget.Global);
}
}
但是 运行 需要大约 10 - 20 秒,至少在我当前的设置下,并且每次删除设置时 window 都会闪烁。
下一个问题是从 settings.json 中获取设置以保存在配置文件配置中。当您执行 workspace.getConfguration().inspect("")?.globalValue
时,返回的对象不是带有 settings.json 的 1:1,所有带点符号的键都将被删除,对象将被展开。这很糟糕,因为现在,我再次不知道需要与 WorkspaceConfiguration.update()
一起使用的正确键来设置加载配置文件时的设置。
所以我编写了这个函数来尝试从 workspace.getConfiguration()...
调用中探测返回的对象,以获取 settings.json 文件的 1:1 表示以保存在配置文件配置中:
/**
* Attempts to get an object that matches the contents of the user's
* settings.json file exactly.
*
* @returns An object that should match the contents of the user
* settings.json
*/
public async getGlobalSettingsFileContents(): Promise<Dictionary> {
// Get the current user settings (minus this extension's settings)
const runningConfig = this.getGlobalConfig();
// Get all the possible full dot notated paths in the config object (from
// most specific to least specific)
const configPaths = mapObjectPaths(runningConfig);
// Grab the WorkSpaceConfiguration object update function for reuse
const updateFunction = workspace.getConfiguration().update;
// The settings object with the proper settings.json keys to store in the
// profile
let actualSettings: Dictionary = {};
// Previously checked config object path
let previousPath = "";
// Iterate over all the possible configuration object's dot paths
for (const configPath of configPaths) {
// If the previous path was a valid settings key AND the current path
// is just a less specific object path
if (has(actualSettings, previousPath) && startsWith(previousPath, configPath)) {
continue;
}
// Get the current value before testing
const currentValue = get(runningConfig, configPath);
// Attempt to see if unsetting the settings value at this object path
// works
await updateFunction(configPath, undefined, ConfigurationTarget.Global);
// Get the new value after the attempted unset
const newValue = get(this.getGlobalConfig(), configPath);
// If the value has changed (newValue probably being undefined)
if (!isEqual(currentValue, newValue)) {
// Then this was a valid settings key, save it
actualSettings[configPath] = currentValue;
}
// Save path for checking against the next path
previousPath = configPath;
}
// Get the actual settings keys that were just probed
const actualConfigKeys = keys(actualSettings);
// Iterate over the settings keys
for (const configKey of actualConfigKeys) {
// Attempt to re-add all the settings that were removed in the probing
// process
// WILL FAIL IF THERE ISN'T AN EXTENSION THAT CORRESPONDS TO THE SETTING
await updateFunction(configKey, actualSettings[configKey], ConfigurationTarget.Global);
}
// Return what should be in the actual settings.json file
return actualSettings;
}
但现在的问题是,在删除设置后,然后尝试在删除它们的确切密钥处重新添加它们,如果未安装相应的扩展程序,则会抛出错误:
所以现在我的问题是,是否有更好的方式以编程方式编辑用户 settings.json,最好是在 vscode API 内并且不需要直接执行文件系统操作?
Link 到项目:https://github.com/SLGShark6/vscode-profile-manager/tree/development
有点俗气,但我发现在 vscode 生态系统中编辑 settings.json 文件足够安全。
(注:Dictionary
类型只是我自己定义的类型,大部分等同于object
)
import * as JSONC from 'jsonc-parser';
import {
commands,
window,
Range,
Position
} from 'vscode';
/**
* Gets the settings object directly from the settings.json file.
*
* @returns Parsed object from the user settings.json file
*/
async function getSettingsJSON(): Promise<Dictionary> {
// Open the user settings.json file in a new editor
await commands.executeCommand("workbench.action.openSettingsJson");
// Grab the new active editor from the window (should be the one we just
// opened)
const activeEditor = window.activeTextEditor!;
// Get the open document from the active editor (should be the
// settings.json file)
const settingsDocument = activeEditor.document;
// Get all of the text contained in the file
const documentText = settingsDocument.getText();
// Close the active settings.json editor
await commands.executeCommand("workbench.action.closeActiveEditor");
// Return the document parsed to a proper object
return JSONC.parse(documentText);
}
/**
* Writes a passed settings object directly to the user settings.json file,
* overwriting the contents.
*
* @param settings Settings object to overwrite the settings.json file with
*/
async function setSettingsJSON(settings: Dictionary) {
// Open the user settings.json file in a new editor
await commands.executeCommand("workbench.action.openSettingsJson");
// Grab the new active editor from the window (should be the one we just
// opened)
const activeEditor = window.activeTextEditor!;
// Get the open document from the active editor (should be the
// settings.json file)
const settingsDocument = activeEditor.document;
// Open an edit operation to update the settings document
activeEditor.edit((editBuilder) => {
// Make a range from start to end of the document
const startPosition = new Position(0,0);
const endPosition = settingsDocument.lineAt(settingsDocument.lineCount - 1).rangeIncludingLineBreak.end;
const range = new Range(startPosition, endPosition);
// Replace everything with the new settings object
editBuilder.replace(range, JSON.stringify(settings));
});
// Save the changed settings.json file
await settingsDocument.save();
// Close the active settings.json editor
await commands.executeCommand("workbench.action.closeActiveEditor");
}