Refactor code.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
CismonX 2021-08-12 01:23:04 +08:00
parent b3b9644af0
commit 3ecb2a5b03
Signed by: cismonx
GPG Key ID: 3094873E29A482FB
16 changed files with 156 additions and 111 deletions

View File

@ -28,8 +28,8 @@ import { prompt } from './utils/misc';
* Manage mappings between Texinfo documents and corresponding
* document-specific contexts.
*/
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.
*

View File

@ -28,8 +28,8 @@ import PreviewContext from './preview';
/**
* Holds all contexts for a Texinfo document.
*/
export default class DocumentContext {
export default class DocumentContext
{
readonly foldingRange = new FoldingRangeContext(this);
readonly documentSymbol = new DocumentSymbolContext(this);

View File

@ -27,8 +27,8 @@ import { FoldingRange, Optional } from '../utils/types';
/**
* Context for symbols in a Texinfo document.
*/
export default class DocumentSymbolContext {
export default class DocumentSymbolContext
{
get documentSymbols() {
return this._documentSymbols ??= this._calculcateDocumentSymbols();
}
@ -63,11 +63,16 @@ function foldingRangeToSymbols(
const symbols = <vscode.DocumentSymbol[]>[];
for (let idx = start; idx < end; ++idx) {
const node = ranges[idx];
if (node === undefined) continue;
const range = lineNumToRange(idx, node.end);
const selectionRange = lineNumToRange(idx);
const symbol = new vscode.DocumentSymbol('@' + node.name, node.detail,
vscode.SymbolKind.String, range, selectionRange);
if (node === undefined) {
continue;
}
const symbol = new vscode.DocumentSymbol(
'@' + node.name,
node.detail,
vscode.SymbolKind.String,
lineNumToRange(idx, node.end), // full range
lineNumToRange(idx), // selection range
);
symbol.children = foldingRangeToSymbols(ranges, idx + 1, node.end);
symbols.push(symbol);
idx = node.end;

View File

@ -30,8 +30,8 @@ import DocumentContext from './document';
* Actually, more than folding ranges (e.g. code lens) is handled within
* this context, so perhaps we should use another name...
*/
export default class FoldingRangeContext {
export default class FoldingRangeContext
{
/**
* Get VSCode folding ranges from the context.
*/
@ -129,7 +129,9 @@ export default class FoldingRangeContext {
let verbatim = false;
for (let idx = lastLine; idx >= 0; --idx) {
const line = this._document.lineAt(idx).text.trimLeft();
if (!line.startsWith('@')) continue;
if (!line.startsWith('@')) {
continue;
}
if (!verbatim) {
if (line === '@bye') {
lastLine = idx;
@ -139,7 +141,9 @@ export default class FoldingRangeContext {
this._clearTemporaries();
continue;
}
if (this._processComment(line, idx)) continue;
if (this._processComment(line, idx)) {
continue;
}
}
// Process block.
if (line.startsWith('@end ')) {
@ -151,9 +155,13 @@ export default class FoldingRangeContext {
closingBlocks.push({ name: name, line: idx });
continue;
}
if (!verbatim && this._processNode(line, idx, lastLine)) continue;
if (!verbatim && this._processNode(line, idx, lastLine)) {
continue;
}
const closingBlock = closingBlocks.pop();
if (closingBlock === undefined) continue;
if (closingBlock === undefined) {
continue;
}
const name = closingBlock.name;
if (line.substring(1, name.length + 2).trim() === name) {
this._addRange(idx, closingBlock.line, { name: name });
@ -165,8 +173,11 @@ export default class FoldingRangeContext {
}
}
if (this._commentRange !== undefined) {
this._addRange(this._commentRange.start, this._commentRange.end,
{ kind: vscode.FoldingRangeKind.Comment });
this._addRange(
this._commentRange.start,
this._commentRange.end,
{ kind: vscode.FoldingRangeKind.Comment },
);
}
return this._foldingRanges;
}

View File

@ -28,8 +28,8 @@ import { getNodeHtmlRef, prompt } from '../utils/misc';
/**
* Stores information of a Texinfo document preview.
*/
export default class PreviewContext {
export default class PreviewContext
{
close() {
this._disposables.forEach(event => event.dispose());
this._panel.dispose();
@ -57,11 +57,16 @@ export default class PreviewContext {
// Inform the user that the preview is updating, when `makeinfo`
// takes too long.
setTimeout(() => this._updating && this._updateTitle(), 500);
const initFile = this._globalContext.path + '/ext/html-preview.pm';
const converter = new Converter(this._document.fileName, initFile,
this._globalContext.options, this._logger);
const { data, error } = await converter
.toHTML(path => this._webview.asWebviewUri(path), this._script);
const converter = new Converter(
this._document.fileName,
this._globalContext.path + '/ext/html-preview.pm',
this._globalContext.options,
this._logger,
);
const { data, error } = await converter.toHTML(
path => this._webview.asWebviewUri(path),
this._script,
);
if (error) {
this._logger.log(error);
this._diagnosis.update(this._document, error);
@ -86,8 +91,11 @@ export default class PreviewContext {
retainContextWhenHidden: true,
enableScripts: true,
};
this._panel = vscode.window.createWebviewPanel('texinfo.preview', '',
vscode.ViewColumn.Beside, options);
this._panel = vscode.window.createWebviewPanel(
'texinfo.preview', '',
vscode.ViewColumn.Beside,
options,
);
this._webview = this._panel.webview;
this._disposables.push(this._panel.onDidDispose(() => this.close()));
this._updateTitle();

View File

@ -26,8 +26,8 @@ import { isDefined } from './utils/types';
/**
* Manage diagnostic information of Texinfo documents.
*/
export default class Diagnosis implements vscode.Disposable {
export default class Diagnosis implements vscode.Disposable
{
/**
* Remove a document's diagnostic entry from the collection.
*
@ -68,10 +68,13 @@ export default class Diagnosis implements vscode.Disposable {
*/
function logToDiagnostic(lineText: string) {
const lineNum = parseInt(lineText) - 1;
// Ignore error that does not correspond a line in document.
if (isNaN(lineNum)) return undefined;
// Ignore error that does not correspond to a line in document.
if (isNaN(lineNum)) {
return undefined;
}
const message = lineText.substring(lineNum.toString().length + 2);
const severity = message.startsWith('warning:')
? vscode.DiagnosticSeverity.Warning : undefined;
? vscode.DiagnosticSeverity.Warning
: undefined;
return new vscode.Diagnostic(lineNumToRange(lineNum), message, severity);
}

View File

@ -33,14 +33,14 @@ import FoldingRangeProvider from './providers/folding_range';
/**
* Manage extension-level global-scope contexts.
*/
export default class GlobalContext {
export default class GlobalContext
{
readonly contextMapping = new ContextMapping(this);
readonly diagnosis = new Diagnosis;
readonly indicator = new Indicator(this);
readonly logger = new Logger;
readonly path = this.context.extensionPath;
readonly path = this._context.extensionPath;
/**
* Note: `Options`' no singleton.
@ -52,22 +52,35 @@ export default class GlobalContext {
}
subscribe(...items: vscode.Disposable[]) {
this.context.subscriptions.push(...items);
this._context.subscriptions.push(...items);
}
constructor(private readonly context: vscode.ExtensionContext) {
constructor(private readonly _context: vscode.ExtensionContext) {
this.subscribe(
this.contextMapping, this.diagnosis, this.indicator, this.logger,
vscode.languages.registerCodeLensProvider('texinfo',
new CodeLensProvider(this)),
vscode.languages.registerCompletionItemProvider('texinfo',
new CompletionItemProvider(this), '@'),
vscode.languages.registerDocumentSymbolProvider('texinfo',
new DocumentSymbolProvider(this)),
vscode.languages.registerFoldingRangeProvider('texinfo',
new FoldingRangeProvider(this)),
this.contextMapping,
this.diagnosis,
this.indicator,
this.logger,
vscode.languages.registerCodeLensProvider(
'texinfo',
new CodeLensProvider(this),
),
vscode.languages.registerCompletionItemProvider(
'texinfo',
new CompletionItemProvider(this),
'@',
),
vscode.languages.registerDocumentSymbolProvider(
'texinfo',
new DocumentSymbolProvider(this),
),
vscode.languages.registerFoldingRangeProvider(
'texinfo',
new FoldingRangeProvider(this),
),
vscode.workspace.onDidChangeConfiguration(
() => this._options = undefined),
() => this._options = undefined,
),
);
}

View File

@ -26,8 +26,8 @@ import { exec } from './utils/misc';
/**
* Shows whether GNU Texinfo is properly installed and configured.
*/
export default class Indicator implements vscode.Disposable {
export default class Indicator implements vscode.Disposable
{
get canDisplayPreview() {
return this._canDisplayPreview;
}
@ -36,12 +36,15 @@ export default class Indicator implements vscode.Disposable {
this._statusBarItem.dispose();
}
constructor(private readonly globalContext: GlobalContext) {
globalContext.subscribe(
vscode.commands.registerCommand('texinfo.indicator.click',
this._click.bind(this)),
constructor(private readonly _globalContext: GlobalContext) {
_globalContext.subscribe(
vscode.commands.registerCommand(
'texinfo.indicator.click',
this._click.bind(this),
),
vscode.window.onDidChangeActiveTextEditor(
this._refresh.bind(this)),
this._refresh.bind(this),
),
);
this._updateStatus()
.then(() => this._refresh(vscode.window.activeTextEditor));
@ -78,9 +81,9 @@ export default class Indicator implements vscode.Disposable {
* by checking `makeinfo --version`.
*/
private async _updateStatus() {
const options = this.globalContext.options;
const output = await exec(options.makeinfo, ['--version'],
options.maxSize);
const options = this._globalContext.options;
const output
= await exec(options.makeinfo, ['--version'], options.maxSize);
const result = output.data?.match(/\(GNU texinfo\) (.*)\n/);
let tooltip = '', icon: string, version = '';
if (result && result[1]) {

View File

@ -24,11 +24,13 @@ import * as vscode from 'vscode';
/**
* Logger which prints message to VSCode output channel.
*/
export default class Logger implements vscode.Disposable {
export default class Logger implements vscode.Disposable
{
log(message: string) {
const dateTime = new Date()
.toLocaleString(undefined, { hour12: false });
const dateTime = new Date().toLocaleString(
undefined,
{ hour12: false }
);
this._outputChannel.appendLine(`[ ${dateTime} ]\n${message}`);
}

View File

@ -26,8 +26,8 @@ import * as vscode from 'vscode';
*
* See the `contributes.configuration` entry in package.json for details.
*/
export default class Options {
export default class Options
{
get enableSnippets() {
return this._getBoolean('completion.enableSnippets');
}

View File

@ -25,13 +25,17 @@ import GlobalContext from '../global_context';
/**
* Provide code lenses for Texinfo document.
*/
export default class CodeLensProvider implements vscode.CodeLensProvider {
export default class CodeLensProvider implements vscode.CodeLensProvider
{
provideCodeLenses(document: vscode.TextDocument) {
if (!this._globalContext.options.enableCodeLens) return undefined;
if (!this._globalContext.indicator.canDisplayPreview) return undefined;
return this._globalContext.contextMapping.getDocumentContext(document)
.foldingRange.nodeValues;
if (!this._globalContext.options.enableCodeLens) {
return undefined;
}
if (!this._globalContext.indicator.canDisplayPreview) {
return undefined;
}
return this._globalContext.contextMapping
.getDocumentContext(document).foldingRange.nodeValues;
}
constructor(private readonly _globalContext: GlobalContext) {}

View File

@ -32,15 +32,16 @@ export default class CompletionItemProvider
/**
* Full list of completion items.
*
* Note: Descriptions of completion items for @-commands are excerpted from
* the GNU Texinfo manual
* ({@link https://www.gnu.org/software/texinfo/manual/texinfo }),
* which is licensed under the GNU Free Documentation License, version 1.3.
* Note: Descriptions of completion items for @-commands
* are excerpted from the [GNU Texinfo manual], which is licensed under the
* GNU Free Documentation License, version 1.3.
*
* According to GFDL, this usage is considered "aggregation with
* independent work", which means that GFDL applies to lines 48-367 of this
* file, while the remainder is under GPL like other source code files of
* the project.
* independent work", which means that GFDL applies to lines 50-1117 of
* this file, while the remainder is under GPL like other source code files
* of the project.
*
* [GNU Texinfo manual]: https://gnu.org/software/texinfo/manual/texinfo
*/
private _getCompletionItems() {
const enableSnippets = this._oldOptions.enableSnippets;
@ -159,10 +160,6 @@ export default class CompletionItemProvider
'Center the line of text following the command',
'text-line',
),
...lineCommand('centerchap',
'Like @chapter, but centers the chapter title',
'text-line',
),
...lineCommand('chapheading',
'Print an unnumbered chapter-like heading',
'title',
@ -245,11 +242,6 @@ export default class CompletionItemProvider
'Define a new index, print entries in a roman font',
'index-name',
),
...lineCommand('definfoenclose',
'Create a new command for Info that marks text by enclosing ' +
'it in strings that precede and follow the text.',
'newcmd', 'before', 'after',
),
...lineCommandX('defivar',
'Format a description for an instance variable ' +
'in object-oriented programming',
@ -612,10 +604,6 @@ export default class CompletionItemProvider
'Indicate text that is a URL',
1, 'URL',
),
...braceCommand('inforef',
'Make a cross-reference to an Info file',
3, 'node-name', 'entry-name', 'info-file-name',
),
...braceCommand('inlinefmt',
'Insert text only if the output format is fmt',
2, 'fmt', 'text',
@ -820,10 +808,6 @@ export default class CompletionItemProvider
'any special text',
1, 'node', 'entry', 'node-title', 'info-node', 'manual',
),
command('refill',
'Refill and indent the paragraph after all the ' +
'other processing has been done',
),
command('registeredsymbol',
'Generate the legal symbol, "®"',
{ hasEmptyBrace: true },
@ -1153,12 +1137,18 @@ export default class CompletionItemProvider
// Triggered in the middle of a word.
if (context.triggerKind === vscode.CompletionTriggerKind.Invoke) {
const wordRange = document.getWordRangeAtPosition(position);
if (wordRange === undefined) return undefined;
if (wordRange === undefined) {
return undefined;
}
// Normalize position so that it can be treated as
// triggered by '@' character.
position = wordRange.start;
const pos = new vscode.Range(position.translate(0, -1), position);
if (document.getText(pos) !== '@') return undefined;
const charBeforeWord = new vscode.Range(
wordRange.start.translate(0, -1),
wordRange.start,
);
if (document.getText(charBeforeWord) !== '@') {
return undefined;
}
}
// Check whether options has changed.
const newOptions = this._globalContext.options;
@ -1168,9 +1158,11 @@ export default class CompletionItemProvider
}
if (position.character === 1) return this._getCompletionItems();
// Check whether the '@' character is escaped.
const pos = new vscode.Range(
position.translate(0, -2), position.translate(0, -1));
if (document.getText(pos) === '@') {
const secondCharBeforeWord = new vscode.Range(
position.translate(0, -2),
position.translate(0, -1)
);
if (document.getText(secondCharBeforeWord) === '@') {
return undefined;
} else {
return this._getCompletionItems();

View File

@ -29,8 +29,8 @@ export default class DocumentSymbolProvider
implements vscode.DocumentSymbolProvider
{
provideDocumentSymbols(document: vscode.TextDocument) {
return this._globalContext.contextMapping.getDocumentContext(document)
.documentSymbol.documentSymbols;
return this._globalContext.contextMapping
.getDocumentContext(document).documentSymbol.documentSymbols;
}
constructor(private readonly _globalContext: GlobalContext) {}

View File

@ -29,8 +29,8 @@ export default class FoldingRangeProvider
implements vscode.FoldingRangeProvider
{
provideFoldingRanges(document: vscode.TextDocument) {
return this._globalContext.contextMapping.getDocumentContext(document)
.foldingRange.foldingRanges;
return this._globalContext.contextMapping
.getDocumentContext(document).foldingRange.foldingRanges;
}
constructor(private readonly _globalContext: GlobalContext) {}

View File

@ -29,8 +29,8 @@ import { Operator } from './types';
/**
* Converter which converts file from Texinfo to other formats.
*/
export default class Converter {
export default class Converter
{
async toHTML(imgTransformer: Operator<vscode.Uri>, insertScript?: string) {
const pathUri = vscode.Uri.file(path.dirname(this._path));
const newPath = imgTransformer(pathUri).toString() + '/';
@ -49,8 +49,11 @@ export default class Converter {
this._addIncludePaths(this._options.includePaths, options);
this._defineVariables(this._options.variables, options);
this._includeCustomCSS(this._options.customCSS, options);
return await exec(this._options.makeinfo, options.concat(this._path),
this._options.maxSize);
return await exec(
this._options.makeinfo,
options.concat(this._path),
this._options.maxSize,
);
}
constructor(

View File

@ -112,6 +112,7 @@ export function getNodeHtmlRef(nodeName: string) {
.join(''))
.join('-');
const firstCharCode = result.charCodeAt(0);
return isAlpha(firstCharCode) ? result : 'g_t_00'
+ firstCharCode.toString(16) + result.substring(1);
return isAlpha(firstCharCode)
? result
: 'g_t_00' + firstCharCode.toString(16) + result.substring(1);
}