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

Cleanup cursor drawing and remove Motion class #238

Merged
merged 5 commits into from
Jun 5, 2016
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// "runtimeArgs": ["--harmony-default-parameters", "--harmony-rest-parameters"],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out/src"
"outDir": "${workspaceRoot}/out"
// "preLaunchTask": "npm"
},
{
Expand All @@ -23,7 +23,7 @@
// "runtimeArgs": ["--js-flags=\"--harmony --harmony-default-parameters\""],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out/test"
"outDir": "${workspaceRoot}/out"
// "preLaunchTask": "npm"
}
]
Expand Down
5 changes: 5 additions & 0 deletions extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,8 @@ function handleKeyEvent(key: string) : Promise<Boolean> {

return modeHandler.handleKeyEvent(key);
}

process.on('unhandledRejection', function(reason, p){
console.log("Possibly Unhandled Rejection at: Promise ", p, " reason: ", reason);
// application specific logging here
});
14 changes: 1 addition & 13 deletions src/mode/mode.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"use strict";

import { Motion } from './../motion/motion';

export enum ModeName {
Normal,
Insert,
Expand All @@ -12,26 +10,16 @@ export enum ModeName {
export abstract class Mode {
private _isActive : boolean;
private _name : ModeName;
private _motion : Motion;

constructor(name: ModeName, motion: Motion) {
constructor(name: ModeName) {
this._name = name;
this._motion = motion;
this._isActive = false;
}

get name(): ModeName {
return this._name;
}

get motion() : Motion {
return this._motion;
}

set motion(val : Motion) {
this._motion = val;
}

get isActive() : boolean {
return this._isActive;
}
Expand Down
107 changes: 63 additions & 44 deletions src/mode/modeHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import * as vscode from 'vscode';

import { Mode, ModeName } from './mode';
import { Motion, MotionMode } from './../motion/motion';
import { NormalMode } from './modeNormal';
import { InsertMode } from './modeInsert';
import { VisualMode } from './modeVisual';
Expand Down Expand Up @@ -182,25 +181,40 @@ export class ActionState {
}

export class ModeHandler implements vscode.Disposable {
private _motion: Motion;
private _modes: Mode[];
private _statusBarItem: vscode.StatusBarItem;
private _configuration: Configuration;
private _vimState: VimState;

// Caret Styling
private _caretDecoration = vscode.window.createTextEditorDecorationType(
{
dark: {
// used for dark colored themes
backgroundColor: 'rgba(224, 224, 224, 0.4)',
borderColor: 'rgba(240, 240, 240, 0.8)'
},
light: {
// used for light colored themes
backgroundColor: 'rgba(32, 32, 32, 0.4)',
borderColor: 'rgba(16, 16, 16, 0.8)'
},
borderStyle: 'solid',
borderWidth: '1px'
});

private get currentModeName(): ModeName {
return this.currentMode.name;
}

constructor() {
this._configuration = Configuration.fromUserFile();

this._motion = new Motion(null);
this._vimState = new VimState();
this._modes = [
new NormalMode(this._motion, this),
new InsertMode(this._motion),
new VisualMode(this._motion, this),
new NormalMode(this),
new InsertMode(),
new VisualMode(this),
];

this.setCurrentModeByName(ModeName.Normal);
Expand Down Expand Up @@ -229,20 +243,6 @@ export class ModeHandler implements vscode.Disposable {
mode.isActive = (mode.name === modeName);
}

switch (modeName) {
case ModeName.Insert:
this._motion = this._motion.changeMode(MotionMode.Cursor);
break;

case ModeName.Normal:
this._motion = this._motion.changeMode(MotionMode.Caret);
break;

case ModeName.Visual:
(activeMode as VisualMode).start();
break;
}

const statusBarText = (this.currentMode.name === ModeName.Normal) ? '' : ModeName[modeName];
this.setupStatusBarItem(statusBarText ? `-- ${statusBarText.toUpperCase()} --` : '');
}
Expand All @@ -264,13 +264,15 @@ export class ModeHandler implements vscode.Disposable {
let action = Actions.getRelevantAction(actionState.keysPressed.join(""), this._vimState);

if (action === KeypressState.NoPossibleMatch) {
// TODO: Slightly janky, for reasons that are hard to describe.

if (this.currentModeName === ModeName.Insert) {
await (this.currentMode as any).handleAction(actionState);
this._vimState.actionState = new ActionState(this._vimState);

this._vimState.cursorPosition = this._motion.position.getRight();
// TODO: Forcing a return here and handling this case is pretty janky when you
// could just allow this to pass through the post processing down below anyways.

this._vimState.cursorStartPosition = Position.FromVSCodePosition(vscode.window.activeTextEditor.selection.start);
this._vimState.cursorPosition = Position.FromVSCodePosition(vscode.window.activeTextEditor.selection.start);

return true;
} else {
Expand Down Expand Up @@ -301,7 +303,7 @@ export class ModeHandler implements vscode.Disposable {
if (actionState.readyToExecute) {
if (this.currentMode.name !== ModeName.Visual &&
this.currentMode.name !== ModeName.VisualLine) {
this._vimState.cursorStartPosition = this._motion.position;
this._vimState.cursorStartPosition = this._vimState.cursorPosition;
}

this._vimState = await this.executeState();
Expand Down Expand Up @@ -331,8 +333,11 @@ export class ModeHandler implements vscode.Disposable {

// Update cursor position

let start = this._vimState.cursorStartPosition;
let stop = this._vimState.cursorPosition;

// Keep the cursor within bounds

if (!(this.currentMode instanceof InsertMode)) {
if (stop.character >= TextEditor.getLineAt(stop).text.length) {
stop = new Position(stop.line, TextEditor.getLineAt(stop).text.length);
Expand All @@ -344,33 +349,57 @@ export class ModeHandler implements vscode.Disposable {
stop = stop.getLineEnd().getLeft();
this._vimState.cursorPosition = stop;
}

this._motion.moveTo(stop.line, stop.character);
} else if (this.currentMode instanceof VisualMode) {
if (stop.character >= Position.getLineLength(stop.line)) {
stop = stop.getLineEnd().getLeft();
this._vimState.cursorPosition = stop;
}

await (this.currentMode as VisualMode).handleMotion(this._vimState.cursorStartPosition, stop);
} else if (this.currentMode instanceof InsertMode) {
this._motion.moveTo(stop.line, stop.character);
} else {
console.log("TODO: My janky thing doesn't handle this case!");
/**
* Always select the letter that we started visual mode on, no matter
* if we are in front or behind it. Imagine that we started visual mode
* with some text like this:
*
* abc|def
*
* (The | represents the cursor.) If we now press w, we'll select def,
* but if we hit b we expect to select abcd, so we need to getRight() on the
* start of the selection when it precedes where we started visual mode.
*/

// TODO: At this point, start and stop become desynchronoized from cursor(Start)Position
// and just become where to draw the selection. This is just begging for bugs.

if (start.compareTo(stop) > 0) {
start = start.getRight();
}
}

// Draw block cursor.

return;
if (this.currentMode.name !== ModeName.Insert) {
let range = new vscode.Range(stop, stop.getRight());
vscode.window.activeTextEditor.revealRange(range, vscode.TextEditorRevealType.InCenterIfOutsideViewport);
vscode.window.activeTextEditor.setDecorations(this._caretDecoration, [range]);
} else {
vscode.window.activeTextEditor.setDecorations(this._caretDecoration, []);
}

// TODO: Draw cursor and/or selection.
// Draw selection (or cursor)

if (this.currentMode.name === ModeName.Visual) {
vscode.window.activeTextEditor.selection = new vscode.Selection(start, stop);
} else {
vscode.window.activeTextEditor.selection = new vscode.Selection(stop, stop);
}
// Updated desired column

const movement = actionState.movement, command = actionState.command;
if ((movement && !movement.doesntChangeDesiredColumn) || command) {
if (movement && movement.setsDesiredColumnToEOL) {
this._vimState.desiredColumn = Number.POSITIVE_INFINITY;
} else {
this._vimState.desiredColumn = this._motion.position.character;
this._vimState.desiredColumn = this._vimState.cursorPosition.character;
}
}

Expand Down Expand Up @@ -401,15 +430,6 @@ export class ModeHandler implements vscode.Disposable {
}

if (actionState.operator) {
if (this.currentModeName === ModeName.Visual ||
this.currentModeName === ModeName.VisualLine) {

start = (this.currentMode as VisualMode).selectionStart;
stop = (this.currentMode as VisualMode).selectionStop;
}

this._motion.changeMode(MotionMode.Cursor);

/*
From the Vim documentation:

Expand Down Expand Up @@ -466,6 +486,5 @@ export class ModeHandler implements vscode.Disposable {
dispose() {
this._statusBarItem.hide();
this._statusBarItem.dispose();
this._motion.dispose();
}
}
5 changes: 2 additions & 3 deletions src/mode/modeInsert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

import { ModeName, Mode } from './mode';
import { TextEditor } from './../textEditor';
import { Motion } from './../motion/motion';
import { ActionState } from './modeHandler';

export class InsertMode extends Mode {
constructor(motion: Motion) {
super(ModeName.Insert, motion);
constructor() {
super(ModeName.Insert);
}

async handleAction(action: ActionState): Promise<void> {
Expand Down
5 changes: 2 additions & 3 deletions src/mode/modeNormal.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
"use strict";

import { ModeName, Mode } from './mode';
import { Motion } from './../motion/motion';
import { ModeHandler } from './modeHandler';

export class NormalMode extends Mode {
private _modeHandler: ModeHandler;

constructor(motion: Motion, modeHandler: ModeHandler) {
super(ModeName.Normal, motion);
constructor(modeHandler: ModeHandler) {
super(ModeName.Normal);

this._modeHandler = modeHandler;
}
Expand Down
37 changes: 2 additions & 35 deletions src/mode/modeVisual.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use strict";

import { ModeName, Mode } from './mode';
import { Motion} from './../motion/motion';
import { Position } from './../motion/position';
import { ModeHandler } from './modeHandler.ts';

Expand Down Expand Up @@ -29,41 +28,9 @@ export class VisualMode extends Mode {
this._selectionStop = p;
}

constructor(motion: Motion, modeHandler: ModeHandler) {
super(ModeName.Visual, motion);
constructor(modeHandler: ModeHandler) {
super(ModeName.Visual);

this._modeHandler = modeHandler;
}

public start(): void {
this._selectionStart = this.motion.position;
this._selectionStop = this._selectionStart;

this.motion.select(this._selectionStart, this._selectionStop);
}

public async handleMotion(start: Position, position: Position): Promise<boolean> {
this._selectionStop = position;
this._selectionStart = start;
this.motion.moveTo(this._selectionStart.line, this._selectionStart.character);

/**
* Always select the letter that we started visual mode on, no matter
* if we are in front or behind it. Imagine that we started visual mode
* with some text like this:
*
* abc|def
*
* (The | represents the cursor.) If we now press w, we'll select def,
* but if we hit b we expect to select abcd, so we need to getRight() on the
* start of the selection when it precedes where we started visual mode.
*/
if (this._selectionStart.compareTo(this._selectionStop) <= 0) {
this.motion.select(this._selectionStart, this._selectionStop);
} else {
this.motion.select(this._selectionStart.getRight(), this._selectionStop);
}

return true;
}
}
Loading