UNPKG

smart-column-indenter

Version:

A smart source code indenter that indent the code into columns

70 lines 3.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const fs = require("fs"); const assert = require("assert"); const LanguageFactory_1 = require("./languages/LanguageFactory"); const multiple_lcs_1 = require("multiple-lcs"); const Columnizer_1 = require("./Columnizer"); const intersection = require("lodash.intersection"); class Indenter { constructor(code, extension, config) { this.code = code; this.extension = extension; this.config = this.overrideDefaultConfig(config); } overrideDefaultConfig(newConfig) { const jsonDefaultConfig = fs.readFileSync(`${__dirname}/config.json`, { encoding: "utf-8" }); const defaultConfig = JSON.parse(jsonDefaultConfig); return Object.assign({}, defaultConfig, newConfig); } indent(type) { const language = LanguageFactory_1.default.getLanguage(this.config, this.extension); const linesOfCode = this.code.split(/\r\n|\r|\n/).map(l => l.trim()).filter(l => l !== ""); assert.ok(linesOfCode.length >= 2, "The code to indent must have at least 2 lines of code."); const linesOfTokens = language.tokenize(linesOfCode); const inputTokens = language.preProcessInput(linesOfTokens); const commonTokens = this.commonTokens(language, inputTokens, type); const outputTokens = language.preProcessOutput(linesOfTokens); const columnizedTokens = new Columnizer_1.default(language, commonTokens, outputTokens).columnize(); const indentedCode = this.stringify(language, columnizedTokens); this.ensureSameCode(this.code, indentedCode); return indentedCode; } commonTokens(language, linesOfTokens, type) { const sequencesOfStrings = linesOfTokens.map(line => line.map(token => language.token2string(token))); if (type === "N") { return new multiple_lcs_1.default().execute(sequencesOfStrings); } else if (type === "2") { let firstCommonToken; let i = 0; do { firstCommonToken = intersection(...sequencesOfStrings.map(line => line.slice(0, ++i))); } while (!firstCommonToken.length); return [firstCommonToken[0]]; } else { throw new Error("Unknown indentation type."); } } stringify(language, columnizedTokens) { const spacesBefore = this.code.replace(/\S[\s\S]*/, ""); const spacesAfter = this.code.replace(/[\s\S]*\S/, ""); const lineBreak = (this.code.match(/\r\n|\r|\n/) || ["\n"])[0]; const indentation = this.code.trim().split(/\r\n|\r|\n/g)[1].replace(/^(\s*).*/, "$1"); const indentedCode = language .stringify(columnizedTokens) .map(line => line.replace(/\s+$/, "")) .join(lineBreak + indentation); return spacesBefore + indentedCode + spacesAfter; } ensureSameCode(code, indentedCode) { const codeWithoutIndentation = code.replace(/[ \t]/g, "").replace(/\r\n|\r|\n/g, "\n").trim(); const indentedCodeWithoutIndentation = indentedCode.replace(/[ \t]/g, "").replace(/\r\n|\r|\n/g, "\n").trim(); if (codeWithoutIndentation !== indentedCodeWithoutIndentation) { throw new Error("The indentation process are trying to change the code. It is a bug, please, open an issue: https://github.com/lmcarreiro/smart-column-indenter"); } } } exports.default = Indenter; //# sourceMappingURL=Indenter.js.map