Add support for opening .pory scripts to the selected event script

This commit is contained in:
BigBahss 2020-11-26 06:09:58 -05:00
parent 4aaae1a264
commit a4528fb0d9
3 changed files with 74 additions and 24 deletions

View file

@ -41,7 +41,7 @@ public:
ParseUtil();
void set_root(QString);
static QString readTextFile(QString);
static void strip_comment(QString*);
void strip_comment(QString*);
QList<QStringList>* parseAsm(QString);
int evaluateDefine(QString, QMap<QString, int>*);
QStringList readCArray(QString text, QString label);
@ -56,7 +56,12 @@ public:
// Returns the 1-indexed line number for the definition of scriptLabel in the scripts file at filePath.
// Returns 0 if a definition for scriptLabel cannot be found.
static int getScriptLineNumber(const QString &scriptLabel, const QString &filePath);
static int getScriptLineNumber(const QString &filePath, const QString &scriptLabel);
static int getRawScriptLineNumber(QString text, const QString &scriptLabel);
static int getPoryScriptLineNumber(QString text, const QString &scriptLabel);
static QString &removeStringLiterals(QString &text);
static QString &removeLineComments(QString &text, const QString &commentSymbol);
static QString &removeLineComments(QString &text, const QStringList &commentSymbols);
private:
QString root;

View file

@ -421,21 +421,66 @@ bool ParseUtil::ensureFieldsExist(QJsonObject obj, QList<QString> fields) {
return true;
}
int ParseUtil::getScriptLineNumber(const QString &scriptLabel, const QString &filePath) {
if (filePath.endsWith(".inc")) {
const QString text = readTextFile(filePath);
const QStringList lines = text.split('\n');
for (int lineNumber = 0; lineNumber < lines.count(); ++lineNumber) {
QString line = lines.at(lineNumber);
strip_comment(&line);
if (line.contains(':')) {
const QString parsedLabel = line.left(line.indexOf(':')).trimmed();
if (parsedLabel == scriptLabel)
return lineNumber + 1;
}
}
} else if (filePath.endsWith(".pory")) {
int ParseUtil::getScriptLineNumber(const QString &filePath, const QString &scriptLabel) {
if (filePath.endsWith(".inc"))
return getRawScriptLineNumber(readTextFile(filePath), scriptLabel);
else if (filePath.endsWith(".pory"))
return getPoryScriptLineNumber(readTextFile(filePath), scriptLabel);
}
return 0;
}
int ParseUtil::getRawScriptLineNumber(QString text, const QString &scriptLabel) {
removeStringLiterals(text);
removeLineComments(text, "@");
static const QRegularExpression re_incScriptLabel("(?<label>[a-zA-Z_]+[a-zA-Z0-9_]*):");
QRegularExpressionMatchIterator it = re_incScriptLabel.globalMatch(text);
while (it.hasNext()) {
const QRegularExpressionMatch match = it.next();
if (match.captured("label") == scriptLabel)
return text.left(match.capturedStart("label")).count('\n') + 1;
}
return 0;
}
int ParseUtil::getPoryScriptLineNumber(QString text, const QString &scriptLabel) {
removeStringLiterals(text);
removeLineComments(text, {"//", "#"});
static const QRegularExpression re_poryScriptLabel("\\b(script)\\b[\\s]+(?<label>[a-zA-Z_]+[a-zA-Z0-9_]*)");
QRegularExpressionMatchIterator it = re_poryScriptLabel.globalMatch(text);
while (it.hasNext()) {
const QRegularExpressionMatch match = it.next();
if (match.captured("label") == scriptLabel)
return text.left(match.capturedStart("label")).count('\n') + 1;
}
static const QRegularExpression re_poryRawSection("\\b(raw)\\b[\\s]*`(?<script>[^`]*)");
QRegularExpressionMatchIterator raw_it = re_poryRawSection.globalMatch(text);
while (raw_it.hasNext()) {
const QRegularExpressionMatch match = raw_it.next();
const int relative_lineNum = getRawScriptLineNumber(match.captured("script"), scriptLabel);
if (relative_lineNum)
return text.left(match.capturedStart("script")).count('\n') + relative_lineNum;
}
return 0;
}
QString &ParseUtil::removeStringLiterals(QString &text) {
static const QRegularExpression re_string("\".*\"");
return text.remove(re_string);
}
QString &ParseUtil::removeLineComments(QString &text, const QString &commentSymbol) {
const QRegularExpression re_lineComment(commentSymbol + "+.*");
return text.remove(re_lineComment);
}
QString &ParseUtil::removeLineComments(QString &text, const QStringList &commentSymbols) {
for (const auto &commentSymbol : commentSymbols)
removeLineComments(text, commentSymbol);
return text;
}

View file

@ -2001,13 +2001,13 @@ void Editor::deleteEvent(Event *event) {
}
void Editor::openMapScripts() const {
const QString path = project->getMapScriptsFilePath(map->name);
const QString scriptsPath = project->getMapScriptsFilePath(map->name);
const QString commandTemplate = porymapConfig.getTextEditorCommandTemplate();
if (commandTemplate.isEmpty()) {
// Open map scripts in the system's default editor.
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
QDesktopServices::openUrl(QUrl::fromLocalFile(scriptsPath));
} else {
const QString command = constructTextEditorCommand(commandTemplate, path);
const QString command = constructTextEditorCommand(commandTemplate, scriptsPath);
#ifdef Q_OS_WIN
// On Windows, a QProcess command must be wrapped in a cmd.exe command.
const QString program = QProcessEnvironment::systemEnvironment().value("COMSPEC");
@ -2023,17 +2023,17 @@ void Editor::openMapScripts() const {
}
}
QString Editor::constructTextEditorCommand(QString commandTemplate, const QString &path) const {
QString Editor::constructTextEditorCommand(QString commandTemplate, const QString &filePath) const {
if (commandTemplate.contains("%F")) {
if (commandTemplate.contains("%L")) {
const QString scriptLabel = selected_events->isEmpty() ?
QString() : selected_events->first()->event->get("script_label");
const int lineNum = ParseUtil::getScriptLineNumber(scriptLabel, path);
const int lineNum = ParseUtil::getScriptLineNumber(filePath, scriptLabel);
commandTemplate.replace("%L", QString::number(lineNum));
}
commandTemplate.replace("%F", path);
commandTemplate.replace("%F", filePath);
} else {
commandTemplate += path;
commandTemplate += filePath;
}
return commandTemplate;
}