diff --git a/tools/lammps-gui/highlighter.cpp b/tools/lammps-gui/highlighter.cpp index 7ed4844c69..4b415b3401 100644 --- a/tools/lammps-gui/highlighter.cpp +++ b/tools/lammps-gui/highlighter.cpp @@ -13,242 +13,221 @@ #include "highlighter.h" -Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) +Highlighter::Highlighter(QTextDocument *parent) : + QSyntaxHighlighter(parent), + isLattice1(QStringLiteral("^\\s*(units|atom_style|dielectric|dimension)\\s+(\\S+)")), + isLattice2(QStringLiteral("^\\s*(lattice|region|create_box|create_atoms|delete_atoms|displace_" + "atoms)\\s+(\\S+)\\s+(\\S+)")), + isLattice3(QStringLiteral("^\\s*(boundary|replicate)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)")), + isOutput1(QStringLiteral( + "^\\s*(log|write_data|write_coeff|write_restart|restart|info|thermo|print|thermo_style|" + "timer|pair_write|bond_write|angle_write|dihedral_write)\\s+(\\S+)")), + isOutput2(QStringLiteral("^\\s*(write_dump|shell|thermo_modify)\\s+(\\S+)\\s+(\\S+)")), + isRead(QStringLiteral("^\\s*(include|read_restart|read_data|read_dump|molecule)")), + isStyle(QStringLiteral("^\\s*(fix|compute|dump|set)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)")), + isForce(QStringLiteral("^\\s*(pair_style|bond_style|angle_style|dihedral_style|" + "improper_style|kspace_style)\\s+(\\S+)")), + isDefine(QStringLiteral("^\\s*(group|variable|python|set|group2ndx|ndx2group|kim|kim_query|mdi)" + "\\s+(\\S+)\\s+(\\S+)")), + isUndo(QStringLiteral("^\\s*(unfix|uncompute|undump|label|jump|next|loop)\\s+(\\S+)")), + isParticle(QStringLiteral("^\\s*(pair_coeff|pair_modify|mass|velocity|create_bonds|delete_" + "bonds|kspace_modify|labelmap)\\s+(\\S+)")), + isSetup( + QStringLiteral("^\\s*(min_style|min_modify|run_style|timestep|neighbor|neigh_modify|" + "suffix|special_bonds|balance|box|clear|quit|comm_modify|comm_style|newton|" + "package|processors|reset_atoms|reset_ids|reset_timestep|dump_modify|fix_" + "modify|compute_modify)")), + + isRun(QStringLiteral("^\\s*(minimize|minimize/kk|run|rerun|tad|neb|neb/spin|prd|server|temper/" + "npt|temper/grem|temper|message|hyper|dynamical_matrix|dynamical_matrix/" + "kk|third_order|third_order/kk|fitpod)")), + isVariable(QStringLiteral("\\s+(\\$[a-z]|\\${[^} ]+})")), + isReference( + QStringLiteral("\\s+(c_\\S+|C_\\S+|f_\\S+|F_\\S+|i_\\S+|i2_\\S+|d_\\S+|d2_\\S+|v_\\S+)")), + isNumber1(QStringLiteral("(^|\\s+)[0-9:*]+")), // integer and integer ranges + isNumber2(QStringLiteral("(^|\\s+)[0-9]+\\.[0-9]*[edED]?[-+]?[0-9]*")), // floating point 1 + isNumber3(QStringLiteral("(^|\\s+)[0-9]*\\.[0-9]+[edED]?[-+]?[0-9]*")), // floating point 2 + isNumber4(QStringLiteral("(^|\\s+)[0-9]+([edED][-+]?[0-9]+)?")), // floating point 3 + isSpecial( + QStringLiteral("(\\s\\+?-?INF|\\sEDGE|\\sNULL|\\sSELF|if\\s|then\\s|else\\s|elif\\s)")), + isContinue(QStringLiteral("&$")), isComment(QStringLiteral("#.*")), + isQuotedComment(QStringLiteral("(\".*#.*\"|'.*#.*')")), + isTriple(QStringLiteral("[^\"]*\"\"\"[^\"]*")), + isString(QStringLiteral("(\".+?\"|'.+?'|\"\"\".*\"\"\")")), in_triple(false) { - HighlightingRule rule; + formatNumber.setForeground(Qt::blue); + formatString.setForeground(Qt::darkGreen); + formatString.setFontWeight(QFont::Normal); + formatComment.setForeground(Qt::red); + formatSpecial.setForeground(Qt::darkMagenta); + formatSpecial.setFontWeight(QFont::Bold); + formatParticle.setForeground(Qt::darkRed); + formatParticle.setFontWeight(QFont::Bold); + formatRun.setForeground(Qt::darkBlue); + formatRun.setFontWeight(QFont::Bold); + formatVariable.setForeground(Qt::darkGray); + formatVariable.setFontWeight(QFont::Bold); - outputFormat.setForeground(Qt::darkYellow); - outputFormat.setFontWeight(QFont::Bold); - readFormat.setForeground(Qt::magenta); - readFormat.setFontWeight(QFont::Bold); - latticeFormat.setForeground(Qt::darkGreen); - latticeFormat.setFontWeight(QFont::Bold); - particleFormat.setForeground(Qt::darkRed); - particleFormat.setFontWeight(QFont::Bold); - setupFormat.setForeground(Qt::darkCyan); - setupFormat.setFontWeight(QFont::Bold); - runFormat.setForeground(Qt::darkBlue); - runFormat.setFontWeight(QFont::Bold); - defineFormat.setForeground(Qt::darkMagenta); - defineFormat.setFontWeight(QFont::Bold); - - numberFormat.setForeground(Qt::blue); - commentFormat.setForeground(Qt::red); - stringFormat.setForeground(Qt::darkGreen); - stringFormat.setFontWeight(QFont::Normal); - - const QString output_keywords[] = { - QStringLiteral("^\\s*log\\W"), QStringLiteral("^\\s*write_data\\W"), - QStringLiteral("^\\s*write_dump\\W"), QStringLiteral("^\\s*write_coeff\\W"), - QStringLiteral("^\\s*info\\W"), QStringLiteral("^\\s*shell\\W"), - QStringLiteral("^\\s*write_restart\\W"), QStringLiteral("^\\s*restart\\W"), - QStringLiteral("^\\s*dump\\W"), QStringLiteral("^\\s*undump\\W"), - QStringLiteral("^\\s*thermo\\W"), QStringLiteral("^\\s*thermo_modify\\W"), - QStringLiteral("^\\s*thermo_style\\W"), QStringLiteral("^\\s*print\\W"), - QStringLiteral("^\\s*timer\\W")}; - for (const QString &pattern : output_keywords) { - rule.pattern = QRegularExpression(pattern); - rule.format = outputFormat; - highlightingRules.append(rule); - } - - const QString read_keywords[] = { - QStringLiteral("^\\s*include\\W"), QStringLiteral("^\\s*read_restart\\W"), - QStringLiteral("^\\s*read_data\\W"), QStringLiteral("^\\s*read_dump\\W"), - QStringLiteral("^\\s*molecule\\W")}; - for (const QString &pattern : read_keywords) { - rule.pattern = QRegularExpression(pattern); - rule.format = readFormat; - highlightingRules.append(rule); - } - - const QString lattice_keywords[] = { - QStringLiteral("^\\s*boundary\\W"), QStringLiteral("^\\s*units\\W"), - QStringLiteral("^\\s*atom_style\\W"), QStringLiteral("^\\s*lattice\\W"), - QStringLiteral("^\\s*region\\W"), QStringLiteral("^\\s*create_box\\W"), - QStringLiteral("^\\s*create_atoms\\W"), QStringLiteral("^\\s*dielectric\\W"), - QStringLiteral("^\\s*delete_atoms\\W"), QStringLiteral("^\\s*displace_atoms\\W"), - QStringLiteral("^\\s*change_box\\W"), QStringLiteral("^\\s*dimension\\W"), - QStringLiteral("^\\s*replicate\\W")}; - for (const QString &pattern : lattice_keywords) { - rule.pattern = QRegularExpression(pattern); - rule.format = latticeFormat; - highlightingRules.append(rule); - } - - const QString particle_keywords[] = { - QStringLiteral("^\\s*pair_coeff\\W"), QStringLiteral("^\\s*pair_style\\W"), - QStringLiteral("^\\s*pair_modify\\W"), QStringLiteral("^\\s*pair_write\\W"), - QStringLiteral("^\\s*mass\\W"), QStringLiteral("^\\s*velocity\\W"), - QStringLiteral("^\\s*angle_coeff\\W"), QStringLiteral("^\\s*angle_style\\W"), - QStringLiteral("^\\s*angle_write\\W"), QStringLiteral("^\\s*atom_modify\\W"), - QStringLiteral("^\\s*atom_style\\W"), QStringLiteral("^\\s*bond_coeff\\W"), - QStringLiteral("^\\s*bond_style\\W"), QStringLiteral("^\\s*bond_write\\W"), - QStringLiteral("^\\s*create_bonds\\W"), QStringLiteral("^\\s*delete_bonds\\W"), - QStringLiteral("^\\s*kspace_style\\W"), QStringLiteral("^\\s*kspace_modify\\W"), - QStringLiteral("^\\s*dihedral_style\\W"), QStringLiteral("^\\s*dihedral_coeff\\W"), - QStringLiteral("^\\s*dihedral_write\\W"), QStringLiteral("^\\s*improper_style\\W"), - QStringLiteral("^\\s*improper_coeff\\W"), QStringLiteral("^\\s*labelmap\\W")}; - for (const QString &pattern : particle_keywords) { - rule.pattern = QRegularExpression(pattern); - rule.format = particleFormat; - highlightingRules.append(rule); - } - - const QString setup_keywords[] = {QStringLiteral("^\\s*min_style\\W"), - QStringLiteral("^\\s*min_modify\\W"), - QStringLiteral("^\\s*run_style\\W"), - QStringLiteral("^\\s*timestep\\W"), - QStringLiteral("^\\s*neighbor\\W"), - QStringLiteral("^\\s*neigh_modify\\W"), - QStringLiteral("^\\s*suffix\\W"), - QStringLiteral("^\\s*special_bonds\\W"), - QStringLiteral("^\\s*balance\\W"), - QStringLiteral("^\\s*box\\W"), - QStringLiteral("^\\s*clear\\W"), - QStringLiteral("^\\s*comm_modify\\W"), - QStringLiteral("^\\s*comm_style\\W"), - QStringLiteral("^\\s*newton\\W"), - QStringLiteral("^\\s*package\\W"), - QStringLiteral("^\\s*processors\\W"), - QStringLiteral("^\\s*reset_atoms\\W"), - QStringLiteral("^\\s*dump_modify\\W"), - QStringLiteral("^\\s*reset_ids\\W"), - QStringLiteral("^\\s*reset_timestep\\W"), - QStringLiteral("^\\s*label\\W"), - QStringLiteral("^\\s*jump\\W"), - QStringLiteral("^\\s*next\\W"), - QStringLiteral("^\\s*loop\\W") - - }; - for (const QString &pattern : setup_keywords) { - rule.pattern = QRegularExpression(pattern); - rule.format = setupFormat; - highlightingRules.append(rule); - } - - const QString run_keywords[] = {QStringLiteral("^\\s*minimize\\W"), - QStringLiteral("^\\s*minimize/kk\\W"), - QStringLiteral("^\\s*run\\W"), - QStringLiteral("^\\s*rerun\\W"), - QStringLiteral("^\\s*tad\\W"), - QStringLiteral("^\\s*neb\\W"), - QStringLiteral("^\\s*neb/spin\\W"), - QStringLiteral("^\\s*prd\\W"), - QStringLiteral("^\\s*quit\\W"), - QStringLiteral("^\\s*server\\W"), - QStringLiteral("^\\s*temper/npt\\W"), - QStringLiteral("^\\s*temper/grem\\W"), - QStringLiteral("^\\s*temper\\W"), - QStringLiteral("^\\s*message\\W"), - QStringLiteral("^\\s*hyper\\W"), - QStringLiteral("^\\s*dynamical_matrix\\W"), - QStringLiteral("^\\s*dynamical_matrix/kk\\W"), - QStringLiteral("^\\s*third_order\\W"), - QStringLiteral("^\\s*third_order/kk\\W"), - QStringLiteral("^\\s*fitpod\\W"), - QStringLiteral("^\\s*if\\W"), - QStringLiteral("^\\s*then\\W"), - QStringLiteral("^\\s*elif\\W"), - QStringLiteral("^\\s*else\\W")}; - for (const QString &pattern : run_keywords) { - rule.pattern = QRegularExpression(pattern); - rule.format = runFormat; - highlightingRules.append(rule); - } - - const QString define_keywords[] = {QStringLiteral("^\\s*variable\\W"), - QStringLiteral("^\\s*group\\W"), - QStringLiteral("^\\s*compute\\W"), - QStringLiteral("^\\s*python\\W"), - QStringLiteral("^\\s*set\\W"), - QStringLiteral("^\\s*uncompute\\W"), - QStringLiteral("^\\s*kim_query\\W"), - QStringLiteral("^\\s*kim\\W"), - QStringLiteral("^\\s*group2ndx\\W"), - QStringLiteral("^\\s*ndx2group\\W"), - QStringLiteral("^\\s*compute_modify\\W"), - QStringLiteral("^\\s*fix_modify\\W"), - QStringLiteral("^\\s*fix\\W"), - QStringLiteral("^\\s*unfix\\W"), - QStringLiteral("^\\s*INF\\W"), - QStringLiteral("^\\s*EDGE\\W"), - QStringLiteral("^\\s*NULL\\W"), - QStringLiteral("^\\s*&\\s*$"), - QStringLiteral("^\\s*mdi\\W")}; - for (const QString &pattern : define_keywords) { - rule.pattern = QRegularExpression(pattern); - rule.format = defineFormat; - highlightingRules.append(rule); - } - - const QString number_keywords[] = { - QStringLiteral("(^|\\s+)[0-9:*]+"), // integer and integer ranges - QStringLiteral("(^|\\s+)[0-9]+\\.[0-9]*[edED]?[-+]?[0-9]*"), // floating point 1 - QStringLiteral("(^|\\s+)[0-9]*\\.[0-9]+[edED]?[-+]?[0-9]*"), // floating point 2 - QStringLiteral("(^|\\s+)[0-9]+([edED][-+]?[0-9]+)?") // floating point 3 - }; - for (const QString &pattern : number_keywords) { - rule.pattern = QRegularExpression(pattern); - rule.format = numberFormat; - highlightingRules.append(rule); - } - - // comments, must come before strings but after other keywords. - rule.pattern = QRegularExpression("#.*"); - rule.format = commentFormat; - highlightingRules.append(rule); - - // strings, must come last so it overwrites other formatting - rule.pattern = QRegularExpression("(\".*\"|'.*')"); - rule.format = stringFormat; - highlightingRules.append(rule); + formatOutput.setForeground(Qt::darkYellow); + formatOutput.setFontWeight(QFont::Bold); + formatRead.setForeground(Qt::magenta); + formatRead.setFontWeight(QFont::Bold); + formatLattice.setForeground(Qt::darkGreen); + formatLattice.setFontWeight(QFont::Bold); + formatSetup.setForeground(Qt::darkCyan); + formatSetup.setFontWeight(QFont::Bold); } void Highlighter::highlightBlock(const QString &text) { - // clang-format off - auto style = QRegularExpression("^(fix|compute|dump|set)\\s+(\\w+)\\s+(\\S+)\\s+(\\S+)").match(text); - auto force = QRegularExpression("^(atom_style|pair_style|bond_style|angle_style|dihedral_style|improper_style|kspace_style)\\s+(\\S+)").match(text); - auto defs = QRegularExpression("^(group|variable)\\s+(\\S+)\\s+(\\S+)").match(text); - auto undo = QRegularExpression("^(unfix|uncompute|undump)\\s+(\\w+)").match(text); - // clang-format on - bool do_style = true; - bool do_force = true; - bool do_defs = true; - bool do_undo = true; - for (const HighlightingRule &rule : qAsConst(highlightingRules)) { - QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); - while (matchIterator.hasNext()) { - QRegularExpressionMatch match = matchIterator.next(); - // special treatment for fix/compute/dump styles etc. - if (style.hasMatch() && do_style) { - setFormat(style.capturedStart(1), style.capturedLength(1), defineFormat); - setFormat(style.capturedStart(2), style.capturedLength(2), numberFormat); - setFormat(style.capturedStart(3), style.capturedLength(3), stringFormat); - setFormat(style.capturedStart(4), style.capturedLength(4), runFormat); - do_style = false; - // special treatment for force styles styles - } else if (force.hasMatch() && do_force) { - setFormat(force.capturedStart(1), force.capturedLength(1), particleFormat); - setFormat(force.capturedStart(2), force.capturedLength(2), runFormat); - do_force = false; - // special treatment for undo commands - } else if (undo.hasMatch() && do_undo) { - setFormat(undo.capturedStart(1), undo.capturedLength(1), defineFormat); - setFormat(undo.capturedStart(2), undo.capturedLength(2), stringFormat); - do_undo = false; - // special treatment for some definitions - } else if (defs.hasMatch() && do_defs) { - setFormat(defs.capturedStart(1), defs.capturedLength(1), particleFormat); - setFormat(defs.capturedStart(2), defs.capturedLength(2), stringFormat); - setFormat(defs.capturedStart(3), defs.capturedLength(3), runFormat); - do_defs = false; - } else { - setFormat(match.capturedStart(), match.capturedLength(), rule.format); - } + // nothing to do for empty lines + if (text.isEmpty()) return; + + auto match = isLattice1.match(text); + if (match.hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), formatLattice); + setFormat(match.capturedStart(2), match.capturedLength(2), formatRun); + } + + match = isLattice2.match(text); + if (match.hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), formatLattice); + setFormat(match.capturedStart(2), match.capturedLength(2), formatString); + setFormat(match.capturedStart(3), match.capturedLength(3), formatRun); + } + + match = isLattice3.match(text); + if (match.hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), formatLattice); + setFormat(match.capturedStart(2), match.capturedLength(2), formatString); + setFormat(match.capturedStart(3), match.capturedLength(3), formatString); + setFormat(match.capturedStart(4), match.capturedLength(4), formatString); + } + + match = isOutput1.match(text); + if (match.hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), formatOutput); + setFormat(match.capturedStart(2), match.capturedLength(2), formatString); + } + + match = isOutput2.match(text); + if (match.hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), formatOutput); + setFormat(match.capturedStart(2), match.capturedLength(2), formatString); + setFormat(match.capturedStart(3), match.capturedLength(3), formatRun); + } + + match = isRead.match(text); + if (match.hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), formatRead); + setFormat(match.capturedStart(2), match.capturedLength(2), formatString); + } + + match = isStyle.match(text); + if (match.hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), formatParticle); + setFormat(match.capturedStart(2), match.capturedLength(2), formatNumber); + setFormat(match.capturedStart(3), match.capturedLength(3), formatString); + setFormat(match.capturedStart(4), match.capturedLength(4), formatRun); + } + + match = isForce.match(text); + if (match.hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), formatParticle); + setFormat(match.capturedStart(2), match.capturedLength(2), formatRun); + } + + match = isUndo.match(text); + if (match.hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), formatSpecial); + setFormat(match.capturedStart(2), match.capturedLength(2), formatString); + } + + match = isDefine.match(text); + if (match.hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), formatParticle); + setFormat(match.capturedStart(2), match.capturedLength(2), formatString); + setFormat(match.capturedStart(3), match.capturedLength(3), formatRun); + } + + match = isParticle.match(text); + if (match.hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), formatParticle); + setFormat(match.capturedStart(2), match.capturedLength(2), formatString); + } + + match = isSetup.match(text); + if (match.hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), formatSetup); + } + + match = isRun.match(text); + if (match.hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), formatRun); + } + + // numbers + QRegularExpression numbers[] = {isNumber1, isNumber2, isNumber3, isNumber4}; + for (auto &number : numbers) { + auto num = number.globalMatch(text); + while (num.hasNext()) { + auto match = num.next(); + setFormat(match.capturedStart(), match.capturedLength(), formatNumber); } } + + // variables + auto vars = isVariable.globalMatch(text); + while (vars.hasNext()) { + auto match = vars.next(); + setFormat(match.capturedStart(), match.capturedLength(), formatVariable); + } + + // references + auto refs = isReference.globalMatch(text); + while (refs.hasNext()) { + auto match = refs.next(); + setFormat(match.capturedStart(), match.capturedLength(), formatVariable); + } + + // continuation character + auto multiline = isContinue.match(text); + if (multiline.hasMatch()) + setFormat(multiline.capturedStart(0), multiline.capturedLength(0), formatSpecial); + + // special keywords + auto special = isSpecial.globalMatch(text); + while (special.hasNext()) { + auto match = special.next(); + setFormat(match.capturedStart(), match.capturedLength(), formatSpecial); + } + + // comments, must come before strings but after other keywords. + auto comment = isComment.match(text); + if (comment.hasMatch() && !isQuotedComment.match(text).hasMatch() && !in_triple) { + setFormat(comment.capturedStart(0), comment.capturedLength(0), formatComment); + return; + } + + // strings, must come last so they can overwrite other formatting + auto string = isString.globalMatch(text); + while (string.hasNext()) { + auto match = string.next(); + setFormat(match.capturedStart(), match.capturedLength(), formatString); + } + + auto triple = isTriple.match(text); + if (triple.hasMatch()) { + if (in_triple) { + in_triple = false; + setFormat(0, triple.capturedStart(0) + triple.capturedLength(0), formatString); + } else { + in_triple = true; + setFormat(triple.capturedStart(0), -1, formatString); + } + } else { + if (in_triple) setFormat(0, text.size(), formatString); + } } // Local Variables: // c-basic-offset: 4 diff --git a/tools/lammps-gui/highlighter.h b/tools/lammps-gui/highlighter.h index 234333924e..57ca34f23b 100644 --- a/tools/lammps-gui/highlighter.h +++ b/tools/lammps-gui/highlighter.h @@ -28,23 +28,27 @@ protected: void highlightBlock(const QString &text) override; private: - struct HighlightingRule { - QRegularExpression pattern; - QTextCharFormat format; - }; - QVector highlightingRules; + QRegularExpression isLattice1, isLattice2, isLattice3; + QRegularExpression isOutput1, isOutput2, isRead; + QTextCharFormat formatOutput, formatRead, formatLattice, formatSetup; + QRegularExpression isStyle, isForce, isDefine, isUndo; + QRegularExpression isParticle, isSetup, isRun; + QTextCharFormat formatParticle, formatRun, formatDefine; + QRegularExpression isVariable, isReference; + QTextCharFormat formatVariable; + QRegularExpression isNumber1, isNumber2, isNumber3, isNumber4; + QTextCharFormat formatNumber; + QRegularExpression isSpecial, isContinue; + QTextCharFormat formatSpecial; + QRegularExpression isComment; + QRegularExpression isQuotedComment; + QTextCharFormat formatComment; + QRegularExpression isTriple; + QRegularExpression isString; + QTextCharFormat formatString; - QTextCharFormat outputFormat; - QTextCharFormat readFormat; - QTextCharFormat latticeFormat; - QTextCharFormat particleFormat; - QTextCharFormat setupFormat; - QTextCharFormat runFormat; - QTextCharFormat defineFormat; - - QTextCharFormat numberFormat; - QTextCharFormat stringFormat; - QTextCharFormat commentFormat; + int in_triple; + int startIndex; }; #endif // Local Variables: