4.9 KiB
4.9 KiB
Search Module
Quick Start
Basic Usage
import { SearchPanelComponent } from './components/search-panel/search-panel.component';
// In your component template
<app-search-panel
placeholder="Search in vault..."
context="vault"
(noteOpen)="openNote($event)"
/>
Standalone Search Bar
import { SearchBarComponent } from './components/search-bar/search-bar.component';
<app-search-bar
placeholder="Search..."
context="my-context"
(search)="onSearch($event)"
/>
Supported Operators
Operator | Description | Example |
---|---|---|
file: |
Match file name | file:.jpg |
path: |
Match file path | path:"Daily notes" |
content: |
Match in content | content:"hello" |
tag: |
Search tags | tag:#work |
line: |
Same line | line:(mix flour) |
block: |
Same block | block:(dog cat) |
section: |
Same section | section:(intro) |
task: |
In tasks | task:call |
task-todo: |
Uncompleted tasks | task-todo:review |
task-done: |
Completed tasks | task-done:meeting |
match-case: |
Case-sensitive | match-case:API |
ignore-case: |
Case-insensitive | ignore-case:test |
[property] |
Property exists | [description] |
[property:value] |
Property value | [status]:"draft" |
Boolean Operators
- AND (implicit):
term1 term2
- OR:
term1 OR term2
- NOT:
-term
- Grouping:
(term1 OR term2) term3
Special Syntax
- Exact phrase:
"hello world"
- Wildcard:
test*
- Regex:
/\d{4}/
Services
SearchIndexService
Indexes vault content for fast searching.
constructor(private searchIndex: SearchIndexService) {}
// Rebuild index
this.searchIndex.rebuildIndex(notes);
// Get suggestions
const suggestions = this.searchIndex.getSuggestions('tag', '#');
SearchEvaluatorService
Executes search queries.
constructor(private evaluator: SearchEvaluatorService) {}
// Search
const results = this.evaluator.search('tag:#work', {
caseSensitive: false
});
SearchAssistantService
Provides autocomplete and suggestions.
constructor(private assistant: SearchAssistantService) {}
// Get filtered options
const options = this.assistant.getFilteredOptions('pa');
// Get contextual suggestions
const suggestions = this.assistant.getSuggestions('path:proj');
SearchHistoryService
Manages search history.
constructor(private history: SearchHistoryService) {}
// Add to history
this.history.add('vault', 'my query');
// Get history
const items = this.history.list('vault');
// Clear history
this.history.clear('vault');
Components
SearchBarComponent
Main search input with Aa and .* buttons.
Inputs:
placeholder: string
- Placeholder textcontext: string
- History contextshowSearchIcon: boolean
- Show search iconinputClass: string
- Custom CSS classesinitialQuery: string
- Initial query value
Outputs:
search: { query: string; options: SearchOptions }
- Search eventqueryChange: string
- Query change event
SearchResultsComponent
Displays search results with grouping.
Inputs:
results: SearchResult[]
- Search results
Outputs:
noteOpen: { noteId: string; line?: number }
- Note open event
SearchPanelComponent
Complete search UI (bar + results).
Inputs:
placeholder: string
- Placeholder textcontext: string
- History context
Outputs:
noteOpen: { noteId: string; line?: number }
- Note open event
Examples
Complex Query
const query = `
path:projects/
tag:#active
(Python OR JavaScript)
-deprecated
file:".md"
match-case:"API"
`;
const results = this.evaluator.search(query, {
caseSensitive: false,
regexMode: false
});
Custom Search Context
import { SearchContext } from './search-parser.types';
const context: SearchContext = {
filePath: 'notes/test.md',
fileName: 'test',
fileNameWithExt: 'test.md',
content: 'Hello world',
tags: ['#test'],
properties: { status: 'draft' },
lines: ['Hello world'],
blocks: ['Hello world'],
sections: [{ heading: 'Title', content: 'Hello world', level: 1 }],
tasks: [{ text: 'Do something', completed: false, line: 1 }]
};
const predicate = queryToPredicate(parsed);
const matches = predicate(context);
Performance Tips
- Debounce input: Avoid searching on every keystroke
- Limit results: Cap results at reasonable number (e.g., 100)
- Incremental indexing: Update index incrementally instead of full rebuild
- Lazy loading: Load results as user scrolls
Testing
import { parseSearchQuery } from './search-parser';
describe('Search Parser', () => {
it('should parse file operator', () => {
const parsed = parseSearchQuery('file:test.md');
expect(parsed.isEmpty).toBe(false);
// Assert AST structure
});
});