提交 f8bb4ade 编写于 作者: E Erich Gamma

Added wrapWithAbbreviation, updateTag, removeTag

上级 b7ee78d6
......@@ -700,7 +700,7 @@ class InsertSnippetController {
}
export interface ISnippetController extends editorCommon.IEditorContribution {
run(snippet: CodeSnippet, overwriteBefore: number, overwriteAfter: number): void;
run(snippet: CodeSnippet, overwriteBefore: number, overwriteAfter: number, stripPrefix?:boolean): void;
jumpToNextPlaceholder(): void;
jumpToPrevPlaceholder(): void;
acceptSnippet(): void;
......@@ -736,7 +736,7 @@ class SnippetController implements ISnippetController {
return SnippetController.ID;
}
public run(snippet:CodeSnippet, overwriteBefore:number, overwriteAfter:number): void {
public run(snippet:CodeSnippet, overwriteBefore:number, overwriteAfter:number, stripPrefix?:boolean): void {
let prevController = this._currentController;
this._currentController = null;
......@@ -744,7 +744,7 @@ class SnippetController implements ISnippetController {
// No placeholders => execute for all editor selections
this._runForAllSelections(snippet, overwriteBefore, overwriteAfter);
} else {
this._runForPrimarySelection(snippet, overwriteBefore, overwriteAfter);
this._runForPrimarySelection(snippet, overwriteBefore, overwriteAfter, stripPrefix);
}
if (!this._currentController) {
......@@ -785,12 +785,12 @@ class SnippetController implements ISnippetController {
}
}
private _runForPrimarySelection(snippet: CodeSnippet, overwriteBefore: number, overwriteAfter: number): void {
private _runForPrimarySelection(snippet: CodeSnippet, overwriteBefore: number, overwriteAfter: number, stripPrefix?:boolean): void {
let initialAlternativeVersionId = this._editor.getModel().getAlternativeVersionId();
let edits: editorCommon.IIdentifiedSingleEditOperation[] = [];
let prepared = SnippetController._prepareSnippet(this._editor, this._editor.getSelection(), snippet, overwriteBefore, overwriteAfter);
let prepared = SnippetController._prepareSnippet(this._editor, this._editor.getSelection(), snippet, overwriteBefore, overwriteAfter, stripPrefix);
SnippetController._addCommandForSnippet(this._editor.getModel(), prepared.adaptedSnippet, prepared.typeRange, edits);
if (edits.length > 0) {
......@@ -822,7 +822,7 @@ class SnippetController implements ISnippetController {
}
}
private static _prepareSnippet(editor:editorCommon.ICommonCodeEditor, selection:Selection, snippet:CodeSnippet, overwriteBefore:number, overwriteAfter:number): { typeRange: Range; adaptedSnippet: ICodeSnippet; } {
private static _prepareSnippet(editor:editorCommon.ICommonCodeEditor, selection:Selection, snippet:CodeSnippet, overwriteBefore:number, overwriteAfter:number, stripPrefix?:boolean): { typeRange: Range; adaptedSnippet: ICodeSnippet; } {
var model = editor.getModel();
var typeRange = SnippetController._getTypeRangeForSelection(model, selection, overwriteBefore, overwriteAfter);
......@@ -831,7 +831,7 @@ class SnippetController implements ISnippetController {
var nextInSnippet = snippet.lines[0].substr(overwriteBefore);
var commonPrefix = strings.commonPrefixLength(nextTextOnLine, nextInSnippet);
if (commonPrefix > 0) {
if (commonPrefix > 0 && !stripPrefix === false) {
typeRange = typeRange.setEndPosition(typeRange.endLineNumber, typeRange.endColumn + commonPrefix);
}
}
......
......@@ -60,7 +60,7 @@ export class EditorAccessor implements emmet.Editor {
}
public setCaretPos(pos: number): void {
//
this.createSelection(pos);
}
public getCurrentLine(): string {
......@@ -86,29 +86,29 @@ export class EditorAccessor implements emmet.Editor {
// shift column by +1 since they are 1 based
let range = new Range(startPosition.lineNumber, startPosition.column + 1, endPosition.lineNumber, endPosition.column + 1);
let deletePreviousChars = 0;
if (range.startLineNumber === range.endLineNumber) {
// The snippet will delete
deletePreviousChars = range.endColumn - range.startColumn;
} else {
// We must manually delete
let command = new ReplaceCommand(range, '');
this.editor.executeCommand('emmet', command);
deletePreviousChars = 0;
}
let command = new ReplaceCommand(range, '');
this.editor.executeCommand('emmet', command);
let snippet = snippets.CodeSnippet.convertExternalSnippet(value, snippets.ExternalSnippetType.EmmetSnippet);
let codeSnippet = new snippets.CodeSnippet(snippet);
snippets.getSnippetController(this.editor).run(codeSnippet, deletePreviousChars, 0);
snippets.getSnippetController(this.editor).run(codeSnippet, 0, 0, false);
}
public getContent(): string {
return this.editor.getModel().getValue();
}
public createSelection(start: number, end: number): void {
//
public createSelection(startOffset: number, endOffset?: number): void {
let startPosition = this.getPositionFromOffset(startOffset);
let endPosition = null;
if (!endOffset) {
endPosition = startPosition;
} else {
endPosition = this.getPositionFromOffset(endOffset);
}
let range = new Range(startPosition.lineNumber, startPosition.column + 1, endPosition.lineNumber, endPosition.column + 1);
this.editor.setSelection(range);
}
public getSyntax(): string {
......@@ -136,7 +136,12 @@ export class EditorAccessor implements emmet.Editor {
}
public getSelection(): string {
return '';
let selection = this.editor.getSelection();
let model = this.editor.getModel();
let start = selection.getStartPosition();
let end = selection.getEndPosition();
let range = new Range(start.lineNumber, start.column, end.lineNumber, end.column);
return model.getValueInRange(range);
}
public getFilePath(): string {
......
......@@ -11,7 +11,7 @@ import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/edi
import {IConfigurationRegistry, Extensions as ConfigurationExtensions} from 'vs/platform/configuration/common/configurationRegistry';
import editorCommon = require('vs/editor/common/editorCommon');
import {ExpandAbbreviationAction} from './emmetActions';
import {ExpandAbbreviationAction, WrapWithAbbreviationAction, RemoveTagAction, UpdateTagAction} from './emmetActions';
import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
import {KeyCode} from 'vs/base/common/keyCodes';
import {KbExpr} from 'vs/platform/keybinding/common/keybindingService';
......@@ -21,6 +21,21 @@ CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(ExpandAbbre
nls.localize('expandAbbreviationAction',
"Emmet: Expand Abbreviation"), void 0, 'Emmet: Expand Abbreviation'));
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(WrapWithAbbreviationAction,
WrapWithAbbreviationAction.ID,
nls.localize('wrapWithAbbreviationAction',
"Emmet: Wrap with Abbreviation"), void 0, 'Emmet: Wrap with Abbreviation'));
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(RemoveTagAction,
RemoveTagAction.ID,
nls.localize('removeTag',
"Emmet: Remove Tag"), void 0, 'Emmet: Remove Tag'));
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(UpdateTagAction,
UpdateTagAction.ID,
nls.localize('updateTag',
"Emmet: Update Tag"), void 0, 'Emmet: Update Tag'));
KeybindingsRegistry.registerCommandRule({
id: ExpandAbbreviationAction.ID,
weight: KeybindingsRegistry.WEIGHT.editorContrib(),
......
......@@ -13,30 +13,30 @@ declare module 'emmet' {
export interface Editor {
/**
* Returns character indexes of selected text: object with <code>start</code>
* and <code>end</code> properties. If there's no selection, should return
* and <code>end</code> properties. If there's no selection, should return
* object with <code>start</code> and <code>end</code> properties referring
* to current caret position
* @return {Object}
* @example
* var selection = editor.getSelectionRange();
* alert(selection.start + ', ' + selection.end);
* alert(selection.start + ', ' + selection.end);
*/
getSelectionRange(): Range;
/**
* Creates selection from <code>start</code> to <code>end</code> character
* indexes. If <code>end</code> is omitted, this method should place caret
* indexes. If <code>end</code> is omitted, this method should place caret
* and <code>start</code> index
* @param {Number} start
* @param {Number} [end]
* @example
* editor.createSelection(10, 40);
*
*
* //move caret to 15th character
* editor.createSelection(15);
*/
createSelection(start: number, end: number): void;
createSelection(start: number, end?: number): void;
/**
* Returns current line's start and end indexes as object with <code>start</code>
* and <code>end</code> properties
......@@ -46,72 +46,72 @@ declare module 'emmet' {
* alert(range.start + ', ' + range.end);
*/
getCurrentLineRange(): Range;
/**
* Returns current caret position
* @return {Number|null}
*/
getCaretPos(): number;
/**
* Set new caret position
* @param {Number} pos Caret position
*/
setCaretPos(pos: number): void;
/**
* Returns content of current line
* @return {String}
*/
getCurrentLine(): string;
/**
* Replace editor's content or it's part (from <code>start</code> to
* <code>end</code> index). If <code>value</code> contains
* <code>caret_placeholder</code>, the editor will put caret into
* Replace editor's content or it's part (from <code>start</code> to
* <code>end</code> index). If <code>value</code> contains
* <code>caret_placeholder</code>, the editor will put caret into
* this position. If you skip <code>start</code> and <code>end</code>
* arguments, the whole target's content will be replaced with
* <code>value</code>.
*
* arguments, the whole target's content will be replaced with
* <code>value</code>.
*
* If you pass <code>start</code> argument only,
* the <code>value</code> will be placed at <code>start</code> string
* index of current content.
*
* the <code>value</code> will be placed at <code>start</code> string
* index of current content.
*
* If you pass <code>start</code> and <code>end</code> arguments,
* the corresponding substring of current target's content will be
* replaced with <code>value</code>.
* the corresponding substring of current target's content will be
* replaced with <code>value</code>.
* @param {String} value Content you want to paste
* @param {Number} [start] Start index of editor's content
* @param {Number} [end] End index of editor's content
* @param {Boolean} [no_indent] Do not auto indent <code>value</code>
*/
replaceContent(value: string, start: number, end: number, no_indent: boolean): void;
/**
* Returns editor's content
* @return {String}
*/
getContent(): string;
/**
* Returns current editor's syntax mode
* @return {String}
*/
getSyntax(): string;
/**
* Returns current output profile name (see profile module).
* In most cases, this method should return <code>null</code> and let
* In most cases, this method should return <code>null</code> and let
* Emmet guess best profile name for current syntax and user data.
* In case you’re using advanced editor with access to syntax scopes
* (like Sublime Text 2), you can return syntax name for current scope.
* In case you’re using advanced editor with access to syntax scopes
* (like Sublime Text 2), you can return syntax name for current scope.
* For example, you may return `line` profile when editor caret is inside
* string of programming language.
*
*
* @return {String}
*/
getProfileName(): string;
/**
* Ask user to enter something
* @param {String} title Dialog title
......@@ -124,7 +124,7 @@ declare module 'emmet' {
getFilePath(): string;
}
/**
* Runs given action
* @param {String} name Action name
......
......@@ -10,34 +10,113 @@ import {IEditorActionDescriptorData, ICommonCodeEditor} from 'vs/editor/common/e
import {EditorAction} from 'vs/editor/common/editorAction';
import {Behaviour} from 'vs/editor/common/editorActionEnablement';
import {EditorAccessor} from './editorAccessor';
import {IQuickOpenService, IInputOptions} from 'vs/workbench/services/quickopen/common/quickOpenService';
import nls = require('vs/nls');
export class ExpandAbbreviationAction extends EditorAction {
static ID = 'editor.emmet.action.expandAbbreviation';
export abstract class EmmetEditorAction extends EditorAction {
private editorAccessor: EditorAccessor;
protected static editorAccessor: EditorAccessor;
constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor) {
super(descriptor, editor, Behaviour.TextFocus);
this.editorAccessor = new EditorAccessor(editor);
if (!EmmetEditorAction.editorAccessor) {
EmmetEditorAction.editorAccessor = new EditorAccessor(editor);
}
}
abstract runEmmetAction(_module: any);
public run(): TPromise<boolean> {
return new TPromise((c, e) => {
require(['emmet'], (_module) => {
try {
if (!this.editorAccessor.isEmmetEnabledMode()) {
this.editorAccessor.noExpansionOccurred();
if (!EmmetEditorAction.editorAccessor.isEmmetEnabledMode()) {
EmmetEditorAction.editorAccessor.noExpansionOccurred();
return;
}
if (!_module.run('expand_abbreviation', this.editorAccessor)) {
this.editorAccessor.noExpansionOccurred();
}
this.runEmmetAction(_module);
} catch (err) {
//
} finally {
this.editorAccessor.flushCache();
EmmetEditorAction.editorAccessor.flushCache();
}
}, e);
});
}
}
export class ExpandAbbreviationAction extends EmmetEditorAction {
static ID = 'editor.emmet.action.expandAbbreviation';
constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor) {
super(descriptor, editor);
}
public runEmmetAction(_module) {
if (!_module.run('expand_abbreviation', EmmetEditorAction.editorAccessor)) {
EmmetEditorAction.editorAccessor.noExpansionOccurred();
}
}
}
export class RemoveTagAction extends EmmetEditorAction {
static ID = 'editor.emmet.action.removeTag';
constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor) {
super(descriptor, editor);
}
public runEmmetAction(_module) {
if (!_module.run('remove_tag', EmmetEditorAction.editorAccessor)) {
EmmetEditorAction.editorAccessor.noExpansionOccurred();
}
}
}
export class UpdateTagAction extends EmmetEditorAction {
static ID = 'editor.emmet.action.updateTag';
constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IQuickOpenService private quickOpenService: IQuickOpenService) {
super(descriptor, editor);
}
public runEmmetAction(_module) {
let options: IInputOptions = {
prompt: nls.localize('enterTag', "Enter Tag"),
placeHolder: nls.localize('tag', "Tag")
};
this.quickOpenService.input(options).then(tag => {
this.wrapAbbreviation(_module, tag);
});
}
private wrapAbbreviation(_module: any, tag) {
if (!_module.run('update_tag', EmmetEditorAction.editorAccessor, tag)) {
EmmetEditorAction.editorAccessor.noExpansionOccurred();
}
}
}
export class WrapWithAbbreviationAction extends EmmetEditorAction {
static ID = 'editor.emmet.action.wrapWithAbbreviation';
constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IQuickOpenService private quickOpenService: IQuickOpenService) {
super(descriptor, editor);
}
public runEmmetAction(_module) {
let options: IInputOptions = {
prompt: nls.localize('enterAbbreviation', "Enter Abbreviation"),
placeHolder: nls.localize('abbreviation', "Abbreviation")
};
this.quickOpenService.input(options).then(abbreviation => {
this.wrapAbbreviation(_module, abbreviation);
});
}
private wrapAbbreviation(_module: any, abbreviation) {
if (!_module.run('wrap_with_abbreviation', EmmetEditorAction.editorAccessor, abbreviation)) {
EmmetEditorAction.editorAccessor.noExpansionOccurred();
}
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册