-
Notifications
You must be signed in to change notification settings - Fork 1
/
extension.js
125 lines (105 loc) · 3.87 KB
/
extension.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
var vscode = require('vscode');
var { Range, Position } = vscode;
var { workspace, window } = vscode;
var http = require('http');
var ws = require('nodejs-websocket');
var tmp = require('tmp');
class OnMessage {
constructor(webSocketConnection) {
this.webSocketConnection = webSocketConnection;
let that = this;
this.onTextCallBack = text => that.onMessage(text);
this.editor = null;
this.document = null;
this.webSocketConnection.on('text', this.onTextCallBack);
this.webSocketConnection.on('close', this.doCleanup);
this.remoteChangedText = null;
this.editorTitle = null;
this.cleanupCallback = null;
this.disposables = [];
this.closed = false;
}
doCleanup() {
this.cleanupCallback && this.cleanupCallback();
this.disposables.forEach((d) => d.dispose());
}
updateEditorText(text) {
this.editor.edit((editBuilder) => {
var lineCount = this.editor.document.lineCount;
var lastLine = this.editor.document.lineAt(lineCount - 1);
var endPos = lastLine.range.end;
var range = new Range(new Position(0, 0), endPos);
editBuilder.delete(range);
editBuilder.insert(new Position(0,0), text);
});
}
onMessage(text) {
let request = JSON.parse(text);
if (this.editor === null) {
this.editorTitle = request.title;
var fileSuffix=vscode.workspace.getConfiguration().get('tmpFileSuffix');
tmp.file({postfix:fileSuffix},(err, path, fd, cleanupCallback) => {
this.cleanupCallback = cleanupCallback;
workspace.openTextDocument(path)
.then((textDocument) => {
this.document = textDocument;
window.showTextDocument(textDocument).then((editor) => {
this.editor = editor;
this.updateEditorText(request.text);
this.disposables.push(workspace.onDidCloseTextDocument((doc) => {
if(doc == this.document && doc.isClosed) {
this.closed = true;
this.webSocketConnection.close();
this.doCleanup();
}
}));
this.disposables.push(workspace.onDidChangeTextDocument((event) => {
if(event.document == this.document) {
let changedText = this.document.getText();
if (changedText !== this.remoteChangedText) {
var change = {
title: this.editorTitle,
text: changedText,
syntax: 'TODO',
selections: []
};
change = JSON.stringify(change);
// empty doc change event fires before close. Work around race.
return setTimeout(() => this.closed || this.webSocketConnection.sendText(change), 50);
}
}
}));
});
});
});
} else {
this.updateEditorText(request.text);
return this.remoteChangedText = request.text;
}
}
}
var httpStatusServer = null;
var activate = () => {
var fileSuffix=vscode.workspace.getConfiguration().get('tmpFileSuffix');
window.showInformationMessage('Ghost text has been enabled! Default suffix: '+fileSuffix+'. You can change this in settings.');
this.httpStatusServer = http.createServer(function(req, res) {
let wsServer = ws.createServer((conn) => new OnMessage(conn));
wsServer.on('listening', function() {
let response = {
ProtocolVersion: 1,
WebSocketPort: wsServer.socket.address().port
};
response = JSON.stringify(response);
res.writeHead(200, {'Content-Type': 'application/json'});
return res.end(response);
});
return wsServer.listen(0);
});
return this.httpStatusServer.listen(4001);
};
var deactivate = () => {
return this.httpStatusServer.close();
};
exports.httpStatusServer = httpStatusServer;
exports.activate = activate;
exports.deactivate = deactivate;