<commit_before>import * as assert from 'assert';
import * as vscode from 'vscode';

import { Jump } from './../src/jumps/jump';
import { getAndUpdateModeHandler } from '../extension';
import { ModeHandler } from '../src/mode/modeHandler';
import { TextEditor } from '../src/textEditor';
import { cleanUpWorkspace, setupWorkspace } from './testUtils';
import { JumpTracker } from '../src/jumps/jumpTracker';
import { Position } from '../src/common/motion/position';
import { waitForCursorSync } from '../src/util/util';

suite('Jump Tracker', () => {
  let jumpTracker: JumpTracker;
  let modeHandler: ModeHandler;
  let editor: vscode.TextEditor;

  const text = `start
{
a1
b1
a2
b2
}
end`;

  const jump = (lineNumber, columnNumber) =>
    new Jump({
      editor,
      fileName: 'Untitled',
      position: new Position(lineNumber, columnNumber),
    });

  const start = jump(0, 0);
  const open = jump(1, 0);
  const a1 = jump(2, 0);
  const b1 = jump(3, 0);
  const a2 = jump(4, 0);
  const b2 = jump(5, 0);
  const close = jump(6, 0);
  const end = jump(7, 0);

  setup(async () => {
    await setupWorkspace();
    modeHandler = await getAndUpdateModeHandler();
    editor = modeHandler.vimState.editor!;

    modeHandler.vimState.editor = vscode.window.activeTextEditor!;
    (modeHandler as any).vimState.cursorPosition = new Position(0, 0);

    await TextEditor.insert(text);
    await waitForCursorSync();

    jumpTracker = modeHandler.vimState.globalState.jumpTracker;
    await modeHandler.handleMultipleKeyEvents(['gg']);
    await waitForCursorSync();
    jumpTracker.clearJumps();
  });

  teardown(() => {
    jumpTracker.clearJumps();
    cleanUpWorkspace();
  });

  const fixLineEndings = (t: string): string =>
    process.platform === 'win32' ? t.replace(/\\n/g, '\\r\\n') : t;
  const flatten = list => list.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
  const hasPrefix = (t: string): boolean => t.startsWith('<') && t.endsWith('>');
  const tokenize = (t: string): string[] => (hasPrefix(t) ? [t] : t.split(''));
  const sendKeys = async (keys: string[]) => {
    for (var i = 0; i < keys.length; i++) {
      const key = keys[i];
      await modeHandler.handleKeyEvent(key);
      await waitForCursorSync();
    }
  };

  const position = j => [j.position.line, j.position.character];
  const line = j => j.position.line;

  const assertJumps = (expectedJumps: Jump[]) => {
    assert.deepEqual(
      jumpTracker.jumps.map(line),
      expectedJumps.map(line),
      'Jumps are not in the correct order or the jumps are for the wrong lines'
    );
  };
  const assertCurrentJump = (expectedCurrentJump: Jump) =>
    assert.deepEqual(
      position(jumpTracker.currentJump || jumpTracker.end),
      position(expectedCurrentJump),
      'Current jump is incorrect'
    );

  const testJumps = async (keys: string[], jumps: Jump[], currentJump?: Jump) => {
    test(`Can record jumps for key events: ${keys.map(k => k.replace('\n', '\\n'))}`, async () => {
      await sendKeys(flatten(keys.map(fixLineEndings).map(tokenize)));

      assertJumps(jumps);
      assertCurrentJump(currentJump || jumpTracker.jumps[jumpTracker.jumps.length - 1]);
    });
  };

  testJumps(['G', 'gg'], [start, end]);
  testJumps(['G', 'gg', 'G'], [end, start]);
  testJumps(['G', 'gg', 'G', 'gg'], [start, end]);
  testJumps(['/b\n', 'n'], [start, b1]);
  testJumps(['G', '?b\n', 'gg', 'G'], [end, b2, start]);
  testJumps(['j', '%', '%'], [open, close]);

  testJumps(['j', '%', '%'], [open, close], close);
  testJumps(['j', '%', '%', '<C-o>'], [close, open], close);
  testJumps(['j', '%', '%', '<C-o>', '<C-i>'], [close, open], open);
  testJumps(['j', '%', '%', '<C-o>', '%'], [open, close], close);
  testJumps(['j', '%', '%', '<C-o>', 'gg'], [open, close], close);
});<commit_msg>Fixed some jump behaviors to work the same as vanilla Vim<commit_after>import * as assert from "assert";
import * as vscode from "vscode";

