mirror of
https://github.com/microsoft/vscode-extension-samples.git
synced 2026-04-27 16:55:44 +08:00
Implement move active tab
This commit is contained in:
@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import {MotionState, Motion} from './motions';
|
||||
|
||||
export enum Mode {
|
||||
@ -34,7 +35,13 @@ export interface IController {
|
||||
getDeleteRegister(): DeleteRegister;
|
||||
}
|
||||
|
||||
export abstract class AbstractCommandDescriptor {
|
||||
|
||||
public abstract createCommand(args?: any): Command;
|
||||
|
||||
}
|
||||
|
||||
export interface Command {
|
||||
commandId: string,
|
||||
args?: any
|
||||
args?: any[]
|
||||
}
|
||||
@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import {
|
||||
TextEditorCursorStyle,
|
||||
Position,
|
||||
@ -135,12 +136,12 @@ export class Controller implements IController {
|
||||
return `VIM:> ${label}` + (this._currentInput ? ` >${this._currentInput}` : ``);
|
||||
}
|
||||
|
||||
public type(editor: TextEditor, text: string): ITypeResult {
|
||||
public type(editor: TextEditor, text: string): Thenable<ITypeResult> {
|
||||
if (this._currentMode !== Mode.NORMAL && this._currentMode !== Mode.REPLACE) {
|
||||
return {
|
||||
return Promise.resolve({
|
||||
hasConsumedInput: false,
|
||||
executeEditorCommand: null
|
||||
};
|
||||
});
|
||||
}
|
||||
if (this._currentMode === Mode.REPLACE) {
|
||||
let pos = editor.selection.active;
|
||||
@ -150,10 +151,10 @@ export class Controller implements IController {
|
||||
setPositionAndReveal(editor, pos.line, pos.character + 1);
|
||||
});
|
||||
|
||||
return {
|
||||
return Promise.resolve({
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
};
|
||||
});
|
||||
}
|
||||
this._currentInput += text;
|
||||
return this._interpretNormalModeInput(editor);
|
||||
@ -175,8 +176,31 @@ export class Controller implements IController {
|
||||
return true;
|
||||
}
|
||||
|
||||
private _interpretNormalModeInput(editor: TextEditor): ITypeResult {
|
||||
let command = Mappings.findCommand(this._currentInput);
|
||||
private _interpretNormalModeInput(editor: TextEditor): Thenable<ITypeResult> {
|
||||
if (this._currentInput.startsWith(':')) {
|
||||
return vscode.window.showInputBox({value: 'tabm'}).then((value) => {
|
||||
let motionCommand = value ? Mappings.findMotionCommand(value) : null;
|
||||
this._currentInput = '';
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: motionCommand
|
||||
};
|
||||
});
|
||||
}
|
||||
let result = this._findMapping(this._currentInput, editor);
|
||||
if (!result) {
|
||||
// INVALID INPUT - beep!!
|
||||
this._currentInput = '';
|
||||
result = {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
};
|
||||
}
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
|
||||
private _findMapping(input: string, editor: TextEditor): ITypeResult {
|
||||
let command = Mappings.findCommand(input);
|
||||
if (command) {
|
||||
this._currentInput = '';
|
||||
return {
|
||||
@ -185,7 +209,7 @@ export class Controller implements IController {
|
||||
};
|
||||
}
|
||||
|
||||
let operator = Mappings.findOperator(this._currentInput);
|
||||
let operator = Mappings.findOperator(input);
|
||||
if (operator) {
|
||||
if (this._isVisual) {
|
||||
if (operator.runVisual(this, editor)) {
|
||||
@ -203,7 +227,7 @@ export class Controller implements IController {
|
||||
};
|
||||
}
|
||||
|
||||
let motionCommand = Mappings.findMotionCommand(this._currentInput, this._isVisual);
|
||||
let motionCommand = Mappings.findMotionCommand(input, this._isVisual);
|
||||
if (motionCommand) {
|
||||
this._currentInput = '';
|
||||
return {
|
||||
@ -212,7 +236,7 @@ export class Controller implements IController {
|
||||
};
|
||||
}
|
||||
|
||||
let motion = Mappings.findMotion(this._currentInput);
|
||||
let motion = Mappings.findMotion(input);
|
||||
if (motion) {
|
||||
let newPos = motion.run(editor.document, editor.selection.active, this._motionState);
|
||||
if (this._isVisual) {
|
||||
@ -229,20 +253,14 @@ export class Controller implements IController {
|
||||
}
|
||||
|
||||
// is it motion building
|
||||
if (this.isMotionPrefix(this._currentInput)) {
|
||||
if (this.isMotionPrefix(input)) {
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
};
|
||||
}
|
||||
|
||||
// INVALID INPUT - beep!!
|
||||
this._currentInput = '';
|
||||
|
||||
return {
|
||||
hasConsumedInput: true,
|
||||
executeEditorCommand: null
|
||||
};
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -127,17 +127,22 @@ class VimExt {
|
||||
}
|
||||
|
||||
public type(text: string): void {
|
||||
let r = this._controller.type(vscode.window.activeTextEditor, text);
|
||||
if (r.hasConsumedInput) {
|
||||
this._ensureState();
|
||||
if (r.executeEditorCommand) {
|
||||
vscode.commands.executeCommand(r.executeEditorCommand.commandId, r.executeEditorCommand.args);
|
||||
let r = this._controller.type(vscode.window.activeTextEditor, text).then(
|
||||
(r) => {
|
||||
if (r.hasConsumedInput) {
|
||||
this._ensureState();
|
||||
if (r.executeEditorCommand) {
|
||||
let args = [r.executeEditorCommand.commandId];
|
||||
args = args.concat(r.executeEditorCommand.args);
|
||||
vscode.commands.executeCommand.apply(this, args);
|
||||
}
|
||||
return;
|
||||
}
|
||||
vscode.commands.executeCommand('default:type', {
|
||||
text: text
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
vscode.commands.executeCommand('default:type', {
|
||||
text: text
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
public replacePrevChar(text: string, replaceCharCnt: number): void {
|
||||
|
||||
@ -5,9 +5,9 @@
|
||||
'use strict';
|
||||
|
||||
import {TextEditor} from 'vscode';
|
||||
import {Motion, Motions, MotionCommand} from './motions';
|
||||
import {Motion, Motions} from './motions';
|
||||
import {Operator, Operators} from './operators';
|
||||
import {IController, Command} from './common';
|
||||
import {IController, Command, AbstractCommandDescriptor} from './common';
|
||||
|
||||
|
||||
const CHAR_TO_MOTION: { [char: string]: Motion; } = {};
|
||||
@ -15,8 +15,8 @@ function defineMotion(char: string, motion: Motion): void {
|
||||
CHAR_TO_MOTION[char] = motion;
|
||||
};
|
||||
|
||||
const CHAR_TO_MOTION_COMMAND: { [char: string]: MotionCommand; } = {};
|
||||
function defineMotionCommand(char: string, motionCommand: MotionCommand): void {
|
||||
const CHAR_TO_MOTION_COMMAND: { [char: string]: AbstractCommandDescriptor; } = {};
|
||||
function defineMotionCommand(char: string, motionCommand: AbstractCommandDescriptor): void {
|
||||
CHAR_TO_MOTION_COMMAND[char] = motionCommand;
|
||||
};
|
||||
|
||||
@ -52,6 +52,13 @@ defineMotionCommand('L', Motions.ViewPortBottom);
|
||||
defineMotion('w', Motions.NextWordStart);
|
||||
defineMotion('e', Motions.NextWordEnd);
|
||||
|
||||
// Window motions
|
||||
defineMotionCommand('tabm', Motions.MoveActiveEditor);
|
||||
defineMotionCommand('tabm<', Motions.MoveActiveEditorLeft);
|
||||
defineMotionCommand('tabm>', Motions.MoveActiveEditorRight);
|
||||
defineMotionCommand('tabm<<', Motions.MoveActiveEditorFirst);
|
||||
defineMotionCommand('tabm>>', Motions.MoveActiveEditorLast);
|
||||
defineMotionCommand('tabm.', Motions.MoveActiveEditorCenter);
|
||||
|
||||
const CHAR_TO_OPERATOR: { [char: string]: Operator; } = {};
|
||||
function defineOperator(char: string, operator: Operator): void {
|
||||
@ -106,7 +113,10 @@ export class Mappings {
|
||||
if (!motionCommand) {
|
||||
motionCommand = CHAR_TO_MOTION_COMMAND[parsed.input.substr(1, 3)];
|
||||
}
|
||||
return motionCommand ? motionCommand.command({ isVisual: isVisual, repeat: parsed.repeatCount }) : null;
|
||||
if (!motionCommand) {
|
||||
motionCommand = CHAR_TO_MOTION_COMMAND[parsed.input];
|
||||
}
|
||||
return motionCommand ? motionCommand.createCommand({ isVisual: isVisual, repeat: parsed.hasRepeatCount ? parsed.repeatCount : undefined}) : null;
|
||||
}
|
||||
|
||||
public static findOperator(input: string): IFoundOperator {
|
||||
@ -117,10 +127,10 @@ export class Mappings {
|
||||
}
|
||||
let operatorArgs = parsed.input.substr(1);
|
||||
return {
|
||||
runNormal: (controller: IController, editor:TextEditor) => {
|
||||
runNormal: (controller: IController, editor: TextEditor) => {
|
||||
return operator.runNormalMode(controller, editor, parsed.repeatCount, operatorArgs);
|
||||
},
|
||||
runVisual: (controller: IController, editor:TextEditor) => {
|
||||
runVisual: (controller: IController, editor: TextEditor) => {
|
||||
return operator.runVisualMode(controller, editor, operatorArgs);
|
||||
}
|
||||
};
|
||||
@ -150,6 +160,14 @@ function _parseNumberAndString(input: string): INumberAndString {
|
||||
input: input.substr(repeatCountMatch[0].length)
|
||||
};
|
||||
}
|
||||
repeatCountMatch = input.match(/(\d+)$/);
|
||||
if (repeatCountMatch) {
|
||||
return {
|
||||
hasRepeatCount: true,
|
||||
repeatCount: parseInt(repeatCountMatch[1], 10),
|
||||
input: input.substr(0, input.length - repeatCountMatch[1].length)
|
||||
};
|
||||
}
|
||||
return {
|
||||
hasRepeatCount: false,
|
||||
repeatCount: 1,
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
import {Position, TextDocument} from 'vscode';
|
||||
import {Words, WordCharacters} from './words';
|
||||
import {Command} from './common';
|
||||
import {Command, AbstractCommandDescriptor} from './common';
|
||||
|
||||
export class MotionState {
|
||||
|
||||
@ -22,12 +22,6 @@ export class MotionState {
|
||||
|
||||
}
|
||||
|
||||
export abstract class MotionCommand {
|
||||
|
||||
public abstract command(args: any): Command;
|
||||
|
||||
}
|
||||
|
||||
export abstract class Motion {
|
||||
public abstract run(doc: TextDocument, pos: Position, state: MotionState): Position;
|
||||
|
||||
@ -250,37 +244,60 @@ class GoToLineDefinedMotion extends GoToLineMotion {
|
||||
}
|
||||
}
|
||||
|
||||
class CursorMoveCommand extends MotionCommand {
|
||||
class CursorMoveCommand extends AbstractCommandDescriptor {
|
||||
|
||||
constructor(private to: string, private by?: string) {
|
||||
super();
|
||||
}
|
||||
|
||||
public command(count?: number): Command {
|
||||
let cursorMoveArgs= { to: this.to }
|
||||
public createCommand(args?: any): Command {
|
||||
let cursorMoveArgs: any = {
|
||||
to: this.to,
|
||||
by: this.by,
|
||||
value: args.repeat || 1,
|
||||
select: !!args.isVisual
|
||||
}
|
||||
return {
|
||||
commandId: 'cursorMove',
|
||||
args: this.addArgs(cursorMoveArgs, count)
|
||||
args: cursorMoveArgs
|
||||
};
|
||||
}
|
||||
|
||||
protected addArgs(cursorMoveArgs: any, args: any): any {
|
||||
cursorMoveArgs.select = !!args.isVisual;
|
||||
if (this.by) {
|
||||
cursorMoveArgs.by = this.by;
|
||||
}
|
||||
return cursorMoveArgs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RepeatCursorMoveCommand extends CursorMoveCommand {
|
||||
class MoveActiveEditorCommandByPosition extends AbstractCommandDescriptor {
|
||||
|
||||
protected addArgs(cursorMoveArgs: any, args: any): any {
|
||||
cursorMoveArgs.amount = args.repeat || 1;
|
||||
return super.addArgs(cursorMoveArgs, args);
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public createCommand(args?: any): Command {
|
||||
let moveActiveEditorArgs: any = {
|
||||
to: args.repeat === void 0 ? 'last' : 'position',
|
||||
value: args.repeat !== void 0 ? args.repeat + 1 : undefined
|
||||
}
|
||||
return {
|
||||
commandId: 'moveActiveEditor',
|
||||
args: moveActiveEditorArgs
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class MoveActiveEditorCommand extends AbstractCommandDescriptor {
|
||||
|
||||
constructor(private to: string) {
|
||||
super();
|
||||
}
|
||||
|
||||
public createCommand(args?: any): Command {
|
||||
let moveActiveEditorArgs: any = {
|
||||
to: this.to,
|
||||
value: args.repeat ? args.repeat : 1
|
||||
}
|
||||
return {
|
||||
commandId: 'moveActiveEditor',
|
||||
args: moveActiveEditorArgs
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const Motions = {
|
||||
@ -288,8 +305,8 @@ export const Motions = {
|
||||
|
||||
NextCharacter: new NextCharacterMotion(),
|
||||
|
||||
Left: new RepeatCursorMoveCommand('left'),
|
||||
Right: new RepeatCursorMoveCommand('right'),
|
||||
Left: new CursorMoveCommand('left'),
|
||||
Right: new CursorMoveCommand('right'),
|
||||
Down: new DownMotion(),
|
||||
Up: new UpMotion(),
|
||||
|
||||
@ -301,20 +318,27 @@ export const Motions = {
|
||||
GoToFirstLine: new GoToFirstLineMotion(),
|
||||
GoToLastLine: new GoToLastLineMotion(),
|
||||
|
||||
ScrollLeft: new RepeatCursorMoveCommand('left'),
|
||||
ScrollRight: new RepeatCursorMoveCommand('right'),
|
||||
ScrollLeftByHalfLine: new RepeatCursorMoveCommand('left', 'halfLine'),
|
||||
ScrollRightByHalfLine: new RepeatCursorMoveCommand('right', 'halfLine'),
|
||||
ScrollLeft: new CursorMoveCommand('left'),
|
||||
ScrollRight: new CursorMoveCommand('right'),
|
||||
ScrollLeftByHalfLine: new CursorMoveCommand('left', 'halfLine'),
|
||||
ScrollRightByHalfLine: new CursorMoveCommand('right', 'halfLine'),
|
||||
|
||||
WrappedLineUp: new RepeatCursorMoveCommand('up', 'wrappedLine'),
|
||||
WrappedLineDown: new RepeatCursorMoveCommand('down', 'wrappedLine'),
|
||||
WrappedLineUp: new CursorMoveCommand('up', 'wrappedLine'),
|
||||
WrappedLineDown: new CursorMoveCommand('down', 'wrappedLine'),
|
||||
|
||||
WrappedLineStart: new CursorMoveCommand('wrappedLineStart'),
|
||||
WrappedLineFirstNonWhiteSpaceCharacter: new CursorMoveCommand('wrappedLineFirstNonWhitespaceCharacter'),
|
||||
WrappedLineColumnCenter: new CursorMoveCommand('wrappedLineColumnCenter'),
|
||||
WrappedLineEnd: new CursorMoveCommand('wrappedLineEnd'),
|
||||
|
||||
ViewPortTop: new RepeatCursorMoveCommand('viewPortTop'),
|
||||
ViewPortBottom: new RepeatCursorMoveCommand('viewPortBottom'),
|
||||
ViewPortTop: new CursorMoveCommand('viewPortTop'),
|
||||
ViewPortBottom: new CursorMoveCommand('viewPortBottom'),
|
||||
ViewPortCenter: new CursorMoveCommand('viewPortCenter'),
|
||||
|
||||
MoveActiveEditor: new MoveActiveEditorCommandByPosition(),
|
||||
MoveActiveEditorLeft: new MoveActiveEditorCommand('left'),
|
||||
MoveActiveEditorRight: new MoveActiveEditorCommand('right'),
|
||||
MoveActiveEditorFirst: new MoveActiveEditorCommand('first'),
|
||||
MoveActiveEditorLast: new MoveActiveEditorCommand('last'),
|
||||
MoveActiveEditorCenter: new MoveActiveEditorCommand('center')
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user