Skip to content
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

Copy clipboard command in ADS (html/plain text supported) #13527

Merged
merged 10 commits into from
Nov 26, 2020
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/sql/platform/clipboard/browser/clipboardService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService';
import { IClipboardService as vsIClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { ClipboardData, IClipboardService as vsIClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { URI } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
Expand All @@ -25,6 +25,10 @@ export class BrowserClipboardService implements IClipboardService {
this._notificationService.info(localize('imageCopyingNotSupported', "Copying images is not supported"));
}

write(data: ClipboardData): Promise<void> {
return this._vsClipboardService.write(data);
}

writeText(text: string): Promise<void> {
return this._vsClipboardService.writeText(text);
}
Expand Down
70 changes: 70 additions & 0 deletions src/sql/workbench/contrib/query/browser/keyboardQueryActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Action } from 'vs/base/common/actions';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';

import * as azdata from 'azdata';
import { escape } from 'sql/base/common/strings';

import { IQueryManagementService } from 'sql/workbench/services/query/common/queryManagement';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
Expand All @@ -21,6 +22,7 @@ import { EditDataEditor } from 'sql/workbench/contrib/editData/browser/editDataE
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { QueryEditorInput } from 'sql/workbench/common/editor/query/queryEditorInput';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';

const singleQuote = '\'';

Expand Down Expand Up @@ -131,6 +133,74 @@ export class RunCurrentQueryKeyboardAction extends Action {
}
}

export class CopyQueryWithResultsKeyboardAction extends Action {
public static ID = 'copyQueryWithResultsKeyboardAction';
public static LABEL = nls.localize('copyQueryWithResultsKeyboardAction', "Copy Query With Results");

constructor(
id: string,
label: string,
@IEditorService private _editorService: IEditorService,
@IClipboardService private _clipboardService: IClipboardService,
@IQueryModelService protected readonly queryModelService: IQueryModelService,
) {
super(id, label);
}

public async getFormattedResults(editor): Promise<any> {
gupta1 marked this conversation as resolved.
Show resolved Hide resolved
let queryRunner = this.queryModelService.getQueryRunner(editor.input.uri);
let allResults = '';
let allHtmlResults = '';

if (queryRunner && queryRunner.batchSets.length > 0) {
for (let i = 0; i < queryRunner.batchSets[0].resultSetSummaries.length; i++) {
let resultSummary = queryRunner.batchSets[0].resultSetSummaries[i];
let result = await queryRunner.getQueryRows(0, resultSummary.rowCount, resultSummary.batchId, resultSummary.id);
let tableHeaders = resultSummary.columnInfo.map((col, i) => (col.columnName));
let htmlTableHeaders = resultSummary.columnInfo.map((col, i) => (`<th style="border:solid black 1.0pt; whiteSpace:nowrap">${escape(col.columnName)}</th>`));
let copyString = '\n';
let htmlCopyString = '<tr>';

for (let rowEntry of result.rows) {
for (let colIdx = 0; colIdx < rowEntry.length; colIdx++) {
let value = rowEntry[colIdx].displayValue;
if (value) {
copyString = `${copyString}${value}\t`;
htmlCopyString = `${htmlCopyString}<td style="border:solid black 1.0pt;white-space:nowrap">${escape(value)}</td>`;
}
}
// Removes the tab seperator from the end of a row
copyString = copyString.slice(0, -1 * '\t'.length) + '\n';
htmlCopyString = htmlCopyString + '</tr>';
}

allResults = `${allResults}${tableHeaders.join('\t')}${copyString}\n`;
allHtmlResults = `${allHtmlResults}<div><br/><br/>
<table cellPadding="5" cellSpacing="1" style="border:1;border-color:Black;font-family:Segoe UI;font-size:12px;border-collapse:collapse">
<tr style="background-color:DarkGray">${htmlTableHeaders.join('')}</tr>${htmlCopyString}
</table></div>`;
}
}

return { result: allResults, htmlResult: allHtmlResults };
}

public async run(): Promise<void> {
const editor = this._editorService.activeEditorPane;
if (editor instanceof QueryEditor) {
let allResults = await this.getFormattedResults(editor);
let queryText = editor.getAllText();

let data = {
text: `${queryText}\n\n${allResults.result}`,
html: `${escape(queryText).replace(/\r\n|\n|\r/gm, '<br />')}${allResults.htmlResult}`
};

await this._clipboardService.write(data);
}
}
}

