[utilities/kate] addons/openlink: Improve file link matching
Waqar Ahmed <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit d9c356f2ff75071c99de56edc0cfc1d6c81c515e by Waqar Ahmed.
Committed on 04/08/2026 at 09:13.
Pushed by waqar into branch 'master'.
Improve file link matching
Skip punctuation at the beginning and end
M +5 -0 addons/openlink/linkmatchtest.cpp
M +30 -18 addons/openlink/matchers.h
https://invent.kde.org/utilities/kate/-/commit/d9c356f2ff75071c99de56edc0cfc1d6c81c515e
diff --git a/addons/openlink/linkmatchtest.cpp b/addons/openlink/linkmatchtest.cpp
index 13d6f6ae08..ecbddac871 100644
--- a/addons/openlink/linkmatchtest.cpp
+++ b/addons/openlink/linkmatchtest.cpp
@@ -30,6 +30,7 @@ private Q_SLOTS:
QTest::addColumn<std::vector<OpenLinkRange>>("expected");
using R = std::vector<OpenLinkRange>;
+
QTest::addRow("1") << "Line has https://google.com"
<< R{OpenLinkRange{.start = 9, .end = 27, .link = QStringLiteral("https://google.com"), .type = HttpLink}};
QTest::addRow("2") << "Line has https://google.com and https://google.com"
@@ -106,6 +107,10 @@ private Q_SLOTS:
QTest::addRow("22") << QStringLiteral("<https://cullmann.dev> xxx <https://hello.dev>")
<< R{OpenLinkRange{.start = 1, .end = 21, .link = QStringLiteral("https://cullmann.dev"), .type = HttpLink},
OpenLinkRange{.start = 28, .end = 45, .link = QStringLiteral("https://hello.dev"), .type = HttpLink}};
+
+ // something like: (/home/user/projects/file/Extensions/xyz/File.cpp:713,
+ QTest::addRow("23") << QLatin1String("(%1:713,").arg(filePath)
+ << R{OpenLinkRange{.start = 1, .end = 1 + fileLen + 4, .link = filePath, .startPos = {713, 0}, .type = FileLink}};
}
void test()
diff --git a/addons/openlink/matchers.h b/addons/openlink/matchers.h
index 50164b47eb..a97e7a989c 100644
--- a/addons/openlink/matchers.h
+++ b/addons/openlink/matchers.h
@@ -87,8 +87,22 @@ static KTextEditor::Cursor parseLineCol(QStringView &link)
return KTextEditor::Cursor(line, col);
}
+static void pushLink(int s, int e, QStringView line, std::vector<OpenLinkRange> *outColumnRanges)
+{
+ QStringView linkView(QStringView(line).mid(s, e - s));
+ KTextEditor::Cursor c = parseLineCol(linkView);
+ QString link = linkView.toString();
+ if (QFileInfo(link).isFile()) {
+ outColumnRanges->push_back({.start = s, .end = e, .link = link, .startPos = c, .type = FileLink});
+ }
+}
+
static void matchFilePaths(const QString &line, std::vector<OpenLinkRange> *outColumnRanges)
{
+ const auto isPrevCharAcceptable = [](QChar c) {
+ return c == u' ' || c == u'"' || c == u'(' || c == u')' || c == u'=';
+ };
+
#ifdef Q_OS_WIN
const auto isValidDriveLetter = [](QChar letter) {
return (letter.isLetter() && letter.toUpper() >= u'A' && letter.toUpper() <= u'Z');
@@ -112,8 +126,8 @@ static void matchFilePaths(const QString &line, std::vector<OpenLinkRange> *outC
s = isAbsoloutePath ? s - 2 : s - 1;
s = isDotDotRelativePath ? s - 1 : s;
- // must be preceded by a space or d-quote
- if (s != 0 && line[s - 1] != u'"' && line[s - 1] != u' ') {
+ // must be preceded by a space or a symbol
+ if (s != 0 && !isPrevCharAcceptable(line[s - 1])) {
s = orignalS + 1;
continue;
}
@@ -123,6 +137,11 @@ static void matchFilePaths(const QString &line, std::vector<OpenLinkRange> *outC
if (!matchNextQuote) {
e = line.indexOf(QLatin1String(" "), s);
e = e == -1 ? line.size() : e;
+
+ // Strip trailing punctuation
+ while (e > s && (line[e - 1] == u',' || line[e - 1] == u'.')) {
+ e--;
+ }
} else {
e = line.indexOf(u'"', s);
if (e == -1) {
@@ -137,15 +156,9 @@ static void matchFilePaths(const QString &line, std::vector<OpenLinkRange> *outC
}
if (e != -1) {
- QStringView linkView(QStringView(line).mid(s, e - s));
- KTextEditor::Cursor c = parseLineCol(linkView);
- QString link = linkView.toString();
- if (QFileInfo(link).isFile()) {
- outColumnRanges->push_back({s, e, link, c, FileLink});
- }
+ pushLink(s, e, line, outColumnRanges);
}
s = e;
- continue;
} else {
s++;
}
@@ -158,17 +171,21 @@ static void matchFilePaths(const QString &line, std::vector<OpenLinkRange> *outC
if (s == -1) {
break;
}
- // must be preceded by a space or d-quote
- if (s != 0 && line[s - 1] != u'"' && line[s - 1] != u' ') {
+ // must be preceded by a space or a symbol
+ if (s != 0 && !isPrevCharAcceptable(line[s - 1])) {
s++;
continue;
}
-
const bool matchNextQuote = s > 0 && line[s - 1] == u'"'; // last char is quote?
int e = -1;
if (!matchNextQuote) {
e = line.indexOf(QLatin1String(" "), s);
e = e == -1 ? line.size() : e;
+
+ // Strip trailing punctuation
+ while (e > s && (line[e - 1] == u',' || line[e - 1] == u'.')) {
+ e--;
+ }
} else {
e = line.indexOf(u'"', s);
if (e == -1) {
@@ -177,12 +194,7 @@ static void matchFilePaths(const QString &line, std::vector<OpenLinkRange> *outC
}
if (e != -1) {
- QStringView linkView(QStringView(line).mid(s, e - s));
- KTextEditor::Cursor c = parseLineCol(linkView);
- QString link = linkView.toString();
- if (QFileInfo(link).isFile()) {
- outColumnRanges->push_back({s, e, link, c, FileLink});
- }
+ pushLink(s, e, line, outColumnRanges);
}
s = e;
}