Skip to content

Commit

Permalink
fix: missing -negative query + fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
jillro committed Dec 20, 2024
1 parent 5d417bf commit 17005be
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 13 deletions.
5 changes: 3 additions & 2 deletions src/components/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ export const searchResultFiles = derived(
Promise.all(
$sortedFiles.map(async (file) => {
const content = await file.vault.cachedRead(file);
const tags =
getAllTags($appCache.getFileCache(file) as CachedMetadata) || [];
const tags = (
getAllTags($appCache.getFileCache(file) as CachedMetadata) || []
).map((t) => t.replace(/^#/, ""));

let frontmatter;
await $app.fileManager.processFrontMatter(file, (fm) => {
Expand Down
7 changes: 5 additions & 2 deletions src/search/search.grammar
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
@precedence {
Not
subExpression
or @left
SearchOperator @left
}

@top Program { expression }

expression { And | Or | Not }
expression { And | Or }

And { subExpression+ }
And { subExpressionOrNot+ }
Or { expression !or orOperator expression }
Not { "-" subExpression }
subExpressionOrNot { subExpression | Not }
subExpression { term | "(" expression ")" }
term { text | searchOperator | PropertyOperator }
text { Word | Quote | Regex }
Expand Down
40 changes: 40 additions & 0 deletions src/search/search.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@ describe("search", async () => {
assert.equal(await filter({ content: "ipsum" }), false);
});

await test("-lorem", async () => {
const query = "-lorem";
const filter = generateFilter(query);
assert.equal(await filter({ content: "lorem ipsum" }), false);
assert.equal(await filter({ content: "Lorem" }), false);
assert.equal(await filter({ content: "ipsum" }), true);
});

await test("lorem ipsum OR dolor sic", async () => {
const query = "lorem ipsum OR dolor sic";
const filter = generateFilter(query);
assert.equal(await filter({ content: "lorem ipsum" }), true);
assert.equal(await filter({ content: "dolor sic" }), true);
});

await test("lorem in filename", async () => {
const query = "lorem";
const filter = generateFilter(query);
Expand All @@ -74,6 +89,24 @@ describe("search", async () => {
assert.equal(await filter({ content: "dolor" }), false);
});

await test("-(lorem OR ipsum)", async () => {
const query = "-(lorem OR ipsum)";
const filter = generateFilter(query);
assert.equal(await filter({ content: "lorem ipsum" }), false);
assert.equal(await filter({ content: "ipsum" }), false);
assert.equal(await filter({ content: "lorem" }), false);
assert.equal(await filter({ content: "dolor" }), true);
});

await test("lorem -(ipsum OR dolor)", async () => {
const query = "lorem -(ipsum OR dolor)";
const filter = generateFilter(query);
assert.equal(await filter({ content: "lorem" }), true);
assert.equal(await filter({ content: "lorem ipsum" }), false);
assert.equal(await filter({ content: "lorem dolor" }), false);
assert.equal(await filter({ content: "sic amet" }), false);
});

await test("lorem ipsum OR dolor", async () => {
const query = "lorem ipsum OR dolor";
const filter = generateFilter(query);
Expand Down Expand Up @@ -199,6 +232,13 @@ describe("search", async () => {
assert.equal(await filter({ tags: ["ipsum"] }), false);
});

await test("tag:#lorem", async () => {
const query = "tag:#lorem";
const filter = generateFilter(query);
assert.equal(await filter({ tags: ["lorem"] }), true);
assert.equal(await filter({ tags: ["ipsum"] }), false);
});

await test("[lorem]", async () => {
const query = "[lorem]";
const filter = generateFilter(query);
Expand Down
26 changes: 17 additions & 9 deletions src/search/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { TFile } from "obsidian";
type FilterFn = (params: {
file?: TFile;
content?: string;
tags?: string[];
tags?: string[]; // Without the # prefix
frontmatter?: object;
caseSensitive?: boolean;
}) => Promise<boolean>;
Expand All @@ -22,9 +22,9 @@ function getAndFilter(input: string, cursor: TreeCursor): FilterFn {
if (!cursor.firstChild()) {
return async () => true;
}
filters.push(getTermFilter(input, cursor));
filters.push(getExpressionFilter(input, cursor));
while (cursor.nextSibling()) {
filters.push(getTermFilter(input, cursor));
filters.push(getExpressionFilter(input, cursor));
}

cursor.parent();
Expand All @@ -37,9 +37,9 @@ function getOrFilter(input: string, cursor: TreeCursor): FilterFn {
if (!cursor.firstChild()) {
return async () => true;
}
filters.push(expressionFilter(input, cursor));
filters.push(getExpressionFilter(input, cursor));
while (cursor.nextSibling()) {
filters.push(expressionFilter(input, cursor));
filters.push(getExpressionFilter(input, cursor));
}

cursor.parent();
Expand Down Expand Up @@ -229,7 +229,7 @@ function getTermFilter(input: string, cursor: TreeCursor): FilterFn {
if (!cursor.firstChild()) {
return async () => true;
}
const termFilter = expressionFilter(input, cursor);
const termFilter = getExpressionFilter(input, cursor);
cursor.parent();
return async ({
content,
Expand Down Expand Up @@ -304,7 +304,7 @@ function getTermFilter(input: string, cursor: TreeCursor): FilterFn {
return async () => true;
}

function expressionFilter(input: string, cursor: TreeCursor): FilterFn {
function getExpressionFilter(input: string, cursor: TreeCursor): FilterFn {
if (cursor.node.type.name === "And") {
return getAndFilter(input, cursor);
}
Expand All @@ -313,7 +313,14 @@ function expressionFilter(input: string, cursor: TreeCursor): FilterFn {
return getOrFilter(input, cursor);
}

return async () => true;
if (cursor.node.type.name === "Not") {
cursor.firstChild();
const filter = getExpressionFilter(input, cursor);
cursor.parent();
return async (params) => !(await filter(params));
}

return getTermFilter(input, cursor);
}

export default function generateFilter(input: string): FilterFn {
Expand All @@ -322,5 +329,6 @@ export default function generateFilter(input: string): FilterFn {
if (!cursor.firstChild()) {
return async () => true;
}
return expressionFilter(input, cursor);

return getExpressionFilter(input, cursor);
}

0 comments on commit 17005be

Please sign in to comment.