File indexing completed on 2024-05-12 04:02:14
0001 /* 0002 SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: MIT 0005 */ 0006 0007 #include "ksyntaxhighlighting_version.h" 0008 0009 #include <KSyntaxHighlighting/Definition> 0010 #include <KSyntaxHighlighting/DefinitionDownloader> 0011 #include <KSyntaxHighlighting/Repository> 0012 #include <KSyntaxHighlighting/Theme> 0013 #include <ansihighlighter.h> 0014 #include <htmlhighlighter.h> 0015 0016 #include <QCommandLineParser> 0017 #include <QCoreApplication> 0018 #include <QFile> 0019 0020 #include <iostream> 0021 0022 using namespace KSyntaxHighlighting; 0023 0024 template<class Highlighter, class... Ts> 0025 static void applyHighlighter(Highlighter &highlighter, 0026 QCommandLineParser &parser, 0027 bool fromFileName, 0028 const QString &inFileName, 0029 const QCommandLineOption &outputName, 0030 const Ts &...highlightParams) 0031 { 0032 if (parser.isSet(outputName)) { 0033 highlighter.setOutputFile(parser.value(outputName)); 0034 } else { 0035 highlighter.setOutputFile(stdout); 0036 } 0037 0038 if (fromFileName) { 0039 highlighter.highlightFile(inFileName, highlightParams...); 0040 } else { 0041 QFile inFile; 0042 inFile.open(stdin, QIODevice::ReadOnly); 0043 highlighter.highlightData(&inFile, highlightParams...); 0044 } 0045 } 0046 0047 static Theme theme(const Repository &repo, const QString &themeName, Repository::DefaultTheme t) 0048 { 0049 if (themeName.isEmpty()) { 0050 return repo.defaultTheme(t); 0051 } 0052 return repo.theme(themeName); 0053 } 0054 0055 int main(int argc, char **argv) 0056 { 0057 QCoreApplication app(argc, argv); 0058 QCoreApplication::setApplicationName(QStringLiteral("ksyntaxhighlighter")); 0059 QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org")); 0060 QCoreApplication::setOrganizationName(QStringLiteral("KDE")); 0061 QCoreApplication::setApplicationVersion(QStringLiteral(KSYNTAXHIGHLIGHTING_VERSION_STRING)); 0062 0063 QCommandLineParser parser; 0064 parser.setApplicationDescription(app.translate("SyntaxHighlightingCLI", "Command line syntax highlighter using KSyntaxHighlighting syntax definitions.")); 0065 parser.addHelpOption(); 0066 parser.addVersionOption(); 0067 parser.addPositionalArgument( 0068 app.translate("SyntaxHighlightingCLI", "source"), 0069 app.translate("SyntaxHighlightingCLI", "The source file to highlight. If absent, read the file from stdin and the --syntax option must be used.")); 0070 0071 QCommandLineOption listDefs(QStringList() << QStringLiteral("l") << QStringLiteral("list"), 0072 app.translate("SyntaxHighlightingCLI", "List all available syntax definitions.")); 0073 parser.addOption(listDefs); 0074 QCommandLineOption listThemes(QStringList() << QStringLiteral("list-themes"), app.translate("SyntaxHighlightingCLI", "List all available themes.")); 0075 parser.addOption(listThemes); 0076 0077 QCommandLineOption updateDefs(QStringList() << QStringLiteral("u") << QStringLiteral("update"), 0078 app.translate("SyntaxHighlightingCLI", "Download new/updated syntax definitions.")); 0079 parser.addOption(updateDefs); 0080 0081 QCommandLineOption outputName(QStringList() << QStringLiteral("o") << QStringLiteral("output"), 0082 app.translate("SyntaxHighlightingCLI", "File to write HTML output to (default: stdout)."), 0083 app.translate("SyntaxHighlightingCLI", "output")); 0084 parser.addOption(outputName); 0085 0086 QCommandLineOption syntaxName(QStringList() << QStringLiteral("s") << QStringLiteral("syntax"), 0087 app.translate("SyntaxHighlightingCLI", "Highlight using this syntax definition (default: auto-detect based on input file)."), 0088 app.translate("SyntaxHighlightingCLI", "syntax")); 0089 parser.addOption(syntaxName); 0090 0091 QCommandLineOption themeName(QStringList() << QStringLiteral("t") << QStringLiteral("theme"), 0092 app.translate("SyntaxHighlightingCLI", "Color theme to use for highlighting."), 0093 app.translate("SyntaxHighlightingCLI", "theme")); 0094 parser.addOption(themeName); 0095 0096 QCommandLineOption outputFormatOption( 0097 QStringList() << QStringLiteral("f") << QStringLiteral("output-format"), 0098 app.translate("SyntaxHighlightingCLI", "Use the specified format instead of html. Must be html, ansi or ansi256Colors."), 0099 app.translate("SyntaxHighlightingCLI", "format"), 0100 QStringLiteral("html")); 0101 parser.addOption(outputFormatOption); 0102 0103 QCommandLineOption traceOption(QStringList() << QStringLiteral("syntax-trace"), 0104 app.translate("SyntaxHighlightingCLI", 0105 "Add information to debug a syntax file. Only works with --output-format=ansi or ansi256Colors. Possible " 0106 "values are format, region, context, stackSize and all."), 0107 app.translate("SyntaxHighlightingCLI", "type")); 0108 parser.addOption(traceOption); 0109 0110 QCommandLineOption noAnsiEditorBg(QStringList() << QStringLiteral("b") << QStringLiteral("no-ansi-background"), 0111 app.translate("SyntaxHighlightingCLI", "Disable ANSI background for the default color.")); 0112 parser.addOption(noAnsiEditorBg); 0113 0114 QCommandLineOption unbufferedAnsi(QStringList() << QStringLiteral("U") << QStringLiteral("unbuffered"), 0115 app.translate("SyntaxHighlightingCLI", "For ansi and ansi256Colors formats, flush the output buffer on each line.")); 0116 parser.addOption(unbufferedAnsi); 0117 0118 QCommandLineOption titleOption( 0119 QStringList() << QStringLiteral("T") << QStringLiteral("title"), 0120 app.translate("SyntaxHighlightingCLI", "Set HTML page's title\n(default: the filename or \"KSyntaxHighlighter\" if reading from stdin)."), 0121 app.translate("SyntaxHighlightingCLI", "title")); 0122 parser.addOption(titleOption); 0123 0124 parser.process(app); 0125 0126 Repository repo; 0127 0128 if (parser.isSet(listDefs)) { 0129 for (const auto &def : repo.definitions()) { 0130 std::cout << qPrintable(def.name()) << std::endl; 0131 } 0132 return 0; 0133 } 0134 0135 if (parser.isSet(listThemes)) { 0136 for (const auto &theme : repo.themes()) { 0137 std::cout << qPrintable(theme.name()) << std::endl; 0138 } 0139 return 0; 0140 } 0141 0142 if (parser.isSet(updateDefs)) { 0143 DefinitionDownloader downloader(&repo); 0144 QObject::connect(&downloader, &DefinitionDownloader::informationMessage, [](const QString &msg) { 0145 std::cout << qPrintable(msg) << std::endl; 0146 }); 0147 QObject::connect(&downloader, &DefinitionDownloader::done, &app, &QCoreApplication::quit); 0148 downloader.start(); 0149 return app.exec(); 0150 } 0151 0152 bool fromFileName = false; 0153 QString inFileName; 0154 if (parser.positionalArguments().size() == 1) { 0155 fromFileName = true; 0156 inFileName = parser.positionalArguments().at(0); 0157 } 0158 0159 Definition def; 0160 if (parser.isSet(syntaxName)) { 0161 const QString syntax = parser.value(syntaxName); 0162 def = repo.definitionForName(syntax); 0163 if (!def.isValid()) { 0164 /* see if it's a mimetype instead */ 0165 def = repo.definitionForMimeType(syntax); 0166 if (!def.isValid()) { 0167 /* see if it's a extension instead */ 0168 def = repo.definitionForFileName(QLatin1String("f.") + syntax); 0169 if (!def.isValid()) { 0170 /* see if it's a filename instead */ 0171 def = repo.definitionForFileName(syntax); 0172 } 0173 } 0174 } 0175 } else if (fromFileName) { 0176 def = repo.definitionForFileName(inFileName); 0177 } else { 0178 parser.showHelp(1); 0179 } 0180 0181 if (!def.isValid()) { 0182 std::cerr << "Unknown syntax." << std::endl; 0183 return 1; 0184 } 0185 0186 const QString outputFormat = parser.value(outputFormatOption); 0187 if (0 == outputFormat.compare(QLatin1String("html"), Qt::CaseInsensitive)) { 0188 QString title; 0189 if (parser.isSet(titleOption)) { 0190 title = parser.value(titleOption); 0191 } 0192 0193 HtmlHighlighter highlighter; 0194 highlighter.setDefinition(def); 0195 highlighter.setTheme(theme(repo, parser.value(themeName), Repository::LightTheme)); 0196 applyHighlighter(highlighter, parser, fromFileName, inFileName, outputName, title); 0197 } else { 0198 auto AnsiFormat = AnsiHighlighter::AnsiFormat::TrueColor; 0199 if (0 == outputFormat.compare(QLatin1String("ansi256Colors"), Qt::CaseInsensitive)) { 0200 AnsiFormat = AnsiHighlighter::AnsiFormat::XTerm256Color; 0201 } else if (0 != outputFormat.compare(QLatin1String("ansi"), Qt::CaseInsensitive)) { 0202 std::cerr << "Unknown output format." << std::endl; 0203 return 2; 0204 } 0205 0206 AnsiHighlighter::Options options{}; 0207 options |= parser.isSet(noAnsiEditorBg) ? AnsiHighlighter::Option::NoOptions : AnsiHighlighter::Option::UseEditorBackground; 0208 options |= parser.isSet(unbufferedAnsi) ? AnsiHighlighter::Option::Unbuffered : AnsiHighlighter::Option::NoOptions; 0209 if (parser.isSet(traceOption)) { 0210 const auto traceOptions = parser.values(traceOption); 0211 for (auto const &option : traceOptions) { 0212 if (option == QStringLiteral("format")) { 0213 options |= AnsiHighlighter::Option::TraceFormat; 0214 } else if (option == QStringLiteral("region")) { 0215 options |= AnsiHighlighter::Option::TraceRegion; 0216 } else if (option == QStringLiteral("context")) { 0217 options |= AnsiHighlighter::Option::TraceContext; 0218 } else if (option == QStringLiteral("stackSize")) { 0219 options |= AnsiHighlighter::Option::TraceStackSize; 0220 } else if (option == QStringLiteral("all")) { 0221 options |= AnsiHighlighter::Option::TraceAll; 0222 } else { 0223 std::cerr << "Unknown trace name." << std::endl; 0224 return 2; 0225 } 0226 } 0227 } 0228 0229 AnsiHighlighter highlighter; 0230 highlighter.setDefinition(def); 0231 highlighter.setTheme(theme(repo, parser.value(themeName), Repository::DarkTheme)); 0232 applyHighlighter(highlighter, parser, fromFileName, inFileName, outputName, AnsiFormat, options); 0233 } 0234 0235 return 0; 0236 }