Skip to content

Instantly share code, notes, and snippets.

@mseddon
Last active December 15, 2018 14:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mseddon/bb8b50f04604e186aeed491749079db7 to your computer and use it in GitHub Desktop.
Save mseddon/bb8b50f04604e186aeed491749079db7 to your computer and use it in GitHub Desktop.
import * as vscode from "vscode";
class ClojureSourceLine {
constructor(public text: string) {}
get length() {
return this.text.length;
}
}
let debugValidation = false
class DocumentMirror {
lines: ClojureSourceLine[] = [];
constructor(public doc: vscode.TextDocument) {
for(let i=0; i<doc.lineCount; i++) {
let line = doc.lineAt(i);
this.lines.push(new ClojureSourceLine(line.text));
}
}
changeRange(e: vscode.TextDocumentContentChangeEvent) {
let replaceLines = e.text.split(this.doc.eol == vscode.EndOfLine.LF ? /\n/ : /\r\n/);
let left = this.lines[e.range.start.line].text.substr(0, e.range.start.character);
let right = this.lines[e.range.end.line].text.substr(e.range.end.character);
let items: ClojureSourceLine[] = [];
if(replaceLines.length == 1) {
items.push(new ClojureSourceLine(left + replaceLines[0] + right));
} else {
items.push(new ClojureSourceLine(left + replaceLines[0]));
for(let i=1; i<replaceLines.length-1; i++) {
items.push(new ClojureSourceLine(replaceLines[i]));
}
items.push(new ClojureSourceLine(replaceLines[replaceLines.length-1] + right))
}
this.lines.splice(e.range.start.line, e.range.end.line-e.range.start.line+1, ...items);
}
processChanges(e: vscode.TextDocumentContentChangeEvent[]) {
for(let change of e) {
this.changeRange(change);
}
if(debugValidation && this.doc.getText() != this.text) {
vscode.window.showErrorMessage("DocumentMirror failed");
}
}
get text() {
return this.lines.map(x => x.text).join(this.doc.eol == vscode.EndOfLine.LF ? "\n" : "\r\n");
}
}
let documents = new Map<vscode.TextDocument, DocumentMirror>();
let registered = false;
export function activate() {
// the last thing we want is to register twice and receive double events...
if(registered)
return;
registered = true;
vscode.workspace.onDidCloseTextDocument(e => {
if(e.languageId == "clojure") {
documents.delete(e);
}
})
vscode.workspace.onDidChangeTextDocument(e => {
if(e.document.languageId == "clojure") {
if(!documents.get(e.document))
documents.set(e.document, new DocumentMirror(e.document));
else
documents.get(e.document).processChanges(e.contentChanges)
}
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment