diff options
author | Ken Moore <ken@ixsystems.com> | 2017-06-08 21:50:09 -0400 |
---|---|---|
committer | Ken Moore <ken@ixsystems.com> | 2017-06-08 21:50:09 -0400 |
commit | 21a0f25bcf3859b1d7294e0842e4f06a203fdee6 (patch) | |
tree | 5086c98cf3bef461716766b6f7c5725dc19bd5b8 /src-qt5 | |
parent | Start the prep-work for a new way of loading syntax highlighting rules in LTE. (diff) | |
download | lumina-21a0f25bcf3859b1d7294e0842e4f06a203fdee6.tar.gz lumina-21a0f25bcf3859b1d7294e0842e4f06a203fdee6.tar.bz2 lumina-21a0f25bcf3859b1d7294e0842e4f06a203fdee6.zip |
Get a lot more of the new plugin-based syntax highlighting system setup (not integrated/tested yet).
Diffstat (limited to 'src-qt5')
4 files changed, 170 insertions, 22 deletions
diff --git a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.cpp b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.cpp index 0edb2160..4c3b3805 100644 --- a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.cpp +++ b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.cpp @@ -6,6 +6,123 @@ //=========================================== #include "syntaxSupport.h" +#include <QJsonArray> +#include <QJsonDocument> +#include <QFontDatabase> +#include <QFont> + +#include <LUtils.h> + +// ================ +// SYNTAX FILE CLASS +// ================ +QColor SyntaxFile::colorFromOption(QString opt, QSettings *settings){ + opt = opt.simplified(); + if(opt.startsWith("rgb(")){ + QStringList opts = opt.section("(",1,-1).section(")",0,0).split(","); + if(opts.length()!=3){ return QColor(); } + return QColor( opts[0].simplified().toInt(), opts[1].simplified().toInt(), opts[2].simplified().toInt() ); + }else if(opt.startsWith("#")){ + return QColor(opt); + }else if(opt.startsWith("colors/")){ + return QColor(settings->value(opt,"").toString()); + } + return QColor(); +} + +QString SyntaxFile::name(){ + if(!metaObj.contains("name")){ return ""; } + return metaObj.value("name").toString(); +} + +int SyntaxFile::char_limit(){ + if(!formatObj.contains("columns_per_line")){ return -1; } + int num = formatObj.value("columns_per_line").toInt(); + return num; +} + +bool SyntaxFile::highlight_excess_whitespace(){ + if(!formatObj.contains("highlight_whitespace_eol")){ return false; } + return formatObj.value("highlight_whitespace_eol").toBool(); +} + +void SyntaxFile::SetupDocument(QPlainTextEdit* editor){ + if(formatObj.contains("line_wrap")){ + editor->setLineWrapMode( formatObj.value("line_wrap").toBool() ? QPlainTextEdit::WidgetWidth : QPlainTextEdit::NoWrap); + } + if(formatObj.contains("font_type")){ + QString type = formatObj.value("font_type").toString(); + QFont font = editor->document()->defaultFont(); // current font + if(type=="monospace"){ + font = QFontDatabase::systemFont(QFontDatabase::FixedFont); //get the default fixed-size font for the system + } + font.setStyle(QFont::StyleNormal); + font.setStyleStrategy(QFont::PreferAntialias); + editor->document()->setDefaultFont(font); + } + if(formatObj.contains("tab_width")){ + int num = formatObj.value("tab_width").toInt(); + if(num<=0){ num = 8; } //UNIX Standard of 8 characters per tab + editor->setTabStopWidth( num * QFontMetrics(editor->document()->defaultFont()).width(" ") ); + } +} + +bool SyntaxFile::supportsFile(QString file){ + if(metaObj.contains("file_suffix")){ + return metaObj.value("file_suffix").toArray().contains( file.section("/",-1).section(".",-1) ); + } + return false; +} + +bool SyntaxFile::LoadFile(QString file, QSettings *settings){ + QStringList contents = LUtils::readFile(file); + //Now trim the extra non-JSON off the beginning of the file + while(!contents.isEmpty()){ + if(contents[0].startsWith("{")){ break; } //stop here + else{ contents.removeAt(0); } + } + QJsonObject obj = QJsonDocument::fromJson(contents.join("\n").simplified().toLocal8Bit()).object(); + if(!obj.contains("meta") || !obj.contains("format") || !obj.contains("rules")){ return false; } //could not get any info + //Save the raw meta/format objects for later + fileLoaded = file; + metaObj = obj.value("meta").toObject(); + formatObj = obj.value("format").toObject(); + //Now read/save the rules structure + QJsonArray rulesArray = obj.value("rules").toArray(); + rules.clear(); + //Create the blank/generic text format + for(int i=0; i<rulesArray.count(); i++){ + QJsonObject rule = rulesArray[i].toObject(); + SyntaxRule tmp; + //First load the rule + if(rule.contains("words")){} //valid option - handled at the end though + else if(rule.contains("regex")){ + tmp.pattern = QRegExp(rule.value("regex").toString()); + }else if(rule.contains("regex_start") && rule.contains("regex_stop")){ + + }else{ continue; } //bad rule - missing the actual detection logic + //Now load the appearance logic + if(rule.contains("foreground")){ tmp.format.setForeground( colorFromOption(rule.value("foreground").toString(), settings) ); } + if(rule.contains("background")){ tmp.format.setBackground( colorFromOption(rule.value("background").toString(), settings) ); } + if(rule.contains("font-weight")){ + QString wgt = rule.value("font-weight").toString(); + if(wgt =="bold"){ tmp.format.setFontWeight(QFont::Bold); } + if(wgt =="light"){ tmp.format.setFontWeight(QFont::Light); } + else{ tmp.format.setFontWeight(QFont::Normal); } + } + //Now save the rule(s) to the list + if(rule.contains("words")){ + //special logic - this generates a bunch of rules all at once (one per word) + QJsonArray tmpArr = rule.value("words").toArray(); + for(int a=0; a<tmpArr.count(); a++){ + tmp.pattern = QRegExp("\\b"+tmpArr[a].toString()+"\\b"); //turn each keyword into a QRegExp and insert the rule + rules << tmp; + } + }else{ rules << tmp; } //just a single rule + } + return true; +} + QStringList Custom_Syntax::availableRules(){ QStringList avail; avail << "C++"; diff --git a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h index f834e275..ba4c211a 100644 --- a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h +++ b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h @@ -13,10 +13,15 @@ #include <QString> #include <QSettings> #include <QDebug> +#include <QDateTime> +#include <QJsonObject> +#include <QPlainTextEdit> + //Simple syntax rules struct SyntaxRule{ - QRegExp pattern; + QRegExp pattern; //single-line rule + QRegExp startPattern, endPattern; //multi-line rules QTextCharFormat format; }; //Complicated/multi-line rules @@ -25,6 +30,32 @@ struct SyntaxRuleSplit{ QTextCharFormat format; }; +class SyntaxFile{ +private: + QJsonObject metaObj; + QJsonObject formatObj; + + QColor colorFromOption(QString opt, QSettings *settings); + +public: + QVector<SyntaxRule> rules; + QDateTime lastLoaded; + QString fileLoaded; + + SyntaxFile(){} + + QString name(); + int char_limit(); + bool highlight_excess_whitespace(); + + void SetupDocument(QPlainTextEdit *editor); + bool supportsFile(QString file); //does this syntax set support the file? + + //Main Loading routine (run this before other functions) + bool LoadFile(QString file, QSettings *settings); + +}; + class Custom_Syntax : public QSyntaxHighlighter{ Q_OBJECT private: diff --git a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/README.md b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/README.md index aaf134aa..0bd0616b 100644 --- a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/README.md +++ b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/README.md @@ -12,15 +12,17 @@ A small comment section may be placed at the top of the file where every line st 2. "file_suffix" : An array of suffixes for identifying which files this rule set supports. 2. A "format" object containing the following variables (file-wide formatting): 1. "columns_per_line" : (integer, optional) For file formats with line-length restrictions, this will automatically highlight/flag any "overage" of the designated limit. - 2. "font_type" : One of the following ["fixed-width", "all", "monospace"]. This is for assisting with file formats that need characters to line up within the file (all columns are in the same place per line, etc). - 3. "line_wrap" : (boolian, optional) Automatically enable/disable line wrapping for this type of file -3. A "rules" object containing each of the individual rules, with the name of the rules objects being a number which corresponds to when the rule should be applied (lower numbers are applied before higher numbers). The required fields are: - 1. "name" : Not directly used by LTE (yet) - but is useful for noting what each rule is for - 2. Exactly **one** of the following fields must also be included: + 2. "highlight_whitespace_eol" : (boolian, optional) Highlight any excess whitespace at the end of a line. + 3. "font_type" : (optional) One of the following ["all", "monospace"]. This is for assisting with file formats that need characters to line up within the file (all columns are in the same place per line, etc). + 4. "line_wrap" : (boolian) Automatically enable/disable line wrapping for this type of file + 5. "tab_width" : (integer - 8 by default) Have tabs automatically take up this many characters. +3. A "rules" array containing each of the individual rules (earlier rules are applied before later ones). The required fields for a rule are: + 1. "name" : Not directly used by LTE (yet) - but is useful for noting the purpose of each rule + 2. Exactly **one** of the following options must also be included: 1. "words" : Array of exact words/text which should be matched (automatically converted to a regular expression with a break on either side of the word) 2. "regex" : single-line regular expression to be used for finding matching text 3. "regex_start" **and** "regex_end" : multi-line regular expression. Everything between the start/end matches will be highlighted. - 3. At least **one** of the following fields should also be supplied (format of any text matches) + 3. At least **one** of the following fields should also be supplied: 1. "foreground" : Font color of the matching text (see the Colors section for additional information) 2. "background" : Highlighting color of the matching text (see the Colors section for additional information) 3. "font-weight" : One of the following ["bold","normal", "light"]. Changes the thickness of the font for the matching text @@ -30,9 +32,9 @@ There are a number of built-in colors which may be defined by the user, and thes `"colors/[name of color]"` The currently-valid colors are: ["keyword", "altkeyword", "class", "text", "function", "comment", "bracket-found", "bracket-missing"]. -Alternatively, an RGB (0-255)or Hex color code may be used instead (please limit this though - it can conflict with the user's preferred color scheme quite badly) +Alternatively, an RGB (0-255) or Hex color code may be used instead (please limit this though - it can conflict with the user's preferred color scheme quite badly) Examples: - `"foreground" : "rgb(10,10,15)"` + `"foreground" : "rgb(10,10,255)"` `"background" : "colors/text"` `"foreground" : "#0F0F0F"` diff --git a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/cpp.syntax b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/cpp.syntax index d5a5e4d9..c09fbec2 100644 --- a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/cpp.syntax +++ b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/cpp.syntax @@ -11,57 +11,55 @@ "file_suffix" : ["cpp","hpp","c", "h" ] }, "format" : { - "columns_per_line" : -1, - "font_type" : "fixed-width", + "font_type" : "monospace", "line_wrap" : false }, - "rules" : { - "1" : { + "rules" : [ + { "name" : "multi-line comment", "regex_start" : "/\\*", "regex_end" : "\\*/", "foreground" : "colors/comment" }, - "2" : { + { "name" : "single-line comment", "regex" : "//[^\n]*", "foreground" : "colors/comment", }, - "3" : { + { "name" : "keywords", "words" : ["char", "class", "const", "double", "enum", "explicit", "extern", "float", "friend", "inline", "int", "long", "namespace", "operator", "private", "protected", "public" , "short", "signals", "signed", "slots", "static", "struct", "template", "typedef", "typename", "union", "unsigned", "virtual", "void", "volatile", "true", "false", "bool"], "foreground" : "colors/keyword", "background" : "none", "font_weight" : "bold" }, - "4" : { + { "name" : "alternate keywords", "words" : ["for", "while", "switch", "case", "continue", "break", "if", "else", "return", "exit"], "foreground" : "colors/altkeyword", "background" : "none", "font_weight" : "bold" }, - "5" : { + { "name" : "class names", "regex" : "\\b[A-Za-z0-9_-\\.]+(?=::)\\b", "foreground" : "colors/class", "font_weight" : "bold" }, - "6" : { + { "name" : "function names", "regex" : "\\b[A-Za-z0-9_]+(?=\\()", "foreground" : "colors/function" }, - "7" : { + { "name" : "text", "regex" : "\"[^\"\\\\]*(\\\\(.|\\n)[^\"\\\\]*)*\"|'[^'\\\\]*(\\\\(.|\\n)[^'\\\\]*)*'", "foreground" : "colors/text" }, - "8" : { + { "name" : "preprocessor", "regex" : "^[\\s]*#[^\n]*", "foreground" : "colors/preprocessor" } - - } + ] } |