syntaxhighlighter.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #include "syntaxhighlighter.h"
  2. SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent) :
  3. QSyntaxHighlighter(parent)
  4. {
  5. // TODO: export into config
  6. levelColor.push_back(QTextCharFormat());
  7. levelColor.push_back(QTextCharFormat());
  8. levelColor.push_back(QTextCharFormat());
  9. levelColor.push_back(QTextCharFormat());
  10. levelColor.push_back(QTextCharFormat());
  11. levelColor.push_back(QTextCharFormat());
  12. levelColor[0].setForeground(Qt::cyan);
  13. levelColor[1].setForeground(Qt::darkGreen);
  14. levelColor[2].setForeground(Qt::darkRed);
  15. levelColor[3].setForeground(Qt::darkYellow);
  16. levelColor[4].setForeground(Qt::magenta);
  17. levelColor[5].setForeground(Qt::green);
  18. for (auto& tcf : levelColor) {
  19. tcf.setFontWeight(99);
  20. }
  21. comment.setForeground(Qt::gray);
  22. error.setForeground(Qt::red);
  23. error.setFontItalic(true);
  24. error.setFontWeight(99);
  25. }
  26. void SyntaxHighlighter::highlightBlock(const QString &text)
  27. {
  28. struct FormatState {
  29. QTextCharFormat* currentFormat;
  30. int startIndex = 0;
  31. int length = 0;
  32. SyntaxHighlighter* sh;
  33. FormatState(SyntaxHighlighter* sh) : currentFormat{ &sh->comment }, sh{ sh } {}
  34. void upateFormat(int len, QTextCharFormat* format) {
  35. if (format == currentFormat) {
  36. length++;
  37. }
  38. else {
  39. sh->setFormat(startIndex, length, *currentFormat);
  40. currentFormat = format;
  41. startIndex += length;
  42. length = 1;
  43. }
  44. }
  45. void finish() {
  46. sh->setFormat(startIndex, length, *currentFormat);
  47. }
  48. };
  49. const int INVALID_LEVEL = -2;
  50. int level = previousBlockState();
  51. // if uninitialized set to zero
  52. if (level == -1) level = 0;
  53. FormatState fs(this);
  54. for (int i = 0; i < text.length(); i++) {
  55. auto& c = text[i];
  56. if (c == '[' && level >= 0) {
  57. level++;
  58. }
  59. if (isBfChar(c)) {
  60. if (level < 0 || (level == 0 && c == ']')) {
  61. fs.upateFormat(1, &error);
  62. level = INVALID_LEVEL;
  63. }
  64. else {
  65. fs.upateFormat(1, &levelColor[level % levelColor.size()]);
  66. }
  67. }
  68. else {
  69. fs.upateFormat(1, &comment);
  70. }
  71. if (c == ']' && level != INVALID_LEVEL) {
  72. level--;
  73. }
  74. }
  75. fs.finish();
  76. setCurrentBlockState(level);
  77. }
  78. bool SyntaxHighlighter::isBfChar(const QChar& c)
  79. {
  80. switch (c.unicode()) {
  81. case '+':
  82. case '-':
  83. case '<':
  84. case '>':
  85. case ',':
  86. case '.':
  87. case '[':
  88. case ']':
  89. return true;
  90. default:
  91. return false;
  92. }
  93. }