forked from asciidoctor/asciidoctor-vscode
/
topmostLineMonitor.ts
74 lines (63 loc) · 2.28 KB
/
topmostLineMonitor.ts
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
/*---------------------------------------------------------------------------------------------
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode'
import { disposeAll } from '../util/dispose'
import { isAsciidocFile } from './file'
export class AsciidocFileTopmostLineMonitor {
private readonly disposables: vscode.Disposable[] = [];
private readonly pendingUpdates = new Map<string, number>();
private readonly throttle = 50;
constructor () {
vscode.window.onDidChangeTextEditorVisibleRanges((event) => {
if (isAsciidocFile(event.textEditor.document)) {
const line = getVisibleLine(event.textEditor)
if (typeof line === 'number') {
this.updateLine(event.textEditor.document.uri, line)
}
}
}, null, this.disposables)
}
dispose () {
disposeAll(this.disposables)
}
private readonly _onDidChangeTopmostLineEmitter = new vscode.EventEmitter<{ resource: vscode.Uri, line: number }>();
public readonly onDidChangeTopmostLine = this._onDidChangeTopmostLineEmitter.event;
private updateLine (
resource: vscode.Uri,
line: number
) {
const key = resource.toString()
if (!this.pendingUpdates.has(key)) {
// schedule update
setTimeout(() => {
if (this.pendingUpdates.has(key)) {
this._onDidChangeTopmostLineEmitter.fire({
resource,
line: this.pendingUpdates.get(key) as number,
})
this.pendingUpdates.delete(key)
}
}, this.throttle)
}
this.pendingUpdates.set(key, line)
}
}
/**
* Get the top-most visible range of `editor`.
*
* Returns a fractional line number based the visible character within the line.
* Floor to get real line number
*/
export function getVisibleLine (
editor: vscode.TextEditor
): number | undefined {
if (!editor.visibleRanges.length) {
return undefined
}
const firstVisiblePosition = editor.visibleRanges[0].start
const lineNumber = firstVisiblePosition.line
const line = editor.document.lineAt(lineNumber)
const progress = firstVisiblePosition.character / (line.text.length + 2)
return lineNumber + progress
}