~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

A code search's pages go on from the one before

Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:serve/search-ties
crates/knotless-serve/src/web/search.rs+4−4
@@ -7,8 +7,8 @@ use serde_json::{Value, json};
/// How many files a search shows, if not asked, and at most.
const FILES: usize = 20;
const FILES_MAX: usize = 50;
/// How deep the pages of a search go: Zoekt answers the best files from
/// the first, so each page asks again for those before it.
/// How deep the pages of a search go: each page asks Zoekt for all of
/// them, as it cuts off files it scores alike as they come.
const DEEPEST: usize = 200;
#[derive(Deserialize)]
@@ -75,11 +75,11 @@ pub async fn search_code(
_ => Vec::new(),
}
};
let (found, faceted) = tokio::join!(code.search(&p.q, within, upto), faceted);
let (found, faceted) = tokio::join!(code.search(&p.q, within, DEEPEST), faceted);
let found = found?;
let more = upto < DEEPEST && found.file_count > upto as u64;
let listed = |h: crate::code::Hit| Some((index.listed(&h.did, &h.key).ok().flatten()?, h));
let pages_before = found.hits.into_iter().skip(skip);
let pages_before = found.hits.into_iter().take(upto).skip(skip);
let shown: Vec<_> = pages_before.filter_map(listed).collect();
let owners = shown.iter().map(|(r, _)| actor(&app, &r.did));
let owners = futures::future::join_all(owners).await;
crates/knotless-serve/src/code.rs+16−6
@@ -113,6 +113,8 @@ struct ZResult {
#[derive(Deserialize)]
#[serde(rename_all = "PascalCase")]
struct ZFile {
#[serde(default)]
score: f64,
file_name: String,
repository: String,
language: String,
@@ -278,12 +280,18 @@ impl Code {
"MaxWallTime": WALL.as_nanos() as u64,
});
let found = self.ask(within(q, repo), opts).await?;
let hits = found
.files
.unwrap_or_default()
.into_iter()
.filter_map(hit)
.collect();
let mut files = found.files.unwrap_or_default();
// The best first, and files Zoekt scores alike, as its shards
// answered in parallel, by repository and path: so each page
// after the first goes on from it rather than showing it again.
files.sort_by(|a, b| {
let named = a
.repository
.cmp(&b.repository)
.then(a.file_name.cmp(&b.file_name));
b.score.total_cmp(&a.score).then(named)
});
let hits = files.into_iter().filter_map(hit).collect();
Ok(Results {
hits,
file_count: found.file_count,
@@ -599,6 +607,7 @@ mod tests {
file_name: false,
};
let found = hit(ZFile {
score: 0.0,
file_name: "a".into(),
repository: "did:plc:a/k".into(),
language: String::new(),
@@ -610,6 +619,7 @@ mod tests {
assert_eq!(lines, [2, 30]);
assert!(
hit(ZFile {
score: 0.0,
file_name: "a".into(),
repository: "no-slash".into(),
language: String::new(),
docs/design/serve.md+7−5
@@ -442,11 +442,13 @@ query, run at the same time: the same one with its `lang:` filters taken
out, asking only for files (`type:file`), up to 1000 of them. Picking a
language then leaves the others listed.
Zoekt ranks the files it finds but has no cursor, so a page after the
first asks it for the best files up to that page's end, and leaves out
those the pages before held. Each page costs a little more than the one
before, so the pages stop 200 files deep: a search that finds more is
narrowed rather than read further. Only the first page asks for the
Zoekt ranks the files it finds but has no cursor, and files it scores
alike come back in whatever order its shards answered. So each page asks
it for the best 200 files, sorts those it scores alike by repository and
path, and answers its own slice of them: a page goes on from the one
before rather than showing a file again or passing one over. The pages
stop 200 files deep: a search that finds more is narrowed rather than
read further. Only the first page asks for the
languages.
### Shared steps
docs/reference/api.md+2−1
@@ -164,7 +164,8 @@ alone.
| `limit` | 20 | the most files answered, clamped to 1 to 50 |
| `cursor` | | from the page before: how many files it held |
Answers `files`, the best first, each with its `repo` (as `listRepos`
Answers `files`, the best first, and those found alike by repository and
path, each with its `repo` (as `listRepos`
answers one), `path`, `language?`, `commit?` (the commit of the default
branch that was indexed, which its lines are of) and `chunks`: runs of lines holding
matches, each its `startLine`, its `content` and its `ranges`, a match