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

Improved performance of addChange() #4380

Closed
wants to merge 3 commits into from
Closed
Changes from 1 commit
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
26 changes: 11 additions & 15 deletions src/history/historyTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Logger } from './../util/logger';
import { VimState } from './../state/vimState';
import { TextEditor } from './../textEditor';
import { StatusBar } from '../statusBar';
import { Mode } from '../mode/mode';

const diffEngine = new DiffMatchPatch.diff_match_patch();
diffEngine.Diff_Timeout = 1; // 1 second
Expand All @@ -29,7 +30,7 @@ class DocumentChange {
* true => addition
* false => deletion
*/
// TODO: support replacement, which would cut the number of changes for :s/foo/bar in half
// TODO: support replacement, which would cut the number of changes for :s/foo/bar in half
public isAdd: boolean;

private _end: Position;
Expand Down Expand Up @@ -427,14 +428,16 @@ export class HistoryTracker {
* used to look like.
*/
public addChange(cursorPosition = [new Position(0, 0)]): void {
const newText = this._getDocumentText();
// Get the current document's text which is conveniently equals to the zero based offset at the document's end.
const documentEnd = cursorPosition[0].getDocumentEnd();
const newTextLength = this.vimState.editor.document.offsetAt(documentEnd);

if (newText === this.oldText) {
// Check if the document's text changed.
if (newTextLength === this.oldText.length) {
Copy link
Member

@J-Fields J-Fields Dec 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we can just enumerate the special cases and deal with them separately, but doesn't this break with :s/abc/def, for instance?

Copy link
Contributor Author

@cvaldev cvaldev Dec 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you're referring to the case of doing iabc<Esc>:s/abc/def\nu which results in | when it should be abc. It does break that, sorry. I hadn't considered that case and it seems we aren't currently testing for it. Can I add a test for it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah a test for this would be great. If we go in this direction of optimization, I'd like to make sure we cover all the edge cases

return;
}

// Determine if we should add a new Step.

// Determine if we should add a new Step. Additionally, If we are on Insert mode and this isn't the first change we made then we should get out of here.
if (
this.currentHistoryStepIndex === this.historySteps.length - 1 &&
this.currentHistoryStep.isFinished
Expand All @@ -444,7 +447,10 @@ export class HistoryTracker {
this.historySteps = this.historySteps.slice(0, this.currentHistoryStepIndex + 1);

this._addNewHistoryStep();
} else if (this.vimState.currentMode === Mode.Insert) {
return;
}
const newText = this._getDocumentText();

// TODO: This is actually pretty stupid! Since we already have the cursorPosition,
// and most diffs are just +/- a few characters, we can just do a direct comparison rather
Expand All @@ -456,14 +462,6 @@ export class HistoryTracker {

const diffs = diffEngine.diff_main(this.oldText, newText);

/*
this.historySteps.push(new HistoryStep({
changes : [new DocumentChange(new Position(0, 0), TextEditor._getDocumentText(), true)],
isFinished : true,
cursorStart: new Position(0, 0)
}));
*/

let currentPosition = new Position(0, 0);

for (const diff of diffs) {
Expand All @@ -472,8 +470,6 @@ export class HistoryTracker {
const removed = whatHappened === DiffMatchPatch.DIFF_DELETE;

let change: DocumentChange;
// let lastChange = this.currentHistoryStep.changes.length > 1 &&
// this.currentHistoryStep.changes[this.currentHistoryStep.changes.length - 2];

if (added || removed) {
change = new DocumentChange(currentPosition, text, !!added);
Expand Down