This commit is contained in:
CismonX 2020-10-24 23:50:20 +08:00
parent 4cbbcdfd4d
commit c52c7b5924
Signed by: cismonx
GPG Key ID: 3094873E29A482FB
9 changed files with 56 additions and 71 deletions

View File

@ -35,7 +35,7 @@ See `File -> Preferences -> Settings -> Extensions -> Texinfo` for details. The
## Notes
* If syntax highlighting is not satisfactory, try another color theme where keyword/operator colors are distinct (e.g. Solarized Light/Dark, Monokai).
* If syntax highlighting is not satisfactory, try another color theme (e.g. Solarized Light/Dark, Monokai) where keyword/operator colors are distinct.
* Preview content is updated on document save rather than document change.
* For macOS users: Preinstalled GNU Texinfo distribution is very old. Use a latest one instead. This can be easily done by `brew install texinfo` and change extension setting `texinfo.makeinfo` value.

26
package-lock.json generated
View File

@ -44,9 +44,9 @@
}
},
"@eslint/eslintrc": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz",
"integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==",
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.0.tgz",
"integrity": "sha512-+cIGPCBdLCzqxdtwppswP+zTsH9BOIGzAeKfBIbtb4gW/giMlfMwP0HUSFfhzh20f9u8uZ8hOp62+4GPquTbwQ==",
"dev": true,
"requires": {
"ajv": "^6.12.4",
@ -74,9 +74,9 @@
"dev": true
},
"@types/node": {
"version": "14.11.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.10.tgz",
"integrity": "sha512-yV1nWZPlMFpoXyoknm4S56y2nlTAuFYaJuQtYRAOU7xA/FJ9RY0Xm7QOkaYMMmr8ESdHIuUb6oQgR/0+2NqlyA==",
"version": "14.14.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.2.tgz",
"integrity": "sha512-jeYJU2kl7hL9U5xuI/BhKPZ4vqGM/OmK6whiFAXVhlstzZhVamWhDSmHyGLIp+RVyuF9/d0dqr2P85aFj4BvJg==",
"dev": true
},
"@types/vscode": {
@ -169,9 +169,9 @@
"dev": true
},
"ajv": {
"version": "6.12.5",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz",
"integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==",
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
@ -403,13 +403,13 @@
"dev": true
},
"eslint": {
"version": "7.11.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.11.0.tgz",
"integrity": "sha512-G9+qtYVCHaDi1ZuWzBsOWo2wSwd70TXnU6UHA3cTYHp7gCTXZcpggWFoUVAMRarg68qtPoNfFbzPh+VdOgmwmw==",
"version": "7.12.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.12.0.tgz",
"integrity": "sha512-n5pEU27DRxCSlOhJ2rO57GDLcNsxO0LPpAbpFdh7xmcDmjmlGUfoyrsB3I7yYdQXO5N3gkSTiDrPSPNFiiirXA==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"@eslint/eslintrc": "^0.1.3",
"@eslint/eslintrc": "^0.2.0",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",

View File

@ -1,7 +1,7 @@
{
"name": "texinfo",
"displayName": "Texinfo Language Support",
"description": "Syntax highlighting, code completion and preview support for Texinfo.",
"description": "Syntax highlighting, code completion, folding and preview support for Texinfo.",
"version": "0.1.0",
"author": {
"name": "CismonX",
@ -15,12 +15,12 @@
},
"icon": "assets/texinfo.png",
"devDependencies": {
"@types/node": "^14.11.10",
"@types/node": "^14.14.2",
"@types/vscode": "^1.50.0",
"@typescript-eslint/eslint-plugin": "^3.8.0",
"@typescript-eslint/parser": "^3.8.0",
"cson": "^7.20.0",
"eslint": "^7.11.0",
"eslint": "^7.12.0",
"language-texinfo": "^1.0.0",
"typescript": "^4.0.3"
},
@ -128,7 +128,7 @@
"type": "integer",
"default": 100,
"minimum": 0,
"markdownDescription": "Max tolerated number of errors when trying to display preview.\n\nThis corresponds to the `--error-limit=NUM` option of `makeinfo`."
"markdownDescription": "Max number of errors before quit when trying to display preview.\n\nThis corresponds to the `--error-limit=NUM` option of `makeinfo`."
},
"texinfo.preview.force": {
"type": "boolean",

View File

@ -17,7 +17,6 @@ export default class Converter {
* Convert a Texinfo document to HTML.
*
* @param path Path to the Texinfo document.
* @returns HTML code, or `undefined` if conversion fails.
*/
static async convertToHtml(path: string) {
return await new Converter().convert(path);

View File

@ -32,7 +32,7 @@ export default class Document {
static update(event: vscode.TextDocumentChangeEvent) {
const documentContext = Document.get(event.document);
if (documentContext?.foldingRange.update(event.contentChanges)) {
documentContext.symbol.update(documentContext.foldingRange.values);
documentContext.symbol.clear();
}
}

View File

@ -14,18 +14,10 @@ export default class Logger {
private static singleton?: Logger;
private static get instance() {
static get instance() {
return Logger.singleton ??= new Logger();
}
static log(message: string) {
Logger.instance.log(message);
}
static show() {
Logger.instance.show();
}
static destroy() {
Logger.instance.outputChannel.dispose();
Logger.singleton = undefined;
@ -37,12 +29,12 @@ export default class Logger {
this.outputChannel = vscode.window.createOutputChannel('Texinfo');
}
private log(message: string) {
log(message: string) {
const dateTime = new Date().toLocaleString(undefined, { hour12: false });
this.outputChannel.appendLine(`[ ${dateTime} ]:\n${message}`);
this.outputChannel.appendLine(`[ ${dateTime} ]\n${message}`);
}
private show() {
show() {
this.outputChannel.show(true);
}
}

View File

@ -53,7 +53,8 @@ export default class Preview {
private pendingUpdate = false;
constructor(private readonly documentContext: Document) {
this.panel = vscode.window.createWebviewPanel('texinfo.preview', '', vscode.ViewColumn.Beside);
this.panel = vscode.window.createWebviewPanel('texinfo.preview', '', vscode.ViewColumn.Beside,
{ enableFindWidget: true, retainContextWhenHidden: true });
this.disposables.push(this.panel.onDidDispose(() => this.close()));
this.updateTitle();
this.updateWebview();

View File

@ -29,34 +29,33 @@ export class DocumentSymbolContext {
private symbols?: vscode.DocumentSymbol[];
private foldingRanges?: FoldingRange[];
private foldingRanges?: readonly FoldingRange[];
get values() {
return this.symbols ??= this.calculcateDocumentSymbols();
}
update(foldingRanges: FoldingRange[]) {
this.foldingRanges = foldingRanges;
clear() {
this.foldingRanges = undefined;
this.symbols = undefined;
}
/**
* Calculate (very limited) document symbols based on folding ranges.
* Calculate document symbols based on folding ranges.
*/
private calculcateDocumentSymbols() {
this.symbols = [];
if (this.foldingRanges === undefined) {
this.foldingRanges = this.documentContext.foldingRange.values;
}
const ranges = Array<RangeNode>(this.document.lineCount);
this.foldingRanges.forEach(range => {
if (range.kind !== undefined) return;
ranges[range.start] = range;
});
return this.symbols = this.rangeToSymbols(ranges, 0, ranges.length);
(this.foldingRanges ??= this.documentContext.foldingRange.values)
.forEach(range => range.kind ?? (ranges[range.start] = range));
return this.symbols = foldingRangeToSymbols(ranges, 0, ranges.length);
}
private rangeToSymbols(ranges: RangeNode[], start: number, end: number) {
constructor(private readonly documentContext: Document) {}
}
type RangeNode = Optional<FoldingRange>;
function foldingRangeToSymbols(ranges: readonly RangeNode[], start: number, end: number) {
const symbols = <vscode.DocumentSymbol[]>[];
for (let idx = start; idx < end; ++idx) {
const node = ranges[idx];
@ -68,14 +67,9 @@ export class DocumentSymbolContext {
const selectionRange = new vscode.Range(startPosition, endFirstLine);
const symbol = new vscode.DocumentSymbol('@' + node.name, node.detail,
vscode.SymbolKind.String, range, selectionRange);
symbol.children = this.rangeToSymbols(ranges, idx + 1, node.end);
symbol.children = foldingRangeToSymbols(ranges, idx + 1, node.end);
symbols.push(symbol);
idx = node.end;
}
return symbols;
}
constructor(private readonly documentContext: Document) {}
}
type RangeNode = Optional<FoldingRange>;

View File

@ -8,7 +8,6 @@
import * as child_process from 'child_process';
import * as htmlparser from 'node-html-parser';
import * as vscode from 'vscode';
import Logger from './logger';
/**
* Open a prompt with two buttons, "Confirm" and "Cancel", and wait for user action.
@ -32,14 +31,12 @@ export async function prompt(message: string, confirm: string, error = false) {
* @returns The output data, or `undefined` if execution fails.
*/
export function exec(path: string, args: string[], maxBuffer: number) {
return new Promise<Optional<string>>(resolve => {
return new Promise<ExecResult>(resolve => {
child_process.execFile(path, args, { maxBuffer: maxBuffer }, (error, stdout, stderr) => {
if (error) {
Logger.log(stderr ? stderr : error.message);
resolve(undefined);
resolve({ error: stderr ? stderr : error.message });
} else {
stderr && Logger.log(stderr);
resolve(stdout);
resolve({ data: stdout, error: stderr });
}
});
});
@ -65,4 +62,6 @@ export function transformHtmlImageUri(htmlCode: string, transformer: (src: strin
export type Optional<T> = T | undefined;
export type ExecResult = { data?: string, error: string };
export type Range = { start: number, end: number };