KSyntaxHighlighting

kate-syntax-highlighter.cpp
1 /*
2  SPDX-FileCopyrightText: 2016 Volker Krause <[email protected]>
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 
22 using namespace KSyntaxHighlighting;
23 
24 template<class Highlighter, class... Ts>
25 static void applyHighlighter(Highlighter &highlighter,
26  QCommandLineParser &parser,
27  bool fromFileName,
28  const QString &inFileName,
29  const QCommandLineOption &stdinOption,
30  const QCommandLineOption &outputName,
31  const Ts &...highlightParams)
32 {
33  if (parser.isSet(outputName)) {
34  highlighter.setOutputFile(parser.value(outputName));
35  } else {
36  highlighter.setOutputFile(stdout);
37  }
38 
39  if (fromFileName) {
40  highlighter.highlightFile(inFileName, highlightParams...);
41  } else if (parser.isSet(stdinOption)) {
42  QFile inFile;
43  inFile.open(stdin, QIODevice::ReadOnly);
44  highlighter.highlightData(&inFile, highlightParams...);
45  } else {
46  parser.showHelp(1);
47  }
48 }
49 
50 int main(int argc, char **argv)
51 {
52  QCoreApplication app(argc, argv);
53  QCoreApplication::setApplicationName(QStringLiteral("kate-syntax-highlighter"));
54  QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org"));
55  QCoreApplication::setOrganizationName(QStringLiteral("KDE"));
56  QCoreApplication::setApplicationVersion(QStringLiteral(SyntaxHighlighting_VERSION_STRING));
57 
58  Repository repo;
59 
60  QCommandLineParser parser;
61  parser.setApplicationDescription(app.translate("SyntaxHighlightingCLI", "Command line syntax highlighter using Kate syntax definitions."));
62  parser.addHelpOption();
63  parser.addVersionOption();
64  parser.addPositionalArgument(app.translate("SyntaxHighlightingCLI", "source"), app.translate("SyntaxHighlightingCLI", "The source file to highlight."));
65 
66  QCommandLineOption listDefs(QStringList() << QStringLiteral("l") << QStringLiteral("list"),
67  app.translate("SyntaxHighlightingCLI", "List all available syntax definitions."));
68  parser.addOption(listDefs);
69  QCommandLineOption listThemes(QStringList() << QStringLiteral("list-themes"), app.translate("SyntaxHighlightingCLI", "List all available themes."));
70  parser.addOption(listThemes);
71 
72  QCommandLineOption updateDefs(QStringList() << QStringLiteral("u") << QStringLiteral("update"),
73  app.translate("SyntaxHighlightingCLI", "Download new/updated syntax definitions."));
74  parser.addOption(updateDefs);
75 
76  QCommandLineOption outputName(QStringList() << QStringLiteral("o") << QStringLiteral("output"),
77  app.translate("SyntaxHighlightingCLI", "File to write HTML output to (default: stdout)."),
78  app.translate("SyntaxHighlightingCLI", "output"));
79  parser.addOption(outputName);
80 
81  QCommandLineOption syntaxName(QStringList() << QStringLiteral("s") << QStringLiteral("syntax"),
82  app.translate("SyntaxHighlightingCLI", "Highlight using this syntax definition (default: auto-detect based on input file)."),
83  app.translate("SyntaxHighlightingCLI", "syntax"));
84  parser.addOption(syntaxName);
85 
86  QCommandLineOption themeName(QStringList() << QStringLiteral("t") << QStringLiteral("theme"),
87  app.translate("SyntaxHighlightingCLI", "Color theme to use for highlighting."),
88  app.translate("SyntaxHighlightingCLI", "theme"),
90  parser.addOption(themeName);
91 
92  QCommandLineOption outputFormatOption(
93  QStringList() << QStringLiteral("f") << QStringLiteral("output-format"),
94  app.translate("SyntaxHighlightingCLI", "Use the specified format instead of html. Must be html, ansi or ansi256Colors."),
95  app.translate("SyntaxHighlightingCLI", "format"),
96  QStringLiteral("html"));
97  parser.addOption(outputFormatOption);
98 
99  QCommandLineOption traceOption(QStringList() << QStringLiteral("syntax-trace"),
100  app.translate("SyntaxHighlightingCLI",
101  "Add information to debug a syntax file. Only works with --output-format=ansi or ansi256Colors. Possible "
102  "values are format, region, context and stackSize."),
103  app.translate("SyntaxHighlightingCLI", "type"));
104  parser.addOption(traceOption);
105 
106  QCommandLineOption noAnsiEditorBg(QStringList() << QStringLiteral("b") << QStringLiteral("no-ansi-background"),
107  app.translate("SyntaxHighlightingCLI", "Disable ANSI background for the default color."));
108  parser.addOption(noAnsiEditorBg);
109 
110  QCommandLineOption titleOption(
111  QStringList() << QStringLiteral("T") << QStringLiteral("title"),
112  app.translate("SyntaxHighlightingCLI", "Set HTML page's title\n(default: the filename or \"Kate Syntax Highlighter\" if reading from stdin)."),
113  app.translate("SyntaxHighlightingCLI", "title"));
114  parser.addOption(titleOption);
115 
116  QCommandLineOption stdinOption(QStringList() << QStringLiteral("stdin"),
117  app.translate("SyntaxHighlightingCLI", "Read file from stdin. The -s option must also be used."));
118  parser.addOption(stdinOption);
119 
120  parser.process(app);
121 
122  if (parser.isSet(listDefs)) {
123  for (const auto &def : repo.definitions()) {
124  std::cout << qPrintable(def.name()) << std::endl;
125  }
126  return 0;
127  }
128 
129  if (parser.isSet(listThemes)) {
130  for (const auto &theme : repo.themes()) {
131  std::cout << qPrintable(theme.name()) << std::endl;
132  }
133  return 0;
134  }
135 
136  if (parser.isSet(updateDefs)) {
137  DefinitionDownloader downloader(&repo);
139  std::cout << qPrintable(msg) << std::endl;
140  });
142  downloader.start();
143  return app.exec();
144  }
145 
146  bool fromFileName = false;
147  QString inFileName;
148  if (parser.positionalArguments().size() == 1) {
149  fromFileName = true;
150  inFileName = parser.positionalArguments().at(0);
151  }
152 
153  Definition def;
154  if (parser.isSet(syntaxName)) {
155  const QString syntax = parser.value(syntaxName);
156  def = repo.definitionForName(syntax);
157  if (!def.isValid()) {
158  /* see if it's a mimetype instead */
159  def = repo.definitionForMimeType(syntax);
160  if (!def.isValid()) {
161  /* see if it's a extension instead */
162  def = repo.definitionForFileName(QLatin1String("f.") + syntax);
163  if (!def.isValid()) {
164  /* see if it's a filename instead */
165  def = repo.definitionForFileName(syntax);
166  }
167  }
168  }
169  } else if (fromFileName) {
170  def = repo.definitionForFileName(inFileName);
171  } else {
172  parser.showHelp(1);
173  }
174 
175  if (!def.isValid()) {
176  std::cerr << "Unknown syntax." << std::endl;
177  return 1;
178  }
179 
180  QString outputFormat = parser.value(outputFormatOption);
181  if (0 == outputFormat.compare(QLatin1String("html"), Qt::CaseInsensitive)) {
182  QString title;
183  if (parser.isSet(titleOption)) {
184  title = parser.value(titleOption);
185  }
186 
187  HtmlHighlighter highlighter;
188  highlighter.setDefinition(def);
189  highlighter.setTheme(repo.theme(parser.value(themeName)));
190  applyHighlighter(highlighter, parser, fromFileName, inFileName, stdinOption, outputName, title);
191  } else {
192  auto AnsiFormat = AnsiHighlighter::AnsiFormat::TrueColor;
193  if (0 == outputFormat.compare(QLatin1String("ansi256Colors"), Qt::CaseInsensitive)) {
194  AnsiFormat = AnsiHighlighter::AnsiFormat::XTerm256Color;
195  } else if (0 != outputFormat.compare(QLatin1String("ansi"), Qt::CaseInsensitive)) {
196  std::cerr << "Unknown output format." << std::endl;
197  return 2;
198  }
199 
200  auto debugOptions = AnsiHighlighter::TraceOptions();
201  if (parser.isSet(traceOption)) {
202  const auto options = parser.values(traceOption);
203  for (auto const &option : options) {
204  if (option == QStringLiteral("format")) {
205  debugOptions |= AnsiHighlighter::TraceOption::Format;
206  } else if (option == QStringLiteral("region")) {
207  debugOptions |= AnsiHighlighter::TraceOption::Region;
208  } else if (option == QStringLiteral("context")) {
209  debugOptions |= AnsiHighlighter::TraceOption::Context;
210  } else if (option == QStringLiteral("stackSize")) {
211  debugOptions |= AnsiHighlighter::TraceOption::StackSize;
212  } else {
213  std::cerr << "Unknown trace name." << std::endl;
214  return 2;
215  }
216  }
217  }
218 
219  AnsiHighlighter highlighter;
220  highlighter.setDefinition(def);
221  highlighter.setTheme(repo.theme(parser.value(themeName)));
222  applyHighlighter(highlighter, parser, fromFileName, inFileName, stdinOption, outputName, AnsiFormat, !parser.isSet(noAnsiEditorBg), debugOptions);
223  }
224 
225  return 0;
226 }
Definition definitionForMimeType(const QString &mimeType) const
Returns the best matching Definition to the type named mimeType.
Definition: repository.cpp:135
CaseInsensitive
Helper class to download definition file updates.
void setApplicationDescription(const QString &description)
virtual bool open(QIODevice::OpenMode mode) override
bool isValid() const
Checks whether this object refers to a valid syntax definition.
Definition: definition.cpp:78
QVector< Theme > themes() const
Returns all available color themes.
Definition: repository.cpp:150
@ LightTheme
Theme with a light background color.
Definition: repository.h:216
Theme defaultTheme(DefaultTheme t=LightTheme) const
Returns a default theme instance of the given type.
Definition: repository.cpp:172
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax)
void setApplicationVersion(const QString &version)
QStringList positionalArguments() const const
Theme theme(const QString &themeName) const
Returns the theme called themeName.
Definition: repository.cpp:162
Definition definitionForName(const QString &defName) const
Returns the Definition named defName.
Definition: repository.cpp:120
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setOrganizationDomain(const QString &orgDomain)
QVector< Definition > definitions() const
Returns all available Definitions.
Definition: repository.cpp:145
void showHelp(int exitCode)
int size() const const
Syntax highlighting repository.
Definition: repository.h:127
void process(const QStringList &arguments)
QCommandLineOption addVersionOption()
const T & at(int i) const const
QString value(const QString &optionName) const const
QStringList values(const QString &optionName) const const
void setApplicationName(const QString &application)
bool isSet(const QString &name) const const
void informationMessage(const QString &msg)
Prints the information about the current state of the definition files.
Definition definitionForFileName(const QString &fileName) const
Returns the best matching Definition for the file named fileName.
Definition: repository.cpp:125
void setOrganizationName(const QString &orgName)
int compare(const QString &other, Qt::CaseSensitivity cs) const const
bool addOption(const QCommandLineOption &option)
QCommandLineOption addHelpOption()
Represents a syntax definition.
Definition: definition.h:86
void done()
This signal is emitted when there are no pending downloads anymore.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Mar 26 2023 04:09:17 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.