UNPKG

cpp-merge

Version:

Command line tool to produce single source file from multiple C/C++ files

183 lines 8.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const CppFileMerger_1 = __importDefault(require("../parse/CppFileMerger")); const errors_1 = require("../parse/errors"); const ArgumentParser_1 = __importStar(require("./ArgumentParser")); const CliError_1 = __importStar(require("./CliError")); var ArgumentName; (function (ArgumentName) { ArgumentName["File"] = "file"; })(ArgumentName || (ArgumentName = {})); var OptionName; (function (OptionName) { OptionName["Help"] = "help"; OptionName["Include"] = "include"; OptionName["Source"] = "source"; OptionName["Output"] = "output"; })(OptionName || (OptionName = {})); class Cli { constructor(output = process.stdout) { this.output = output; this.argumentParser = new ArgumentParser_1.default({ programName: "cpp-merge", description: "A tool to produce single file from multiple C/C++ files. By default the produced content is " + "displayed on the standard output. To store it in a file use option -o or --output." }); this.argumentParser.addArgument({ name: ArgumentName.File, description: "Input file which will be processed. In most cases it will be file with main function.", valueName: "file" }); this.argumentParser.addOption({ name: OptionName.Help, options: ["--help"], description: "Show this help text." }); this.argumentParser.addOption({ name: OptionName.Include, options: ["-i", "--include"], description: "Path to additional directory where header files are located. Program will search for include " + "files first in directory where currently processed file is located and then in this directory.", value: { name: "path" } }); this.argumentParser.addOption({ name: OptionName.Source, options: ["-s", "--source"], description: "Path to additional directory where source files are located. After processing all included files, " + "program will try to find related source file for each of included local header files. If file with same " + "base name and extension .c or .cpp exists, it will be appended to the output. Program will search first " + "in the same directory where main source file is located and then in additional source directory.", value: { name: "path" } }); this.argumentParser.addOption({ name: OptionName.Output, options: ["-o", "--output"], description: "Store output in a file, instead of displaying it on the standard output.", value: { name: "file" } }); } run(args) { if (args.length === 0) { this.printHelp(); return; } try { const { help, inputFilePath, includeDirectory, sourceDirectory, outputFilePath } = this.parseArguments(args); if (help) { this.printHelp(); return; } const content = this.parseFile(inputFilePath, includeDirectory, sourceDirectory); if (outputFilePath) { this.writeToFile(outputFilePath, content); } else { this.output.write(content); } } catch (error) { if (error instanceof errors_1.ParseError) { throw new CliError_1.default(`Error parsing file '${error.file}': ${error.message}`, CliError_1.ErrorCode.ParseError); } if (error instanceof ArgumentParser_1.UnknownOptionError) { throw new CliError_1.default(`Unknown option: '${error.argument}'`, CliError_1.ErrorCode.ArgumentError); } if (error instanceof ArgumentParser_1.UnknownArgumentError) { throw new CliError_1.default(`Unknown argument: '${error.argument}'`, CliError_1.ErrorCode.ArgumentError); } if (error instanceof ArgumentParser_1.ArgumentError) { throw new CliError_1.default(`Invalid argument '${error.argument}': ${error.message}`, CliError_1.ErrorCode.ArgumentError); } throw error; } } printHelp() { this.output.write(this.argumentParser.formatHelp()); } parseArguments(args) { const result = this.argumentParser.parseArguments(args); return { help: result.options[OptionName.Help] != null, inputFilePath: result.arguments[ArgumentName.File], includeDirectory: result.options[OptionName.Include], sourceDirectory: result.options[OptionName.Source], outputFilePath: result.options[OptionName.Output] }; } parseFile(inputFilePath, includeDirectory, sourceDirectory) { if (!inputFilePath) { throw new CliError_1.default('Missing input file', CliError_1.ErrorCode.ArgumentError); } this.validateInputFile(inputFilePath); if (includeDirectory) { this.validateIncludeDirectory(includeDirectory); } if (sourceDirectory) { this.validateSourceDirectory(sourceDirectory); } const fileMerger = new CppFileMerger_1.default({ includeDirectory, sourceDirectory }); return fileMerger.parse(inputFilePath); } validateInputFile(inputFilePath) { if (!fs_1.default.existsSync(inputFilePath)) { throw new CliError_1.default(`Input file '${inputFilePath}' doesn't exist`, CliError_1.ErrorCode.ArgumentError); } if (!fs_1.default.statSync(inputFilePath).isFile()) { throw new CliError_1.default(`${inputFilePath} is not a file`, CliError_1.ErrorCode.ArgumentError); } } validateIncludeDirectory(includeDirectory) { if (!fs_1.default.existsSync(includeDirectory)) { throw new CliError_1.default(`Include directory '${includeDirectory}' doesn't exist`, CliError_1.ErrorCode.ArgumentError); } if (!fs_1.default.statSync(includeDirectory).isDirectory()) { throw new CliError_1.default(`${includeDirectory} is not a directory`, CliError_1.ErrorCode.ArgumentError); } } validateSourceDirectory(sourceDirectory) { if (!fs_1.default.existsSync(sourceDirectory)) { throw new CliError_1.default(`Source directory '${sourceDirectory}' doesn't exist`, CliError_1.ErrorCode.ArgumentError); } if (!fs_1.default.statSync(sourceDirectory).isDirectory()) { throw new CliError_1.default(`${sourceDirectory} is not a directory`, CliError_1.ErrorCode.ArgumentError); } } writeToFile(outputFilePath, content) { try { fs_1.default.writeFileSync(outputFilePath, content); } catch (error) { const causeMessage = error instanceof Error ? error.message : 'Unknown error'; throw new CliError_1.default(`Error writing output to file '${outputFilePath}': ${causeMessage}`, CliError_1.ErrorCode.WriteError); } } } exports.default = Cli; //# sourceMappingURL=Cli.js.map