diff --git a/src/vs/workbench/services/languageRuntime/common/languageRuntimeDataExplorerClient.ts b/src/vs/workbench/services/languageRuntime/common/languageRuntimeDataExplorerClient.ts index 2f6486ebed7..7dbf9c56f07 100644 --- a/src/vs/workbench/services/languageRuntime/common/languageRuntimeDataExplorerClient.ts +++ b/src/vs/workbench/services/languageRuntime/common/languageRuntimeDataExplorerClient.ts @@ -9,8 +9,14 @@ import { Disposable } from '../../../../base/common/lifecycle.js'; import { generateUuid } from '../../../../base/common/uuid.js'; import { ArraySelection, BackendState, ColumnFilter, ColumnProfileRequest, ColumnProfileResult, ColumnSchema, ColumnSelection, ColumnSortKey, DataExplorerFrontendEvent, DataUpdateEvent, ExportedData, ExportFormat, FilterResult, FormatOptions, ReturnColumnProfilesEvent, RowFilter, SchemaUpdateEvent, SupportedFeatures, SupportStatus, TableData, TableRowLabels, TableSchema, TableSelection } from './positronDataExplorerComm.js'; +import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js'; +import { localize } from '../../../../nls.js'; +import { Registry } from '../../../../platform/registry/common/platform.js'; +import { ConfigurationScope, Extensions, IConfigurationRegistry } from '../../../../platform/configuration/common/configurationRegistry.js'; +import { positronConfigurationNodeBase } from './languageRuntime.js'; + /** - * TableSchemaSearchResult interface. This is here temporarily until searching the tabe schema + * TableSchemaSearchResult interface. This is here temporarily until searching the table schema * becomespart of the PositronDataExplorerComm. */ export interface TableSchemaSearchResult { @@ -187,17 +193,14 @@ export class DataExplorerClientInstance extends Disposable { * Creates a new data explorer client instance. * @param backendClient The data explorer backend client instance. */ - constructor(backendClient: IDataExplorerBackendClient) { + constructor( + backendClient: IDataExplorerBackendClient, + configurationService: IConfigurationService + ) { // Call the disposable constructor. super(); - this._dataFormatOptions = { - large_num_digits: 2, - small_num_digits: 4, - max_integral_digits: 7, - max_value_length: 1000, - thousands_sep: '', - }; + this._dataFormatOptions = mapScipenToFormatOptions(getDataExplorerScipen(configurationService)); this._profileFormatOptions = { large_num_digits: 2, @@ -272,7 +275,7 @@ export class DataExplorerClientInstance extends Disposable { /** * Get the current active state of the data explorer backend. - * @returns A promose that resolves to the current backend state. + * @returns A promise that resolves to the current backend state. */ async getBackendState(): Promise { if (this._backendPromise) { @@ -402,7 +405,7 @@ export class DataExplorerClientInstance extends Disposable { /** * Request a batch of column profiles - * @param profiles An array of profile types and colum indexes + * @param profiles An array of profile types and column indexes * @returns A Promise> that resolves when the operation is complete. */ async getColumnProfiles( @@ -553,3 +556,52 @@ export class DataExplorerClientInstance extends Disposable { //#endregion Public Events } + +function mapScipenToFormatOptions(scipen: number): FormatOptions { + const clamped = Math.max(-10, Math.min(scipen, 20)); // avoid extreme values + + const max_integral_digits = + clamped >= 10 ? 99 : Math.max(4, 12 + clamped); // prefer fixed-point for high scipen + + const small_num_digits = + clamped <= -5 ? 0 : Math.max(2, 3 + clamped); // fewer digits for scientific lean + + return { + large_num_digits: 2, + small_num_digits, + max_integral_digits, + max_value_length: 1000, + thousands_sep: '' + }; +} + +// Key for the configuration setting +const DATA_EXPLORER_SCIPEN_KEY = + 'dataExplorer.scipen'; + +function getDataExplorerScipen(configurationService: IConfigurationService): number { + const value = configurationService.getValue(DATA_EXPLORER_SCIPEN_KEY); + if (typeof value === 'number' && Number.isFinite(value)) { + return Math.round(value); + } + return 0; +} + +// Register the configuration setting +const configurationRegistry = Registry.as( + Extensions.Configuration +); +configurationRegistry.registerConfiguration({ // for scipen + ...positronConfigurationNodeBase, + scope: ConfigurationScope.MACHINE_OVERRIDABLE, + properties: { + [DATA_EXPLORER_SCIPEN_KEY]: { + type: 'number', + default: 0, + markdownDescription: localize( + 'positron.dataExplorer.scipen', + 'Controls the bias toward fixed-point notation in the Data Explorer. Higher values favor fixed-point; lower values favor scientific notation. Mirrors the effect of `options(scipen)` in R.' + ), + }, + }, +}); diff --git a/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerService.ts b/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerService.ts index 3e91ac8b2b2..70c16ea63c5 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerService.ts +++ b/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerService.ts @@ -66,9 +66,10 @@ class DataExplorerRuntime extends Disposable { */ constructor( private readonly _notificationService: INotificationService, - private readonly _session: ILanguageRuntimeSession + private readonly _session: ILanguageRuntimeSession, + private readonly _configurationService: IConfigurationService ) { - // Call the disposable constrcutor. + // Call the disposable constructor. super(); /** @@ -83,7 +84,7 @@ class DataExplorerRuntime extends Disposable { // Create and register the DataExplorerClientInstance for the client instance. const commInstance = new PositronDataExplorerComm(e.client); - const dataExplorerClientInstance = new DataExplorerClientInstance(commInstance); + const dataExplorerClientInstance = new DataExplorerClientInstance(commInstance, this._configurationService); this._register(dataExplorerClientInstance); // Add the onDidClose event handler on the DataExplorerClientInstance, @@ -325,7 +326,7 @@ class PositronDataExplorerService extends Disposable implements IPositronDataExp // TODO: error handling if opening the file failed - const client = new DataExplorerClientInstance(backend); + const client = new DataExplorerClientInstance(backend, this._configurationService); this.registerDataExplorerClient('duckdb', client); } @@ -350,7 +351,7 @@ class PositronDataExplorerService extends Disposable implements IPositronDataExp // If we don't have a Data Explorer client instance, create one and open the editor. if (!existingInstance) { const commInstance = new PositronDataExplorerComm(client); - const dataExplorerClientInstance = new DataExplorerClientInstance(commInstance); + const dataExplorerClientInstance = new DataExplorerClientInstance(commInstance, this._configurationService); this.openEditor(session.runtimeMetadata.languageName, dataExplorerClientInstance); } } @@ -358,7 +359,7 @@ class PositronDataExplorerService extends Disposable implements IPositronDataExp } // Create and add the data explorer runtime. - const dataExplorerRuntime = new DataExplorerRuntime(this._notificationService, session); + const dataExplorerRuntime = new DataExplorerRuntime(this._notificationService, session, this._configurationService); this._dataExplorerRuntimes.set(session.sessionId, dataExplorerRuntime); // Add the onDidOpenDataExplorerClient event handler.