Skip to content

Commit

Permalink
Merge pull request #258 from alisonatwork/add-go-to-definition-motion
Browse files Browse the repository at this point in the history
Add `gd` go to definition motion
  • Loading branch information
alisonatwork authored Jun 23, 2020
2 parents a9c0e22 + 1c9dc25 commit eea373a
Show file tree
Hide file tree
Showing 17 changed files with 216 additions and 115 deletions.
48 changes: 25 additions & 23 deletions src/Actions/Delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,36 @@ import { UtilRange } from '../Utils/Range';

export class ActionDelete {
@StaticReflect.metadata(SymbolMetadata.Action.isChange, true)
static byMotions(args: {
static async byMotions(args: {
motions: Motion[];
isChangeAction?: boolean;
shouldYank?: boolean;
}): Thenable<boolean> {
}): Promise<boolean> {
args.isChangeAction = args.isChangeAction === undefined ? false : args.isChangeAction;
args.shouldYank = args.shouldYank === undefined ? false : args.shouldYank;

const activeTextEditor = window.activeTextEditor;

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

const document = activeTextEditor.document;

let ranges = activeTextEditor.selections.map((selection) => {
let ranges: Range[] = [];

for (const selection of activeTextEditor.selections) {
const start = selection.active;
const end = args.motions.reduce((position, motion) => {
return motion.apply(position, {
let position = start;
for (const motion of args.motions) {
position = await motion.apply(position, {
isInclusive: true,
shouldCrossLines: false,
isChangeAction: args.isChangeAction,
});
}, start);
return new Range(start, end);
});
}
ranges.push(new Range(start, position));
}

if (args.motions.some((motion) => motion.isLinewise)) {
ranges = ranges.map((range) => UtilRange.toLinewise(range, document));
Expand All @@ -46,20 +49,19 @@ export class ActionDelete {

// TODO: Move cursor to first non-space if needed

return (args.shouldYank
? ActionRegister.yankByMotions({
motions: args.motions,
isChangeAction: args.isChangeAction,
})
: Promise.resolve(true)
)
.then(() => {
return activeTextEditor.edit((editBuilder) => {
ranges.forEach((range) => editBuilder.delete(range));
});
})
.then(() => ActionSelection.shrinkToStarts())
.then(() => ActionReveal.primaryCursor());
if (args.shouldYank) {
await ActionRegister.yankByMotions({
motions: args.motions,
isChangeAction: args.isChangeAction,
});
}
await activeTextEditor.edit((editBuilder) => {
ranges.forEach((range) => editBuilder.delete(range));
});
await ActionSelection.shrinkToStarts();
await ActionReveal.primaryCursor();

return true;
}

@StaticReflect.metadata(SymbolMetadata.Action.isChange, true)
Expand Down
39 changes: 22 additions & 17 deletions src/Actions/MoveCursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,20 @@ export class ActionMoveCursor {
return Promise.resolve(true);
}

static byMotions(args: {
static async byMotions(args: {
motions: Motion[];
isVisualMode?: boolean;
isVisualLineMode?: boolean;
noEmptyAtLineEnd?: boolean;
}): Thenable<boolean> {
}): Promise<boolean> {
args.isVisualMode = args.isVisualMode === undefined ? false : args.isVisualMode;
args.isVisualLineMode = args.isVisualLineMode === undefined ? false : args.isVisualLineMode;
args.noEmptyAtLineEnd = args.noEmptyAtLineEnd === undefined ? false : args.noEmptyAtLineEnd;

const activeTextEditor = window.activeTextEditor;

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

// Prevent preferred character update if no motion updates character.
Expand All @@ -65,19 +65,21 @@ export class ActionMoveCursor {

const document = activeTextEditor.document;

activeTextEditor.selections = activeTextEditor.selections.map((selection, i) => {
const selections: Selection[] = [];

for (let i = 0; i < activeTextEditor.selections.length; i++) {
const selection = activeTextEditor.selections[i];
let anchor: Position;

let active = args.motions.reduce(
(position, motion) => {
return motion.apply(position, {
preferredColumn: ActionMoveCursor.preferredColumnBySelectionIndex[i],
});
},
args.isVisualMode
? UtilSelection.getActiveInVisualMode(selection)
: selection.active,
);
let active = args.isVisualMode
? UtilSelection.getActiveInVisualMode(selection)
: selection.active;

for (const motion of args.motions) {
active = await motion.apply(active, {
preferredColumn: ActionMoveCursor.preferredColumnBySelectionIndex[i],
});
}

if (args.isVisualMode) {
anchor = selection.anchor;
Expand Down Expand Up @@ -127,9 +129,12 @@ export class ActionMoveCursor {
anchor = active;
}

return new Selection(anchor, active);
});
selections.push(new Selection(anchor, active));
}

activeTextEditor.selections = selections;
await ActionReveal.primaryCursor();

return ActionReveal.primaryCursor();
return true;
}
}
27 changes: 17 additions & 10 deletions src/Actions/Register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,33 +72,40 @@ export class ActionRegister {
return Promise.resolve(true);
}

static yankByMotions(args: { motions: Motion[]; isChangeAction?: boolean }): Thenable<boolean> {
static async yankByMotions(args: {
motions: Motion[];
isChangeAction?: boolean;
}): Promise<boolean> {
args.isChangeAction = args.isChangeAction === undefined ? false : args.isChangeAction;

const activeTextEditor = window.activeTextEditor;

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

const isLinewise = args.motions.some((motion) => motion.isLinewise);

const ranges = activeTextEditor.selections.map((selection) => {
let ranges: Range[] = [];

for (const selection of activeTextEditor.selections) {
const start = selection.active;
const end = args.motions.reduce((position, motion) => {
return motion.apply(position, {
let position = start;
for (const motion of args.motions) {
position = await motion.apply(position, {
isInclusive: true,
shouldCrossLines: false,
isChangeAction: args.isChangeAction,
});
}, start);
return new Range(start, end);
});

return ActionRegister.yankRanges({
}
ranges.push(new Range(start, position));
}
await ActionRegister.yankRanges({
ranges: ranges,
isLinewise: isLinewise,
});

return true;
}

static async yankByTextObject(args: { textObject: TextObject }): Promise<boolean> {
Expand Down
3 changes: 3 additions & 0 deletions src/Mappers/SpecialKeys/Motion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { MotionMatchPair } from '../../Motions/MatchPair';
import { MotionLine } from '../../Motions/Line';
import { MotionParagraph } from '../../Motions/Paragraph';
import { MotionDocument } from '../../Motions/Document';
import { MotionNavigation } from '../../Motions/Navigation';

interface MotionGenerator {
(args?: {}): Motion;
Expand Down Expand Up @@ -120,6 +121,8 @@ export class SpecialKeyMotion extends GenericMapper implements SpecialKeyCommon

{ keys: 'space', motionGenerators: [MotionDirection.next] },
{ keys: 'backspace', motionGenerators: [MotionDirection.prev] },
{ keys: 'g d', motionGenerators: [MotionNavigation.toDeclaration] },
{ keys: 'g D', motionGenerators: [MotionNavigation.toTypeDefinition] },
];

constructor() {
Expand Down
4 changes: 2 additions & 2 deletions src/Motions/Direction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ export class MotionDirection extends Motion {
});
}

apply(from: Position, option?: any): Position {
from = super.apply(from);
async apply(from: Position, option?: any): Promise<Position> {
from = await super.apply(from);

const activeTextEditor = window.activeTextEditor;

Expand Down
4 changes: 2 additions & 2 deletions src/Motions/Document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export class MotionDocument extends Motion {
return obj;
}

apply(from: Position): Position {
from = super.apply(from);
async apply(from: Position): Promise<Position> {
from = await super.apply(from);

const activeTextEditor = window.activeTextEditor;

Expand Down
4 changes: 2 additions & 2 deletions src/Motions/Line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export class MotionLine extends Motion {
return obj;
}

apply(from: Position): Position {
from = super.apply(from);
async apply(from: Position): Promise<Position> {
from = await super.apply(from);

const activeTextEditor = window.activeTextEditor;

Expand Down
4 changes: 2 additions & 2 deletions src/Motions/Match.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ export class MotionMatch extends Motion {
return obj;
}

apply(from: Position, option: { isInclusive?: boolean } = {}): Position {
async apply(from: Position, option: { isInclusive?: boolean } = {}): Promise<Position> {
option.isInclusive = option.isInclusive === undefined ? false : option.isInclusive;

from = super.apply(from);
from = await super.apply(from);

const activeTextEditor = window.activeTextEditor;

Expand Down
6 changes: 3 additions & 3 deletions src/Motions/MatchPair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ export class MotionMatchPair extends Motion {
return new MotionMatchPair();
}

apply(
async apply(
from: Position,
option: {
isInclusive?: boolean;
} = {},
): Position {
): Promise<Position> {
option.isInclusive = option.isInclusive === undefined ? false : option.isInclusive;

from = super.apply(from);
from = await super.apply(from);

const activeTextEditor = window.activeTextEditor;

Expand Down
2 changes: 1 addition & 1 deletion src/Motions/Motion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export abstract class Motion {
this.characterDelta += characterDelta;
}

apply(from: Position, option?: any): Position {
async apply(from: Position, option?: any): Promise<Position> {
const activeTextEditor = window.activeTextEditor;

if (!activeTextEditor) {
Expand Down
32 changes: 32 additions & 0 deletions src/Motions/Navigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { commands, window, Position } from 'vscode';
import { Motion } from './Motion';

export class MotionNavigation extends Motion {
private command: string;

static toDeclaration(): Motion {
const obj = new MotionNavigation({ isLinewise: true });
obj.command = 'editor.action.goToDeclaration';
return obj;
}

static toTypeDefinition(): Motion {
const obj = new MotionNavigation({ isLinewise: true });
obj.command = 'editor.action.goToTypeDefinition';
return obj;
}

async apply(from: Position): Promise<Position> {
from = await super.apply(from);

const activeTextEditor = window.activeTextEditor;

if (!activeTextEditor) {
return from;
}

await commands.executeCommand(this.command);

return activeTextEditor.selection.active;
}
}
4 changes: 2 additions & 2 deletions src/Motions/Paragraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ export class MotionParagraph extends Motion {
});
}

apply(from: Position): Position {
from = super.apply(from);
async apply(from: Position): Promise<Position> {
from = await super.apply(from);

const activeTextEditor = window.activeTextEditor;

Expand Down
6 changes: 3 additions & 3 deletions src/Motions/Word.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,20 @@ export class MotionWord extends Motion {
return obj;
}

apply(
async apply(
from: Position,
option: {
isInclusive?: boolean;
isChangeAction?: boolean;
shouldCrossLines?: boolean;
} = {},
): Position {
): Promise<Position> {
option.isInclusive = option.isInclusive === undefined ? false : option.isInclusive;
option.isChangeAction = option.isChangeAction === undefined ? false : option.isChangeAction;
option.shouldCrossLines =
option.shouldCrossLines === undefined ? true : option.shouldCrossLines;

from = super.apply(from);
from = await super.apply(from);

const activeTextEditor = window.activeTextEditor;

Expand Down
Loading

0 comments on commit eea373a

Please sign in to comment.