Go-to-File: match and show the full project-relative path

The palette model matches only against PaletteItem::label (and the
delegate renders only the label; group was never shown). The file
switcher put the base name in label and the dir in group, so the
directory was neither matched nor displayed. Use the full relative path
as the label: FuzzyRanker already treats '/' as a word boundary and
length-penalises longer paths, so base-name hits still rank first while
orderless path-spanning queries work. 2 path-ranking tests added.
This commit is contained in:
Levi Neely 2026-10-07 20:10:31 +02:00
parent 42363157d3
commit 707e7c7250
3 changed files with 49 additions and 15 deletions

View File

@ -198,11 +198,16 @@ Therefore the palette is replaced, not extended, and the replacement is built on
(`walkDirectory`) that skips noise dirs (node_modules, build, target, …) and (`walkDirectory`) that skips noise dirs (node_modules, build, target, …) and
symlinks when there is no git (or git yields nothing). symlinks when there is no git (or git yields nothing).
- Wired into the plugin: **Alt+P** "Go to File (project)" opens a second - Wired into the plugin: **Alt+P** "Go to File (project)" opens a second
PaletteWidget populated with the project's files (base name as the label, PaletteWidget populated with the project's files. The **full project-relative
directory as the trailing hint). The root is derived from the active path** is the matched/displayed label, so FuzzyRanker scores across the
document's directory (fallback: cwd). Activation opens the file via whole path (orderless: "palette model" matches `src/palette/palettemodel.cpp`)
`MainWindow::openUrl` + `activateView`. Also reachable from the M-x palette and highlights matched characters along it; a base-name hit still ranks first
(`ollie:switch:file`) and, by objectName `ollie_goto_file`, from a radial. because `/` is a word boundary and the length penalty favours shorter paths.
The root is derived from the active document's directory (fallback: cwd).
Activation opens the file via `MainWindow::openUrl` + `activateView`. Also
reachable from the M-x palette (`ollie:switch:file`) and, by objectName
`ollie_goto_file`, from a radial. (2 path-ranking tests in
`test_palettemodel`.)
- Fuzzy symbol switcher scoped to the folder: DONE. - Fuzzy symbol switcher scoped to the folder: DONE.
`src/project/symbolindex.{h,cpp}` (in `project_lib`, 7 unit tests incl. a `src/project/symbolindex.{h,cpp}` (in `project_lib`, 7 unit tests incl. a
live ctags run): live ctags run):

View File

@ -125,6 +125,39 @@ private Q_SLOTS:
m.setQuery(QStringLiteral("ren")); m.setQuery(QStringLiteral("ren"));
QCOMPARE(spy.count(), 1); QCOMPARE(spy.count(), 1);
} }
// Full project-relative paths are matched as labels. A base-name query must
// rank the file whose base name it hits above files that only match the
// query as a scattered subsequence through their directory.
void pathLabelsRankBaseNameFirst()
{
PaletteModel m;
m.setItems({
{QStringLiteral("a"), QStringLiteral("src/plugin/ollieplugin.cpp"), QString(), 0},
{QStringLiteral("b"), QStringLiteral("src/palette/palettemodel.cpp"), QString(), 0},
{QStringLiteral("c"), QStringLiteral("src/main.cpp"), QString(), 0},
});
m.setQuery(QStringLiteral("main"));
QVERIFY(m.rowCount() >= 1);
// "src/main.cpp" has 'main' as a word-start substring; it must win.
QCOMPARE(m.index(0, 0).data(PaletteModel::LabelRole).toString(),
QStringLiteral("src/main.cpp"));
}
// Orderless, path-spanning tokens: "palette model" matches the directory and
// the base name in any order.
void pathLabelsMatchOrderlessTokens()
{
PaletteModel m;
m.setItems({
{QStringLiteral("a"), QStringLiteral("src/plugin/ollieplugin.cpp"), QString(), 0},
{QStringLiteral("b"), QStringLiteral("src/palette/palettemodel.cpp"), QString(), 0},
});
m.setQuery(QStringLiteral("palette model"));
QCOMPARE(m.rowCount(), 1);
QCOMPARE(m.index(0, 0).data(PaletteModel::LabelRole).toString(),
QStringLiteral("src/palette/palettemodel.cpp"));
}
}; };
QTEST_MAIN(TestPaletteModel) QTEST_MAIN(TestPaletteModel)

View File

@ -503,16 +503,12 @@ void OllieView::showFileSwitcher()
for (const QString &rel : files) { for (const QString &rel : files) {
PaletteItem item; PaletteItem item;
item.id = kFilePrefix + rel; item.id = kFilePrefix + rel;
// Show the file name as the label and the directory as the trailing // Match and display the full project-relative path: FuzzyRanker scores
// hint, so fuzzy matching favours the base name while the path stays // against the label (orderless tokens, so "src main" matches
// visible for disambiguation. // "src/main.cpp"), and the delegate highlights matched characters across
const int slash = rel.lastIndexOf(QLatin1Char('/')); // the whole path. The base name still ranks well because an exact or
if (slash >= 0) { // substring hit on it outscores a scattered subsequence.
item.label = rel.mid(slash + 1);
item.group = rel.left(slash);
} else {
item.label = rel; item.label = rel;
}
items.push_back(item); items.push_back(item);
} }
m_filePalette->setItems(items); m_filePalette->setItems(items);