mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Add a config for copying with trailing line break (#23481)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||||
"version": "4.8.0.32",
|
"version": "4.8.0.35",
|
||||||
"downloadFileNames": {
|
"downloadFileNames": {
|
||||||
"Windows_86": "win-x86-net7.0.zip",
|
"Windows_86": "win-x86-net7.0.zip",
|
||||||
"Windows_64": "win-x64-net7.0.zip",
|
"Windows_64": "win-x64-net7.0.zip",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const providerId = 'MSSQL';
|
|||||||
export const serviceCrashLink = 'https://github.com/Microsoft/vscode-mssql/wiki/SqlToolsService-Known-Issues';
|
export const serviceCrashLink = 'https://github.com/Microsoft/vscode-mssql/wiki/SqlToolsService-Known-Issues';
|
||||||
export const extensionConfigSectionName = 'mssql';
|
export const extensionConfigSectionName = 'mssql';
|
||||||
export const telemetryConfigSectionName = 'telemetry';
|
export const telemetryConfigSectionName = 'telemetry';
|
||||||
|
export const queryEditorConfigSectionName = 'queryEditor';
|
||||||
export const packageName = 'Microsoft.mssql';
|
export const packageName = 'Microsoft.mssql';
|
||||||
|
|
||||||
// DATA PROTOCOL VALUES ///////////////////////////////////////////////////////////
|
// DATA PROTOCOL VALUES ///////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -219,7 +219,8 @@ function getClientOptions(context: AppContext): ClientOptions {
|
|||||||
synchronize: {
|
synchronize: {
|
||||||
configurationSection: [
|
configurationSection: [
|
||||||
Constants.extensionConfigSectionName,
|
Constants.extensionConfigSectionName,
|
||||||
Constants.telemetryConfigSectionName
|
Constants.telemetryConfigSectionName,
|
||||||
|
Constants.queryEditorConfigSectionName,
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
providerId: Constants.providerId,
|
providerId: Constants.providerId,
|
||||||
|
|||||||
4
src/sql/azdata.proposed.d.ts
vendored
4
src/sql/azdata.proposed.d.ts
vendored
@@ -862,10 +862,6 @@ declare module 'azdata' {
|
|||||||
* Whether to include the column headers.
|
* Whether to include the column headers.
|
||||||
*/
|
*/
|
||||||
includeHeaders: boolean
|
includeHeaders: boolean
|
||||||
/**
|
|
||||||
* Whether to remove line breaks from the cell value.
|
|
||||||
*/
|
|
||||||
removeNewLines: boolean;
|
|
||||||
/**
|
/**
|
||||||
* The selected ranges to be copied.
|
* The selected ranges to be copied.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export interface IQueryEditorConfiguration {
|
|||||||
readonly streaming: boolean;
|
readonly streaming: boolean;
|
||||||
readonly copyIncludeHeaders: boolean;
|
readonly copyIncludeHeaders: boolean;
|
||||||
readonly copyRemoveNewLine: boolean;
|
readonly copyRemoveNewLine: boolean;
|
||||||
|
readonly skipNewLineAfterTrailingLineBreak: boolean;
|
||||||
readonly optimizedTable: boolean;
|
readonly optimizedTable: boolean;
|
||||||
readonly inMemoryDataProcessingThreshold: number;
|
readonly inMemoryDataProcessingThreshold: number;
|
||||||
readonly openAfterSave: boolean;
|
readonly openAfterSave: boolean;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { IDataResource, rowHasColumnNameKeys } from 'sql/workbench/services/notebook/browser/sql/sqlSessionManager';
|
import { IDataResource, rowHasColumnNameKeys } from 'sql/workbench/services/notebook/browser/sql/sqlSessionManager';
|
||||||
import { getEolString, shouldIncludeHeaders, shouldRemoveNewLines } from 'sql/workbench/services/query/common/queryRunner';
|
import { getEolString, shouldSkipNewLineAfterTrailingLineBreak, shouldIncludeHeaders, shouldRemoveNewLines } from 'sql/workbench/services/query/common/queryRunner';
|
||||||
import { ResultSetSummary, ResultSetSubset, ICellValue } from 'sql/workbench/services/query/common/query';
|
import { ResultSetSummary, ResultSetSubset, ICellValue } from 'sql/workbench/services/query/common/query';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||||
@@ -441,6 +441,9 @@ export class DataResourceDataProvider implements IGridDataProvider {
|
|||||||
shouldRemoveNewLines(): boolean {
|
shouldRemoveNewLines(): boolean {
|
||||||
return shouldRemoveNewLines(this._configurationService);
|
return shouldRemoveNewLines(this._configurationService);
|
||||||
}
|
}
|
||||||
|
shouldSkipNewLineAfterTrailingLineBreak(): boolean {
|
||||||
|
return shouldSkipNewLineAfterTrailingLineBreak(this._configurationService);
|
||||||
|
}
|
||||||
|
|
||||||
getColumnHeaders(range: Slick.Range): string[] {
|
getColumnHeaders(range: Slick.Range): string[] {
|
||||||
let headers: string[] = this._resultSet.columnInfo.slice(range.fromCell, range.toCell + 1).map((info, i) => {
|
let headers: string[] = this._resultSet.columnInfo.slice(range.fromCell, range.toCell + 1).map((info, i) => {
|
||||||
|
|||||||
@@ -303,6 +303,11 @@ const queryEditorConfiguration: IConfigurationNode = {
|
|||||||
'description': localize('queryEditor.results.copyRemoveNewLine', "Configuration options for copying multi-line results from the Results View"),
|
'description': localize('queryEditor.results.copyRemoveNewLine', "Configuration options for copying multi-line results from the Results View"),
|
||||||
'default': true
|
'default': true
|
||||||
},
|
},
|
||||||
|
'queryEditor.results.skipNewLineAfterTrailingLineBreak': {
|
||||||
|
'type': 'boolean',
|
||||||
|
'description': localize('queryEditor.results.skipNewLineAfterTrailingLineBreak', "Whether to skip adding a line break between rows when copying results if the previous row already has a trailing line break. The default value is false."),
|
||||||
|
'default': false
|
||||||
|
},
|
||||||
'queryEditor.results.preferProvidersCopyHandler': {
|
'queryEditor.results.preferProvidersCopyHandler': {
|
||||||
'type': 'boolean',
|
'type': 'boolean',
|
||||||
'description': localize('queryEditor.results.preferProvidersCopyHandler', "Whether the copy result request should be handled by the query provider when it is supported. The default value is true, set this to false to force all copy handling to be done by Azure Data Studio."),
|
'description': localize('queryEditor.results.preferProvidersCopyHandler', "Whether the copy result request should be handled by the query provider when it is supported. The default value is true, set this to false to force all copy handling to be done by Azure Data Studio."),
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ export interface IGridDataProvider {
|
|||||||
|
|
||||||
shouldRemoveNewLines(): boolean;
|
shouldRemoveNewLines(): boolean;
|
||||||
|
|
||||||
|
shouldSkipNewLineAfterTrailingLineBreak(): boolean;
|
||||||
|
|
||||||
getColumnHeaders(range: Slick.Range): string[] | undefined;
|
getColumnHeaders(range: Slick.Range): string[] | undefined;
|
||||||
|
|
||||||
readonly canSerialize: boolean;
|
readonly canSerialize: boolean;
|
||||||
@@ -101,6 +103,7 @@ export async function copySelectionToClipboard(clipboardService: IClipboardServi
|
|||||||
const eol = provider.getEolString();
|
const eol = provider.getEolString();
|
||||||
const valueSeparator = '\t';
|
const valueSeparator = '\t';
|
||||||
const shouldRemoveNewLines = provider.shouldRemoveNewLines();
|
const shouldRemoveNewLines = provider.shouldRemoveNewLines();
|
||||||
|
const shouldSkipNewLineAfterTrailingLineBreak = provider.shouldSkipNewLineAfterTrailingLineBreak();
|
||||||
|
|
||||||
// Merge the selections to get the unique columns and unique rows.
|
// Merge the selections to get the unique columns and unique rows.
|
||||||
const gridRanges = GridRange.fromSlickRanges(selections);
|
const gridRanges = GridRange.fromSlickRanges(selections);
|
||||||
@@ -154,7 +157,9 @@ export async function copySelectionToClipboard(clipboardService: IClipboardServi
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!cancellationTokenSource.token.isCancellationRequested) {
|
if (!cancellationTokenSource.token.isCancellationRequested) {
|
||||||
resultString += rowValues.join(eol);
|
resultString += rowValues.reduce(
|
||||||
|
(prevVal, currVal, idx) => prevVal + (idx > 0 && (!prevVal?.endsWith(eol) || !shouldSkipNewLineAfterTrailingLineBreak) ? eol : '') + currVal,
|
||||||
|
);
|
||||||
await clipboardService.writeText(resultString);
|
await clipboardService.writeText(resultString);
|
||||||
}
|
}
|
||||||
}, cancellationTokenSource);
|
}, cancellationTokenSource);
|
||||||
|
|||||||
@@ -465,15 +465,13 @@ export default class QueryRunner extends Disposable {
|
|||||||
* @param selections The selection range to copy
|
* @param selections The selection range to copy
|
||||||
* @param batchId The batch id of the result to copy from
|
* @param batchId The batch id of the result to copy from
|
||||||
* @param resultId The result id of the result to copy from
|
* @param resultId The result id of the result to copy from
|
||||||
* @param removeNewLines Whether to remove line breaks from values.
|
|
||||||
* @param includeHeaders [Optional]: Should column headers be included in the copy selection
|
* @param includeHeaders [Optional]: Should column headers be included in the copy selection
|
||||||
*/
|
*/
|
||||||
async copyResults(selections: Slick.Range[], batchId: number, resultId: number, removeNewLines: boolean, includeHeaders?: boolean): Promise<void> {
|
async copyResults(selections: Slick.Range[], batchId: number, resultId: number, includeHeaders?: boolean): Promise<void> {
|
||||||
await this.queryManagementService.copyResults({
|
await this.queryManagementService.copyResults({
|
||||||
ownerUri: this.uri,
|
ownerUri: this.uri,
|
||||||
batchIndex: batchId,
|
batchIndex: batchId,
|
||||||
resultSetIndex: resultId,
|
resultSetIndex: resultId,
|
||||||
removeNewLines: removeNewLines,
|
|
||||||
includeHeaders: includeHeaders,
|
includeHeaders: includeHeaders,
|
||||||
selections: selections.map(selection => {
|
selections: selections.map(selection => {
|
||||||
return {
|
return {
|
||||||
@@ -592,7 +590,7 @@ export class QueryGridDataProvider implements IGridDataProvider {
|
|||||||
|
|
||||||
private async handleCopyRequestByProvider(selections: Slick.Range[], includeHeaders?: boolean): Promise<void> {
|
private async handleCopyRequestByProvider(selections: Slick.Range[], includeHeaders?: boolean): Promise<void> {
|
||||||
executeCopyWithNotification(this._notificationService, selections, async () => {
|
executeCopyWithNotification(this._notificationService, selections, async () => {
|
||||||
await this.queryRunner.copyResults(selections, this.batchId, this.resultSetId, this.shouldRemoveNewLines(), this.shouldIncludeHeaders(includeHeaders));
|
await this.queryRunner.copyResults(selections, this.batchId, this.resultSetId, this.shouldIncludeHeaders(includeHeaders));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -614,6 +612,9 @@ export class QueryGridDataProvider implements IGridDataProvider {
|
|||||||
shouldRemoveNewLines(): boolean {
|
shouldRemoveNewLines(): boolean {
|
||||||
return shouldRemoveNewLines(this._configurationService);
|
return shouldRemoveNewLines(this._configurationService);
|
||||||
}
|
}
|
||||||
|
shouldSkipNewLineAfterTrailingLineBreak(): boolean {
|
||||||
|
return shouldSkipNewLineAfterTrailingLineBreak(this._configurationService);
|
||||||
|
}
|
||||||
getColumnHeaders(range: Slick.Range): string[] | undefined {
|
getColumnHeaders(range: Slick.Range): string[] | undefined {
|
||||||
return this.queryRunner.getColumnHeaders(this.batchId, this.resultSetId, range);
|
return this.queryRunner.getColumnHeaders(this.batchId, this.resultSetId, range);
|
||||||
}
|
}
|
||||||
@@ -648,6 +649,12 @@ export function shouldRemoveNewLines(configurationService: IConfigurationService
|
|||||||
return !!removeNewLines;
|
return !!removeNewLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function shouldSkipNewLineAfterTrailingLineBreak(configurationService: IConfigurationService): boolean {
|
||||||
|
// get config skipNewLineAfterTrailingLineBreak option from vscode config
|
||||||
|
let skipNewLineAfterTrailingLineBreak = configurationService.getValue<IQueryEditorConfiguration>('queryEditor').results.skipNewLineAfterTrailingLineBreak;
|
||||||
|
return !!skipNewLineAfterTrailingLineBreak;
|
||||||
|
}
|
||||||
|
|
||||||
function isRangeOrUndefined(input: string | IRange | undefined): input is IRange | undefined {
|
function isRangeOrUndefined(input: string | IRange | undefined): input is IRange | undefined {
|
||||||
return Range.isIRange(input) || types.isUndefinedOrNull(input);
|
return Range.isIRange(input) || types.isUndefinedOrNull(input);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user