KSyntaxHighlighting

ksyntaxhighlighter.cpp
1/*
2 SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: MIT
5*/
6
7#include "ksyntaxhighlighting_version.h"
8
9#include <KSyntaxHighlighting/Definition>
10#include <KSyntaxHighlighting/DefinitionDownloader>
11#include <KSyntaxHighlighting/Repository>
12#include <KSyntaxHighlighting/Theme>
13#include <ansihighlighter.h>
14#include <htmlhighlighter.h>
15
16#include <QCommandLineParser>
17#include <QCoreApplication>
18#include <QFile>
19
20#include <iostream>
21
22using namespace KSyntaxHighlighting;
23
24template<class Highlighter, class... Ts>
25static void applyHighlighter(Highlighter &highlighter,
26 QCommandLineParser &parser,
27 bool fromFileName,
28 const QString &inFileName,
29 const QCommandLineOption &outputName,
30 const Ts &...highlightParams)
31{
32 if (parser.isSet(outputName)) {
33 highlighter.setOutputFile(parser.value(outputName));
34 } else {
35 highlighter.setOutputFile(stdout);
36 }
37
38 if (fromFileName) {
39 highlighter.highlightFile(inFileName, highlightParams...);
40 } else {
41 QFile inFile;
42 inFile.open(stdin, QIODevice::ReadOnly);
43 highlighter.highlightData(&inFile, highlightParams...);
44 }
45}
46
47static Theme theme(const Repository &repo, const QString &themeName, Repository::DefaultTheme t)
48{
49 if (themeName.isEmpty()) {
50 return repo.defaultTheme(t);
51 }
52 return repo.theme(themeName);
53}
54
55int main(int argc, char **argv)
56{
57 QCoreApplication app(argc, argv);
58 QCoreApplication::setApplicationName(QStringLiteral("ksyntaxhighlighter"));
59 QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org"));
60 QCoreApplication::setOrganizationName(QStringLiteral("KDE"));
61 QCoreApplication::setApplicationVersion(QStringLiteral(KSYNTAXHIGHLIGHTING_VERSION_STRING));
62
63 QCommandLineParser parser;
64 parser.setApplicationDescription(app.translate("SyntaxHighlightingCLI", "Command line syntax highlighter using KSyntaxHighlighting syntax definitions."));
65 parser.addHelpOption();
66 parser.addVersionOption();
68 app.translate("SyntaxHighlightingCLI", "source"),
69 app.translate("SyntaxHighlightingCLI", "The source file to highlight. If absent, read the file from stdin and the --syntax option must be used."));
70
71 QCommandLineOption listDefs(QStringList() << QStringLiteral("l") << QStringLiteral("list"),
72 app.translate("SyntaxHighlightingCLI", "List all available syntax definitions."));
73 parser.addOption(listDefs);
74 QCommandLineOption listThemes(QStringList() << QStringLiteral("list-themes"), app.translate("SyntaxHighlightingCLI", "List all available themes."));
75 parser.addOption(listThemes);
76
77 QCommandLineOption updateDefs(QStringList() << QStringLiteral("u") << QStringLiteral("update"),
78 app.translate("SyntaxHighlightingCLI", "Download new/updated syntax definitions."));
79 parser.addOption(updateDefs);
80
81 QCommandLineOption outputName(QStringList() << QStringLiteral("o") << QStringLiteral("output"),
82 app.translate("SyntaxHighlightingCLI", "File to write HTML output to (default: stdout)."),
83 app.translate("SyntaxHighlightingCLI", "output"));
84 parser.addOption(outputName);
85
86 QCommandLineOption syntaxName(QStringList() << QStringLiteral("s") << QStringLiteral("syntax"),
87 app.translate("SyntaxHighlightingCLI", "Highlight using this syntax definition (default: auto-detect based on input file)."),
88 app.translate("SyntaxHighlightingCLI", "syntax"));
89 parser.addOption(syntaxName);
90
91 QCommandLineOption themeName(QStringList() << QStringLiteral("t") << QStringLiteral("theme"),
92 app.translate("SyntaxHighlightingCLI", "Color theme to use for highlighting."),
93 app.translate("SyntaxHighlightingCLI", "theme"));
94 parser.addOption(themeName);
95
96 QCommandLineOption outputFormatOption(
97 QStringList() << QStringLiteral("f") << QStringLiteral("output-format"),
98 app.translate("SyntaxHighlightingCLI", "Use the specified format instead of html. Must be html, ansi or ansi256Colors."),
99 app.translate("SyntaxHighlightingCLI", "format"),
100 QStringLiteral("html"));
101 parser.addOption(outputFormatOption);
102
103 QCommandLineOption traceOption(QStringList() << QStringLiteral("syntax-trace"),
104 app.translate("SyntaxHighlightingCLI",
105 "Add information to debug a syntax file. Only works with --output-format=ansi or ansi256Colors. Possible "
106 "values are format, region, context, stackSize and all."),
107 app.translate("SyntaxHighlightingCLI", "type"));
108 parser.addOption(traceOption);
109
110 QCommandLineOption noAnsiEditorBg(QStringList() << QStringLiteral("b") << QStringLiteral("no-ansi-background"),
111 app.translate("SyntaxHighlightingCLI", "Disable ANSI background for the default color."));
112 parser.addOption(noAnsiEditorBg);
113
114 QCommandLineOption unbufferedAnsi(QStringList() << QStringLiteral("U") << QStringLiteral("unbuffered"),
115 app.translate("SyntaxHighlightingCLI", "For ansi and ansi256Colors formats, flush the output buffer on each line."));
116 parser.addOption(unbufferedAnsi);
117
118 QCommandLineOption titleOption(
119 QStringList() << QStringLiteral("T") << QStringLiteral("title"),
120 app.translate("SyntaxHighlightingCLI", "Set HTML page's title\n(default: the filename or \"KSyntaxHighlighter\" if reading from stdin)."),
121 app.translate("SyntaxHighlightingCLI", "title"));
122 parser.addOption(titleOption);
123
124 parser.process(app);
125
126 Repository repo;
127
128 if (parser.isSet(listDefs)) {
129 for (const auto &def : repo.definitions()) {
130 std::cout << qPrintable(def.name()) << std::endl;
131 }
132 return 0;
133 }
134
135 if (parser.isSet(listThemes)) {
136 for (const auto &theme : repo.themes()) {
137 std::cout << qPrintable(theme.name()) << std::endl;
138 }
139 return 0;
140 }
141
142 if (parser.isSet(updateDefs)) {
143 DefinitionDownloader downloader(&repo);
145 std::cout << qPrintable(msg) << std::endl;
146 });
148 downloader.start();
149 return app.exec();
150 }
151
152 bool fromFileName = false;
153 QString inFileName;
154 if (parser.positionalArguments().size() == 1) {
155 fromFileName = true;
156 inFileName = parser.positionalArguments().at(0);
157 }
158
159 Definition def;
160 if (parser.isSet(syntaxName)) {
161 const QString syntax = parser.value(syntaxName);
162 def = repo.definitionForName(syntax);
163 if (!def.isValid()) {
164 /* see if it's a mimetype instead */
165 def = repo.definitionForMimeType(syntax);
166 if (!def.isValid()) {
167 /* see if it's a extension instead */
168 def = repo.definitionForFileName(QLatin1String("f.") + syntax);
169 if (!def.isValid()) {
170 /* see if it's a filename instead */
171 def = repo.definitionForFileName(syntax);
172 }
173 }
174 }
175 } else if (fromFileName) {
176 def = repo.definitionForFileName(inFileName);
177 } else {
178 parser.showHelp(1);
179 }
180
181 if (!def.isValid()) {
182 std::cerr << "Unknown syntax." << std::endl;
183 return 1;
184 }
185
186 const QString outputFormat = parser.value(outputFormatOption);
187 if (0 == outputFormat.compare(QLatin1String("html"), Qt::CaseInsensitive)) {
188 QString title;
189 if (parser.isSet(titleOption)) {
190 title = parser.value(titleOption);
191 }
192
193 HtmlHighlighter highlighter;
194 highlighter.setDefinition(def);
195 highlighter.setTheme(theme(repo, parser.value(themeName), Repository::LightTheme));
196 applyHighlighter(highlighter, parser, fromFileName, inFileName, outputName, title);
197 } else {
198 auto AnsiFormat = AnsiHighlighter::AnsiFormat::TrueColor;
199 if (0 == outputFormat.compare(QLatin1String("ansi256Colors"), Qt::CaseInsensitive)) {
200 AnsiFormat = AnsiHighlighter::AnsiFormat::XTerm256Color;
201 } else if (0 != outputFormat.compare(QLatin1String("ansi"), Qt::CaseInsensitive)) {
202 std::cerr << "Unknown output format." << std::endl;
203 return 2;
204 }
205
206 AnsiHighlighter::Options options{};
207 options |= parser.isSet(noAnsiEditorBg) ? AnsiHighlighter::Option::NoOptions : AnsiHighlighter::Option::UseEditorBackground;
208 options |= parser.isSet(unbufferedAnsi) ? AnsiHighlighter::Option::Unbuffered : AnsiHighlighter::Option::NoOptions;
209 if (parser.isSet(traceOption)) {
210 const auto traceOptions = parser.values(traceOption);
211 for (auto const &option : traceOptions) {
212 if (option == QStringLiteral("format")) {
213 options |= AnsiHighlighter::Option::TraceFormat;
214 } else if (option == QStringLiteral("region")) {
215 options |= AnsiHighlighter::Option::TraceRegion;
216 } else if (option == QStringLiteral("context")) {
217 options |= AnsiHighlighter::Option::TraceContext;
218 } else if (option == QStringLiteral("stackSize")) {
219 options |= AnsiHighlighter::Option::TraceStackSize;
220 } else if (option == QStringLiteral("all")) {
221 options |= AnsiHighlighter::Option::TraceAll;
222 } else {
223 std::cerr << "Unknown trace name." << std::endl;
224 return 2;
225 }
226 }
227 }
228
229 AnsiHighlighter highlighter;
230 highlighter.setDefinition(def);
231 highlighter.setTheme(theme(repo, parser.value(themeName), Repository::DarkTheme));
232 applyHighlighter(highlighter, parser, fromFileName, inFileName, outputName, AnsiFormat, options);
233 }
234
235 return 0;
236}
virtual void setDefinition(const Definition &def)
Sets the syntax definition used for highlighting.
virtual void setTheme(const Theme &theme)
Sets the theme used for highlighting.
Helper class to download definition file updates.
void done()
This signal is emitted when there are no pending downloads anymore.
void informationMessage(const QString &msg)
Prints the information about the current state of the definition files.
Represents a syntax definition.
Definition definition.h:83
bool isValid() const
Checks whether this object refers to a valid syntax definition.
DefaultTheme
Built-in default theme types.
Definition repository.h:213
Color theme definition used for highlighting.
Definition theme.h:65
Syntax highlighting engine for Kate syntax definitions.
QCommandLineOption addHelpOption()
bool addOption(const QCommandLineOption &option)
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax)
QCommandLineOption addVersionOption()
bool isSet(const QCommandLineOption &option) const const
QStringList positionalArguments() const const
void process(const QCoreApplication &app)
void setApplicationDescription(const QString &description)
void showHelp(int exitCode)
QString value(const QCommandLineOption &option) const const
QStringList values(const QCommandLineOption &option) const const
void setApplicationName(const QString &application)
void setApplicationVersion(const QString &version)
void setOrganizationDomain(const QString &orgDomain)
void setOrganizationName(const QString &orgName)
bool open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
const_reference at(qsizetype i) const const
qsizetype size() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
int compare(QLatin1StringView s1, const QString &s2, Qt::CaseSensitivity cs)
bool isEmpty() const const
CaseInsensitive
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 3 2024 11:50:18 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.