mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 21:11:30 +08: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"]); | ||||
|     }); | ||||
| 
 | ||||
|     it("negation of label and relation", () => { | ||||
|         expect(lexer(`#!capital ~!neighbor`).expressionTokens) | ||||
|             .toEqual(["#!capital", "~!neighbor"]); | ||||
|     }); | ||||
| 
 | ||||
|     it("negation of sub-expression", () => { | ||||
|         expect(lexer(`# not(#capital) and note.noteId != "root"`).expressionTokens) | ||||
|             .toEqual(["#", "not", "(", "#capital", ")", "and", "note", ".", "noteid", "!=", "root"]); | ||||
|  | ||||
| @ -21,13 +21,16 @@ describe("Parser", () => { | ||||
|         }); | ||||
| 
 | ||||
|         expect(rootExp.constructor.name).toEqual("OrExp"); | ||||
|         const [firstSub, secondSub] = rootExp.subExpressions; | ||||
|         const subs = rootExp.subExpressions; | ||||
| 
 | ||||
|         expect(firstSub.constructor.name).toEqual("NoteCacheFulltextExp"); | ||||
|         expect(firstSub.tokens).toEqual(["hello", "hi"]); | ||||
|         expect(subs[0].constructor.name).toEqual("NoteCacheFulltextExp"); | ||||
|         expect(subs[0].tokens).toEqual(["hello", "hi"]); | ||||
| 
 | ||||
|         expect(secondSub.constructor.name).toEqual("NoteContentFulltextExp"); | ||||
|         expect(secondSub.tokens).toEqual(["hello", "hi"]); | ||||
|         expect(subs[1].constructor.name).toEqual("NoteContentProtectedFulltextExp"); | ||||
|         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", () => { | ||||
| @ -43,6 +46,30 @@ describe("Parser", () => { | ||||
|         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", () => { | ||||
|         const rootExp = parser({ | ||||
|             fulltextTokens: [], | ||||
|  | ||||
| @ -83,6 +83,10 @@ function lexer(str) { | ||||
| 
 | ||||
|                 continue; | ||||
|             } | ||||
|             else if (['#', '~'].includes(currentWord) && chr === '!') { | ||||
|                 currentWord += chr; | ||||
|                 continue; | ||||
|             } | ||||
|             else if (chr === ' ') { | ||||
|                 finishWord(); | ||||
|                 continue; | ||||
| @ -93,7 +97,10 @@ function lexer(str) { | ||||
|                 finishWord(); | ||||
|                 continue; | ||||
|             } | ||||
|             else if (fulltextEnded && previousOperatorSymbol() !== isOperatorSymbol(chr)) { | ||||
|             else if (fulltextEnded | ||||
|                 && !['#!', '~!'].includes(currentWord) | ||||
|                 && previousOperatorSymbol() !== isOperatorSymbol(chr)) { | ||||
| 
 | ||||
|                 finishWord(); | ||||
| 
 | ||||
|                 currentWord += chr; | ||||
|  | ||||
| @ -70,8 +70,8 @@ function getExpression(tokens, parsingContext, level = 0) { | ||||
|             i++; | ||||
| 
 | ||||
|             return new OrExp([ | ||||
|                 NoteContentUnprotectedFulltextExp(operator, [tokens[i]]), | ||||
|                 NoteContentProtectedFulltextExp(operator, [tokens[i]]) | ||||
|                 new NoteContentUnprotectedFulltextExp(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]}"`); | ||||
|     } | ||||
| 
 | ||||
|     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) { | ||||
|         parsingContext.highlightedTokens.push(labelName); | ||||
| 
 | ||||
| @ -234,15 +250,8 @@ function getExpression(tokens, parsingContext, level = 0) { | ||||
|         if (Array.isArray(token)) { | ||||
|             expressions.push(getExpression(token, parsingContext, level++)); | ||||
|         } | ||||
|         else if (token.startsWith('#')) { | ||||
|             const labelName = token.substr(1); | ||||
| 
 | ||||
|             expressions.push(parseLabel(labelName)); | ||||
|         } | ||||
|         else if (token.startsWith('~')) { | ||||
|             const relationName = token.substr(1); | ||||
| 
 | ||||
|             expressions.push(parseRelation(relationName)); | ||||
|         else if (token.startsWith('#') || token.startsWith('~')) { | ||||
|             expressions.push(parseAttribute(token)); | ||||
|         } | ||||
|         else if (['orderby', 'limit'].includes(token)) { | ||||
|             if (level !== 0) { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zadam
						zadam