QString LayerListModel::getAvailableLayerName(QString basename) const { // Return a layer name of format "basename n" where n is one bigger than the // biggest suffix number of layers named "basename n". // First, strip suffix number from the basename (if it exists) QRegularExpression suffixNumRe("(\\d+)$"); { auto m = suffixNumRe.match(basename); if(m.hasMatch()) { basename = basename.mid(0, m.capturedStart()).trimmed(); } } // Find the biggest suffix in the layer stack int suffix = 0; for(const LayerListItem &l : _items) { auto m = suffixNumRe.match(l.title); if(m.hasMatch()) { if(l.title.startsWith(basename)) { suffix = qMax(suffix, m.captured(1).toInt()); } } } // Make unique name return QString("%2 %1").arg(suffix+1).arg(basename); }
void SyntaxHighlighter::highlightBlock(const QString& text) { for (auto r : rules) { auto iter = r.first.globalMatch(text); while (iter.hasNext()) { auto match = iter.next(); auto index = match.lastCapturedIndex(); setFormat(match.capturedStart(index), match.capturedLength(index), r.second); } } }
/** * @brief prepend the match string with specify symbol * @param input string need to prepend symbol * @param number_length the length of the number, will prepend symbol * if the length smaller than this number * @param symbol symbol prepand before the number * @return the name after alter * @example ex : number_length == 3, reg = (\\d+), symbol = '0' * then "1" == "001", "10" == "010" * ex : number_length == 2, reg = (\\d+), symbol = '0' * then "1" == "01", "10" == "10" */ QString prepend_symbol_on_match(QString const &input, int number_length, QRegularExpression const ®, QChar symbol) { auto new_file_name = input; auto match = reg.match(new_file_name); if(match.hasMatch()){ auto const Captured = match.captured(0); if(Captured.size() < number_length){ new_file_name.insert(match.capturedStart(0), QString(number_length - match.capturedLength(1), symbol)); } } return new_file_name; }
KTextEditor::Cursor KTextEditorHelpers::extractCursor(const QString& input, int* pathLength) { static const QRegularExpression pattern(QStringLiteral(":(\\d+)(?::(\\d+))?$")); const auto match = pattern.match(input); if (!match.hasMatch()) { if (pathLength) *pathLength = input.length(); return KTextEditor::Cursor::invalid(); } int line = match.capturedRef(1).toInt() - 1; // don't use an invalid column when the line is valid int column = qMax(0, match.captured(2).toInt() - 1); if (pathLength) *pathLength = match.capturedStart(0); return {line, column}; }
void ItemSourceHighlighter::highlightBlock(const QString& text) { // // Apply matching highlighting rules. // for (const auto& rule : rules_) { for (const auto& expression : rule.expressions) { auto matches = expression.globalMatch(text); while (matches.hasNext() == true) { auto match = matches.next(); setFormat(match.capturedStart(1), match.capturedLength(1), rule.format); } } } }
const QString clearHTMLTags(const QString &text) { const QRegularExpression regex("<(\\w+)[^>]*>([^<]*)</\\1>"); QString ret = text; do { const auto match = regex.match(ret); if (!match.isValid() || !match.hasMatch()) break; const int start = match.capturedStart(); const int len = match.capturedLength(); const QString &cap = match.captured(2); ret.replace(start, len, cap); } while (true); return ret; }
QString linkify(const QString &input) { // This regular expression is from: http://blog.mattheworiordan.com/post/13174566389/url-regular-expression-for-links-with-or-without-the static const QRegularExpression linkre( "((([A-Za-z]{3,9}:(?:\\/\\/)?)(?:[\\-;:&=\\+\\$,\\w]+@)?[A-Za-z0-9\\.\\-]+|(?:www\\.|[\\-;:&=\\+\\$,\\w]+@)[A-Za-z0-9\\.\\-]+)((?:\\/[\\+~%\\/\\.\\w\\-_]*)?\\?" "?(?:[\\-\\+=&;%@\\.\\w_]*)#?(?:[\\.\\!\\/\\\\\\w]*))?)" ); static const QRegularExpression protore("^[a-zA-Z]{3,}:"); auto matches = linkre.globalMatch(input); QString out; int pos=0; while(matches.hasNext()) { auto m = matches.next(); QString url = m.captured(); out.append(input.midRef(pos, m.capturedStart() - pos)); pos = m.capturedEnd(); out.append("<a href=\""); if(!protore.match(url).hasMatch()) out.append("http://"); out.append(url); out.append("\">"); out.append(url); out.append("</a>"); } // special case optimization: no matches if(pos==0) return input; out.append(input.midRef(pos)); return out; }
void MessageLinksParser::parse() { const auto &textWithTags = _field->getTextWithTags(); const auto &text = textWithTags.text; const auto &tags = textWithTags.tags; const auto &markdownTags = _field->getMarkdownTags(); if (text.isEmpty()) { _list = QStringList(); return; } auto ranges = QVector<LinkRange>(); auto tag = tags.begin(); const auto tagsEnd = tags.end(); const auto processTag = [&] { Expects(tag != tagsEnd); if (Ui::InputField::IsValidMarkdownLink(tag->id) && !IsMentionLink(tag->id)) { ranges.push_back({ tag->offset, tag->length, tag->id }); } ++tag; }; const auto processTagsBefore = [&](int offset) { while (tag != tagsEnd && tag->offset + tag->length <= offset) { processTag(); } }; const auto hasTagsIntersection = [&](int till) { if (tag == tagsEnd || tag->offset >= till) { return false; } while (tag != tagsEnd && tag->offset < till) { processTag(); } return true; }; auto markdownTag = markdownTags.begin(); const auto markdownTagsEnd = markdownTags.end(); const auto markdownTagsAllow = [&](int from, int length) { while (markdownTag != markdownTagsEnd && (markdownTag->adjustedStart + markdownTag->adjustedLength <= from || !markdownTag->closed)) { ++markdownTag; continue; } if (markdownTag == markdownTagsEnd || markdownTag->adjustedStart >= from + length) { return true; } // Ignore http-links that are completely inside some tags. // This will allow sending http://test.com/__test__/test correctly. return (markdownTag->adjustedStart > from) || (markdownTag->adjustedStart + markdownTag->adjustedLength < from + length); }; const auto len = text.size(); const QChar *start = text.unicode(), *end = start + text.size(); for (auto offset = 0, matchOffset = offset; offset < len;) { auto m = TextUtilities::RegExpDomain().match(text, matchOffset); if (!m.hasMatch()) break; auto domainOffset = m.capturedStart(); auto protocol = m.captured(1).toLower(); auto topDomain = m.captured(3).toLower(); auto isProtocolValid = protocol.isEmpty() || TextUtilities::IsValidProtocol(protocol); auto isTopDomainValid = !protocol.isEmpty() || TextUtilities::IsValidTopDomain(topDomain); if (protocol.isEmpty() && domainOffset > offset + 1 && *(start + domainOffset - 1) == QChar('@')) { auto forMailName = text.mid(offset, domainOffset - offset - 1); auto mMailName = TextUtilities::RegExpMailNameAtEnd().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; } } const auto range = LinkRange { domainOffset, static_cast<int>(p - start - domainOffset), QString() }; processTagsBefore(domainOffset); if (!hasTagsIntersection(range.start + range.length)) { if (markdownTagsAllow(range.start, range.length)) { ranges.push_back(range); } } offset = matchOffset = p - start; } processTagsBefore(QFIXED_MAX); apply(text, ranges); }