diff options
author | Ken Moore <ken@ixsystems.com> | 2017-06-09 14:04:11 -0400 |
---|---|---|
committer | Ken Moore <ken@ixsystems.com> | 2017-06-09 14:04:11 -0400 |
commit | bbf81abc29e626b654366b7083babe9f355709ea (patch) | |
tree | f62602228809158e4e48d465f58f323b453a673c | |
parent | Get the SyntaxFile loading mechanisms all setup. (diff) | |
download | lumina-bbf81abc29e626b654366b7083babe9f355709ea.tar.gz lumina-bbf81abc29e626b654366b7083babe9f355709ea.tar.bz2 lumina-bbf81abc29e626b654366b7083babe9f355709ea.zip |
Get the new syntax highlighting support framework functional with the C++ rules files as the example (still need to convert the other existing rulesets over to the new format).
6 files changed, 170 insertions, 312 deletions
diff --git a/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp b/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp index ec2d7d0d..40ff2c71 100644 --- a/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp @@ -65,7 +65,7 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ connect(closeFindS, SIGNAL(activated()), this, SLOT(closeFindReplace()) ); ui->groupReplace->setVisible(false); //Update the menu of available syntax highlighting modes - QStringList smodes = Custom_Syntax::availableRules(); + QStringList smodes = Custom_Syntax::availableRules(settings); for(int i=0; i<smodes.length(); i++){ ui->menuSyntax_Highlighting->addAction(smodes[i]); } @@ -242,13 +242,13 @@ void MainUI::fontChanged(const QFont &font){ //Save this font for later settings->setValue("lastfont", font.toString()); //Now apply this font to all the open editors - QApplication::setFont(font, "PlainTextEditor"); + //QApplication::setFont(font, "PlainTextEditor"); } void MainUI::changeFontSize(int newFontSize){ QFont currentFont = fontbox->currentFont(); currentFont.setPointSize(newFontSize); - QApplication::setFont(currentFont, "PlainTextEditor"); + //QApplication::setFont(currentFont, "PlainTextEditor"); } void MainUI::changeTabsLocation(QAction *act){ diff --git a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp index a0aff9cc..e62ff0d4 100644 --- a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp +++ b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp @@ -68,7 +68,15 @@ void PlainTextEditor::LoadFile(QString filepath){ bool diffFile = (filepath != this->whatsThis()); this->setWhatsThis(filepath); this->clear(); - SYNTAX->loadRules( Custom_Syntax::ruleForFile(filepath.section("/",-1)) ); + QList<SyntaxFile> files = SyntaxFile::availableFiles(settings); + for(int i=0; i<files.length(); i++){ + if(files[i].supportsFile(filepath) ){ + files[i].SetupDocument(this); + SYNTAX->loadRules(files[i]); + break; + } + } + //SYNTAX->loadRules( Custom_Syntax::ruleForFile(filepath.section("/",-1), settings) ); lastSaveContents = LUtils::readFile(filepath).join("\n"); if(diffFile){ this->setPlainText( lastSaveContents ); @@ -94,7 +102,7 @@ void PlainTextEditor::SaveFile(bool newname){ QString file = QFileDialog::getSaveFileName(this, tr("Save File"), this->whatsThis(), tr("Text File (*)")); if(file.isEmpty()){ return; } this->setWhatsThis(file); - SYNTAX->loadRules( Custom_Syntax::ruleForFile(this->whatsThis().section("/",-1)) ); + SYNTAX->loadRules( Custom_Syntax::ruleForFile(this->whatsThis().section("/",-1), settings) ); SYNTAX->rehighlight(); } if( !watcher->files().isEmpty() ){ watcher->removePaths(watcher->files()); } diff --git a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.cpp b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.cpp index a590d3a4..9c264fca 100644 --- a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.cpp +++ b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.cpp @@ -27,7 +27,7 @@ QColor SyntaxFile::colorFromOption(QString opt, QSettings *settings){ }else if(opt.startsWith("colors/")){ return QColor(settings->value(opt,"").toString()); } - return QColor(); + return QColor("transparent"); } QString SyntaxFile::name(){ @@ -46,6 +46,13 @@ bool SyntaxFile::highlight_excess_whitespace(){ return formatObj.value("highlight_whitespace_eol").toBool(); } +int SyntaxFile::tab_length(){ + int num = -1; + if(formatObj.contains("tab_width")){ num = formatObj.value("tab_width").toInt(); } + if(num<=0){ num = 8; } //UNIX Standard of 8 characters per tab + return num; +} + void SyntaxFile::SetupDocument(QPlainTextEdit* editor){ if(formatObj.contains("line_wrap")){ editor->setLineWrapMode( formatObj.value("line_wrap").toBool() ? QPlainTextEdit::WidgetWidth : QPlainTextEdit::NoWrap); @@ -54,7 +61,8 @@ void SyntaxFile::SetupDocument(QPlainTextEdit* editor){ 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 = QFont("monospace"); + //font = QFontDatabase::systemFont(QFontDatabase::FixedFont); //get the default fixed-size font for the system } font.setStyle(QFont::StyleNormal); font.setStyleStrategy(QFont::PreferAntialias); @@ -81,8 +89,12 @@ bool SyntaxFile::LoadFile(QString file, QSettings *settings){ 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 + //qDebug() << "Contents:" << contents.join("\n").simplified(); + QJsonParseError err; + QJsonDocument doc = QJsonDocument::fromJson(contents.join("\n").simplified().toLocal8Bit(), &err ); + if(doc.isNull()){ qDebug() << "JSON Syntax Error:" << err.errorString(); } + QJsonObject obj = doc.object(); + if(!obj.contains("meta") || !obj.contains("format") || !obj.contains("rules")){ qDebug() << "Could not read syntax file:" << file; return false; } //could not get any info //Save the raw meta/format objects for later fileLoaded = file; metaObj = obj.value("meta").toObject(); @@ -95,11 +107,14 @@ bool SyntaxFile::LoadFile(QString file, QSettings *settings){ QJsonObject rule = rulesArray[i].toObject(); SyntaxRule tmp; //First load the rule + //qDebug() << "Load Rule:" << rule.keys(); 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 if(rule.contains("regex_start") && rule.contains("regex_end")){ + tmp.startPattern = QRegExp(rule.value("regex_start").toString()); + tmp.endPattern = QRegExp(rule.value("regex_end").toString()); + //qDebug() << " -- Multi-line Rule:" << tmp.startPattern << tmp.endPattern; }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) ); } @@ -139,10 +154,12 @@ QList<SyntaxFile> SyntaxFile::availableFiles(QSettings *settings){ for(int i=0; i<paths.length(); i++){ QDir dir(paths[i]+"/lumina-desktop/syntax_rules"); if(!dir.exists()){ continue; } + //qDebug() << "Found directory:" << dir.absolutePath(); QFileInfoList files = dir.entryInfoList(QStringList() << "*.syntax", QDir::Files, QDir::Name); for(int f=0; f<files.length(); f++){ if(paths.contains(files[f].absoluteFilePath()) ){ continue; } //already handled //New Syntax File found + //qDebug() << "Found File:" << files[f].fileName(); SyntaxFile nfile; if( nfile.LoadFile(files[f].absoluteFilePath(), settings) ){ list << nfile; } } @@ -150,12 +167,14 @@ QList<SyntaxFile> SyntaxFile::availableFiles(QSettings *settings){ return list; } -QStringList Custom_Syntax::availableRules(){ +QStringList Custom_Syntax::availableRules(QSettings *settings){ QStringList avail; - avail << "C++"; + QList<SyntaxFile> files = SyntaxFile::availableFiles(settings); + for(int i=0; i<files.length(); i++){ avail << files[i].name(); } + /*avail << "C++"; //avail << "Python"; avail << "Shell"; - avail << "reST"; + avail << "reST";*/ return avail; } @@ -181,232 +200,29 @@ void Custom_Syntax::SetupDefaultColors(QSettings *settings){ if(!settings->contains("colors/preprocessor")){settings->setValue("colors/preprocessor", QColor(Qt::darkYellow).name() ); } } -QString Custom_Syntax::ruleForFile(QString filename){ - QString suffix = filename.section(".",-1); +QString Custom_Syntax::ruleForFile(QString filename, QSettings *settings){ + QList<SyntaxFile> files = SyntaxFile::availableFiles(settings); + for(int i=0; i<files.length(); i++){ + if(files[i].supportsFile(filename)){ return files[i].name(); } + } + + /*QString suffix = filename.section(".",-1); if(suffix=="cpp" || suffix=="hpp" || suffix=="c" || suffix=="h"){ return "C++"; } //else if(suffix=="py" || suffix=="pyc"){ return "Python"; } else if(suffix=="sh"){ return "Shell"; } - else if(suffix=="rst"){ return "reST"; } + else if(suffix=="rst"){ return "reST"; }*/ return ""; } -void Custom_Syntax::loadRules(QString type){ - //NOTE: the "multiLineComment - lasttype = type; - rules.clear(); - splitrules.clear(); - if(type=="C++"){ - //Keywords (standard C/C++/Qt definitions) - QStringList keywords; - keywords << "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"; - SyntaxRule rule; - rule.format.setForeground( QColor(settings->value("colors/keyword").toString()) ); - rule.format.setFontWeight(QFont::Bold); - for(int i=0; i<keywords.length(); i++){ - rule.pattern = QRegExp("\\b"+keywords[i]+"\\b"); //turn each keyword into a QRegExp and insert the rule - rules << rule; - } - //Alternate Keywords (built-in functions) - keywords.clear(); - keywords << "for" << "while" << "switch" << "case" << "if" << "else" << "return" << "exit"; - rule.format.setForeground( QColor(settings->value("colors/altkeyword").toString()) ); - for(int i=0; i<keywords.length(); i++){ - rule.pattern = QRegExp("\\b"+keywords[i]+"\\b"); //turn each keyword into a QRegExp and insert the rule - rules << rule; - } - //Class Names - rule.format.setForeground( QColor(settings->value("colors/class").toString()) ); - rule.pattern = QRegExp("\\b[A-Za-z0-9_-\\.]+(?=::)\\b"); - rules << rule; - //Quotes - rule.format.setForeground( QColor(settings->value("colors/text").toString()) ); - rule.format.setFontWeight(QFont::Normal); - rule.pattern = QRegExp( "\"[^\"\\\\]*(\\\\(.|\\n)[^\"\\\\]*)*\"|'[^'\\\\]*(\\\\(.|\\n)[^'\\\\]*)*'"); - rules << rule; - //Functions - rule.format.setForeground( QColor(settings->value("colors/function").toString()) ); - rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()"); - rules << rule; - //Proprocessor commands - rule.format.setForeground( QColor(settings->value("colors/preprocessor").toString()) ); - rule.pattern = QRegExp("^[\\s]*#[^\n]*"); - rules << rule; - //Comment (single line) - rule.format.setForeground( QColor(settings->value("colors/comment").toString()) ); - rule.pattern = QRegExp("//[^\n]*"); - rules << rule; - //Comment (multi-line) - SyntaxRuleSplit srule; - srule.format = rule.format; //re-use the single-line comment format - srule.startPattern = QRegExp("/\\*"); - srule.endPattern = QRegExp("\\*/"); - splitrules << srule; - - }else if(type=="Shell"){ - //Keywords (standard Shell definitions) - QStringList keywords; - keywords << "alias" << "alloc" << "bg" << "bind" << " bindkey" << "break" \ - << "breaksw"<<"builtins"<<"case"<<"cd"<<"chdir"<<"command"<<"complete"<<"continue"<<"default" \ - <<"dirs"<<"do"<<"done"<<"echo"<<"echotc"<<"elif"<<"else"<<"end"<<"endif"<<"endsw"<<"esac"<<"eval" \ - <<"exec"<<"exit"<<"export"<<"false"<<"fc"<<"fg"<<"filetest"<<"fi"<<"for"<<"foreach"<<"getopts" \ - <<"glob"<<"goto"<<"hash"<<"hashstat"<<"history"<<"hup"<<"if"<<"jobid"<<"jobs"<<"kill"<<"limit" \ - <<"local"<<"log"<<"login"<<"logout"<<"ls-F"<<"nice"<<"nohup"<<"notify"<<"onintr"<<"popd" \ - <<"printenv"<<"printf"<<"pushd"<<"pwd"<<"read"<<"readonly"<<"rehash"<<"repeat"<<"return" \ - <<"sched"<<"set"<<"setenv"<<"settc"<<"setty"<<"setvar"<<"shift"<<"source"<<"stop"<<"suspend" \ - <<"switch"<<"telltc"<<"test"<<"then"<<"time"<<"times"<<"trap"<<"true"<<"type"<<"ulimit"<<"umask" \ - <<"unalias"<<"uncomplete"<<"unhash"<<"unlimit"<<"unset"<<"unsetenv"<<"until"<<"wait" \ - <<"where"<<"which"<<"while"; - - SyntaxRule rule; - rule.format.setForeground( QColor(settings->value("colors/keyword").toString()) ); - rule.format.setFontWeight(QFont::Bold); - for(int i=0; i<keywords.length(); i++){ - rule.pattern = QRegExp("\\b"+keywords[i]+"\\b"); //turn each keyword into a QRegExp and insert the rule - rules << rule; - } - //Alternate Keywords (built-in functions) - /*keywords.clear(); - keywords << "for" << "while" << "switch" << "case" << "if" << "else" << "return" << "exit"; - rule.format.setForeground( QColor(settings->value("colors/altkeyword").toString()) ); - for(int i=0; i<keywords.length(); i++){ - rule.pattern = QRegExp("\\b"+keywords[i]+"\\b"); //turn each keyword into a QRegExp and insert the rule - rules << rule; - }*/ - //Variable Names - rule.format.setForeground( QColor(settings->value("colors/class").toString()) ); - rule.pattern = QRegExp("\\$\\{[^\\n\\}]+\\}"); - rules << rule; - rule.pattern = QRegExp("\\$[^\\s$]+(?=\\s|$)"); - rules << rule; - //Quotes - rule.format.setForeground( QColor(settings->value("colors/text").toString()) ); - rule.format.setFontWeight(QFont::Normal); - rule.pattern = QRegExp( "\"[^\"\\\\]*(\\\\(.|\\n)[^\"\\\\]*)*\"|'[^'\\\\]*(\\\\(.|\\n)[^'\\\\]*)*'"); - rules << rule; - //Functions - rule.format.setForeground( QColor(settings->value("colors/function").toString()) ); - rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()"); - rules << rule; - //Proprocessor commands - rule.format.setForeground( QColor(settings->value("colors/preprocessor").toString()) ); - rule.pattern = QRegExp("^#![^\n]*"); - rules << rule; - //Comment (single line) - rule.format.setForeground( QColor(settings->value("colors/comment").toString()) ); - rule.pattern = QRegExp("#[^\n]*"); - rules << rule; - //Comment (multi-line) - //SyntaxRuleSplit srule; - //srule.format = rule.format; //re-use the single-line comment format - //srule.startPattern = QRegExp("/\\*"); - //srule.endPattern = QRegExp("\\*/"); - //splitrules << srule; - - }else if(type=="Python"){ - //Keywords - QStringList keywords; - keywords << "and" << "as" << "assert" << "break" << "class" << "continue" << "def" << "del" \ - << "elif" << "else" << "except" << "exec" << "finally" << "for" << "from" \ - << "global" << "if" << "import" << "in" << "is" << "lambda" << "not" \ - << "or" << "pass" << "print" << "raise" << "return" << "try" << "while" << "with" << "yield"; - - SyntaxRule rule; - rule.format.setForeground( QColor(settings->value("colors/keyword").toString()) ); - rule.format.setFontWeight(QFont::Bold); - for(int i=0; i<keywords.length(); i++){ - rule.pattern = QRegExp("\\b"+keywords[i]+"\\b"); //turn each keyword into a QRegExp and insert the rule - rules << rule; - } - //Class Names - //rule.format.setForeground(Qt::darkMagenta); - //rule.pattern = QRegExp("\\bQ[A-Za-z]+\\b"); - //rules << rule; - //Quotes - rule.format.setForeground( QColor(settings->value("colors/text").toString()) ); - rule.format.setFontWeight(QFont::Normal); - rule.pattern = QRegExp( "\"[^\"\\\\]*(\\\\(.|\\n)[^\"\\\\]*)*\"|'[^'\\\\]*(\\\\(.|\\n)[^'\\\\]*)*'"); - rules << rule; - //Functions - rule.format.setForeground( QColor(settings->value("colors/function").toString()) ); - rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()"); - rules << rule; - //Comment (single line) - rule.format.setForeground( QColor(settings->value("colors/comment").toString()) ); - rule.pattern = QRegExp("#[^\n]*"); - rules << rule; - //Comment (multi-line) - //SyntaxRuleSplit srule; - //srule.format = rule.format; //re-use the single-line comment format - //srule.startPattern = QRegExp("/\\*"); - //srule.endPattern = QRegExp("\\*/"); - //splitrules << srule; - - }else if(type=="reST"){ - SyntaxRule rule; - // directives - rule.format.setForeground( QColor(settings->value("colors/class").toString()) ); - rule.format.setFontItalic(false); - rule.pattern = QRegExp("(\\s|^):[a-zA-Z0-9 ]*:`[^`]*`"); - rules << rule; - // hyperlinks - rule.format.setFontItalic(true); - rule.format.setFontWeight(QFont::Normal); - rule.pattern = QRegExp("`[^\\<]*\\<[^\\>]*\\>`_"); - rules << rule; - // Code Sample - rule.format.setFontItalic(false); - rule.format.setFontWeight(QFont::Light); - rule.format.setFontFixedPitch(true); - rule.pattern = QRegExp("\\b`{2}.*`{2}\\b"); - rules << rule; - //Quotes - /*rule.format.setForeground( QColor(settings->value("colors/text").toString()) ); - rule.format.setFontWeight(QFont::Normal); - rule.pattern = QRegExp( "\"[^\"\\\\]*(\\\\(.|\\n)[^\"\\\\]*)*\"|'[^'\\\\]*(\\\\(.|\\n)[^'\\\\]*)*'"); - rules << rule;*/ - //TODO - rule = SyntaxRule(); //reset rule - rule.format.setFontWeight( QFont::Bold ); - rule.pattern = QRegExp("^\\.\\.\\sTODO\\b"); - rules << rule; - rule = SyntaxRule(); //reset rule - rule.format.setFontWeight( QFont::Bold ); - rule.pattern = QRegExp("^(\\s*)\\.\\.(\\s*)([a-zA-Z0-9]+)::"); - rules << rule; - //Functions - rule = SyntaxRule(); //reset rule - rule.format.setForeground( QColor(settings->value("colors/preprocessor").toString()) ); - rule.pattern = QRegExp("^(\\s*)\\.\\.(\\s*)\\b_[a-zA-Z0-9 ]*:(\\s|$)"); - rules << rule; - //figures and other properties for them - rule = SyntaxRule(); //reset rule - rule.format.setForeground( QColor(settings->value("colors/keyword").toString()) ); - rule.pattern = QRegExp("^(\\s*)\\.\\.\\sfigure::\\s"); - rules << rule; - rule = SyntaxRule(); //reset rule - rule.format.setForeground( QColor(settings->value("colors/altkeyword").toString()) ); - rule.pattern = QRegExp("^( ){3}:(.)*: "); - rules << rule; - - //Code Blocks - SyntaxRuleSplit srule; - srule.format.setBackground( QColor("lightblue") ); - srule.startPattern = QRegExp("\\:\\:$"); - srule.endPattern = QRegExp("^(?=[^\\s])"); - splitrules << srule; - srule.startPattern = QRegExp("^(\\s*)\\.\\.\\scode-block::\\s"); //alternate start string for the same rule - srule.endPattern = QRegExp("^(?=[^\\s])"); - splitrules << srule; - //Comment (multi-line) - srule = SyntaxRuleSplit(); - srule.format.setForeground( QColor(settings->value("colors/comment").toString()) ); - srule.startPattern = QRegExp("^(\\s*)\\.\\.\\s[^_](?![\\w-_\\.]+::(\\s|$))"); - srule.endPattern = QRegExp("^(?=([^\\s]|$))"); - splitrules << srule; +void Custom_Syntax::loadRules(QString type){ + QList<SyntaxFile> files = SyntaxFile::availableFiles(settings); + for(int i=0; i<files.length(); i++){ + if(files[i].name() == type){ syntax = files[i]; break; } } + return; +} + +void Custom_Syntax::loadRules(SyntaxFile sfile){ + syntax = sfile; } diff --git a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h index 746df750..fde68f84 100644 --- a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h +++ b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h @@ -47,6 +47,7 @@ public: QString name(); int char_limit(); bool highlight_excess_whitespace(); + int tab_length(); void SetupDocument(QPlainTextEdit *editor); bool supportsFile(QString file); //does this syntax set support the file? @@ -62,9 +63,10 @@ class Custom_Syntax : public QSyntaxHighlighter{ Q_OBJECT private: QSettings *settings; - QString lasttype; - QVector<SyntaxRule> rules; - QVector<SyntaxRuleSplit> splitrules; + //QString lasttype; + SyntaxFile syntax; + //QVector<SyntaxRule> rules; + //QVector<SyntaxRuleSplit> splitrules; public: Custom_Syntax(QSettings *set, QTextDocument *parent = 0) : QSyntaxHighlighter(parent){ @@ -72,47 +74,53 @@ public: } ~Custom_Syntax(){} - static QStringList availableRules(); + static QStringList availableRules(QSettings *settings); static QStringList knownColors(); static void SetupDefaultColors(QSettings *settings); - static QString ruleForFile(QString filename); + static QString ruleForFile(QString filename, QSettings *settings); void loadRules(QString type); + void loadRules(SyntaxFile sfile); void reloadRules(){ - loadRules(lasttype); + loadRules( syntax.name() ); } + protected: void highlightBlock(const QString &text){ //qDebug() << "Highlight Block:" << text; //Now look for any multi-line patterns (starting/continuing/ending) int start = 0; int splitactive = previousBlockState(); - if(splitactive>splitrules.length()-1){ splitactive = -1; } //just in case + if(splitactive>syntax.rules.length()-1){ splitactive = -1; } //just in case + while(start>=0 && start<=text.length()-1){ //qDebug() << "split check:" << start << splitactive; if(splitactive>=0){ //Find the end of the current rule - int end = splitrules[splitactive].endPattern.indexIn(text, start); + int end = syntax.rules[splitactive].endPattern.indexIn(text, start); if(end==-1){ //qDebug() << "Highlight to end of line:" << text << start; //rule did not finish - apply to all - if(start>0){ setFormat(start-1, text.length()-start+1, splitrules[splitactive].format); } - else{ setFormat(start, text.length()-start, splitrules[splitactive].format); } + if(start>0){ setFormat(start-1, text.length()-start+1, syntax.rules[splitactive].format); } + else{ setFormat(start, text.length()-start, syntax.rules[splitactive].format); } break; //stop looking for more multi-line patterns }else{ //Found end point within the same line //qDebug() << "Highlight to particular point:" << text << start << end; - int len = end-start+splitrules[splitactive].endPattern.matchedLength(); + int len = end-start+syntax.rules[splitactive].endPattern.matchedLength(); if(start>0){ start--; len++; } //need to include the first character as well - setFormat(start, len , splitrules[splitactive].format); + setFormat(start, len , syntax.rules[splitactive].format); start+=len; //move pointer to the end of handled range splitactive = -1; //done with this rule } } //end check for end match - //Look for the start of any new split rule - for(int i=0; i<splitrules.length() && splitactive<0; i++){ - //qDebug() << "Look for start of split rule:" << splitrules[i].startPattern << splitactive; - int newstart = splitrules[i].startPattern.indexIn(text,start); + //Look for the start of any new split rules + //qDebug() << "Loop over multi-line rules"; + for(int i=0; i<syntax.rules.length() && splitactive<0; i++){ + //qDebug() << "Check Rule:" << i << syntax.rules[i].startPattern << syntax.rules[i].endPattern; + if(syntax.rules[i].startPattern.isEmpty()){ continue; } + //qDebug() << "Look for start of split rule:" << syntax.rules[i].startPattern << splitactive; + int newstart = syntax.rules[i].startPattern.indexIn(text,start); if(newstart>=start){ //qDebug() << "Got Start of split rule:" << start << newstart << text; splitactive = i; @@ -120,24 +128,48 @@ protected: if(start>=text.length()-1){ //qDebug() << "Special case: start now greater than line length"; //Need to apply highlighting to this section too - start matches the end of the line - setFormat(start-1, text.length()-start+1, splitrules[splitactive].format); + setFormat(start-1, text.length()-start+1, syntax.rules[splitactive].format); } } } if(splitactive<0){ break; } //no other rules found - go ahead and exit the loop - } + } //end scan over line length and multi-line formats + setCurrentBlockState(splitactive); //Do all the single-line patterns - for(int i=0; i<rules.length(); i++){ - QRegExp patt(rules[i].pattern); //need a copy of the rule's pattern (will be changing it below) + for(int i=0; i<syntax.rules.length(); i++){ + if(syntax.rules[i].pattern.isEmpty()){ continue; } //not a single-line rule + QRegExp patt(syntax.rules[i].pattern); //need a copy of the rule's pattern (will be changing it below) int index = patt.indexIn(text); if(splitactive>=0 || index<start){ continue; } //skip this one - falls within a multi-line pattern above while(index>=0){ int len = patt.matchedLength(); - if(format(index)==currentBlock().charFormat()){ setFormat(index, len, rules[i].format); } //only apply highlighting if not within a section already + if(format(index)==currentBlock().charFormat()){ setFormat(index, len, syntax.rules[i].format); } //only apply highlighting if not within a section already index = patt.indexIn(text, index+len); //go to the next match } }//end loop over normal (single-line) patterns + + //Now go through and apply any document-wide formatting rules + QTextCharFormat fmt; + fmt.setBackground( QColor( settings->value("colors/bracket-missing").toString() ) ); + int max = syntax.char_limit(); + if(max >= 0 && ( (text.length()+(text.count("\t")*(syntax.tab_length()-1)) )> max) ){ + //Line longer than it should be - highlight the offending characters + //Need to be careful about where tabs show up in the line + int len = 0; + for(int i=0; i<text.length(); i++){ + if(text[i]=='\t'){ len += syntax.tab_length(); } + else{ len++; } + if(len>max){ setFormat(i, text.length()-i, fmt); break; } + } + } + if(syntax.highlight_excess_whitespace()){ + int last = text.length()-1; + while(last>=0 && (text[last]==' ' || text[last]=='\t' ) ){ last--; } + if(last < text.length()-1){ + setFormat(last+1, text.length()-1-last, fmt); + } + } } }; #endif 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 c09fbec2..9a235ae3 100644 --- a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/cpp.syntax +++ b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/cpp.syntax @@ -6,60 +6,57 @@ # =================================== { - "meta" : { - "name" : "C++", - "file_suffix" : ["cpp","hpp","c", "h" ] - }, - "format" : { - "font_type" : "monospace", - "line_wrap" : false - }, - "rules" : [ - { - "name" : "multi-line comment", - "regex_start" : "/\\*", - "regex_end" : "\\*/", - "foreground" : "colors/comment" - }, - { - "name" : "single-line comment", - "regex" : "//[^\n]*", - "foreground" : "colors/comment", - }, - { - "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" - }, - { - "name" : "alternate keywords", - "words" : ["for", "while", "switch", "case", "continue", "break", "if", "else", "return", "exit"], - "foreground" : "colors/altkeyword", - "background" : "none", - "font_weight" : "bold" - }, - { - "name" : "class names", - "regex" : "\\b[A-Za-z0-9_-\\.]+(?=::)\\b", - "foreground" : "colors/class", - "font_weight" : "bold" - }, - { - "name" : "function names", - "regex" : "\\b[A-Za-z0-9_]+(?=\\()", - "foreground" : "colors/function" - }, - { - "name" : "text", - "regex" : "\"[^\"\\\\]*(\\\\(.|\\n)[^\"\\\\]*)*\"|'[^'\\\\]*(\\\\(.|\\n)[^'\\\\]*)*'", - "foreground" : "colors/text" - }, - { - "name" : "preprocessor", - "regex" : "^[\\s]*#[^\n]*", - "foreground" : "colors/preprocessor" - } - ] + "meta": { + "name": "C++", + "file_suffix": ["cpp", "hpp", "c", "h"] + }, + "format": { + "line_wrap": false, + "highlight_whitespace_eol": true + }, + "rules": [{ + "name": "multi-line comment", + "regex_start": "/\\*", + "regex_end": "\\*/", + "foreground": "colors/comment" + }, + { + "name": "single-line comment", + "regex": "//[^\n]*", + "foreground": "colors/comment" + }, + { + "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", + "font_weight": "bold" + }, + { + "name": "alternate keywords", + "words": ["for", "while", "switch", "case", "continue", "break", "if", "else", "return", "exit"], + "foreground": "colors/altkeyword", + "font_weight": "bold" + }, + { + "name": "class names", + "regex": "\\b[A-Za-z0-9_-\\.]+(?=::)\\b", + "foreground": "colors/class", + "font_weight": "bold" + }, + { + "name": "function names", + "regex": "\\b[A-Za-z0-9_]+(?=\\()", + "foreground": "colors/function" + }, + { + "name": "text", + "regex": "\"[^\"\\\\]*(\\\\(.|\\n)[^\"\\\\]*)*\"|'[^'\\\\]*(\\\\(.|\\n)[^'\\\\]*)*'", + "foreground": "colors/text" + }, + { + "name": "preprocessor", + "regex": "^[\\s]*#[^\n]*", + "foreground": "colors/preprocessor" + } + ] } diff --git a/src-qt5/desktop-utils/lumina-textedit/tests/test.cpp b/src-qt5/desktop-utils/lumina-textedit/tests/test.cpp index e135227d..31e15eea 100644 --- a/src-qt5/desktop-utils/lumina-textedit/tests/test.cpp +++ b/src-qt5/desktop-utils/lumina-textedit/tests/test.cpp @@ -12,7 +12,12 @@ line comment */ stuff -some /*single line comment with multi-line tags */ +some /*single line comment with multi-line tags */ and other stuff "some text" "some text with url: http://sample.com" + +switch(something){ + case 1: + +} |