222 lines
4.9 KiB
Markdown
222 lines
4.9 KiB
Markdown
# Search Module
|
|
|
|
## Quick Start
|
|
|
|
### Basic Usage
|
|
|
|
```typescript
|
|
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
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
constructor(private searchIndex: SearchIndexService) {}
|
|
|
|
// Rebuild index
|
|
this.searchIndex.rebuildIndex(notes);
|
|
|
|
// Get suggestions
|
|
const suggestions = this.searchIndex.getSuggestions('tag', '#');
|
|
```
|
|
|
|
### SearchEvaluatorService
|
|
|
|
Executes search queries.
|
|
|
|
```typescript
|
|
constructor(private evaluator: SearchEvaluatorService) {}
|
|
|
|
// Search
|
|
const results = this.evaluator.search('tag:#work', {
|
|
caseSensitive: false
|
|
});
|
|
```
|
|
|
|
### SearchAssistantService
|
|
|
|
Provides autocomplete and suggestions.
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
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 text
|
|
- `context: string` - History context
|
|
- `showSearchIcon: boolean` - Show search icon
|
|
- `inputClass: string` - Custom CSS classes
|
|
- `initialQuery: string` - Initial query value
|
|
|
|
**Outputs:**
|
|
- `search: { query: string; options: SearchOptions }` - Search event
|
|
- `queryChange: 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 text
|
|
- `context: string` - History context
|
|
|
|
**Outputs:**
|
|
- `noteOpen: { noteId: string; line?: number }` - Note open event
|
|
|
|
## Examples
|
|
|
|
### Complex Query
|
|
|
|
```typescript
|
|
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
|
|
|
|
```typescript
|
|
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
|
|
|
|
1. **Debounce input**: Avoid searching on every keystroke
|
|
2. **Limit results**: Cap results at reasonable number (e.g., 100)
|
|
3. **Incremental indexing**: Update index incrementally instead of full rebuild
|
|
4. **Lazy loading**: Load results as user scrolls
|
|
|
|
## Testing
|
|
|
|
```typescript
|
|
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
|
|
});
|
|
});
|
|
```
|