| 27 | } |
| 28 | |
| 29 | export async function cmdSearchTitle(vault: string, args: ParsedArgs): Promise<void> { |
| 30 | const query = getString(args, 'query') ?? args.positionals.join(' ') |
| 31 | if (!query.trim()) throw new Error('zn search-title requires a query.') |
| 32 | const needle = query.trim().toLowerCase() |
| 33 | const limit = getNumber(args, 'limit') ?? 20 |
| 34 | const all = await listNotes(vault) |
| 35 | const matches = all |
| 36 | .filter((n) => n.folder !== 'trash' && n.title.toLowerCase().includes(needle)) |
| 37 | .sort((a, b) => b.updatedAt - a.updatedAt) |
| 38 | .slice(0, limit) |
| 39 | if (getBool(args, 'json')) { |
| 40 | emitJson(matches) |
| 41 | return |
| 42 | } |
| 43 | if (matches.length === 0) { |
| 44 | emitLine(`No notes matching "${query}".`) |
| 45 | return |
| 46 | } |
| 47 | for (const n of matches) emitLine(n.path) |
| 48 | } |
| 49 | |
| 50 | export async function cmdBacklinks(vault: string, args: ParsedArgs): Promise<void> { |
| 51 | const rel = getString(args, 'path') ?? args.positionals[0] |