| 57 | } |
| 58 | |
| 59 | void URLFinder::findURLs() |
| 60 | { |
| 61 | clearURLs(); |
| 62 | |
| 63 | int currentLine = editor->docLineFromVisible(editor->firstVisibleLine()); |
| 64 | int linesLeftToProcess = editor->linesOnScreen(); |
| 65 | const int flags = SCFIND_REGEXP; |
| 66 | |
| 67 | while(linesLeftToProcess >= 0 && currentLine < editor->lineCount()) { |
| 68 | // Should only happen if the line is hidden |
| 69 | if (!editor->lineVisible(currentLine)) { |
| 70 | currentLine++; |
| 71 | continue; |
| 72 | } |
| 73 | |
| 74 | const int startPos = editor->positionFromLine(currentLine); |
| 75 | const int endPos = editor->lineEndPosition(currentLine); |
| 76 | QByteArray reg = QByteArrayLiteral(R"(\bhttps?://[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*))"); |
| 77 | |
| 78 | Sci_TextToFind ttf {{startPos, (Sci_PositionCR)endPos}, reg.constData(), {-1, -1}}; |
| 79 | while (editor->send(SCI_FINDTEXT, flags, (sptr_t)&ttf) != -1) { |
| 80 | const int startUrl = ttf.chrgText.cpMin; |
| 81 | int endUrl = ttf.chrgText.cpMax; |
| 82 | |
| 83 | // Though technically certain characters are allowed in the URL such as brackets, parenthesis, etc |
| 84 | // this adds a bit of logic to trim off the end character based on if something is in front if it, for example |
| 85 | // [https://example.com] probably shouldn't include the last bracket since it starts with an opening bracket. |
| 86 | if (startUrl > 0) { |
| 87 | const int prevChar = static_cast<int>(editor->charAt(startUrl - 1)); |
| 88 | const int nextChar = static_cast<int>(editor->charAt(endUrl - 1)); |
| 89 | |
| 90 | if ((prevChar == '(' && nextChar == ')') || |
| 91 | (prevChar == '[' && nextChar == ']') || |
| 92 | (prevChar == '<' && nextChar == '>') || |
| 93 | (prevChar == '"' && nextChar == '"')) { |
| 94 | endUrl--; |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | editor->indicatorFillRange(startUrl, endUrl - startUrl); |
| 99 | ttf.chrg.cpMin = endUrl; |
| 100 | } |
| 101 | |
| 102 | // If a line is wrapped, skip however many lines it takes up on the screen |
| 103 | linesLeftToProcess -= editor->wrapCount(currentLine); |
| 104 | |
| 105 | // If the current line is a fold header and the fold is not expanded, skip |
| 106 | if (((editor->foldLevel(currentLine) & SC_FOLDLEVELHEADERFLAG) == SC_FOLDLEVELHEADERFLAG) && (!editor->foldExpanded(currentLine))) { |
| 107 | currentLine = editor->lastChild(currentLine, -1) + 1; |
| 108 | } |
| 109 | else { |
| 110 | currentLine++; |
| 111 | } |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | void URLFinder::clearURLs() |
| 116 | { |
nothing calls this directly
no outgoing calls
no test coverage detected