diff --git a/src/actions/actions.ts b/src/actions/actions.ts index 9abe2c8b2ab..227e9bfc58d 100644 --- a/src/actions/actions.ts +++ b/src/actions/actions.ts @@ -615,7 +615,12 @@ class CommandInsertRegisterContent extends BaseCommand { if (register.text instanceof Array) { text = (register.text as string []).join("\n"); } else if (register.text instanceof RecordedState) { - // TODO: Play macro + vimState.recordedState.transformations.push({ + type: "macro", + register: vimState.recordedState.registerName, + replay: "keystrokes" + }); + return vimState; } else { text = register.text; @@ -654,6 +659,7 @@ class CommandRecordMacro extends BaseCommand { public async exec(position: Position, vimState: VimState): Promise { const register = this.keysPressed[1]; + vimState.recordedMacro = new RecordedState(); vimState.recordedMacro.registerName = register; Register.putByKey(new RecordedState(), register); vimState.isRecordingMacro = true; @@ -702,7 +708,8 @@ class CommandExecuteMacro extends BaseCommand { const register = this.keysPressed[1]; vimState.recordedState.transformations.push({ type: "macro", - register: register + register: register, + replay: "contentChange" }); return vimState; @@ -1812,7 +1819,17 @@ export class PutCommand extends BaseCommand { const dest = after ? position : position.getRight(); if (register.text instanceof RecordedState) { - // TODO:w + /** + * Paste content from recordedState. This one is actually complex as Vim has internal key code for key strokes. + * For example, Backspace is stored as `<80>kb`. So if you replay a macro, which is stored in a register as `a1<80>kb2`, you + * shall just get `2` inserted as `a` represents entering Insert Mode, `<80>bk` represents Backspace. However here, we shall + * insert the plain text content of the register, which is `a1<80>kb2`. + */ + vimState.recordedState.transformations.push({ + type: "macro", + register: vimState.recordedState.registerName, + replay: "keystrokes" + }); return vimState; } else if (typeof register.text === "object") { return await this.execVisualBlockPaste(register.text, position, vimState, after); @@ -1965,7 +1982,12 @@ export class GPutCommand extends BaseCommand { let addedLinesCount: number; if (register.text instanceof RecordedState) { - // TODO: run register recordedState + vimState.recordedState.transformations.push({ + type: "macro", + register: vimState.recordedState.registerName, + replay: "keystrokes" + }); + return vimState; } if (typeof register.text === "object") { // visual block mode @@ -2113,7 +2135,12 @@ export class GPutBeforeCommand extends BaseCommand { let addedLinesCount: number; if (register.text instanceof RecordedState) { - // TODO; + vimState.recordedState.transformations.push({ + type: "macro", + register: vimState.recordedState.registerName, + replay: "keystrokes" + }); + return vimState; } else if (typeof register.text === "object") { // visual block mode addedLinesCount = register.text.length * vimState.recordedState.count; diff --git a/src/mode/modeHandler.ts b/src/mode/modeHandler.ts index f6ee6742bf4..92ead02d27b 100644 --- a/src/mode/modeHandler.ts +++ b/src/mode/modeHandler.ts @@ -674,6 +674,8 @@ export class ModeHandler implements vscode.Disposable { let lastAction = recordedState.actionsRun[recordedState.actionsRun.length - 1]; if (lastAction instanceof DocumentContentChangeAction) { + lastAction.keysPressed.push(key); + if (action instanceof CommandInsertInInsertMode || action instanceof CommandInsertPreviousText) { // delay the macro recording actionToRecord = undefined; @@ -688,6 +690,7 @@ export class ModeHandler implements vscode.Disposable { // This means we are already in Insert Mode but there is still not DocumentContentChangeAction in stack vimState.historyTracker.currentContentChanges = []; let newContentChange = new DocumentContentChangeAction(); + newContentChange.keysPressed.push(key); recordedState.actionsRun.push(newContentChange); actionToRecord = newContentChange; } else { @@ -797,8 +800,7 @@ export class ModeHandler implements vscode.Disposable { vimState.previousFullAction = vimState.recordedState; if (recordedState.isInsertion) { - Register.putByKey(recordedState, "."); - // Register.lastContentChange = recordedState; + Register.putByKey(recordedState, '.'); } } @@ -1178,7 +1180,18 @@ export class ModeHandler implements vscode.Disposable { vimState.previousFullAction = clonedAction; break; case "macro": - vimState = await this.runMacro(vimState, vimState.recordedMacro); + let recordedMacro = (await Register.getByKey(command.register)).text as RecordedState; + + if (command.replay === "contentChange") { + vimState = await this.runMacro(vimState, recordedMacro); + } else { + let keyStrokes: string[] = []; + for (let action of recordedMacro.actionsRun) { + keyStrokes = keyStrokes.concat(action.keysPressed); + } + this.vimState.recordedState = new RecordedState(); + await this.handleMultipleKeyEvents(keyStrokes); + } break; } } diff --git a/src/transformations/transformations.ts b/src/transformations/transformations.ts index 881391d1fc8..4527fe1fa4c 100644 --- a/src/transformations/transformations.ts +++ b/src/transformations/transformations.ts @@ -193,6 +193,7 @@ export interface Dot { export interface Macro { type: "macro"; register: string; + replay: "contentChange" | "keystrokes"; } export type Transformation