Refactor code.
This commit is contained in:
parent
165bf9f583
commit
d5b84cdd7b
|
@ -19,7 +19,7 @@ minify-xml --output extension.vsixmanifest{,}
|
||||||
cd extension
|
cd extension
|
||||||
# Minify JSON files.
|
# Minify JSON files.
|
||||||
json -j0 -I -e "$PACKAGE_JSON_CLEANUP_JS" -f package.json
|
json -j0 -I -e "$PACKAGE_JSON_CLEANUP_JS" -f package.json
|
||||||
json5 -o package.json{,}
|
sed -i '' -e '2d' package.json
|
||||||
json5 -o language-configuration.json{,}
|
json5 -o language-configuration.json{,}
|
||||||
# Remove comments from Markdown files.
|
# Remove comments from Markdown files.
|
||||||
sed -i '' -e '1,8d' README.md CHANGELOG.md
|
sed -i '' -e '1,8d' README.md CHANGELOG.md
|
||||||
|
|
|
@ -29,6 +29,12 @@ import { prompt } from './utils/misc';
|
||||||
*/
|
*/
|
||||||
export default class ContextMapping implements vscode.Disposable {
|
export default class ContextMapping implements vscode.Disposable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get context of a Texinfo document. Create one if not exists.
|
||||||
|
*
|
||||||
|
* @param document
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
getDocumentContext(document: vscode.TextDocument) {
|
getDocumentContext(document: vscode.TextDocument) {
|
||||||
let documentContext = this.map.get(document);
|
let documentContext = this.map.get(document);
|
||||||
if (documentContext === undefined) {
|
if (documentContext === undefined) {
|
||||||
|
@ -54,7 +60,7 @@ export default class ContextMapping implements vscode.Disposable {
|
||||||
|
|
||||||
private readonly map = new Map<vscode.TextDocument, DocumentContext>();
|
private readonly map = new Map<vscode.TextDocument, DocumentContext>();
|
||||||
|
|
||||||
private getDocumentContextIfExist(document: vscode.TextDocument) {
|
private tryGetDocumentContext(document: vscode.TextDocument) {
|
||||||
return document.languageId === 'texinfo' ? this.getDocumentContext(document) : undefined;
|
return document.languageId === 'texinfo' ? this.getDocumentContext(document) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,14 +80,14 @@ export default class ContextMapping implements vscode.Disposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDocumentSave(document: vscode.TextDocument) {
|
private onDocumentSave(document: vscode.TextDocument) {
|
||||||
const documentContext = this.getDocumentContextIfExist(document);
|
const documentContext = this.tryGetDocumentContext(document);
|
||||||
if (documentContext === undefined) return;
|
if (documentContext === undefined) return;
|
||||||
documentContext.foldingRange.clear();
|
documentContext.foldingRange.clear();
|
||||||
documentContext.getPreview()?.updateWebview();
|
documentContext.getPreview()?.updateWebview();
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDocumentUpdate(event: vscode.TextDocumentChangeEvent) {
|
private onDocumentUpdate(event: vscode.TextDocumentChangeEvent) {
|
||||||
const documentContext = this.getDocumentContextIfExist(event.document);
|
const documentContext = this.tryGetDocumentContext(event.document);
|
||||||
if (documentContext?.foldingRange.update(event.contentChanges)) {
|
if (documentContext?.foldingRange.update(event.contentChanges)) {
|
||||||
documentContext.documentSymbol.clear();
|
documentContext.documentSymbol.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,9 @@ export default class DocumentSymbolContext {
|
||||||
*/
|
*/
|
||||||
private calculcateDocumentSymbols() {
|
private calculcateDocumentSymbols() {
|
||||||
const ranges = Array<Optional<FoldingRange>>(this.document.lineCount);
|
const ranges = Array<Optional<FoldingRange>>(this.document.lineCount);
|
||||||
this.documentContext.foldingRange.foldingRanges.forEach(range => range.kind ?? (ranges[range.start] = range));
|
this.documentContext.foldingRange.foldingRanges
|
||||||
|
.filter(range => range.kind === undefined)
|
||||||
|
.forEach(range => ranges[range.start] = range);
|
||||||
return foldingRangeToSymbols(ranges, 0, ranges.length);
|
return foldingRangeToSymbols(ranges, 0, ranges.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,10 +55,10 @@ export default class FoldingRangeContext {
|
||||||
update(events: readonly vscode.TextDocumentContentChangeEvent[]) {
|
update(events: readonly vscode.TextDocumentContentChangeEvent[]) {
|
||||||
this.contentMayChange = true;
|
this.contentMayChange = true;
|
||||||
if (this._foldingRanges === undefined) return false;
|
if (this._foldingRanges === undefined) return false;
|
||||||
|
const eol = this.document.eol === vscode.EndOfLine.LF ? '\n' : '\r\n';
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
const updatedLines = event.text.split(this.document.eol === vscode.EndOfLine.LF ? '\n' : '\r\n').length;
|
|
||||||
// Clear cached folding range when line count changes.
|
// Clear cached folding range when line count changes.
|
||||||
if (updatedLines !== 1 || event.range.start.line !== event.range.end.line) {
|
if (event.text.split(eol).length !== 1 || event.range.start.line !== event.range.end.line) {
|
||||||
this._foldingRanges = undefined;
|
this._foldingRanges = undefined;
|
||||||
this.nodes = [];
|
this.nodes = [];
|
||||||
return true;
|
return true;
|
||||||
|
@ -68,8 +68,9 @@ export default class FoldingRangeContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
if (!this.contentMayChange) return;
|
if (this.contentMayChange) {
|
||||||
this._foldingRanges = undefined;
|
this._foldingRanges = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private readonly documentContext: DocumentContext) {}
|
constructor(private readonly documentContext: DocumentContext) {}
|
||||||
|
@ -117,7 +118,7 @@ export default class FoldingRangeContext {
|
||||||
let lastLine = this.document.lineCount - 1;
|
let lastLine = this.document.lineCount - 1;
|
||||||
let verbatim = false;
|
let verbatim = false;
|
||||||
for (let idx = lastLine; idx >= 0; --idx) {
|
for (let idx = lastLine; idx >= 0; --idx) {
|
||||||
const line = this.document.lineAt(idx).text;
|
const line = this.document.lineAt(idx).text.trimLeft();
|
||||||
if (!line.startsWith('@')) continue;
|
if (!line.startsWith('@')) continue;
|
||||||
if (!verbatim) {
|
if (!verbatim) {
|
||||||
if (line === '@bye') {
|
if (line === '@bye') {
|
||||||
|
|
|
@ -114,6 +114,9 @@ export default class PreviewContext {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate script used for jumping to the corresponding location of preview with code lens.
|
||||||
|
*/
|
||||||
private get script() {
|
private get script() {
|
||||||
if (!this.globalContext.options.enableCodeLens) return undefined;
|
if (!this.globalContext.options.enableCodeLens) return undefined;
|
||||||
return "window.addEventListener('message', event => {" +
|
return "window.addEventListener('message', event => {" +
|
||||||
|
|
|
@ -28,6 +28,11 @@ import { isDefined } from './utils/types';
|
||||||
*/
|
*/
|
||||||
export default class Diagnosis implements vscode.Disposable {
|
export default class Diagnosis implements vscode.Disposable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a document's diagnostic entry from the collection.
|
||||||
|
*
|
||||||
|
* @param document
|
||||||
|
*/
|
||||||
delete(document: vscode.TextDocument) {
|
delete(document: vscode.TextDocument) {
|
||||||
this.diagnostics.delete(document.uri);
|
this.diagnostics.delete(document.uri);
|
||||||
}
|
}
|
||||||
|
@ -54,9 +59,15 @@ export default class Diagnosis implements vscode.Disposable {
|
||||||
private readonly diagnostics = vscode.languages.createDiagnosticCollection('texinfo');
|
private readonly diagnostics = vscode.languages.createDiagnosticCollection('texinfo');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a `makeinfo` error log line to a VSCode `Diagnostic` object.
|
||||||
|
*
|
||||||
|
* @param lineText
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
function logLineToDiagnostic(lineText: string) {
|
function logLineToDiagnostic(lineText: string) {
|
||||||
const lineNum = parseInt(lineText) - 1;
|
const lineNum = parseInt(lineText) - 1;
|
||||||
// Ignore error that does not correspond a line.
|
// Ignore error that does not correspond a line in document.
|
||||||
if (isNaN(lineNum)) return undefined;
|
if (isNaN(lineNum)) return undefined;
|
||||||
const message = lineText.substring(lineNum.toString().length + 2);
|
const message = lineText.substring(lineNum.toString().length + 2);
|
||||||
const severity = message.startsWith('warning:') ? vscode.DiagnosticSeverity.Warning : undefined;
|
const severity = message.startsWith('warning:') ? vscode.DiagnosticSeverity.Warning : undefined;
|
||||||
|
|
|
@ -60,13 +60,9 @@ export default class GlobalContext {
|
||||||
vscode.languages.registerCompletionItemProvider('texinfo', new CompletionItemProvider(this), '@'),
|
vscode.languages.registerCompletionItemProvider('texinfo', new CompletionItemProvider(this), '@'),
|
||||||
vscode.languages.registerDocumentSymbolProvider('texinfo', new DocumentSymbolProvider(this)),
|
vscode.languages.registerDocumentSymbolProvider('texinfo', new DocumentSymbolProvider(this)),
|
||||||
vscode.languages.registerFoldingRangeProvider('texinfo', new FoldingRangeProvider(this)),
|
vscode.languages.registerFoldingRangeProvider('texinfo', new FoldingRangeProvider(this)),
|
||||||
vscode.workspace.onDidChangeConfiguration(this.refreshOptions),
|
vscode.workspace.onDidChangeConfiguration(() => this._options = undefined),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _options?: Options;
|
private _options?: Options;
|
||||||
|
|
||||||
private refreshOptions() {
|
|
||||||
this._options = undefined;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,13 +46,21 @@ export default class Indicator implements vscode.Disposable {
|
||||||
|
|
||||||
private _canDisplayPreview = false;
|
private _canDisplayPreview = false;
|
||||||
|
|
||||||
private statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
|
private readonly statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls when the status bar item is clicked.
|
||||||
|
*/
|
||||||
private async click() {
|
private async click() {
|
||||||
await this.updateStatus();
|
await this.updateStatus();
|
||||||
this.refresh(vscode.window.activeTextEditor);
|
this.refresh(vscode.window.activeTextEditor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the show/hide status of the indicator based on given editor.
|
||||||
|
*
|
||||||
|
* @param editor
|
||||||
|
*/
|
||||||
private refresh(editor?: vscode.TextEditor) {
|
private refresh(editor?: vscode.TextEditor) {
|
||||||
if (editor?.document.languageId === 'texinfo') {
|
if (editor?.document.languageId === 'texinfo') {
|
||||||
this.statusBarItem.show();
|
this.statusBarItem.show();
|
||||||
|
@ -61,6 +69,9 @@ export default class Indicator implements vscode.Disposable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the installation status of GNU Texinfo, by checking `makeinfo --version`.
|
||||||
|
*/
|
||||||
private async updateStatus() {
|
private async updateStatus() {
|
||||||
const options = this.globalContext.options;
|
const options = this.globalContext.options;
|
||||||
const output = await exec(options.makeinfo, ['--version'], options.maxSize);
|
const output = await exec(options.makeinfo, ['--version'], options.maxSize);
|
||||||
|
|
|
@ -39,5 +39,5 @@ export default class Logger implements vscode.Disposable {
|
||||||
this.outputChannel.dispose();
|
this.outputChannel.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private outputChannel = vscode.window.createOutputChannel('Texinfo');
|
private readonly outputChannel = vscode.window.createOutputChannel('Texinfo');
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ export default class CompletionItemProvider implements vscode.CompletionItemProv
|
||||||
* which is licensed under the GNU Free Documentation License, version 1.3.
|
* which is licensed under the GNU Free Documentation License, version 1.3.
|
||||||
*
|
*
|
||||||
* According to GFDL, this usage is considered "aggregation with independent work",
|
* According to GFDL, this usage is considered "aggregation with independent work",
|
||||||
* which means that GFDL applies to lines 48-398 of this file, while the remainder
|
* which means that GFDL applies to lines 46-365 of this file, while the remainder
|
||||||
* is under GPL like other source code files of the project.
|
* is under GPL like other source code files of the project.
|
||||||
*/
|
*/
|
||||||
private get completionItems() {
|
private get completionItems() {
|
||||||
|
|
|
@ -32,9 +32,9 @@ import { ExecResult } from './types';
|
||||||
* @returns The output data, or `undefined` if execution fails.
|
* @returns The output data, or `undefined` if execution fails.
|
||||||
*/
|
*/
|
||||||
export function exec(path: string, args: string[], maxBuffer: number) {
|
export function exec(path: string, args: string[], maxBuffer: number) {
|
||||||
return new Promise<ExecResult>(resolve => child_process.execFile(path, args, { maxBuffer: maxBuffer },
|
return new Promise<ExecResult>(resolve => child_process.execFile(path, args,
|
||||||
(error, stdout, stderr) => resolve(
|
{ env: { LC_MESSAGES: 'en_US' }, maxBuffer: maxBuffer }, (error, stdout, stderr) =>
|
||||||
error ? { error: stderr ? stderr : error.message } : { data: stdout, error: stderr })));
|
resolve(error ? { error: stderr ? stderr : error.message } : { data: stdout, error: stderr })));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue