diff --git a/.github/workflows/workstation-lampstand.yml b/.github/workflows/workstation-lampstand.yml index f86cd3e..b0aebee 100644 --- a/.github/workflows/workstation-lampstand.yml +++ b/.github/workflows/workstation-lampstand.yml @@ -23,7 +23,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Syntax check installer + - name: Syntax check installer and helper run: | set -euo pipefail bash -n profiles/linux-dev/workstation-v0/bin/install-lampstand.sh @@ -59,3 +59,49 @@ jobs: svc="$tmp_home/.config/systemd/user/sourceos-lampstand.service" test -f "$svc" grep -F 'lampstandd --root %h --rpc unixjson' "$svc" >/dev/null + + - name: Smoke: sourceos-search runtime commands with stub lampstand + run: | + set -euo pipefail + helper='profiles/linux-dev/workstation-v0/bin/sourceos-search.sh' + stub_bin=$(mktemp -d) + cat > "$stub_bin/lampstand" <<'EOF' + #!/usr/bin/env bash + set -euo pipefail + case "${1:-}" in + query) + printf '/tmp/example.txt\t(score=1.000)\n' + printf ' snippet for %s\n' "$*" + ;; + health) + printf '{"ok": true, "service": "lampstand"}\n' + ;; + stats) + printf '{"documents": 1, "terms": 3}\n' + ;; + index) + printf '{"indexed": 1}\n' + ;; + *) + printf 'unexpected command: %s\n' "$*" >&2 + exit 2 + ;; + esac + EOF + chmod +x "$stub_bin/lampstand" + + tmp_dir=$(mktemp -d) + query_out="$tmp_dir/query.txt" + health_out="$tmp_dir/health.json" + stats_out="$tmp_dir/stats.json" + + PATH="$stub_bin:$PATH" bash "$helper" --snippet --write "$query_out" report + grep -F '/tmp/example.txt' "$query_out" >/dev/null + + PATH="$stub_bin:$PATH" bash "$helper" health --write "$health_out" + grep -F '"ok": true' "$health_out" >/dev/null + + PATH="$stub_bin:$PATH" bash "$helper" stats --write "$stats_out" + grep -F '"documents": 1' "$stats_out" >/dev/null + + PATH="$stub_bin:$PATH" bash "$helper" index --root "$tmp_dir" >/dev/null diff --git a/profiles/linux-dev/workstation-v0/bin/sourceos b/profiles/linux-dev/workstation-v0/bin/sourceos index fbc4840..ee8586d 100644 --- a/profiles/linux-dev/workstation-v0/bin/sourceos +++ b/profiles/linux-dev/workstation-v0/bin/sourceos @@ -49,6 +49,7 @@ Usage: sourceos fix fish [apply|dry-run|revert] [--json] [--open|--write ] sourceos doctor [--json|--open|--write ] sourceos status [--json|--open|--write ] + sourceos search [health|stats|index] [options] sourceos search [--limit N] [--snippet] [--prompt] [--open|--write ] [query...] sourceos profile apply sourceos profile path @@ -473,6 +474,9 @@ Palette: Revert fish config patch sourceos fix fish revert Status (open report) sourceos status --open Doctor (open text report) sourceos doctor --open Search files (Lampstand) sourceos search --prompt --snippet --open +Lampstand health (open report) sourceos search health --open +Lampstand stats (open report) sourceos search stats --open +Lampstand index home sourceos search index --root "$HOME" Apply profile sourceos profile apply Open sesh sesh Open tmux tmux diff --git a/profiles/linux-dev/workstation-v0/bin/sourceos-search.sh b/profiles/linux-dev/workstation-v0/bin/sourceos-search.sh index d4b4b06..a5e67f9 100644 --- a/profiles/linux-dev/workstation-v0/bin/sourceos-search.sh +++ b/profiles/linux-dev/workstation-v0/bin/sourceos-search.sh @@ -26,12 +26,46 @@ run_lampstand(){ return 127 } +usage(){ + cat <<'EOF' +Usage: + sourceos-search.sh [--limit N] [--snippet] [--prompt] [--open|--write ] [query...] + sourceos-search.sh health [--open|--write ] + sourceos-search.sh stats [--open|--write ] + sourceos-search.sh index [--root ]... +EOF +} + +write_or_print(){ + local out=$1 + local default_name=$2 + if [[ "$SEARCH_OPEN" == "1" || -n "$SEARCH_WRITE_PATH" ]]; then + local path="$SEARCH_WRITE_PATH" + if [[ -z "$path" ]]; then mkdir -p "$(cache_dir)"; path="$(cache_dir)/$default_name"; fi + mkdir -p "$(dirname "$path")" + printf '%s\n' "$out" > "$path" + info "wrote: $path" + [[ "$SEARCH_OPEN" == "1" ]] && open_file "$path" + return 0 + fi + printf '%s\n' "$out" +} + SEARCH_LIMIT=20 SEARCH_SNIPPET=0 SEARCH_PROMPT=0 SEARCH_OPEN=0 SEARCH_WRITE_PATH="" QUERY_PARTS=() +LAMPSTAND_ROOTS=() +MODE="query" + +case "${1:-}" in + health|stats|index) + MODE="$1" + shift + ;; +esac while [[ $# -gt 0 ]]; do case "$1" in @@ -40,15 +74,34 @@ while [[ $# -gt 0 ]]; do --prompt) SEARCH_PROMPT=1; shift ;; --open) SEARCH_OPEN=1; shift ;; --write) shift; [[ $# -gt 0 ]] || { err "--write requires a path"; exit 2; }; SEARCH_WRITE_PATH="$1"; shift ;; - -h|--help) - cat <<'EOF' -Usage: sourceos-search.sh [--limit N] [--snippet] [--prompt] [--open|--write ] [query...] -EOF - exit 0 ;; + --root) shift; [[ $# -gt 0 ]] || { err "--root requires a path"; exit 2; }; LAMPSTAND_ROOTS+=("$1"); shift ;; + -h|--help) usage; exit 0 ;; *) QUERY_PARTS+=("$1"); shift ;; esac done +case "$MODE" in + health) + set +e + out="$(run_lampstand health 2>&1)" + rc=$? + set -e + write_or_print "$out" lampstand-health.json + exit "$rc" + ;; + stats) + out="$(run_lampstand stats)" + write_or_print "$out" lampstand-stats.json + exit 0 + ;; + index) + args=(index) + for root in "${LAMPSTAND_ROOTS[@]}"; do args+=(--root "$root"); done + run_lampstand "${args[@]}" + exit $? + ;; +esac + if [[ ${#QUERY_PARTS[@]} -eq 0 && "$SEARCH_PROMPT" == "1" ]]; then if have fuzzel; then q="$(printf '\n' | fuzzel --dmenu --prompt 'search> ' || true)" elif have wofi; then q="$(printf '\n' | wofi --dmenu --prompt 'search> ' || true)" @@ -66,13 +119,8 @@ args=(query "$query" --limit "$SEARCH_LIMIT") [[ "$SEARCH_SNIPPET" == "1" ]] && args+=(--snippet) if [[ "$SEARCH_OPEN" == "1" || -n "$SEARCH_WRITE_PATH" ]]; then - path="$SEARCH_WRITE_PATH" - if [[ -z "$path" ]]; then mkdir -p "$(cache_dir)"; path="$(cache_dir)/search.txt"; fi out="$(run_lampstand "${args[@]}")" - mkdir -p "$(dirname "$path")" - printf '%s\n' "$out" > "$path" - info "wrote: $path" - [[ "$SEARCH_OPEN" == "1" ]] && open_file "$path" + write_or_print "$out" search.txt exit 0 fi