scripts/search_bookmarks.sh
Rama main · réplica de lectura del repositorio original.
#!/bin/bash
# Search bookmarks using the same configured paths and index builder as ingestion.
set -euo pipefail
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
exec python3 - "$SKILL_DIR" "$@" <<'PY'
import contextlib
import json
import os
import sys
from pathlib import Path
sys.path.insert(0, str(Path(sys.argv[1]) / "scripts"))
import xkb_index
import xkb_paths
query = " ".join(sys.argv[2:]).strip()
if not query:
print("Usage: search_bookmarks.sh <keywords>", file=sys.stderr)
sys.exit(1)
print(f"Search: {query}\n================================\n")
index_file = xkb_paths.INDEX_FILE
if os.environ.get("AUTO_INDEX_UPDATE", "1") == "1" or not index_file.exists():
with contextlib.redirect_stdout(sys.stderr):
rebuilt = xkb_index.rebuild()
if not rebuilt:
print("[WARN] Index rebuild failed; results may be incomplete.", file=sys.stderr)
if not index_file.exists():
# Preserve the full-text fallback when no derived index is available.
matches = []
for path in sorted(xkb_paths.BOOKMARKS_DIR.rglob("*.md")):
try:
content = path.read_text(encoding="utf-8", errors="replace")
except OSError:
continue
if query.lower() in content.lower():
matches.append(path)
print(path)
print(f"{len(matches)} matching bookmark files (full-text fallback)")
sys.exit(0)
terms = [t.lower() for t in query.split() if t.strip()]
data = json.loads(index_file.read_text(encoding="utf-8"))
items = data.get('items', [])
matches = []
for item in items:
title = (item.get('title') or '').lower()
category = (item.get('category') or '').lower()
tags = ' '.join(item.get('tags') or []).lower()
summary = (item.get('summary') or '').lower()
blob = (item.get('searchable') or '').lower()
if not all(term in blob for term in terms):
continue
score = 0
for term in terms:
if term in title:
score += 6
if term in tags:
score += 5
if term in category:
score += 3
if term in summary:
score += 2
if term in blob:
score += 1
item['_score'] = score
matches.append(item)
if not matches:
print("❌ 沒有找到相關書籤")
sys.exit(0)
matches.sort(key=lambda x: x.get('_score', 0), reverse=True)
for i, item in enumerate(matches[:30], start=1):
title = item.get('title') or '(untitled)'
category = item.get('category') or 'general'
path = item.get('relative_path') or item.get('path')
summary = (item.get('summary') or '').replace('\n', ' ')
score = item.get('_score', 0)
print(f"📄 [{i}] {title}")
print(f" 分類: {category} | 分數: {score}")
print(f" 檔案: {path}")
if summary:
print(f" 摘要: {summary[:120]}...")
print()
print("================================")
print(f"✅ 共找到 {len(matches)} 個相關書籤(索引模式)")
PY