Skip to content

Commit

Permalink
Merge pull request #17628 from joelday/master
Browse files Browse the repository at this point in the history
Adding an overload to TextEditor.edit for insertion of a SnippetString
  • Loading branch information
jrieken committed Jan 20, 2017
2 parents 133db39 + ff2ea5d commit b4817e5
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 9 deletions.
36 changes: 35 additions & 1 deletion extensions/vscode-api-tests/src/editor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
'use strict';

import * as assert from 'assert';
import { workspace, window, Position, Range, commands, TextEditor, TextDocument, TextEditorCursorStyle, TextEditorLineNumbersStyle } from 'vscode';
import { workspace, window, Position, Range, commands, TextEditor, TextDocument, TextEditorCursorStyle, TextEditorLineNumbersStyle, SnippetString, Selection } from 'vscode';
import { createRandomFile, deleteFile, cleanUp } from './utils';

suite('editor tests', () => {
Expand All @@ -33,6 +33,40 @@ suite('editor tests', () => {
});
}

test('insert snippet', () => {
const snippetString = new SnippetString()
.appendText('This is a ')
.appendTabstop()
.appendPlaceholder('placeholder')
.appendText(' snippet');

return withRandomFileEditor('', (editor, doc) => {
return editor.edit(snippetString).then(inserted => {
assert.ok(inserted);
assert.equal(doc.getText(), 'This is a placeholder snippet');
assert.ok(doc.isDirty);
});
});
});

test('insert snippet with replacement', () => {
const snippetString = new SnippetString()
.appendText('has been');

return withRandomFileEditor('This will be replaced', (editor, doc) => {
editor.selection = new Selection(
new Position(0, 5),
new Position(0, 12)
);

return editor.edit(snippetString).then(inserted => {
assert.ok(inserted);
assert.equal(doc.getText(), 'This has been replaced');
assert.ok(doc.isDirty);
});
});
});

test('make edit', () => {
return withRandomFileEditor('', (editor, doc) => {
return editor.edit((builder) => {
Expand Down
9 changes: 9 additions & 0 deletions src/vs/vscode.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,15 @@ declare module 'vscode' {
*/
edit(callback: (editBuilder: TextEditorEdit) => void, options?: { undoStopBefore: boolean; undoStopAfter: boolean; }): Thenable<boolean>;

/**
* Enters snippet mode in the editor with the specified snippet.
*
* @param snippet The snippet to insert in this edit.
* @param options The undo/redo behaviour around this edit. By default, undo stops will be created before and after this edit.
* @return A promise that resolves with a value indicating if the snippet could be inserted.
*/
edit(snippet: SnippetString, options?: { undoStopBefore: boolean; undoStopAfter: boolean; }): Thenable<boolean>;

/**
* Adds a set of decorations to the text editor. If a set of decorations already exists with
* the given [decoration type](#TextEditorDecorationType), they will be replaced.
Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/api/node/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { IWorkspaceConfigurationValues } from 'vs/workbench/services/configurati
import { IPickOpenEntry, IPickOptions } from 'vs/platform/quickOpen/common/quickOpen';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import { IWorkspaceSymbol } from 'vs/workbench/parts/search/common/search';
import { IApplyEditsOptions, TextEditorRevealType, ITextEditorConfigurationUpdate, IResolvedTextEditorConfiguration, ISelectionChangeEvent } from './mainThreadEditorsTracker';
import { IApplyEditsOptions, IUndoStopOptions, TextEditorRevealType, ITextEditorConfigurationUpdate, IResolvedTextEditorConfiguration, ISelectionChangeEvent } from './mainThreadEditorsTracker';

import { InternalTreeExplorerNodeContent } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel';

Expand Down Expand Up @@ -138,6 +138,7 @@ export abstract class MainThreadEditorsShape {
$tryRevealRange(id: string, range: editorCommon.IRange, revealType: TextEditorRevealType): TPromise<any> { throw ni(); }
$trySetSelections(id: string, selections: editorCommon.ISelection[]): TPromise<any> { throw ni(); }
$tryApplyEdits(id: string, modelVersionId: number, edits: editorCommon.ISingleEditOperation[], opts: IApplyEditsOptions): TPromise<boolean> { throw ni(); }
$tryInsertSnippet(id: string, template: string, opts: IUndoStopOptions): TPromise<any> { throw ni(); }
}

export abstract class MainThreadTreeExplorersShape {
Expand Down
17 changes: 12 additions & 5 deletions src/vs/workbench/api/node/extHostEditors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Event, { Emitter } from 'vs/base/common/event';
import { TPromise } from 'vs/base/common/winjs.base';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { ExtHostDocuments, ExtHostDocumentData } from 'vs/workbench/api/node/extHostDocuments';
import { Selection, Range, Position, EndOfLine, TextEditorRevealType, TextEditorSelectionChangeKind, TextEditorLineNumbersStyle } from './extHostTypes';
import { Selection, Range, Position, EndOfLine, TextEditorRevealType, TextEditorSelectionChangeKind, TextEditorLineNumbersStyle, SnippetString } from './extHostTypes';
import { ISingleEditOperation, TextEditorCursorStyle } from 'vs/editor/common/editorCommon';
import { IResolvedTextEditorConfiguration, ISelectionChangeEvent, ITextEditorConfigurationUpdate } from 'vs/workbench/api/node/mainThreadEditorsTracker';
import * as TypeConverters from './extHostTypeConverters';
Expand Down Expand Up @@ -595,10 +595,17 @@ class ExtHostTextEditor implements vscode.TextEditor {

// ---- editing

edit(callback: (edit: TextEditorEdit) => void, options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Thenable<boolean> {
let edit = new TextEditorEdit(this._documentData.document, options);
callback(edit);
return this._applyEdit(edit);
edit(callback: (edit: TextEditorEdit) => void, options: { undoStopBefore: boolean; undoStopAfter: boolean; }): Thenable<boolean>;
edit(snippet: SnippetString, options: { undoStopBefore: boolean; undoStopAfter: boolean; }): Thenable<boolean>;

edit(callbackOrSnippet: ((edit: TextEditorEdit) => void) | SnippetString, options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Thenable<boolean> {
if (SnippetString.isSnippetString(callbackOrSnippet)) {
return this._proxy.$tryInsertSnippet(this._id, callbackOrSnippet.value, options);
} else {
let edit = new TextEditorEdit(this._documentData.document, options);
callbackOrSnippet(edit);
return this._applyEdit(edit);
}
}

_applyEdit(editBuilder: TextEditorEdit): TPromise<boolean> {
Expand Down
10 changes: 10 additions & 0 deletions src/vs/workbench/api/node/extHostTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,16 @@ export class WorkspaceEdit {

export class SnippetString {

static isSnippetString(thing: any): thing is SnippetString {
if (thing instanceof SnippetString) {
return true;
}
if (!thing) {
return false;
}
return typeof (<SnippetString>thing).value === 'string';
}

private static _escape(value: string): string {
return value.replace(/\$|}|\\/g, '\\$&');
}
Expand Down
9 changes: 8 additions & 1 deletion src/vs/workbench/api/node/mainThreadEditors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import { Position as EditorPosition } from 'vs/platform/editor/common/editor';
import { IModelService } from 'vs/editor/common/services/modelService';
import { MainThreadEditorsTracker, TextEditorRevealType, MainThreadTextEditor, IApplyEditsOptions, ITextEditorConfigurationUpdate } from 'vs/workbench/api/node/mainThreadEditorsTracker';
import { MainThreadEditorsTracker, TextEditorRevealType, MainThreadTextEditor, IApplyEditsOptions, IUndoStopOptions, ITextEditorConfigurationUpdate } from 'vs/workbench/api/node/mainThreadEditorsTracker';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { equals as arrayEquals } from 'vs/base/common/arrays';
import { equals as objectEquals } from 'vs/base/common/objects';
Expand Down Expand Up @@ -293,6 +293,13 @@ export class MainThreadEditors extends MainThreadEditorsShape {
return TPromise.as(this._textEditorsMap[id].applyEdits(modelVersionId, edits, opts));
}

$tryInsertSnippet(id: string, template: string, opts: IUndoStopOptions): TPromise<boolean> {
if (!this._textEditorsMap[id]) {
return TPromise.wrapError('TextEditor disposed');
}
return TPromise.as(this._textEditorsMap[id].insertSnippet(template, opts));
}

$registerTextEditorDecorationType(key: string, options: IDecorationRenderOptions): void {
this._editorTracker.registerTextEditorDecorationType(key, options);
}
Expand Down
28 changes: 27 additions & 1 deletion src/vs/workbench/api/node/mainThreadEditorsTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import { IdGenerator } from 'vs/base/common/idGenerator';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { SnippetController } from 'vs/editor/contrib/snippet/common/snippetController';
import { EndOfLine, TextEditorLineNumbersStyle } from 'vs/workbench/api/node/extHostTypes';

export interface ITextEditorConfigurationUpdate {
Expand Down Expand Up @@ -58,9 +59,12 @@ export enum TextEditorRevealType {
InCenterIfOutsideViewport = 2
}

export interface IApplyEditsOptions {
export interface IUndoStopOptions {
undoStopBefore: boolean;
undoStopAfter: boolean;
}

export interface IApplyEditsOptions extends IUndoStopOptions {
setEndOfLine: EndOfLine;
}

Expand Down Expand Up @@ -383,6 +387,28 @@ export class MainThreadTextEditor {
console.warn('applyEdits on invisible editor');
return false;
}

insertSnippet(template: string, opts: IUndoStopOptions) {
const snippetController = SnippetController.get(this._codeEditor);

if (!this._codeEditor) {
return false;
}

this._codeEditor.focus();

if (opts.undoStopBefore) {
this._codeEditor.pushUndoStop();
}

snippetController.insertSnippet(template, 0, 0);

if (opts.undoStopAfter) {
this._codeEditor.pushUndoStop();
}

return true;
}
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/test/node/api/extHostEditors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ suite('ExtHostTextEditorOptions', () => {
$tryRevealRange: undefined,
$trySetSelections: undefined,
$tryApplyEdits: undefined,
$tryInsertSnippet: undefined
};
opts = new ExtHostTextEditorOptions(mockProxy, '1', {
tabSize: 4,
Expand Down

0 comments on commit b4817e5

Please sign in to comment.