import { Jump } from "./../src/jumps/jump";
import { getAndUpdateModeHandler } from "../extension";
import { ModeHandler } from "../src/mode/modeHandler";
import { TextEditor } from "../src/textEditor";
import { cleanUpWorkspace, setupWorkspace } from "./testUtils";
import { JumpTracker } from "../src/jumps/jumpTracker";
import { Position } from "../src/common/motion/position";
import { waitForCursorSync } from "../src/util/util";

suite("Jump Tracker", () => {
  let jumpTracker: JumpTracker;
  let modeHandler: ModeHandler;
  let editor: vscode.TextEditor;

  const text = `start
{
a1
b1
a2
b2
}
end`;

  const jump = (lineNumber, columnNumber) =>
    new Jump({
      editor,
      fileName: "Untitled",
      position: new Position(lineNumber, columnNumber)
    });

  const start = jump(0, 0);
  const open = jump(1, 0);
  const a1 = jump(2, 0);
  const b1 = jump(3, 0);
  const a2 = jump(4, 0);
  const b2 = jump(5, 0);
  const close = jump(6, 0);
  const end = jump(7, 0);

  setup(async () => {
    await setupWorkspace();
    modeHandler = await getAndUpdateModeHandler();
    editor = modeHandler.vimState.editor!;

    modeHandler.vimState.editor = vscode.window.activeTextEditor!;
    (modeHandler as any).vimState.cursorPosition = new Position(0, 0);

    await TextEditor.insert(text);
    await waitForCursorSync();

    jumpTracker = modeHandler.vimState.globalState.jumpTracker;
    await modeHandler.handleMultipleKeyEvents(["gg"]);
    await waitForCursorSync();
    jumpTracker.clearJumps();
  });

  teardown(() => {
    jumpTracker.clearJumps();
    cleanUpWorkspace();
  });

  const fixLineEndings = (t: string): string =>
    process.platform === "win32" ? t.replace(/\\n/g, "\\r\\n") : t;
  const flatten = list =>
    list.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
  const hasPrefix = (t: string): boolean =>
    t.startsWith("<") && t.endsWith(">");
  const tokenize = (t: string): string[] => (hasPrefix(t) ? [t] : t.split(""));
  const sendKeys = async (keys: string[]) => {
    for (var i = 0; i < keys.length; i++) {
      const key = keys[i];
      await modeHandler.handleKeyEvent(key);
      await waitForCursorSync();
    }
  };

  const position = j => [j.position.line, j.position.character];
  const line = j => j.position.line;

  const assertJumps = (expectedJumps: Jump[]) => {
    assert.deepEqual(
      jumpTracker.jumps.map(line),
      expectedJumps.map(line),
      "Jumps are not in the correct order or the jumps are for the wrong lines"
    );
  };
  const assertCurrentJump = (expectedCurrentJump: Jump) =>
    assert.deepEqual(
      position(jumpTracker.currentJump || jumpTracker.end),
      position(expectedCurrentJump),
      "Current jump is incorrect"
    );

  const testJumps = async (
    keys: string[],
    jumps: Jump[],
    currentJump: Jump
  ) => {
    test(`Can record jumps for key events: ${keys.map(k =>
      k.replace("\n", "\\n")
    )}`, async () => {
      await sendKeys(flatten(keys.map(fixLineEndings).map(tokenize)));

      assertJumps(jumps);
      assertCurrentJump(currentJump);
    });
  };

  testJumps(["G", "gg"], [start, end], end);
  testJumps(["G", "gg", "G"], [end, start], start);
  testJumps(["G", "gg", "G", "gg"], [start, end], end);
  testJumps(["/b\n", "n"], [start, b1], b1);
  testJumps(["G", "?b\n", "gg", "G"], [end, b2, start], start);
  testJumps(["j", "%", "%"], [open, close], close);
  testJumps(["j", "%", "%", "<C-o>"], [close, open], close);
  testJumps(["j", "%", "%", "<C-o>", "<C-i>"], [close, open], open);
  testJumps(["j", "%", "%", "<C-o>", "%"], [open, close], close);
  testJumps(["j", "%", "%", "<C-o>", "gg"], [open, close], close);
});
{'fraction_non_alphanumeric': 0.19926778242677826, 'fraction_numerical': 0.008368200836820083, 'mean_word_length': 3.616173808086904, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1427933', 'n_tokens_mistral': 2665, 'n_tokens_neox': 2605, 'n_words': 634}