Skip to content

Commit

Permalink
Persist global marks on disk
Browse files Browse the repository at this point in the history
  • Loading branch information
EerikSaksi committed Sep 10, 2023
1 parent facf0aa commit fb1badd
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 6 deletions.
3 changes: 2 additions & 1 deletion extensionBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { globalState } from './src/state/globalState';
import { Register } from './src/register/register';
import { SpecialKeys } from './src/util/specialKeys';
import { exCommandParser } from './src/vimscript/exCommandParser';
import { HistoryStep } from './src/history/historyTracker';

let extensionContext: vscode.ExtensionContext;
let previousActiveEditorUri: vscode.Uri | undefined;
Expand Down Expand Up @@ -107,7 +108,7 @@ export async function activate(context: vscode.ExtensionContext, handleLocal: bo

// Load state
Register.loadFromDisk(handleLocal);
await Promise.all([ExCommandLine.loadHistory(context), SearchCommandLine.loadHistory(context)]);
await Promise.all([ExCommandLine.loadHistory(context), SearchCommandLine.loadHistory(context), HistoryStep.loadHistory(context)]);

if (vscode.window.activeTextEditor) {
const filepathComponents = vscode.window.activeTextEditor.document.fileName.split(/\\|\//);
Expand Down
10 changes: 10 additions & 0 deletions src/history/historyFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export class HistoryFile {
this.base.clear();
}

public filter(predicate: (value: string) => boolean) {
this.base.filter(predicate);
}

public async load(): Promise<void> {
await this.base.load();
}
Expand All @@ -43,3 +47,9 @@ export class CommandLineHistory extends HistoryFile {
super(context, '.cmdline_history');
}
}

export class MarkHistory extends HistoryFile {
constructor(context: ExtensionContext) {
super(context, '.mark_history');
}
}
66 changes: 61 additions & 5 deletions src/history/historyTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import { Mode } from '../mode/mode';
import { ErrorCode, VimError } from '../error';
import { Logger } from '../util/logger';
import { earlierOf } from '../common/motion/position';
import { MarkHistory } from './historyFile';
import { ExtensionContext } from 'vscode';

const diffEngine = new DiffMatchPatch.diff_match_patch();
diffEngine.Diff_Timeout = 1; // 1 second
Expand Down Expand Up @@ -106,7 +108,7 @@ export interface IMark {
/**
* An undo's worth of changes; generally corresponds to a single action.
*/
class HistoryStep {
export class HistoryStep {
/**
* The insertions and deletions that occured in this history step.
*/
Expand Down Expand Up @@ -145,6 +147,32 @@ class HistoryStep {
*/
static globalMarks: IMark[] = [];

/**
* all the local marks which were restored from the history file
*/
static historyLocalMarks: IMark[] = [];

public static markHistory: MarkHistory;

public static async loadHistory(context: ExtensionContext): Promise<void> {
HistoryStep.markHistory = new MarkHistory(context);
await HistoryStep.markHistory.load();
HistoryStep.markHistory.get().forEach((row) => {
const parsed = JSON.parse(row);
const newMark: IMark = {
position: parsed.position,
name: parsed.name,
isUppercaseMark: parsed.isUppercaseMark,
document: parsed.document,
};
if (newMark.isUppercaseMark) {
HistoryStep.globalMarks.push(newMark);
} else {
this.historyLocalMarks.push(newMark);
}
});
}

constructor(init: { marks: IMark[]; changes?: DocumentChange[]; cameFromU?: boolean }) {
this.changes = init.changes ?? [];
this.marks = init.marks ?? [];
Expand Down Expand Up @@ -228,7 +256,11 @@ class UndoStack {
private currentStepIndex = -1;

// The marks as they existed before the first HistoryStep
private initialMarks: IMark[] = [];
private initialMarks: IMark[];

constructor(initialMarks: IMark[]) {
this.initialMarks = initialMarks;
}

public getHistoryStepAtIndex(idx: number): HistoryStep | undefined {
return this.historySteps[idx];
Expand Down Expand Up @@ -400,7 +432,12 @@ export class HistoryTracker {

constructor(vimState: VimState) {
this.vimState = vimState;
this.undoStack = new UndoStack();

// get all the local marks which belong to this document and set these as the initial marks
const initialMarks = HistoryStep.historyLocalMarks.filter((mark) => {
return !mark.isUppercaseMark && mark.document?.uri.path === vimState.document.uri.path;
});
this.undoStack = new UndoStack(initialMarks);
this.changeList = new ChangeList();
this.previousDocumentState = {
text: this.getDocumentText(),
Expand Down Expand Up @@ -539,20 +576,39 @@ export class HistoryTracker {
isUppercaseMark,
document: isUppercaseMark ? document : undefined,
};
this.putMarkInList(newMark);
this.putMarkInList(newMark, document);
}

/**
* Puts the mark into either the global or local marks array depending on mark.isUppercaseMark.
*/
private putMarkInList(mark: IMark): void {
private putMarkInList(mark: IMark, document: vscode.TextDocument): void {
const marks = this.getMarkList(mark.isUppercaseMark);
const previousIndex = marks.findIndex((existingMark) => existingMark.name === mark.name);
if (previousIndex !== -1) {
marks[previousIndex] = mark;
if (mark.isUppercaseMark) {
// remove old entry frmo history by finding a mark with the same name before adding this mark
HistoryStep.markHistory.filter((value) => JSON.parse(value).name !== mark.name);
} else {
// remove marks which with this name which belong to this document
HistoryStep.markHistory.filter((value) => {
const parsed = JSON.parse(value);
return !(parsed.name === mark.name && parsed.document?.uri.path === document.uri.path);
});
}
} else {
marks.push(mark);
}

// add the entry to the history to persist it over sessions
if (mark.isUppercaseMark) {
HistoryStep.markHistory.add(JSON.stringify(mark));
} else {
// local marks do not store the path, but we still need to include it in the
// history file so we know which file it belongs to
HistoryStep.markHistory.add(JSON.stringify({ ...mark, document }));
}
}

/**
Expand Down
5 changes: 5 additions & 0 deletions src/platform/node/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ export class HistoryBase {
}
}

// filter history based on predicate
public filter(predicate: (value: string) => boolean) {
this.history = this.history.filter(predicate);
}

public async load(): Promise<void> {
// await this._base.load();
let data = '';
Expand Down

0 comments on commit fb1badd

Please sign in to comment.