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

Editor Scroll #681

Merged
merged 7 commits into from
Sep 15, 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
197 changes: 125 additions & 72 deletions src/actions/actions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { VimSpecialCommands, VimState, SearchState, SearchDirection, ReplaceState } from './../mode/modeHandler';
import { ModeName } from './../mode/mode';
import { VisualBlockInsertionType } from './../mode/modeVisualBlock';
import { TextEditor } from './../textEditor';
import { TextEditor, EditorScrollByUnit, EditorScrollDirection, CursorMovePosition, CursorMoveByUnit } from './../textEditor';
import { Register, RegisterMode } from './../register/register';
import { NumericString } from './../number/numericString';
import { Position } from './../motion/position';
Expand Down Expand Up @@ -522,13 +522,39 @@ class CommandCtrlW extends BaseCommand {
}
}

@RegisterAction
class CommandCtrlE extends BaseCommand {
abstract class CommandEditorScroll extends BaseCommand {
modes = [ModeName.Normal];
keys = ["<C-e>"];
canBePrefixedWithCount = true;
keys: string[];
to: EditorScrollDirection;
by: EditorScrollByUnit;

public async exec(position: Position, vimState: VimState): Promise<VimState> {
await vscode.commands.executeCommand("scrollLineDown");
vimState.postponedCodeViewChanges.push({
command: "editorScroll",
args: {
to: this.to,
by: this.by,
value: 1,
revealCursor: true
}
});

return vimState;
}

public async execCount(position: Position, vimState: VimState): Promise<VimState> {
let timesToRepeat = this.canBePrefixedWithCount ? vimState.recordedState.count || 1 : 1;

vimState.postponedCodeViewChanges.push({
command: "editorScroll",
args: {
to: this.to,
by: this.by,
value: timesToRepeat,
revealCursor: true
}
});

return vimState;
}
Expand All @@ -537,7 +563,7 @@ class CommandCtrlE extends BaseCommand {
@RegisterAction
class CommandInsertBelowChar extends BaseCommand {
modes = [ModeName.Insert];
keys = ["ctrl+e"];
keys = ["<C-e>"];

public async exec(position: Position, vimState: VimState): Promise<VimState> {
if (TextEditor.isLastLine(position)) {
Expand Down Expand Up @@ -610,15 +636,49 @@ class CommandDeleteIndentInCurrentLine extends BaseCommand {
}

@RegisterAction
class CommandCtrlY extends BaseCommand {
modes = [ModeName.Normal];
class CommandCtrlE extends CommandEditorScroll {
keys = ["<C-e>"];
to: EditorScrollDirection = "down";
by: EditorScrollByUnit = "line";
}

@RegisterAction
class CommandCtrlY extends CommandEditorScroll {
keys = ["<C-y>"];
to: EditorScrollDirection = "up";
by: EditorScrollByUnit = "line";
}

public async exec(position: Position, vimState: VimState): Promise<VimState> {
await vscode.commands.executeCommand("scrollLineUp");
@RegisterAction
class CommandMoveFullPageUp extends CommandEditorScroll {
modes = [ModeName.Normal, ModeName.Visual, ModeName.VisualLine, ModeName.VisualBlock];
keys = ["<C-b>"];
to: EditorScrollDirection = "up";
by: EditorScrollByUnit = "page";
}

return vimState;
}
@RegisterAction
class CommandMoveFullPageDown extends CommandEditorScroll {
modes = [ModeName.Normal, ModeName.Visual, ModeName.VisualLine, ModeName.VisualBlock];
keys = ["<C-f>"];
to: EditorScrollDirection = "down";
by: EditorScrollByUnit = "page";
}

@RegisterAction
class CommandMoveHalfPageDown extends CommandEditorScroll {
modes = [ModeName.Normal, ModeName.Visual, ModeName.VisualLine, ModeName.VisualBlock];
keys = ["<C-d>"];
to: EditorScrollDirection = "down";
by: EditorScrollByUnit = "halfPage";
}

@RegisterAction
class CommandMoveHalfPageUp extends CommandEditorScroll {
modes = [ModeName.Normal, ModeName.Visual, ModeName.VisualLine, ModeName.VisualBlock];
keys = ["<C-u>"];
to: EditorScrollDirection = "up";
by: EditorScrollByUnit = "halfPage";
}

@RegisterAction
Expand Down Expand Up @@ -1680,6 +1740,42 @@ class CommandCenterScroll extends BaseCommand {
}
}

@RegisterAction
class CommandTopScroll extends BaseCommand {
modes = [ModeName.Normal];
keys = ["z", "t"];

public async exec(position: Position, vimState: VimState): Promise<VimState> {
vimState.postponedCodeViewChanges.push({
command: "revealLine",
args: {
lineNumber: position.line,
at: "top"
}
});

return vimState;
}
}

@RegisterAction
class CommandBottomScroll extends BaseCommand {
modes = [ModeName.Normal];
keys = ["z", "b"];

public async exec(position: Position, vimState: VimState): Promise<VimState> {
vimState.postponedCodeViewChanges.push({
command: "revealLine",
args: {
lineNumber: position.line,
at: "bottom"
}
});

return vimState;
}
}

@RegisterAction
class CommandGoToOtherEndOfHighlightedText extends BaseCommand {
modes = [ModeName.Visual, ModeName.VisualLine];
Expand Down Expand Up @@ -1725,49 +1821,6 @@ class CommandRedo extends BaseCommand {
}
}

@RegisterAction
class CommandMoveFullPageDown extends BaseCommand {
modes = [ModeName.Normal, ModeName.Visual, ModeName.VisualLine, ModeName.VisualBlock];
keys = ["<C-f>"];

public async exec(position: Position, vimState: VimState): Promise<VimState> {
await vscode.commands.executeCommand("cursorPageDown");
return vimState;
}
}

@RegisterAction
class CommandMoveFullPageUp extends BaseCommand {
modes = [ModeName.Normal, ModeName.Visual, ModeName.VisualLine, ModeName.VisualBlock];
keys = ["<C-b>"];

public async exec(position: Position, vimState: VimState): Promise<VimState> {
await vscode.commands.executeCommand("cursorPageUp");
return vimState;
}
}

@RegisterAction
class CommandMoveHalfPageDown extends BaseMovement {
keys = ["<C-d>"];

public async execAction(position: Position, vimState: VimState): Promise<Position> {
return new Position(
Math.min(TextEditor.getLineCount() - 1, position.line + Configuration.getInstance().scroll),
position.character
);
}
}

@RegisterAction
class CommandMoveHalfPageUp extends BaseMovement {
keys = ["<C-u>"];

public async execAction(position: Position, vimState: VimState): Promise<Position> {
return new Position(Math.max(0, position.line - Configuration.getInstance().scroll), position.character);
}
}

@RegisterAction
class CommandDeleteToLineEnd extends BaseCommand {
modes = [ModeName.Normal];
Expand Down Expand Up @@ -2374,8 +2427,8 @@ class MoveLineBegin extends BaseMovement {

abstract class MoveByScreenLine extends BaseMovement {
modes = [ModeName.Normal, ModeName.Visual, ModeName.VisualLine];
movementType: string;
by: string;
movementType: CursorMovePosition;
by: CursorMoveByUnit;
value: number = 1;

public async execAction(position: Position, vimState: VimState): Promise<Position | IMovement> {
Expand Down Expand Up @@ -2418,25 +2471,25 @@ abstract class MoveByScreenLine extends BaseMovement {
@RegisterAction
class MoveScreenLineBegin extends MoveByScreenLine {
keys = ["g", "0"];
movementType = "wrappedLineStart";
movementType: CursorMovePosition = "wrappedLineStart";
}

@RegisterAction
class MoveScreenNonBlank extends MoveByScreenLine {
keys = ["g", "^"];
movementType = "wrappedLineFirstNonWhitespaceCharacter";
movementType: CursorMovePosition = "wrappedLineFirstNonWhitespaceCharacter";
}

@RegisterAction
class MoveScreenLineEnd extends MoveByScreenLine {
keys = ["g", "$"];
movementType = "wrappedLineEnd";
movementType: CursorMovePosition = "wrappedLineEnd";
}

@RegisterAction
class MoveScreenLienEndNonBlank extends MoveByScreenLine {
keys = ["g", "_"];
movementType = "wrappedLineLastNonWhitespaceCharacter";
movementType: CursorMovePosition = "wrappedLineLastNonWhitespaceCharacter";
canBePrefixedWithCount = true;

public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise<Position | IMovement> {
Expand All @@ -2449,32 +2502,32 @@ class MoveScreenLienEndNonBlank extends MoveByScreenLine {
@RegisterAction
class MoveScreenLineCenter extends MoveByScreenLine {
keys = ["g", "m"];
movementType = "wrappedLineColumnCenter";
movementType: CursorMovePosition = "wrappedLineColumnCenter";
}

@RegisterAction
class MoveUpByScreenLine extends MoveByScreenLine {
modes = [ModeName.Insert, ModeName.Normal, ModeName.Visual, ModeName.VisualLine];
keys = ["g", "k"];
movementType = "up";
by = "wrappedLine";
movementType: CursorMovePosition = "up";
by: CursorMoveByUnit = "wrappedLine";
value = 1;
}

@RegisterAction
class MoveDownByScreenLine extends MoveByScreenLine {
modes = [ModeName.Insert, ModeName.Normal, ModeName.Visual, ModeName.VisualLine];
keys = ["g", "j"];
movementType = "down";
by = "wrappedLine";
movementType: CursorMovePosition = "down";
by: CursorMoveByUnit = "wrappedLine";
value = 1;
}

@RegisterAction
class MoveToLineFromViewPortTop extends MoveByScreenLine {
keys = ["H"];
movementType = "viewPortTop";
by = "line";
movementType: CursorMovePosition = "viewPortTop";
by: CursorMoveByUnit = "line";
value = 1;
canBePrefixedWithCount = true;

Expand All @@ -2487,8 +2540,8 @@ class MoveToLineFromViewPortTop extends MoveByScreenLine {
@RegisterAction
class MoveToLineFromViewPortBottom extends MoveByScreenLine {
keys = ["L"];
movementType = "viewPortBottom";
by = "line";
movementType: CursorMovePosition = "viewPortBottom";
by: CursorMoveByUnit = "line";
value = 1;
canBePrefixedWithCount = true;

Expand All @@ -2501,8 +2554,8 @@ class MoveToLineFromViewPortBottom extends MoveByScreenLine {
@RegisterAction
class MoveToMiddleLineInViewPort extends MoveByScreenLine {
keys = ["M"];
movementType = "viewPortCenter";
by = "line";
movementType: CursorMovePosition = "viewPortCenter";
by: CursorMoveByUnit = "line";
}

@RegisterAction
Expand Down
19 changes: 19 additions & 0 deletions src/mode/modeHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export enum VimSpecialCommands {
Dot
}

export class ViewChange {
public command: string;
public args: any;
}

/**
* The VimState class holds permanent state that carries over from action
* to action.
Expand Down Expand Up @@ -68,6 +73,13 @@ export class VimState {

public focusChanged = false;

/**
* Every time we invoke a VS Code command which might trigger Code's view update,
* we should postpone its view updating phase to avoid conflicting with our internal view updating mechanism.
* This array is used to cache every VS Code view updating event and they will be triggered once we run the inhouse `viewUpdate`.
*/
public postponedCodeViewChanges: ViewChange[] = [];

/**
* Used to prevent non-recursive remappings from looping.
*/
Expand Down Expand Up @@ -1088,6 +1100,13 @@ export class ModeHandler implements vscode.Disposable {

vscode.window.activeTextEditor.setDecorations(this._caretDecoration, rangesToDraw);

for (let i = 0; i < this.vimState.postponedCodeViewChanges.length; i++) {
let viewChange = this.vimState.postponedCodeViewChanges[i];
await vscode.commands.executeCommand(viewChange.command, viewChange.args);
}

this.vimState.postponedCodeViewChanges = [];

if (this.currentMode.name === ModeName.SearchInProgressMode) {
this.setupStatusBarItem(`Searching for: ${ this.vimState.searchState!.searchString }`);
} else {
Expand Down
26 changes: 26 additions & 0 deletions src/textEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,29 @@ export class TextEditor {
}
}

/**
* Directions in the view for editor scroll command.
*/
export type EditorScrollDirection = 'up' | 'down';

/**
* Units for editor scroll 'by' argument
*/
export type EditorScrollByUnit = 'line' | 'wrappedLine' | 'page' | 'halfPage';

/**
* Values for reveal line 'at' argument
*/
export type RevealLineAtArgument = 'top' | 'center' | 'bottom';
/**
* Positions in the view for cursor move command.
*/
export type CursorMovePosition = 'left' | 'right' | 'up' | 'down' |
'wrappedLineStart' |'wrappedLineFirstNonWhitespaceCharacter' |
'wrappedLineColumnCenter' | 'wrappedLineEnd' | 'wrappedLineLastNonWhitespaceCharacter' |
'viewPortTop' | 'viewPortCenter' | 'viewPortBottom' | 'viewPortIfOutside';

/**
* Units for Cursor move 'by' argument
*/
export type CursorMoveByUnit = 'line' | 'wrappedLine' | 'character' | 'halfLine';