mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
shortcut negation syntax
This commit is contained in:
parent
df69b1d8dd
commit
4c7b1d6543
@ -64,6 +64,11 @@ describe("Lexer expression", () => {
|
|||||||
.toEqual(["#", "~author", ".", "title", "=", "hugh howey", "and", "note", ".", "book title", "=", "silo"]);
|
.toEqual(["#", "~author", ".", "title", "=", "hugh howey", "and", "note", ".", "book title", "=", "silo"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("negation of label and relation", () => {
|
||||||
|
expect(lexer(`#!capital ~!neighbor`).expressionTokens)
|
||||||
|
.toEqual(["#!capital", "~!neighbor"]);
|
||||||
|
});
|
||||||
|
|
||||||
it("negation of sub-expression", () => {
|
it("negation of sub-expression", () => {
|
||||||
expect(lexer(`# not(#capital) and note.noteId != "root"`).expressionTokens)
|
expect(lexer(`# not(#capital) and note.noteId != "root"`).expressionTokens)
|
||||||
.toEqual(["#", "not", "(", "#capital", ")", "and", "note", ".", "noteid", "!=", "root"]);
|
.toEqual(["#", "not", "(", "#capital", ")", "and", "note", ".", "noteid", "!=", "root"]);
|
||||||
|
@ -21,13 +21,16 @@ describe("Parser", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(rootExp.constructor.name).toEqual("OrExp");
|
expect(rootExp.constructor.name).toEqual("OrExp");
|
||||||
const [firstSub, secondSub] = rootExp.subExpressions;
|
const subs = rootExp.subExpressions;
|
||||||
|
|
||||||
expect(firstSub.constructor.name).toEqual("NoteCacheFulltextExp");
|
expect(subs[0].constructor.name).toEqual("NoteCacheFulltextExp");
|
||||||
expect(firstSub.tokens).toEqual(["hello", "hi"]);
|
expect(subs[0].tokens).toEqual(["hello", "hi"]);
|
||||||
|
|
||||||
expect(secondSub.constructor.name).toEqual("NoteContentFulltextExp");
|
expect(subs[1].constructor.name).toEqual("NoteContentProtectedFulltextExp");
|
||||||
expect(secondSub.tokens).toEqual(["hello", "hi"]);
|
expect(subs[1].tokens).toEqual(["hello", "hi"]);
|
||||||
|
|
||||||
|
expect(subs[2].constructor.name).toEqual("NoteContentUnprotectedFulltextExp");
|
||||||
|
expect(subs[2].tokens).toEqual(["hello", "hi"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("simple label comparison", () => {
|
it("simple label comparison", () => {
|
||||||
@ -43,6 +46,30 @@ describe("Parser", () => {
|
|||||||
expect(rootExp.comparator).toBeTruthy();
|
expect(rootExp.comparator).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("simple attribute negation", () => {
|
||||||
|
let rootExp = parser({
|
||||||
|
fulltextTokens: [],
|
||||||
|
expressionTokens: ["#!mylabel"],
|
||||||
|
parsingContext: new ParsingContext()
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(rootExp.constructor.name).toEqual("NotExp");
|
||||||
|
expect(rootExp.subExpression.constructor.name).toEqual("AttributeExistsExp");
|
||||||
|
expect(rootExp.subExpression.attributeType).toEqual("label");
|
||||||
|
expect(rootExp.subExpression.attributeName).toEqual("mylabel");
|
||||||
|
|
||||||
|
rootExp = parser({
|
||||||
|
fulltextTokens: [],
|
||||||
|
expressionTokens: ["~!myrelation"],
|
||||||
|
parsingContext: new ParsingContext()
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(rootExp.constructor.name).toEqual("NotExp");
|
||||||
|
expect(rootExp.subExpression.constructor.name).toEqual("AttributeExistsExp");
|
||||||
|
expect(rootExp.subExpression.attributeType).toEqual("relation");
|
||||||
|
expect(rootExp.subExpression.attributeName).toEqual("myrelation");
|
||||||
|
});
|
||||||
|
|
||||||
it("simple label AND", () => {
|
it("simple label AND", () => {
|
||||||
const rootExp = parser({
|
const rootExp = parser({
|
||||||
fulltextTokens: [],
|
fulltextTokens: [],
|
||||||
|
@ -83,6 +83,10 @@ function lexer(str) {
|
|||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if (['#', '~'].includes(currentWord) && chr === '!') {
|
||||||
|
currentWord += chr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
else if (chr === ' ') {
|
else if (chr === ' ') {
|
||||||
finishWord();
|
finishWord();
|
||||||
continue;
|
continue;
|
||||||
@ -93,7 +97,10 @@ function lexer(str) {
|
|||||||
finishWord();
|
finishWord();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (fulltextEnded && previousOperatorSymbol() !== isOperatorSymbol(chr)) {
|
else if (fulltextEnded
|
||||||
|
&& !['#!', '~!'].includes(currentWord)
|
||||||
|
&& previousOperatorSymbol() !== isOperatorSymbol(chr)) {
|
||||||
|
|
||||||
finishWord();
|
finishWord();
|
||||||
|
|
||||||
currentWord += chr;
|
currentWord += chr;
|
||||||
|
@ -70,8 +70,8 @@ function getExpression(tokens, parsingContext, level = 0) {
|
|||||||
i++;
|
i++;
|
||||||
|
|
||||||
return new OrExp([
|
return new OrExp([
|
||||||
NoteContentUnprotectedFulltextExp(operator, [tokens[i]]),
|
new NoteContentUnprotectedFulltextExp(operator, [tokens[i]]),
|
||||||
NoteContentProtectedFulltextExp(operator, [tokens[i]])
|
new NoteContentProtectedFulltextExp(operator, [tokens[i]])
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,6 +134,22 @@ function getExpression(tokens, parsingContext, level = 0) {
|
|||||||
parsingContext.addError(`Unrecognized note property "${tokens[i]}"`);
|
parsingContext.addError(`Unrecognized note property "${tokens[i]}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseAttribute(name) {
|
||||||
|
const isLabel = name.startsWith('#');
|
||||||
|
|
||||||
|
name = name.substr(1);
|
||||||
|
|
||||||
|
const isNegated = name.startsWith('!');
|
||||||
|
|
||||||
|
if (isNegated) {
|
||||||
|
name = name.substr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const subExp = isLabel ? parseLabel(name) : parseRelation(name);
|
||||||
|
|
||||||
|
return isNegated ? new NotExp(subExp) : subExp;
|
||||||
|
}
|
||||||
|
|
||||||
function parseLabel(labelName) {
|
function parseLabel(labelName) {
|
||||||
parsingContext.highlightedTokens.push(labelName);
|
parsingContext.highlightedTokens.push(labelName);
|
||||||
|
|
||||||
@ -234,15 +250,8 @@ function getExpression(tokens, parsingContext, level = 0) {
|
|||||||
if (Array.isArray(token)) {
|
if (Array.isArray(token)) {
|
||||||
expressions.push(getExpression(token, parsingContext, level++));
|
expressions.push(getExpression(token, parsingContext, level++));
|
||||||
}
|
}
|
||||||
else if (token.startsWith('#')) {
|
else if (token.startsWith('#') || token.startsWith('~')) {
|
||||||
const labelName = token.substr(1);
|
expressions.push(parseAttribute(token));
|
||||||
|
|
||||||
expressions.push(parseLabel(labelName));
|
|
||||||
}
|
|
||||||
else if (token.startsWith('~')) {
|
|
||||||
const relationName = token.substr(1);
|
|
||||||
|
|
||||||
expressions.push(parseRelation(relationName));
|
|
||||||
}
|
}
|
||||||
else if (['orderby', 'limit'].includes(token)) {
|
else if (['orderby', 'limit'].includes(token)) {
|
||||||
if (level !== 0) {
|
if (level !== 0) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user