export class RunCurrentQueryWithActualPlanKeyboardAction extends Action {
public static ID = 'runCurrentQueryWithActualPlanKeyboardAction';
public static LABEL = nls.localize('runCurrentQueryWithActualPlanKeyboardAction', "Run Current Query with Actual Plan");
Expand Down
12 changes: 11 additions & 1 deletion src/sql/workbench/contrib/query/browser/query.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { QueryResultsInput } from 'sql/workbench/common/editor/query/queryResult
import * as queryContext from 'sql/workbench/contrib/query/common/queryContext';
import {
RunQueryKeyboardAction, RunCurrentQueryKeyboardAction, CancelQueryKeyboardAction, RefreshIntellisenseKeyboardAction, ToggleQueryResultsKeyboardAction,
RunQueryShortcutAction, RunCurrentQueryWithActualPlanKeyboardAction, FocusOnCurrentQueryKeyboardAction, ParseSyntaxAction
RunQueryShortcutAction, RunCurrentQueryWithActualPlanKeyboardAction, CopyQueryWithResultsKeyboardAction, FocusOnCurrentQueryKeyboardAction, ParseSyntaxAction
} from 'sql/workbench/contrib/query/browser/keyboardQueryActions';
import * as gridActions from 'sql/workbench/contrib/editData/browser/gridActions';
import * as gridCommands from 'sql/workbench/contrib/editData/browser/gridCommands';
Expand Down Expand Up @@ -139,6 +139,16 @@ actionRegistry.registerWorkbenchAction(
RunCurrentQueryWithActualPlanKeyboardAction.LABEL
);

actionRegistry.registerWorkbenchAction(
SyncActionDescriptor.create(
CopyQueryWithResultsKeyboardAction,
CopyQueryWithResultsKeyboardAction.ID,
CopyQueryWithResultsKeyboardAction.LABEL,
{ primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C }
),
CopyQueryWithResultsKeyboardAction.LABEL
);

actionRegistry.registerWorkbenchAction(
SyncActionDescriptor.create(
CancelQueryKeyboardAction,
Expand Down
8 changes: 7 additions & 1 deletion src/vs/platform/clipboard/browser/clipboardService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
// {{SQL CARBON EDIT}}
gupta1 marked this conversation as resolved.
Show resolved Hide resolved
import { ClipboardData, IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { URI } from 'vs/base/common/uri';
import { $ } from 'vs/base/browser/dom';

Expand All @@ -13,6 +14,11 @@ export class BrowserClipboardService implements IClipboardService {

private readonly mapTextToType = new Map<string, string>(); // unsupported in web (only in-memory)

// {{SQL CARBON EDIT}}
async write(data: ClipboardData, type?: string): Promise<void> {
throw new Error('Not Implemented');
}

async writeText(text: string, type?: string): Promise<void> {

// With type: only in-memory is supported
Expand Down
13 changes: 13 additions & 0 deletions src/vs/platform/clipboard/common/clipboardService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,22 @@ import { URI } from 'vs/base/common/uri';

export const IClipboardService = createDecorator<IClipboardService>('clipboardService');

// {{SQL CARBON EDIT}}
gupta1 marked this conversation as resolved.
Show resolved Hide resolved
export interface ClipboardData {
text?: string;
html?: string;
rtf?: string;
bookmark?: string;
}

export interface IClipboardService {

readonly _serviceBrand: undefined;
/**
* Writes data to the system clipboard.
*/
// {{SQL CARBON EDIT}}
gupta1 marked this conversation as resolved.
Show resolved Hide resolved
write(data: ClipboardData, type?: string): Promise<void>;

/**
* Writes text to the system clipboard.
Expand Down
1 change: 1 addition & 0 deletions src/vs/platform/electron/common/electron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export interface ICommonElectronService {
writeClipboardText(text: string, type?: 'selection' | 'clipboard'): Promise<void>;
readClipboardFindText(): Promise<string>;
writeClipboardFindText(text: string): Promise<void>;
writeClipboardData(data: any, type?: 'selection' | 'clipboard'): Promise<void>;
gupta1 marked this conversation as resolved.
Show resolved Hide resolved
writeClipboardBuffer(format: string, buffer: Uint8Array, type?: 'selection' | 'clipboard'): Promise<void>;
readClipboardBuffer(format: string): Promise<Uint8Array>;
hasClipboard(format: string, type?: 'selection' | 'clipboard'): Promise<boolean>;
Expand Down
4 changes: 4 additions & 0 deletions src/vs/platform/electron/electron-main/electronMainService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,10 @@ export class ElectronMainService implements IElectronMainService {
return clipboard.writeText(text, type);
}

async writeClipboardData(windowId: number | undefined, data: any, type?: 'selection' | 'clipboard'): Promise<void> {
gupta1 marked this conversation as resolved.
Show resolved Hide resolved
return clipboard.write(data, type);
}

async readClipboardFindText(windowId: number | undefined,): Promise<string> {
return clipboard.readFindText();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
// {{SQL CARBON EDIT}}
gupta1 marked this conversation as resolved.
Show resolved Hide resolved
import { ClipboardData, IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { URI } from 'vs/base/common/uri';
import { isMacintosh } from 'vs/base/common/platform';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
Expand All @@ -20,6 +21,11 @@ export class NativeClipboardService implements IClipboardService {
@IElectronService private readonly electronService: IElectronService
) { }

// {{SQL CARBON EDIT}}
async write(data: ClipboardData, type?: 'selection' | 'clipboard'): Promise<void> {
return this.electronService.writeClipboardData(data, type);
}

async writeText(text: string, type?: 'selection' | 'clipboard'): Promise<void> {
return this.electronService.writeClipboardText(text, type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ export class TestElectronService implements IElectronService {
async toggleDevTools(): Promise<void> { }
async resolveProxy(url: string): Promise<string | undefined> { return undefined; }
async readClipboardText(type?: 'selection' | 'clipboard' | undefined): Promise<string> { return ''; }
async writeClipboardData(data: any, type?: 'selection' | 'clipboard' | undefined): Promise<void> { }
gupta1 marked this conversation as resolved.
Show resolved Hide resolved
async writeClipboardText(text: string, type?: 'selection' | 'clipboard' | undefined): Promise<void> { }
async readClipboardFindText(): Promise<string> { return ''; }
async writeClipboardFindText(text: string): Promise<void> { }
Expand Down