// Handle the general case QString GumboInterface::fix_self_closing_tags(const QString &source) { QString newsource = source; QRegularExpression selfclosed("<\\s*([a-zA-Z]+)(\\s*[^>/]*)/\\s*>"); QRegularExpressionMatch match = selfclosed.match(newsource, 0); while (match.hasMatch()) { if (match.capturedStart() == -1) { break; } QString tag = match.captured(0); int sp = match.capturedStart(0); int n = match.capturedLength(0); QString name = match.captured(1); QString atts = match.captured(2);; atts = atts.trimmed(); if (!atts.isEmpty()) { atts = " " + atts; } int nsp = sp + n; if (!allowed_void_tags.contains(name)) { QString newtag = "<" + name + atts + "></" + name + ">"; newsource = newsource.replace(sp,n,newtag); nsp = sp + newtag.length(); } match = selfclosed.match(newsource, nsp); } return newsource; }
// The actual generation engine QString ShopTemplateManager::Generate(const Items &items) { QString temp = shopTemplate; { QRegularExpression expr("{(?<key>.+?)(?<options>(\\|(.+?))*?)}"); QRegularExpressionMatchIterator matcher = expr.globalMatch(shopTemplate); int offset = 0; while (matcher.hasNext()) { QRegularExpressionMatch match = matcher.next(); QString key = match.captured("key").toLower(); int startPos = offset + match.capturedStart(); int len = match.capturedLength(); QStringList optionsAndData = match.captured("options").split("|", QString::SkipEmptyParts); QHash<QString, QString> options; for (QString optionAndData : optionsAndData) { int split = optionAndData.indexOf(":"); if (split == -1) { options.insert(optionAndData.toLower(), ""); } else { QString option = optionAndData.left(split).toLower(); QString data = optionAndData.mid(split + 1); options.insert(option, data); } } QString replacement = FetchFromKey(key, items, &options); temp.replace(startPos, len, replacement); offset += replacement.length() - len; } } // Now clean up empty spoiler tags! int matches = -1; while (matches != 0){ QRegularExpression expr("\\[spoiler=\\\"(?>.*?\\\"\\])(?>\\s*?\\[\\/spoiler\\]\\n)"); QRegularExpressionMatchIterator matcher = expr.globalMatch(temp); int offset = 0; matches = 0; while (matcher.hasNext()) { QRegularExpressionMatch match = matcher.next(); int startPos = match.capturedStart() + offset; int length = match.capturedLength(); temp.remove(startPos, length); offset -= length; matches++; } } return temp; }
QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<LocatorFilterEntry> &future, const QString &entry) { QList<LocatorFilterEntry> goodEntries; QList<LocatorFilterEntry> betterEntries; const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(entry); const QRegularExpression regexp = createRegExp(fp.filePath); if (!regexp.isValid()) return goodEntries; const QList<Entry> editorEntries = editors(); for (const Entry &editorEntry : editorEntries) { if (future.isCanceled()) break; QString fileName = editorEntry.fileName.toString(); if (fileName.isEmpty()) continue; QString displayName = editorEntry.displayName; const QRegularExpressionMatch match = regexp.match(displayName); if (match.hasMatch()) { LocatorFilterEntry filterEntry(this, displayName, QString(fileName + fp.postfix)); filterEntry.extraInfo = FileUtils::shortNativePath(FileName::fromString(fileName)); filterEntry.fileName = fileName; filterEntry.highlightInfo = highlightInfo(match); if (match.capturedStart() == 0) betterEntries.append(filterEntry); else goodEntries.append(filterEntry); } } betterEntries.append(goodEntries); return betterEntries; }
/** * @brief prepend symbol on nth match * @param input input string * @param number_length the length of the number, will prepend symbol * if the length smaller than this number * @param nth the number of match * @param reg the pattern want to find * @param symbol symbol prepand before the number * @return the input after symbol prepend if match the condition; if the reg * found the match pattern but the target length less than number_length, do nothing; * if reg do not find any match, return "the number of match is out of range * or found no match in this string" */ QString prepend_symbol_on_nth_match(QString const &input, int number_length, int nth, const QRegularExpression ®, QChar symbol) { auto it = reg.globalMatch(input); QRegularExpressionMatch match; int count = 0; while (it.hasNext()){ match = it.next(); if(count == nth){ if(match.hasMatch()){ QString new_file_name = input; if(!match.captured(1).isEmpty()){ if(match.capturedLength(0) < number_length){ new_file_name.insert(match.capturedStart(0), QString(number_length - match.capturedLength(0), symbol)); } } return new_file_name; }else{ break; } } ++count; } return "the number of match is out of range or found no match in this string"; }
bool QuickFindPattern::isLineMatchingBackward( const QString& line, int column ) const { int pos = 0; if ( ! active_ ) return false; QRegularExpressionMatchIterator matches = regexp_.globalMatch(line); QRegularExpressionMatch lastMatch; while ( matches.hasNext() ) { QRegularExpressionMatch nextMatch = matches.peekNext(); if ( column >= 0 && nextMatch.capturedEnd() >= column ) { break; } lastMatch = matches.next(); } if ( lastMatch.hasMatch() ) { lastMatchStart_ = lastMatch.capturedStart(); lastMatchEnd_ = lastMatch.capturedEnd() - 1; return true; } else { return false; } }
void HtmlParser::parse() { while(!_downloaded) { QThread::msleep(10); } _info->_status = UrlInfo::PARSING; emit processing(_info.data()); _info->_found = _content.contains(_text, Qt::CaseInsensitive); int start_offset = -1; QRegularExpression regExp("(?:https?|ftp)://(((((((((\\w|\\d)|\\055)|\\056)|\\046)|\\077)|\\043)|\\045)|\\057)|\\075)+"); while (true) { QRegularExpressionMatch match = regExp.match(_content, ++start_offset); if (!match.hasMatch()) break; start_offset = match.capturedStart(); int end_offset = match.capturedEnd(); _links << new HtmlParser(_content.mid(start_offset, end_offset), _text); } _content.clear(); if (_downloader) delete _downloader; _downloader = nullptr; _info->_status = UrlInfo::FINISHED; emit processing(_info.data()); }
void Highlighter::highlightBlock(const QString &text) { foreach (const HighlightingRule &rule, highlightingRules) { QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); while (matchIterator.hasNext()) { QRegularExpressionMatch match = matchIterator.next(); setFormat(match.capturedStart(), match.capturedLength(), rule.format); } }
void SyntaxHighlighter::highlightBlock(const QString &text) { for (std::size_t i = 0; i < _keywords.size(); i++) { const KeywordRule &rule = _keywords.at(i); QRegularExpressionMatchIterator it = rule.rulePattern.globalMatch(text); while (it.hasNext()) { QRegularExpressionMatch match = it.next(); setFormat( match.capturedStart(), match.capturedLength(), rule.ruleTextFormat); } } }
void Template::translate(ITemplateTranslationProvider &provider) { //This regex captures expressions of the form //<?= tr("This is a test") ?> and <?= tr("optional %1 parameters %2","bla","blu") ?> //The first capture group is the key (untranslated string), the second the optional list of parameters const QRegularExpression regexp = QRegularExpression("<\\?=\\s*tr\\(\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"((?:,\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")*)\\s*\\)\\?>"); //This one is used to extract the parameters using global matching const QRegularExpression paramExp = QRegularExpression(",\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\""); int offset = 0; QRegularExpressionMatch match; do { match = regexp.match(*this,offset); if(match.hasMatch()) { int start = match.capturedStart(0); int len = match.capturedLength(0); QString key = match.captured(1); //replace escaped double and single quotes key.replace("\\\"","\""); key.replace("\\'", "'"); QString translation = provider.getTranslation(key); //find out if we have optional parameters if(match.capturedLength(2)>0) { QString params = match.captured(2); //extract each optional parameter QRegularExpressionMatchIterator it = paramExp.globalMatch(params); while(it.hasNext()) { QRegularExpressionMatch paramMatch = it.next(); QString param = paramMatch.captured(1); //replace escaped quotes param.replace("\\\"","\""); param.replace("\\'", "'"); //apply the param translation = translation.arg(param); } } this->replace(start,len,translation); offset = start+translation.length(); } }while(match.hasMatch()); }
QString StringUtils::htmlEncode( QString text, bool urlAsLinks, bool newlineAsBr) { QString s; QHash<int,int> linksIndexes; // start of link index -> length of link if (urlAsLinks) { QRegularExpressionMatchIterator it = linkRe.globalMatch(text); while (it.hasNext()) { QRegularExpressionMatch match = it.next(); linksIndexes.insert(match.capturedStart(0), match.capturedLength(0)); } } for (int i = 0; i < text.length(); ) { if (urlAsLinks && linksIndexes.contains(i)) { int l = linksIndexes.value(i); QString html = htmlEncode(text.mid(i, l), false), href = html; href.replace("\"", "%22"); s.append("<a href=\"").append(href).append("\">").append(html) .append("</a>"); i += l; } else { const QChar c = text.at(i); switch(c.toLatin1()) { case '<': s.append("<"); break; case '>': s.append(">"); break; case '&': s.append("&"); break; case '"': s.append("""); break; case '\'': s.append("'"); break; case '\n': if (newlineAsBr) s.append("<br/>\n"); else s.append(c); break; default: s.append(c); } ++i; } } return s; }
foreach (OnePartRule rule, onepartrules) { QRegularExpressionMatchIterator i = rule.pattern.globalMatch(text); while (i.hasNext()) { QRegularExpressionMatch match = i.next(); int length = match.capturedLength(); if (length == 0) continue; int start = match.capturedStart(); setFormat(start, length, rule.format); } }
int QzRegExp::indexIn(const QString &str, int offset) const { QzRegExp* that = const_cast<QzRegExp*>(this); QRegularExpressionMatch m = match(str, offset); if (!m.hasMatch()) { that->m_matchedLength = -1; that->m_capturedTexts.clear(); return -1; } that->m_matchedLength = m.capturedLength(); that->m_capturedTexts = m.capturedTexts(); return m.capturedStart(); }
bool HRProcessor::test(const Element &, const QString &block) { //! No atomic grouping in python so we simulate it here for performance. //! The regex only matches what would be in the atomic group - the HR. //! Then check if we are at end of block or if next char is a newline. QRegularExpressionMatch m = this->SEARCH_RE.match(block); if ( m.hasMatch() && ( m.capturedEnd() == block.size() || block.at(m.capturedStart()+m.capturedLength()) == '\n' ) ) { //! Save match object on class instance so we can use it later. this->match = m; return true; } return false; }
bool QuickFindPattern::isLineMatching( const QString& line, int column ) const { if ( ! active_ ) return false; QRegularExpressionMatch match = regexp_.match( line, column ); if ( match.hasMatch() ) { lastMatchStart_ = match.capturedStart(); lastMatchEnd_ = match.capturedEnd() - 1; return true; } else { return false; } }
// Handle the specific problem of iframe being self-closed QString GumboInterface::fix_self_closing_tags(const QString &source) { QString newsource = source; QRegularExpression selfclosed("<\\s*iframe(\\s*[^>/]*)/\\s*>"); QRegularExpressionMatch match = selfclosed.match(newsource, 0); while (match.hasMatch()) { if (match.capturedStart() == -1) { break; } QString tag = match.captured(0); int sp = match.capturedStart(0); int n = match.capturedLength(0); QString atts = match.captured(1);; atts = atts.trimmed(); if (!atts.isEmpty()) { atts = " " + atts; } QString newtag = "<iframe" + atts + "></iframe>"; newsource = newsource.replace(sp,n,newtag); int nsp = sp + newtag.length(); match = selfclosed.match(newsource, nsp); } return newsource; }
static QString replaceInString (const QRegularExpression &rx, QString string, T func) { QRegularExpressionMatchIterator it = rx.globalMatch (string); int offset = 0; while (it.hasNext ()) { QRegularExpressionMatch match = it.next (); QString replaceWith = func (match); int length = match.capturedLength (); int begin = match.capturedStart () + offset; string.replace (begin, length, replaceWith); offset += replaceWith.length () - length; } return string; }
bool QuickFindPattern::matchLine( const QString& line, QList<QuickFindMatch>& matches ) const { matches.clear(); if ( active_ ) { QRegularExpressionMatchIterator matchIterator = regexp_.globalMatch(line); while( matchIterator.hasNext() ) { QRegularExpressionMatch match = matchIterator.next(); matches << QuickFindMatch ( match.capturedStart(), match.capturedLength() ); } } return ( matches.count() > 0 ); }
QString Toolbox::incrementNumberInString(QString string) noexcept { QRegularExpression regex("([0-9]+)(?!.*[0-9]+)"); QRegularExpressionMatch match = regex.match(string); if (match.hasMatch()) { // string contains numbers -> increment last number bool ok = false; uint number = match.captured().toUInt(&ok); if (ok) { string.replace(match.capturedStart(), match.capturedLength(), QString::number(number + 1U)); return string; } } // fallback: just add a "1" at the end return string % "1"; }
bool run(const markdown::Element &parent, QStringList &blocks) { QString block = blocks.first(); blocks.pop_front(); QRegularExpressionMatch m = this->RE.match(block); if ( m.hasMatch() ) { QString before = block.left(m.capturedStart()); // All lines before direction QString after = block.mid(m.capturedEnd()); // All lines after direction if ( ! before.isEmpty() ) { // As the direction was not the first line of the block and the // lines before the direction must be parsed first, // recursively parse this lines as a block. std::shared_ptr<markdown::BlockParser> parser = this->parser.lock(); QStringList new_blocks = {before}; parser->parseBlocks(parent, new_blocks); } // Create direction QString body = m.captured(2); // background-image m = this->BGIMG_RE.match(body); if ( m.hasMatch() ) { markdown::Element img = markdown::createSubElement(parent, "img"); img->attrib["class"] = "background"; img->attrib["src"] = m.captured(1); img->attrib["alt"] = m.captured(2); } // TODO: other direction if ( ! m.hasMatch() ) { markdown::Element p = markdown::createSubElement(parent, "p"); p->attrib["class"] = "comment"; p->text = body; } if ( ! after.isEmpty() ) { // Insert remaining lines as first block for future parsing. blocks.insert(0, after); } return true; } else { // This should never happen, but just in case... qDebug() << "We've got a problem header: " << block; return false; } }
// Returns the largest index of all the Sigil CSS classes int CleanSource::MaxSigilCSSClassIndex(const QStringList &css_style_tags) { int max_class_index = 0; foreach(QString style_tag, css_style_tags) { QRegularExpression sigil_class(SIGIL_CLASS_NAME_REG); int main_index = 0; while (true) { QRegularExpressionMatch match = sigil_class.match(style_tag, main_index); main_index = match.capturedStart(); if (main_index == -1) { break; } main_index += match.capturedLength(); int class_index = match.captured(1).toInt(); if (class_index > max_class_index) { max_class_index = class_index; } } }
QStringList WorkbookParserPrivate::splitoutCellReference(QString expression) { QStringList result; QRegularExpression re = QRegularExpression(REGEX_CELL_REFERENCE_2); QRegularExpressionMatch match; int start, end = 0; QRegularExpressionMatchIterator it = re.globalMatch(expression); while (it.hasNext()) { match = it.next(); start = match.capturedStart(0); result.append(expression.mid(end, start - end)); // TODO replace cell references with actual contents of cell result.append(match.captured(0)); // TODO above end = match.capturedEnd(0); } if (end < expression.length()) result.append(expression.mid(end)); return result; }
QString TxtFileView::addBoldMarks(QString txtline) { int i=0; if(m_isRegEx) { QRegularExpressionMatch match; while( (match = m_stxtRe.match(txtline, i)).hasMatch() ) { txtline.insert(match.capturedEnd(),"</u></b>"); txtline.insert(match.capturedStart(),"<b><u>"); i=match.capturedEnd()+6+8; m_hits++; } } else { while ((i = txtline.indexOf(m_stxt, i, Qt::CaseInsensitive)) != -1) { txtline.insert(i+m_stxt.size(),"</u></b>"); txtline.insert(i,"<b><u>"); i+=m_stxt.size()+6+8; m_hits++; } } return txtline; }
// neither svg nor math tags need a namespace prefix defined // especially as epub3 now includes them into the html5 spec // So we need to remove the svg prefix from the tags before // processing them with gumbo QString CleanSource::PreprocessSpecialCases(const QString &source) { QString newsource = source; // remove prefix from root tag and add unprefixed svg namespace to it QRegularExpression root_svg_tag_with_prefix("<\\s*svg\\s*:\\s*svg"); QString root_svg_embeddedNS = "<svg xmlns=\"http://www.w3.org/2000/svg\""; newsource.replace(root_svg_tag_with_prefix, root_svg_embeddedNS); // search for any prefixed svg namespace in that root tag and remove it QRegularExpression svg_nsprefix(SVG_NAMESPACE_PREFIX); QRegularExpressionMatch mo = svg_nsprefix.match(newsource); if (mo.hasMatch()) { newsource.replace(mo.capturedStart(1), mo.capturedLength(1), ""); } // now strip the prefix from all child starting tags QRegularExpression starting_child_svg_tag_with_prefix("<\\s*svg\\s*:"); QString starting_child_tag_no_prefix = "<"; newsource.replace(starting_child_svg_tag_with_prefix, starting_child_tag_no_prefix); // do the same for any child ending tags QRegularExpression ending_child_svg_tag_with_prefix("<\\s*/\\s*svg\\s*:"); QString ending_child_tag_no_prefix = "</"; newsource.replace(ending_child_svg_tag_with_prefix, ending_child_tag_no_prefix); return newsource; }
std::string GumboInterface::update_style_urls(const std::string &source) { QString result = QString::fromStdString(source); // Now parse the text once looking urls and replacing them where needed QRegularExpression reference( "(?:(?:src|background|background-image|list-style|list-style-image|border-image|border-image-source|content)\\s*:|@import)\\s*" "[^;\\}\\(\"']*" "(?:" "url\\([\"']?([^\\(\\)\"']*)[\"']?\\)" "|" "[\"']([^\\(\\)\"']*)[\"']" ")"); int start_index = 0; QRegularExpressionMatch mo = reference.match(result, start_index); do { for (int i = 1; i < reference.captureCount(); ++i) { if (mo.captured(i).trimmed().isEmpty()) { continue; } QString apath = Utility::URLDecodePath(mo.captured(i)); QString search_key = QDir::cleanPath(m_currentdir + FORWARD_SLASH + apath); QString new_href; if (m_sourceupdates.contains(search_key)) { new_href = m_sourceupdates.value(search_key); } if (!new_href.isEmpty()) { new_href = Utility::URLEncodePath(new_href); result.replace(mo.capturedStart(i), mo.capturedLength(i), new_href); } } start_index += mo.capturedLength(); mo = reference.match(result, start_index); } while (mo.hasMatch()); return result.toStdString(); }
void TCommandLine::handleTabCompletion(bool direction) { if ((mTabCompletionCount < 0) || (mUserKeptOnTyping)) { mTabCompletionTyped = toPlainText(); if (mTabCompletionTyped.size() == 0) { return; } mUserKeptOnTyping = false; mTabCompletionCount = -1; } int amount = mpHost->mpConsole->buffer.size(); if (amount > 500) { amount = 500; } QStringList bufferList = mpHost->mpConsole->buffer.getEndLines(amount); QString buffer = bufferList.join(QChar::Space); buffer.replace(QChar(0x21af), QChar::LineFeed); buffer.replace(QChar::LineFeed, QChar::Space); QStringList wordList = buffer.split(QRegularExpression(QStringLiteral(R"(\b)"), QRegularExpression::UseUnicodePropertiesOption), QString::SkipEmptyParts); if (direction) { mTabCompletionCount++; } else { mTabCompletionCount--; } if (!wordList.empty()) { if (mTabCompletionTyped.endsWith(QChar::Space)) { return; } QString lastWord; QRegularExpression reg = QRegularExpression(QStringLiteral(R"(\b(\w+)$)"), QRegularExpression::UseUnicodePropertiesOption); QRegularExpressionMatch match = reg.match(mTabCompletionTyped); int typePosition = match.capturedStart(); if (reg.captureCount() >= 1) { lastWord = match.captured(1); } else { lastWord = QString(); } QStringList filterList = wordList.filter(QRegularExpression(QStringLiteral(R"(^%1\w+)").arg(lastWord), QRegularExpression::CaseInsensitiveOption | QRegularExpression::UseUnicodePropertiesOption)); if (filterList.empty()) { return; } int offset = 0; for (;;) { QString tmp = filterList.back(); filterList.removeAll(tmp); filterList.insert(offset, tmp); ++offset; if (offset >= filterList.size()) { break; } } if (!filterList.empty()) { if (mTabCompletionCount >= filterList.size()) { mTabCompletionCount = filterList.size() - 1; } if (mTabCompletionCount < 0) { mTabCompletionCount = 0; } QString proposal = filterList[mTabCompletionCount]; QString userWords = mTabCompletionTyped.left(typePosition); setPlainText(QString(userWords + proposal).trimmed()); moveCursor(QTextCursor::End, QTextCursor::MoveAnchor); mTabCompletionOld = toPlainText(); } } }
void Query::buildG2Keywords( QString strPhrase ) { QStringList lPositive, lNegative; strPhrase = strPhrase.trimmed().replace( "_", " " ).normalized( QString::NormalizationForm_KC ).toLower().append( " " ); QStringList lWords; { QRegularExpression re( "(-?\\\".*\\\"|-?\\w+)\\W+", QRegularExpression::InvertedGreedinessOption ); int nPos = 0, nOldPos = 0; bool bHasDash = false; QRegularExpressionMatch oMatch; while ( ( oMatch = re.match( strPhrase, nPos ) ).hasMatch() ) { nPos = re.match( strPhrase, nPos ).capturedStart(); QString sWord = oMatch.captured( 1 ); if ( bHasDash && nPos - oMatch.capturedLength() - nOldPos == 0 && lWords.last().size() < 4 && sWord.size() < 4 ) { lWords.last().append( "-" ).append( sWord ); } else { lWords << sWord; } nOldPos = nPos; nPos += oMatch.capturedLength(); if ( strPhrase.mid( nPos - 1, 1 ) == "-" ) { bHasDash = true; } else { bHasDash = false; } } } lWords.removeDuplicates(); for ( QStringList::iterator itWord = lWords.begin(); itWord != lWords.end(); ) { if ( ( *itWord ).size() < 4 ) { itWord = lWords.erase( itWord ); } else { itWord++; } } QRegularExpression rx( "\\w+" ); foreach ( const QString& sWord, lWords ) { if ( sWord.at( 0 ) == '-' && sWord.at( 1 ) != '"' ) { // plain negative word m_sG2NegativeWords.append( sWord.mid( 1 ) ).append( "," ); lNegative.append( sWord.mid( 1 ) ); } else if ( sWord.at( 0 ) == '"' ) { // positive quoted phrase m_sG2PositiveWords.append( sWord ).append( "," ); // extract words int p = 0; QRegularExpressionMatch oMatch; while ( ( oMatch = rx.match( sWord, p ) ).hasMatch() ) { p = oMatch.capturedStart() + oMatch.capturedLength(); lPositive.append( oMatch.captured() ); } } else if ( sWord.at( 0 ) == '-' && sWord.at( 1 ) == '"' ) { // negative quoted phrase m_sG2NegativeWords.append( sWord ).append( "," ); // extract words int p = 0; QRegularExpressionMatch oMatch; while ( ( oMatch = rx.match( sWord, p ) ).hasMatch() ) { p = oMatch.capturedStart() + oMatch.capturedLength(); lNegative.append( oMatch.captured() ); } } else { // plain positive word m_sG2PositiveWords.append( sWord ).append( "," ); lPositive.append( sWord ); } } m_sG2PositiveWords.chop( 1 ); m_sG2NegativeWords.chop( 1 ); foreach( const QString& sWord, lNegative ) { lPositive.removeAll( sWord ); }
void SignalSyntax::highlightBlock(const QString& text) { QTextCharFormat pointFormat; pointFormat.setFontWeight(QFont::Normal); pointFormat.setForeground(QBrush(QColor(180,182,182))); pointFormat.setFont(CodeFont{}); QTextCharFormat ppointFormat; ppointFormat.setFontWeight(QFont::Normal); ppointFormat.setForeground(QBrush(QColor(232,117,15))); ppointFormat.setFont(CodeFont{}); QTextCharFormat commaFormat; commaFormat.setFontWeight(QFont::Normal); commaFormat.setForeground(QBrush(QColor(239,93,61))); commaFormat.setFont(CodeFont{}); QRegularExpression countReg("^[0-9]*|\\[[ 0-9]*\\]"); QRegularExpressionMatchIterator itr = countReg.globalMatch(text); while(itr.hasNext()) { QRegularExpressionMatch match = itr.next(); setFormat(match.capturedStart(), match.capturedLength(), ppointFormat); } QRegularExpression pointReg("[A-Za-z,\\.:() <>\\[\\]\\_$0-9]*"); itr = pointReg.globalMatch(text); while(itr.hasNext()) { QRegularExpressionMatch match = itr.next(); setFormat(match.capturedStart(), match.capturedLength(), pointFormat); } QRegularExpression ppointReg("::[A-Za-z0-9_]*:"); itr = ppointReg.globalMatch(text); while(itr.hasNext()) { QRegularExpressionMatch match = itr.next(); setFormat(match.capturedStart(), match.capturedLength(), ppointFormat); } QRegularExpression ppointReg4("[ ]+[A-Za-z0-9_]*:"); itr = ppointReg4.globalMatch(text); while(itr.hasNext()) { QRegularExpressionMatch match = itr.next(); setFormat(match.capturedStart(), match.capturedLength(), ppointFormat); } QRegularExpression commaReg("[\\,]*"); itr = commaReg.globalMatch(text); while(itr.hasNext()) { QRegularExpressionMatch match = itr.next(); setFormat(match.capturedStart(), match.capturedLength(), commaFormat); } QRegularExpression pointReg2("[:]*"); itr = pointReg2.globalMatch(text); while(itr.hasNext()) { QRegularExpressionMatch match = itr.next(); setFormat(match.capturedStart(), match.capturedLength(), pointFormat); } }
void ReplaceMatches::doReplaceNextMatch() { if ((!m_manager) || (m_cancelReplace) || (m_tree->topLevelItemCount() != 1)) { m_rootIndex = -1; emit replaceDone(); return; } // NOTE The document managers signal documentWillBeDeleted() must be connected to // cancelReplace(). A closed file could lead to a crash if it is not handled. // Open the file QTreeWidgetItem *rootItem = m_tree->topLevelItem(0)->child(m_rootIndex); if (!rootItem) { m_rootIndex = -1; emit replaceDone(); return; } if (!rootItem->data(0, ColumnRole).toString().isEmpty()) { // this is a search as you type replace rootItem = m_tree->topLevelItem(0); m_cancelReplace = true; // only one document... } if (rootItem->checkState(0) == Qt::Unchecked) { m_rootIndex++; emit replaceNextMatch(); return; } KTextEditor::Document *doc; QString docUrl = rootItem->data(0, FileUrlRole).toString(); QString docName = rootItem->data(0, FileNameRole).toString(); if (docUrl.isEmpty()) { doc = findNamed(rootItem->data(0, FileNameRole).toString()); } else { doc = m_manager->findUrl(QUrl::fromUserInput(docUrl)); if (!doc) { doc = m_manager->openUrl(QUrl::fromUserInput(rootItem->data(0, FileUrlRole).toString())); } } if (!doc) { m_rootIndex++; emit replaceNextMatch(); return; } QVector<KTextEditor::MovingRange*> rVector; QStringList rTexts; KTextEditor::MovingInterface* miface = qobject_cast<KTextEditor::MovingInterface*>(doc); int line; int column; int matchLen; int endLine; int endColumn; QTreeWidgetItem *item; QString matchLines; // lines might be modified so search the document again for (int i=0; i<rootItem->childCount(); i++) { item = rootItem->child(i); if (item->checkState(0) == Qt::Unchecked) continue; line = endLine= item->data(0, LineRole).toInt(); column = item->data(0, ColumnRole).toInt(); matchLen = item->data(0, MatchLenRole).toInt(); matchLines = doc->line(line).mid(column); while (matchLines.size() < matchLen) { if (endLine+1 >= doc->lines()) break; endLine++; matchLines+= QLatin1Char('\n') + doc->line(endLine); } QRegularExpressionMatch match = m_regExp.match(matchLines); if (match.capturedStart() != 0) { qDebug() << matchLines << "Does not match" << m_regExp.pattern(); continue; } QString replaceText = m_replaceText; replaceText.replace(QStringLiteral("\\\\"), QStringLiteral("¤Search&Replace¤")); // allow captures \0 .. \9 for (int j = qMin(9, match.lastCapturedIndex()); j >= 0; --j) { replaceText.replace(QString(QStringLiteral("\\%1")).arg(j), match.captured(j)); } // allow captures \{0} .. \{9999999}... for (int j = match.lastCapturedIndex(); j >= 0; --j) { replaceText.replace(QString(QStringLiteral("\\{%1}")).arg(j), match.captured(j)); } replaceText.replace(QStringLiteral("\\n"), QStringLiteral("\n")); replaceText.replace(QStringLiteral("\\t"), QStringLiteral("\t")); replaceText.replace(QStringLiteral("¤Search&Replace¤"), QStringLiteral("\\")); rTexts << replaceText; replaceText.replace(QLatin1Char('\n'), QStringLiteral("\\n")); replaceText.replace(QLatin1Char('\t'), QStringLiteral("\\t")); QString html = item->data(0, PreMatchRole).toString(); html += QStringLiteral("<i><s>") + item->data(0, MatchRole).toString() + QStringLiteral("</s></i> "); html += QStringLiteral("<b>") + replaceText + QStringLiteral("</b>"); html += item->data(0, PostMatchRole).toString(); item->setData(0, Qt::DisplayRole, i18n("Line: <b>%1</b>: %2",line+1, html)); endLine = line; endColumn = column+matchLen; while ((endLine < doc->lines()) && (endColumn > doc->line(endLine).size())) { endColumn -= doc->line(endLine).size(); endColumn--; // remove one for '\n' endLine++; } KTextEditor::Range range(line, column, endLine, endColumn); KTextEditor::MovingRange* mr = miface->newMovingRange(range); rVector.append(mr); } for (int i=0; i<rVector.size(); i++) { line = rVector[i]->start().line(); column = rVector[i]->start().column(); doc->replaceText(*rVector[i], rTexts[i]); emit matchReplaced(doc, line, column, rTexts[i].length()); } qDeleteAll(rVector); m_rootIndex++; emit replaceNextMatch(); }
void readInlineText(const QString &data) { QString line = data; // remove all but one space on the front { bool startedWithSpace = line.startsWith(' '); line = line.remove(QRegularExpression("^ *")); if (startedWithSpace) { line = " " + line; } } // inline code { QRegularExpression exp("`(.*)`"); QRegularExpressionMatch match = exp.match(line); while (match.hasMatch()) { codeSections.append(match.captured(1)); line.replace(match.capturedStart(), match.capturedLength(), QString("$${{%1}}$$").arg(codeSections.size() - 1)); match = exp.match(line); } } // link and image { QRegularExpression exp("(\\!?)\\[(.*)\\]\\((.*)\\)"); QRegularExpressionMatch match = exp.match(line); while (match.hasMatch()) { if (match.captured(1) == "!") { // FIXME this no work htmlSections.append(QString("<img src=\"%1\" alt=\"%2\"/>").arg(match.captured(3), match.captured(2))); } else { htmlSections.append(QString("<a href=\"%1\">%2</a>").arg(match.captured(3), match.captured(2))); } line.replace(match.capturedStart(), match.capturedLength(), QString("$$[[%1]]$$").arg(htmlSections.size() - 1)); match = exp.match(line); } } QTextCharFormat fmt; int numStarsOrUnderscores = 0; QChar last = 0; for (const QChar &c : line) { if (last != c) { // bold if (numStarsOrUnderscores == 2) { if (fmt.fontWeight() == QFont::Normal) { fmt.setFontWeight(QFont::Bold); } else { fmt.setFontWeight(QFont::Normal); } } // italic else if (numStarsOrUnderscores == 1) { fmt.setFontItalic(!fmt.fontItalic()); } numStarsOrUnderscores = 0; cursor.setCharFormat(fmt); } last = c; if (c == '*' || c == '_') { numStarsOrUnderscores++; } else { cursor.insertText(c); } } }
void FlatTextarea::parseLinks() { // some code is duplicated in text.cpp! LinkRanges newLinks; QString text(toPlainText()); if (text.isEmpty()) { if (!_links.isEmpty()) { _links.clear(); emit linksChanged(); } return; } initLinkSets(); int32 len = text.size(); const QChar *start = text.unicode(), *end = start + text.size(); for (int32 offset = 0, matchOffset = offset; offset < len;) { QRegularExpressionMatch m = reDomain().match(text, matchOffset); if (!m.hasMatch()) break; int32 domainOffset = m.capturedStart(); QString protocol = m.captured(1).toLower(); QString topDomain = m.captured(3).toLower(); bool isProtocolValid = protocol.isEmpty() || validProtocols().contains(hashCrc32(protocol.constData(), protocol.size() * sizeof(QChar))); bool isTopDomainValid = !protocol.isEmpty() || validTopDomains().contains(hashCrc32(topDomain.constData(), topDomain.size() * sizeof(QChar))); if (protocol.isEmpty() && domainOffset > offset + 1 && *(start + domainOffset - 1) == QChar('@')) { QString forMailName = text.mid(offset, domainOffset - offset - 1); QRegularExpressionMatch mMailName = reMailName().match(forMailName); if (mMailName.hasMatch()) { offset = matchOffset = m.capturedEnd(); continue; } } if (!isProtocolValid || !isTopDomainValid) { offset = matchOffset = m.capturedEnd(); continue; } QStack<const QChar*> parenth; const QChar *domainEnd = start + m.capturedEnd(), *p = domainEnd; for (; p < end; ++p) { QChar ch(*p); if (chIsLinkEnd(ch)) break; // link finished if (chIsAlmostLinkEnd(ch)) { const QChar *endTest = p + 1; while (endTest < end && chIsAlmostLinkEnd(*endTest)) { ++endTest; } if (endTest >= end || chIsLinkEnd(*endTest)) { break; // link finished at p } p = endTest; ch = *p; } if (ch == '(' || ch == '[' || ch == '{' || ch == '<') { parenth.push(p); } else if (ch == ')' || ch == ']' || ch == '}' || ch == '>') { if (parenth.isEmpty()) break; const QChar *q = parenth.pop(), open(*q); if ((ch == ')' && open != '(') || (ch == ']' && open != '[') || (ch == '}' && open != '{') || (ch == '>' && open != '<')) { p = q; break; } } } if (p > domainEnd) { // check, that domain ended if (domainEnd->unicode() != '/' && domainEnd->unicode() != '?') { matchOffset = domainEnd - start; continue; } } newLinks.push_back(qMakePair(domainOffset - 1, p - start - domainOffset + 2)); offset = matchOffset = p - start; } if (newLinks != _links) { _links = newLinks; emit linksChanged(); } }