Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/markdown-language-features/src/preview/topmostLineMonitor.ts
3292 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as vscode from 'vscode';
7
import { Disposable } from '../util/dispose';
8
import { isMarkdownFile } from '../util/file';
9
import { ResourceMap } from '../util/resourceMap';
10
11
export interface LastScrollLocation {
12
readonly line: number;
13
readonly uri: vscode.Uri;
14
}
15
16
export class TopmostLineMonitor extends Disposable {
17
18
private readonly _pendingUpdates = new ResourceMap<number>();
19
private readonly _throttle = 50;
20
private readonly _previousTextEditorInfo = new ResourceMap<LastScrollLocation>();
21
private readonly _previousStaticEditorInfo = new ResourceMap<LastScrollLocation>();
22
23
constructor() {
24
super();
25
26
if (vscode.window.activeTextEditor) {
27
const line = getVisibleLine(vscode.window.activeTextEditor);
28
this.setPreviousTextEditorLine({ uri: vscode.window.activeTextEditor.document.uri, line: line ?? 0 });
29
}
30
31
this._register(vscode.window.onDidChangeTextEditorVisibleRanges(event => {
32
if (isMarkdownFile(event.textEditor.document)) {
33
const line = getVisibleLine(event.textEditor);
34
if (typeof line === 'number') {
35
this.updateLine(event.textEditor.document.uri, line);
36
this.setPreviousTextEditorLine({ uri: event.textEditor.document.uri, line: line });
37
}
38
}
39
}));
40
}
41
42
private readonly _onChanged = this._register(new vscode.EventEmitter<{ readonly resource: vscode.Uri; readonly line: number }>());
43
public readonly onDidChanged = this._onChanged.event;
44
45
public setPreviousStaticEditorLine(scrollLocation: LastScrollLocation): void {
46
this._previousStaticEditorInfo.set(scrollLocation.uri, scrollLocation);
47
}
48
49
public getPreviousStaticEditorLineByUri(resource: vscode.Uri): number | undefined {
50
const scrollLoc = this._previousStaticEditorInfo.get(resource);
51
this._previousStaticEditorInfo.delete(resource);
52
return scrollLoc?.line;
53
}
54
55
56
public setPreviousTextEditorLine(scrollLocation: LastScrollLocation): void {
57
this._previousTextEditorInfo.set(scrollLocation.uri, scrollLocation);
58
}
59
60
public getPreviousTextEditorLineByUri(resource: vscode.Uri): number | undefined {
61
const scrollLoc = this._previousTextEditorInfo.get(resource);
62
this._previousTextEditorInfo.delete(resource);
63
return scrollLoc?.line;
64
}
65
66
public getPreviousStaticTextEditorLineByUri(resource: vscode.Uri): number | undefined {
67
const state = this._previousStaticEditorInfo.get(resource);
68
return state?.line;
69
}
70
71
public updateLine(
72
resource: vscode.Uri,
73
line: number
74
) {
75
if (!this._pendingUpdates.has(resource)) {
76
// schedule update
77
setTimeout(() => {
78
if (this._pendingUpdates.has(resource)) {
79
this._onChanged.fire({
80
resource,
81
line: this._pendingUpdates.get(resource) as number
82
});
83
this._pendingUpdates.delete(resource);
84
}
85
}, this._throttle);
86
}
87
88
this._pendingUpdates.set(resource, line);
89
}
90
}
91
92
/**
93
* Get the top-most visible range of `editor`.
94
*
95
* Returns a fractional line number based the visible character within the line.
96
* Floor to get real line number
97
*/
98
export function getVisibleLine(
99
editor: vscode.TextEditor
100
): number | undefined {
101
if (!editor.visibleRanges.length) {
102
return undefined;
103
}
104
105
const firstVisiblePosition = editor.visibleRanges[0].start;
106
const lineNumber = firstVisiblePosition.line;
107
const line = editor.document.lineAt(lineNumber);
108
const progress = firstVisiblePosition.character / (line.text.length + 2);
109
return lineNumber + progress;
110
}
111
112