Skip to content

Commit

Permalink
Merge pull request #85 from aioutecism/fix/validate-position
Browse files Browse the repository at this point in the history
Validate selections when changed.
  • Loading branch information
aioutecism committed May 4, 2016
2 parents 87bb4bd + 17e9f70 commit a627559
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 10 deletions.
40 changes: 40 additions & 0 deletions src/Actions/Selection.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,47 @@
import {window, Selection} from 'vscode';
import {currentModeId} from '../extension';
import {ModeID} from '../Modes/Mode';

export class ActionSelection {

static validateSelections(): Thenable<boolean> {
if (currentModeId() !== ModeID.NORMAL) {
return Promise.resolve(true);
}

const activeTextEditor = window.activeTextEditor;

if (! activeTextEditor) {
return Promise.resolve(false);
}

const document = activeTextEditor.document;

let isChanged = false;

const validatedSelections = activeTextEditor.selections.map(selection => {
const position = selection.active;
const endCharacter = document.lineAt(position).range.end.character;
const maxCharacter = endCharacter > 0 ? endCharacter - 1 : endCharacter;

if (position.character > maxCharacter) {
isChanged = true;
return new Selection(
position.line, maxCharacter,
position.line, maxCharacter);
}
else {
return selection;
}
});

if (isChanged) {
activeTextEditor.selections = validatedSelections;
}

return Promise.resolve(true);
}

static shrinkAStep(): Thenable<boolean> {
const activeTextEditor = window.activeTextEditor;

Expand Down
10 changes: 10 additions & 0 deletions src/Dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,23 @@ import {ModeVisual} from './Modes/Visual';
import {ModeVisualLine} from './Modes/VisualLine';
import {ModeInsert} from './Modes/Insert';
import {ActionMode} from './Actions/Mode';
import {ActionSelection} from './Actions/Selection';
import {ActionMoveCursor} from './Actions/MoveCursor';

export class Dispatcher {

private currentMode: Mode;
get currentModeId(): ModeID {
return this.currentMode ? this.currentMode.id : null;
}

private modes: {[k: number]: Mode} = {
[ModeID.NORMAL]: new ModeNormal(),
[ModeID.VISUAL]: new ModeVisual(),
[ModeID.VISUAL_LINE]: new ModeVisualLine(),
[ModeID.INSERT]: new ModeInsert(),
};

private disposables: Disposable[] = [];

constructor(context: ExtensionContext) {
Expand Down Expand Up @@ -47,10 +53,14 @@ export class Dispatcher {
window.onDidChangeTextEditorSelection(() => {
ActionMode.switchByActiveSelections(this.currentMode.id);
ActionMoveCursor.updatePreferedCharacter();
// Delay validate execution until other actions complete.
setTimeout(() => ActionSelection.validateSelections());
}),
window.onDidChangeActiveTextEditor(() => {
ActionMode.switchByActiveSelections(this.currentMode.id);
ActionMoveCursor.updatePreferedCharacter();
// Delay validate execution until other actions complete.
setTimeout(() => ActionSelection.validateSelections());
})
);
}
Expand Down
48 changes: 39 additions & 9 deletions src/Modes/Normal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,38 @@ export class ModeNormal extends Mode {
} },

{ keys: 'X', actions: [ActionDelete.selectionsOrLeft], args: {shouldYank: true} },
{ keys: 'x', actions: [ActionDelete.selectionsOrRight], args: {shouldYank: true} },
{ keys: 'delete', actions: [ActionDelete.selectionsOrRight], args: {shouldYank: true} },
{ keys: 'x', actions: [
ActionDelete.selectionsOrRight,
ActionSelection.validateSelections,
], args: {
shouldYank: true
} },
{ keys: 'delete', actions: [
ActionDelete.selectionsOrRight,
ActionSelection.validateSelections,
], args: {
shouldYank: true
} },
{ keys: 'd d', actions: [ActionDelete.line], args: {shouldYank: true} },
{ keys: 'D', actions: [ActionDelete.byMotions], args: {motions: [MotionLine.end()], shouldYank: true} },
{ keys: 'd {motion}', actions: [ActionDelete.byMotions], args: {shouldYank: true} },
{ keys: 'd {textObject}', actions: [ActionDelete.byTextObject], args: {shouldYank: true} },
{ keys: 'D', actions: [
ActionDelete.byMotions,
ActionSelection.validateSelections,
], args: {
motions: [MotionLine.end()],
shouldYank: true
} },
{ keys: 'd {motion}', actions: [
ActionDelete.byMotions,
ActionSelection.validateSelections,
], args: {
shouldYank: true
} },
{ keys: 'd {textObject}', actions: [
ActionDelete.byTextObject,
ActionSelection.validateSelections,
], args: {
shouldYank: true
} },
{ keys: 'C', actions: [
ActionDelete.byMotions,
ActionMode.toInsert,
Expand Down Expand Up @@ -128,8 +154,14 @@ export class ModeNormal extends Mode {
ActionFind.prev,
] },

{ keys: 'u', actions: [ActionHistory.undo] },
{ keys: 'ctrl+r', actions: [ActionHistory.redo] },
{ keys: 'u', actions: [
ActionHistory.undo,
ActionSelection.validateSelections,
] },
{ keys: 'ctrl+r', actions: [
ActionHistory.redo,
ActionSelection.validateSelections,
] },

{ keys: '< <', actions: [ActionIndent.decrease] },
{ keys: '> >', actions: [ActionIndent.increase] },
Expand Down Expand Up @@ -160,8 +192,6 @@ export class ModeNormal extends Mode {
this.maps.forEach(map => {
this.mapper.map(map.keys, map.actions, map.args);
});

// TODO: No empty at line end when changing selections by mouse
}

enter(): void {
Expand Down
9 changes: 8 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import {ExtensionContext} from 'vscode';
import {Configuration} from './Configuration';
import {Dispatcher} from './Dispatcher';
import {ModeID} from './Modes/Mode';

let dispatcher: Dispatcher;

export function activate(context: ExtensionContext) {
Configuration.init();
const dispatcher = new Dispatcher(context);
dispatcher = new Dispatcher(context);

context.subscriptions.push(
Configuration,
dispatcher
);
}

export function currentModeId(): ModeID {
return dispatcher ? dispatcher.currentModeId : null;
}

0 comments on commit a627559

Please sign in to comment.