mirror of
https://github.com/microsoft/vscode-extension-samples.git
synced 2026-06-13 07:10:26 +08:00
Run format on repo
This commit is contained in:
@ -1,303 +1,303 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { TextEditorCursorStyle, Position, Range, Selection, TextEditor, TextEditorRevealType, window } from 'vscode';
|
||||
|
||||
import { Words } from './words';
|
||||
import { MotionState, Motion } from './motions';
|
||||
import { Mode, IController, DeleteRegister, Command, ModifierKeys } from './common';
|
||||
import { Mappings } from './mappings';
|
||||
|
||||
export interface ITypeResult {
|
||||
hasConsumedInput: boolean;
|
||||
executeEditorCommand: Command;
|
||||
}
|
||||
|
||||
export class Controller implements IController {
|
||||
|
||||
private _currentMode: Mode;
|
||||
private _currentInput: string;
|
||||
private _motionState: MotionState;
|
||||
private _isVisual: boolean;
|
||||
|
||||
public get motionState(): MotionState { return this._motionState; }
|
||||
public findMotion(input: string): Motion { return Mappings.findMotion(input); }
|
||||
public isMotionPrefix(input: string): boolean { return Mappings.isMotionPrefix(input); }
|
||||
|
||||
private _deleteRegister: DeleteRegister;
|
||||
public setDeleteRegister(register: DeleteRegister): void { this._deleteRegister = register; }
|
||||
public getDeleteRegister(): DeleteRegister { return this._deleteRegister; }
|
||||
|
||||
constructor() {
|
||||
this._motionState = new MotionState();
|
||||
this._deleteRegister = null;
|
||||
this.setVisual(false);
|
||||
this.setMode(Mode.NORMAL);
|
||||
}
|
||||
|
||||
public setWordSeparators(wordSeparators: string): void {
|
||||
this._motionState.wordCharacterClass = Words.createWordCharacters(wordSeparators);
|
||||
}
|
||||
|
||||
public ensureNormalModePosition(editor: TextEditor): void {
|
||||
if (this._currentMode !== Mode.NORMAL) {
|
||||
return;
|
||||
}
|
||||
if (this._isVisual) {
|
||||
return;
|
||||
}
|
||||
const sel = editor.selection;
|
||||
const pos = sel.active;
|
||||
const doc = editor.document;
|
||||
const lineContent = doc.lineAt(pos.line).text;
|
||||
if (lineContent.length === 0) {
|
||||
return;
|
||||
}
|
||||
const maxCharacter = lineContent.length - 1;
|
||||
if (pos.character > maxCharacter) {
|
||||
setPositionAndReveal(editor, pos.line, maxCharacter);
|
||||
}
|
||||
}
|
||||
|
||||
public hasInput(): boolean {
|
||||
return this._currentInput.length > 0;
|
||||
}
|
||||
|
||||
public clearInput(): void {
|
||||
this._currentInput = '';
|
||||
}
|
||||
|
||||
public getMode(): Mode {
|
||||
return this._currentMode;
|
||||
}
|
||||
|
||||
public setMode(newMode: Mode): void {
|
||||
if (newMode !== this._currentMode) {
|
||||
this._currentMode = newMode;
|
||||
this._motionState.cursorDesiredCharacter = -1; // uninitialized
|
||||
this._currentInput = '';
|
||||
}
|
||||
}
|
||||
|
||||
public setVisual(newVisual: boolean): void {
|
||||
if (this._isVisual !== newVisual) {
|
||||
this._isVisual = newVisual;
|
||||
}
|
||||
}
|
||||
|
||||
public getVisual(): boolean {
|
||||
return this._isVisual;
|
||||
}
|
||||
|
||||
public getCursorStyle(): TextEditorCursorStyle {
|
||||
if (this._currentMode === Mode.NORMAL) {
|
||||
if (/^([1-9]\d*)?(r|c)/.test(this._currentInput)) {
|
||||
return TextEditorCursorStyle.Underline;
|
||||
}
|
||||
return TextEditorCursorStyle.Block;
|
||||
}
|
||||
if (this._currentMode === Mode.REPLACE) {
|
||||
return TextEditorCursorStyle.Underline;
|
||||
}
|
||||
return TextEditorCursorStyle.Line;
|
||||
}
|
||||
|
||||
private _getModeLabel(): string {
|
||||
if (this._currentMode === Mode.NORMAL) {
|
||||
if (this._isVisual) {
|
||||
return '-- VISUAL --';
|
||||
}
|
||||
return '-- NORMAL --';
|
||||
}
|
||||
|
||||
if (this._currentMode === Mode.REPLACE) {
|
||||
if (this._isVisual) {
|
||||
return '-- (replace) VISUAL --';
|
||||
}
|
||||
return '-- REPLACE --';
|
||||
}
|
||||
|
||||
if (this._isVisual) {
|
||||
return '-- (insert) VISUAL --';
|
||||
}
|
||||
return '-- INSERT --';
|
||||
}
|
||||
|
||||
public getStatusText(): string {
|
||||
const label = this._getModeLabel();
|
||||
return `VIM:> ${label}` + (this._currentInput ? ` >${this._currentInput}` : ``);
|
||||
}
|
||||
|
||||
private _isInComposition = false;
|
||||
private _composingText = '';
|
||||
|
||||
public compositionStart(editor: TextEditor): void {
|
||||
this._isInComposition = true;
|
||||
this._composingText = '';
|
||||
}
|
||||
|
||||
public compositionEnd(editor: TextEditor): Thenable<ITypeResult> {
|
||||
this._isInComposition = false;
|
||||
const text = this._composingText;
|
||||
this._composingText = '';
|
||||
|
||||
if (text.length === 0) {
|
||||
return Promise.resolve({
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
});
|
||||
}
|
||||
|
||||
return this.type(editor, text, {});
|
||||
}
|
||||
|
||||
public type(editor: TextEditor, text: string, modifierKeys: ModifierKeys): Thenable<ITypeResult> {
|
||||
if (this._currentMode !== Mode.NORMAL && this._currentMode !== Mode.REPLACE) {
|
||||
return Promise.resolve({
|
||||
hasConsumedInput: false,
|
||||
executeEditorCommand: null
|
||||
});
|
||||
}
|
||||
|
||||
if (this._isInComposition) {
|
||||
this._composingText += text;
|
||||
return Promise.resolve({
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
});
|
||||
}
|
||||
|
||||
if (this._currentMode === Mode.REPLACE) {
|
||||
const pos = editor.selection.active;
|
||||
editor.edit((builder) => {
|
||||
builder.replace(new Range(pos.line, pos.character, pos.line, pos.character + 1), text);
|
||||
}).then(() => {
|
||||
setPositionAndReveal(editor, pos.line, pos.character + 1);
|
||||
});
|
||||
|
||||
return Promise.resolve({
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
});
|
||||
}
|
||||
this._currentInput += text;
|
||||
return this._interpretNormalModeInput(editor, modifierKeys);
|
||||
}
|
||||
|
||||
public replacePrevChar(editor: TextEditor, text: string, replaceCharCnt: number): boolean {
|
||||
if (this._currentMode !== Mode.NORMAL && this._currentMode !== Mode.REPLACE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._isInComposition) {
|
||||
this._composingText = this._composingText.substr(0, this._composingText.length - replaceCharCnt) + text;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this._currentMode === Mode.REPLACE) {
|
||||
const pos = editor.selection.active;
|
||||
editor.edit((builder) => {
|
||||
builder.replace(new Range(pos.line, pos.character - replaceCharCnt, pos.line, pos.character), text);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private _interpretNormalModeInput(editor: TextEditor, modifierKeys: ModifierKeys): Thenable<ITypeResult> {
|
||||
if (this._currentInput.startsWith(':')) {
|
||||
return window.showInputBox({ value: 'tabm' }).then((value) => {
|
||||
return this._findMapping(value || '', editor, modifierKeys);
|
||||
});
|
||||
}
|
||||
const result = this._findMapping(this._currentInput, editor, modifierKeys);
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
|
||||
private _findMapping(input: string, editor: TextEditor, modifierKeys: ModifierKeys): ITypeResult {
|
||||
const command = Mappings.findCommand(input, modifierKeys);
|
||||
if (command) {
|
||||
this._currentInput = '';
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: command
|
||||
};
|
||||
}
|
||||
|
||||
const operator = Mappings.findOperator(input, modifierKeys);
|
||||
if (operator) {
|
||||
if (this._isVisual) {
|
||||
if (operator.runVisual(this, editor)) {
|
||||
this._currentInput = '';
|
||||
}
|
||||
} else {
|
||||
// Mode.NORMAL
|
||||
if (operator.runNormal(this, editor)) {
|
||||
this._currentInput = '';
|
||||
}
|
||||
}
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
};
|
||||
}
|
||||
|
||||
const motionCommand = Mappings.findMotionCommand(input, this._isVisual, modifierKeys);
|
||||
if (motionCommand) {
|
||||
this._currentInput = '';
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: motionCommand
|
||||
};
|
||||
}
|
||||
|
||||
const motion = Mappings.findMotion(input);
|
||||
if (motion) {
|
||||
const newPos = motion.run(editor.document, editor.selection.active, this._motionState);
|
||||
if (this._isVisual) {
|
||||
setSelectionAndReveal(editor, this._motionState.anchor, newPos.line, newPos.character);
|
||||
} else {
|
||||
// Mode.NORMAL
|
||||
setPositionAndReveal(editor, newPos.line, newPos.character);
|
||||
}
|
||||
this._currentInput = '';
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
};
|
||||
}
|
||||
|
||||
// is it motion building
|
||||
if (this.isMotionPrefix(input)) {
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
};
|
||||
}
|
||||
|
||||
// INVALID INPUT - beep!!
|
||||
this._currentInput = '';
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function setSelectionAndReveal(editor: TextEditor, anchor: Position, line: number, char: number): void {
|
||||
editor.selection = new Selection(anchor, new Position(line, char));
|
||||
revealPosition(editor, line, char);
|
||||
}
|
||||
|
||||
function setPositionAndReveal(editor: TextEditor, line: number, char: number): void {
|
||||
editor.selection = new Selection(new Position(line, char), new Position(line, char));
|
||||
revealPosition(editor, line, char);
|
||||
}
|
||||
|
||||
function revealPosition(editor: TextEditor, line: number, char: number): void {
|
||||
editor.revealRange(new Range(line, char, line, char), TextEditorRevealType.Default);
|
||||
}
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { TextEditorCursorStyle, Position, Range, Selection, TextEditor, TextEditorRevealType, window } from 'vscode';
|
||||
|
||||
import { Words } from './words';
|
||||
import { MotionState, Motion } from './motions';
|
||||
import { Mode, IController, DeleteRegister, Command, ModifierKeys } from './common';
|
||||
import { Mappings } from './mappings';
|
||||
|
||||
export interface ITypeResult {
|
||||
hasConsumedInput: boolean;
|
||||
executeEditorCommand: Command;
|
||||
}
|
||||
|
||||
export class Controller implements IController {
|
||||
|
||||
private _currentMode: Mode;
|
||||
private _currentInput: string;
|
||||
private _motionState: MotionState;
|
||||
private _isVisual: boolean;
|
||||
|
||||
public get motionState(): MotionState { return this._motionState; }
|
||||
public findMotion(input: string): Motion { return Mappings.findMotion(input); }
|
||||
public isMotionPrefix(input: string): boolean { return Mappings.isMotionPrefix(input); }
|
||||
|
||||
private _deleteRegister: DeleteRegister;
|
||||
public setDeleteRegister(register: DeleteRegister): void { this._deleteRegister = register; }
|
||||
public getDeleteRegister(): DeleteRegister { return this._deleteRegister; }
|
||||
|
||||
constructor() {
|
||||
this._motionState = new MotionState();
|
||||
this._deleteRegister = null;
|
||||
this.setVisual(false);
|
||||
this.setMode(Mode.NORMAL);
|
||||
}
|
||||
|
||||
public setWordSeparators(wordSeparators: string): void {
|
||||
this._motionState.wordCharacterClass = Words.createWordCharacters(wordSeparators);
|
||||
}
|
||||
|
||||
public ensureNormalModePosition(editor: TextEditor): void {
|
||||
if (this._currentMode !== Mode.NORMAL) {
|
||||
return;
|
||||
}
|
||||
if (this._isVisual) {
|
||||
return;
|
||||
}
|
||||
const sel = editor.selection;
|
||||
const pos = sel.active;
|
||||
const doc = editor.document;
|
||||
const lineContent = doc.lineAt(pos.line).text;
|
||||
if (lineContent.length === 0) {
|
||||
return;
|
||||
}
|
||||
const maxCharacter = lineContent.length - 1;
|
||||
if (pos.character > maxCharacter) {
|
||||
setPositionAndReveal(editor, pos.line, maxCharacter);
|
||||
}
|
||||
}
|
||||
|
||||
public hasInput(): boolean {
|
||||
return this._currentInput.length > 0;
|
||||
}
|
||||
|
||||
public clearInput(): void {
|
||||
this._currentInput = '';
|
||||
}
|
||||
|
||||
public getMode(): Mode {
|
||||
return this._currentMode;
|
||||
}
|
||||
|
||||
public setMode(newMode: Mode): void {
|
||||
if (newMode !== this._currentMode) {
|
||||
this._currentMode = newMode;
|
||||
this._motionState.cursorDesiredCharacter = -1; // uninitialized
|
||||
this._currentInput = '';
|
||||
}
|
||||
}
|
||||
|
||||
public setVisual(newVisual: boolean): void {
|
||||
if (this._isVisual !== newVisual) {
|
||||
this._isVisual = newVisual;
|
||||
}
|
||||
}
|
||||
|
||||
public getVisual(): boolean {
|
||||
return this._isVisual;
|
||||
}
|
||||
|
||||
public getCursorStyle(): TextEditorCursorStyle {
|
||||
if (this._currentMode === Mode.NORMAL) {
|
||||
if (/^([1-9]\d*)?(r|c)/.test(this._currentInput)) {
|
||||
return TextEditorCursorStyle.Underline;
|
||||
}
|
||||
return TextEditorCursorStyle.Block;
|
||||
}
|
||||
if (this._currentMode === Mode.REPLACE) {
|
||||
return TextEditorCursorStyle.Underline;
|
||||
}
|
||||
return TextEditorCursorStyle.Line;
|
||||
}
|
||||
|
||||
private _getModeLabel(): string {
|
||||
if (this._currentMode === Mode.NORMAL) {
|
||||
if (this._isVisual) {
|
||||
return '-- VISUAL --';
|
||||
}
|
||||
return '-- NORMAL --';
|
||||
}
|
||||
|
||||
if (this._currentMode === Mode.REPLACE) {
|
||||
if (this._isVisual) {
|
||||
return '-- (replace) VISUAL --';
|
||||
}
|
||||
return '-- REPLACE --';
|
||||
}
|
||||
|
||||
if (this._isVisual) {
|
||||
return '-- (insert) VISUAL --';
|
||||
}
|
||||
return '-- INSERT --';
|
||||
}
|
||||
|
||||
public getStatusText(): string {
|
||||
const label = this._getModeLabel();
|
||||
return `VIM:> ${label}` + (this._currentInput ? ` >${this._currentInput}` : ``);
|
||||
}
|
||||
|
||||
private _isInComposition = false;
|
||||
private _composingText = '';
|
||||
|
||||
public compositionStart(editor: TextEditor): void {
|
||||
this._isInComposition = true;
|
||||
this._composingText = '';
|
||||
}
|
||||
|
||||
public compositionEnd(editor: TextEditor): Thenable<ITypeResult> {
|
||||
this._isInComposition = false;
|
||||
const text = this._composingText;
|
||||
this._composingText = '';
|
||||
|
||||
if (text.length === 0) {
|
||||
return Promise.resolve({
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
});
|
||||
}
|
||||
|
||||
return this.type(editor, text, {});
|
||||
}
|
||||
|
||||
public type(editor: TextEditor, text: string, modifierKeys: ModifierKeys): Thenable<ITypeResult> {
|
||||
if (this._currentMode !== Mode.NORMAL && this._currentMode !== Mode.REPLACE) {
|
||||
return Promise.resolve({
|
||||
hasConsumedInput: false,
|
||||
executeEditorCommand: null
|
||||
});
|
||||
}
|
||||
|
||||
if (this._isInComposition) {
|
||||
this._composingText += text;
|
||||
return Promise.resolve({
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
});
|
||||
}
|
||||
|
||||
if (this._currentMode === Mode.REPLACE) {
|
||||
const pos = editor.selection.active;
|
||||
editor.edit((builder) => {
|
||||
builder.replace(new Range(pos.line, pos.character, pos.line, pos.character + 1), text);
|
||||
}).then(() => {
|
||||
setPositionAndReveal(editor, pos.line, pos.character + 1);
|
||||
});
|
||||
|
||||
return Promise.resolve({
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
});
|
||||
}
|
||||
this._currentInput += text;
|
||||
return this._interpretNormalModeInput(editor, modifierKeys);
|
||||
}
|
||||
|
||||
public replacePrevChar(editor: TextEditor, text: string, replaceCharCnt: number): boolean {
|
||||
if (this._currentMode !== Mode.NORMAL && this._currentMode !== Mode.REPLACE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._isInComposition) {
|
||||
this._composingText = this._composingText.substr(0, this._composingText.length - replaceCharCnt) + text;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this._currentMode === Mode.REPLACE) {
|
||||
const pos = editor.selection.active;
|
||||
editor.edit((builder) => {
|
||||
builder.replace(new Range(pos.line, pos.character - replaceCharCnt, pos.line, pos.character), text);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private _interpretNormalModeInput(editor: TextEditor, modifierKeys: ModifierKeys): Thenable<ITypeResult> {
|
||||
if (this._currentInput.startsWith(':')) {
|
||||
return window.showInputBox({ value: 'tabm' }).then((value) => {
|
||||
return this._findMapping(value || '', editor, modifierKeys);
|
||||
});
|
||||
}
|
||||
const result = this._findMapping(this._currentInput, editor, modifierKeys);
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
|
||||
private _findMapping(input: string, editor: TextEditor, modifierKeys: ModifierKeys): ITypeResult {
|
||||
const command = Mappings.findCommand(input, modifierKeys);
|
||||
if (command) {
|
||||
this._currentInput = '';
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: command
|
||||
};
|
||||
}
|
||||
|
||||
const operator = Mappings.findOperator(input, modifierKeys);
|
||||
if (operator) {
|
||||
if (this._isVisual) {
|
||||
if (operator.runVisual(this, editor)) {
|
||||
this._currentInput = '';
|
||||
}
|
||||
} else {
|
||||
// Mode.NORMAL
|
||||
if (operator.runNormal(this, editor)) {
|
||||
this._currentInput = '';
|
||||
}
|
||||
}
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
};
|
||||
}
|
||||
|
||||
const motionCommand = Mappings.findMotionCommand(input, this._isVisual, modifierKeys);
|
||||
if (motionCommand) {
|
||||
this._currentInput = '';
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: motionCommand
|
||||
};
|
||||
}
|
||||
|
||||
const motion = Mappings.findMotion(input);
|
||||
if (motion) {
|
||||
const newPos = motion.run(editor.document, editor.selection.active, this._motionState);
|
||||
if (this._isVisual) {
|
||||
setSelectionAndReveal(editor, this._motionState.anchor, newPos.line, newPos.character);
|
||||
} else {
|
||||
// Mode.NORMAL
|
||||
setPositionAndReveal(editor, newPos.line, newPos.character);
|
||||
}
|
||||
this._currentInput = '';
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
};
|
||||
}
|
||||
|
||||
// is it motion building
|
||||
if (this.isMotionPrefix(input)) {
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
};
|
||||
}
|
||||
|
||||
// INVALID INPUT - beep!!
|
||||
this._currentInput = '';
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function setSelectionAndReveal(editor: TextEditor, anchor: Position, line: number, char: number): void {
|
||||
editor.selection = new Selection(anchor, new Position(line, char));
|
||||
revealPosition(editor, line, char);
|
||||
}
|
||||
|
||||
function setPositionAndReveal(editor: TextEditor, line: number, char: number): void {
|
||||
editor.selection = new Selection(new Position(line, char), new Position(line, char));
|
||||
revealPosition(editor, line, char);
|
||||
}
|
||||
|
||||
function revealPosition(editor: TextEditor, line: number, char: number): void {
|
||||
editor.revealRange(new Range(line, char, line, char), TextEditorRevealType.Default);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user