fpf-cli 1.6.45 → 1.6.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/fpf +157 -110
  2. package/package.json +1 -1
package/fpf CHANGED
@@ -3,7 +3,7 @@
3
3
  set -euo pipefail
4
4
 
5
5
  SCRIPT_NAME="fpf"
6
- SCRIPT_VERSION="1.6.45"
6
+ SCRIPT_VERSION="1.6.47"
7
7
  TMP_ROOT="${TMPDIR:-/tmp}/fpf"
8
8
  SESSION_TMP_ROOT=""
9
9
  HELP_FILE=""
@@ -102,7 +102,7 @@ dynamic_reload_query_cache_bypass_value() {
102
102
  local bypass_setting="${FPF_DYNAMIC_RELOAD_BYPASS_QUERY_CACHE:-1}"
103
103
 
104
104
  bypass_setting="$(trim_whitespace "${bypass_setting}")"
105
- bypass_setting="$(printf "%s" "${bypass_setting}" | tr '[:upper:]' '[:lower:]')"
105
+ bypass_setting="${bypass_setting,,}"
106
106
 
107
107
  case "${bypass_setting}" in
108
108
  1|true|yes|on)
@@ -122,7 +122,7 @@ loading_indicator_enabled() {
122
122
  local indicator_setting=""
123
123
 
124
124
  indicator_setting="$(trim_whitespace "${FPF_LOADING_INDICATOR:-1}")"
125
- indicator_setting="$(printf "%s" "${indicator_setting}" | tr '[:upper:]' '[:lower:]')"
125
+ indicator_setting="${indicator_setting,,}"
126
126
 
127
127
  case "${indicator_setting}" in
128
128
  0|false|no|off)
@@ -430,7 +430,7 @@ assume_yes_enabled() {
430
430
  fi
431
431
 
432
432
  env_assume_yes="$(trim_whitespace "${FPF_ASSUME_YES:-0}")"
433
- env_assume_yes="$(printf "%s" "${env_assume_yes}" | tr '[:upper:]' '[:lower:]')"
433
+ env_assume_yes="${env_assume_yes,,}"
434
434
 
435
435
  case "${env_assume_yes}" in
436
436
  1|true|yes|on)
@@ -491,13 +491,14 @@ initialize_cache_root() {
491
491
  }
492
492
 
493
493
  normalize_cache_query() {
494
- printf "%s" "$1" |
495
- awk '{
496
- line=$0
497
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", line)
498
- gsub(/[[:space:]]+/, " ", line)
499
- print tolower(line)
500
- }'
494
+ local value="$1"
495
+ local -a tokens=()
496
+
497
+ read -r -a tokens <<<"${value}"
498
+ value="${tokens[*]}"
499
+ value="${value,,}"
500
+
501
+ printf "%s" "${value}"
501
502
  }
502
503
 
503
504
  trim_whitespace() {
@@ -531,7 +532,10 @@ log_selection_parse_skip() {
531
532
  }
532
533
 
533
534
  platform_cache_token() {
534
- uname -s | tr '[:upper:]' '[:lower:]'
535
+ local os
536
+
537
+ os="$(uname -s)"
538
+ printf "%s" "${os,,}"
535
539
  }
536
540
 
537
541
  cache_fingerprint() {
@@ -655,7 +659,24 @@ brew_catalog_state_token() {
655
659
  printf "state=unknown"
656
660
  }
657
661
 
658
- cache_search_catalog_fingerprint() {
662
+ brew_catalog_state_cache_ttl_seconds() {
663
+ local ttl="${FPF_BREW_CATALOG_STATE_TTL:-300}"
664
+
665
+ if ! [[ "${ttl}" =~ ^[0-9]+$ ]]; then
666
+ ttl=300
667
+ fi
668
+
669
+ printf "%s" "${ttl}"
670
+ }
671
+
672
+ brew_catalog_state_cache_scope_hash() {
673
+ local scope_token
674
+
675
+ scope_token="fixtures=${FPF_TEST_FIXTURES:-0};fixture_dir=${FPF_TEST_FIXTURE_DIR:-}"
676
+ cache_cksum "${scope_token}"
677
+ }
678
+
679
+ cache_search_catalog_fingerprint_uncached() {
659
680
  local manager="$1"
660
681
  local command_path=""
661
682
  local state_token="state=unknown"
@@ -677,6 +698,42 @@ cache_search_catalog_fingerprint() {
677
698
  printf "%s|cmd=%s|%s" "$(cache_fingerprint "${manager}" "" "search-catalog")" "${command_path}" "${state_token}"
678
699
  }
679
700
 
701
+ cache_search_catalog_fingerprint() {
702
+ local manager="$1"
703
+ local state_cache_key=""
704
+ local state_cache_file=""
705
+ local state_cache_ttl=0
706
+ local state_cache_tmp=""
707
+ local state_cache_scope_hash=""
708
+
709
+ if [[ "${manager}" != "brew" ]]; then
710
+ cache_search_catalog_fingerprint_uncached "${manager}"
711
+ return
712
+ fi
713
+
714
+ initialize_cache_root
715
+
716
+ state_cache_scope_hash="$(brew_catalog_state_cache_scope_hash)"
717
+ state_cache_key="state/search-catalog-fingerprint/${manager}.${state_cache_scope_hash}.txt"
718
+ state_cache_file="$(cache_path_for_key "${state_cache_key}")"
719
+ state_cache_ttl="$(brew_catalog_state_cache_ttl_seconds)"
720
+
721
+ if [[ "${state_cache_ttl}" -gt 0 && -s "${state_cache_file}" ]] && cache_is_fresh_with_ttl "${state_cache_key}" "${state_cache_ttl}"; then
722
+ cat "${state_cache_file}"
723
+ return
724
+ fi
725
+
726
+ state_cache_tmp="$(mktemp "${SESSION_TMP_ROOT}/search-catalog-fingerprint.XXXXXX")"
727
+ cache_search_catalog_fingerprint_uncached "${manager}" >"${state_cache_tmp}" || true
728
+
729
+ if [[ -s "${state_cache_tmp}" ]]; then
730
+ cache_store_key_from_file "${state_cache_key}" "${manager}" "${state_cache_tmp}"
731
+ cat "${state_cache_tmp}"
732
+ fi
733
+
734
+ rm -f "${state_cache_tmp}"
735
+ }
736
+
680
737
  cache_search_catalog_key() {
681
738
  local manager="$1"
682
739
  local fingerprint="$2"
@@ -1079,7 +1136,7 @@ search_catalog_async_prewarm_enabled() {
1079
1136
  fi
1080
1137
 
1081
1138
  setting="$(trim_whitespace "${setting}")"
1082
- setting="$(printf "%s" "${setting}" | tr '[:upper:]' '[:lower:]')"
1139
+ setting="${setting,,}"
1083
1140
 
1084
1141
  case "${setting}" in
1085
1142
  0|false|no|off)
@@ -1771,7 +1828,7 @@ normalize_manager() {
1771
1828
  local manager="$1"
1772
1829
 
1773
1830
  manager="$(trim_whitespace "${manager}")"
1774
- manager="$(printf "%s" "${manager}" | tr '[:upper:]' '[:lower:]')"
1831
+ manager="${manager,,}"
1775
1832
 
1776
1833
  case "${manager}" in
1777
1834
  homebrew)
@@ -2086,6 +2143,9 @@ parse_args() {
2086
2143
  --feed-search)
2087
2144
  ACTION="feed-search"
2088
2145
  ;;
2146
+ --dynamic-reload)
2147
+ ACTION="dynamic-reload"
2148
+ ;;
2089
2149
  --ipc-reload)
2090
2150
  ACTION="ipc-reload"
2091
2151
  ;;
@@ -2346,8 +2406,10 @@ exact_query_candidates() {
2346
2406
  local dashed_query=""
2347
2407
  local underscored_query=""
2348
2408
  local nospace_query=""
2409
+ local -a query_tokens=()
2349
2410
 
2350
- compact_query="$(printf "%s" "${query}" | awk '{$1=$1; print}')"
2411
+ read -r -a query_tokens <<<"${query}"
2412
+ compact_query="${query_tokens[*]}"
2351
2413
  [[ -n "${compact_query}" ]] || return 0
2352
2414
 
2353
2415
  printf "%s\n" "${compact_query}"
@@ -2362,41 +2424,6 @@ exact_query_candidates() {
2362
2424
  fi
2363
2425
  }
2364
2426
 
2365
- exact_match_entry() {
2366
- local manager="$1"
2367
- local query="$2"
2368
- local candidate
2369
-
2370
- if [[ -z "${query}" ]]; then
2371
- return 0
2372
- fi
2373
-
2374
- while IFS= read -r candidate; do
2375
- [[ -n "${candidate}" ]] || continue
2376
-
2377
- case "${manager}" in
2378
- brew)
2379
- if brew info --formula "${candidate}" >/dev/null 2>&1 || brew info --cask "${candidate}" >/dev/null 2>&1; then
2380
- printf "%s\t-\n" "${candidate}"
2381
- return 0
2382
- fi
2383
- ;;
2384
- npm)
2385
- if command_exists npm && npm view "${candidate}" name >/dev/null 2>&1; then
2386
- printf "%s\t-\n" "${candidate}"
2387
- return 0
2388
- fi
2389
- ;;
2390
- bun)
2391
- if bun info "${candidate}" >/dev/null 2>&1 || (command_exists npm && npm view "${candidate}" name >/dev/null 2>&1); then
2392
- printf "%s\t-\n" "${candidate}"
2393
- return 0
2394
- fi
2395
- ;;
2396
- esac
2397
- done < <(exact_query_candidates "${query}" | awk '!seen[$0]++')
2398
- }
2399
-
2400
2427
  manager_bun_search_entries_strict() {
2401
2428
  local query="$1"
2402
2429
  local effective_query="${query}"
@@ -2437,7 +2464,6 @@ manager_bun_search_entries_strict() {
2437
2464
 
2438
2465
  {
2439
2466
  awk 'NR > 1 && NF > 0 { name=$1; $1=""; sub(/^[[:space:]]+/, "", $0); if ($0 == "") $0="-"; print name "\t" $0 }' "${bun_search_file}"
2440
- exact_match_entry "bun" "${query}"
2441
2467
  } | awk -F'\t' 'NF >= 1 { if ($2 == "") $2 = "-"; print $1 "\t" $2 }' | awk -F'\t' '!seen[$1]++' | {
2442
2468
  if [[ "${effective_limit}" -gt 0 ]]; then
2443
2469
  awk -v limit="${effective_limit}" 'NR <= limit'
@@ -2568,25 +2594,16 @@ manager_search_entries_uncached() {
2568
2594
  ;;
2569
2595
  brew)
2570
2596
  if search_entries_from_catalog_cache "${manager}" "${effective_query}"; then
2571
- exact_match_entry "${manager}" "${query}"
2597
+ :
2572
2598
  elif [[ -n "${query}" ]] && search_catalog_async_prewarm_enabled; then
2573
2599
  start_search_catalog_prewarm_async "${manager}"
2574
- {
2575
- brew search "${effective_query}" 2>/dev/null |
2576
- awk 'NF >= 1 { print $1 "\t-" }'
2577
- exact_match_entry "${manager}" "${query}"
2578
- }
2600
+ brew search "${effective_query}" 2>/dev/null |
2601
+ awk 'NF >= 1 { print $1 "\t-" }'
2579
2602
  elif ensure_search_catalog_cache "${manager}"; then
2580
- {
2581
- search_entries_from_catalog_cache "${manager}" "${effective_query}" || true
2582
- exact_match_entry "${manager}" "${query}"
2583
- }
2603
+ search_entries_from_catalog_cache "${manager}" "${effective_query}" || true
2584
2604
  else
2585
- {
2586
- brew search "${effective_query}" 2>/dev/null |
2587
- awk 'NF > 0 && $1 != "==>" { print $1 "\t-" }'
2588
- exact_match_entry "${manager}" "${query}"
2589
- }
2605
+ brew search "${effective_query}" 2>/dev/null |
2606
+ awk 'NF > 0 && $1 != "==>" { print $1 "\t-" }'
2590
2607
  fi
2591
2608
  ;;
2592
2609
  winget)
@@ -2658,11 +2675,8 @@ manager_search_entries_uncached() {
2658
2675
  fi
2659
2676
  ;;
2660
2677
  npm)
2661
- {
2662
- npm search "${effective_query}" --searchlimit="${npm_search_limit}" --parseable 2>/dev/null |
2663
- awk -F'\t' 'NF >= 2 { print $1 "\t" $2 }'
2664
- exact_match_entry "${manager}" "${query}"
2665
- }
2678
+ npm search "${effective_query}" --searchlimit="${npm_search_limit}" --parseable 2>/dev/null |
2679
+ awk -F'\t' 'NF >= 2 { print $1 "\t" $2 }'
2666
2680
  ;;
2667
2681
  bun)
2668
2682
  {
@@ -2675,7 +2689,6 @@ manager_search_entries_uncached() {
2675
2689
  awk -F'\t' 'NF >= 2 { print $1 "\t" $2 }'
2676
2690
  fi
2677
2691
  rm -f "${bun_search_file}"
2678
- exact_match_entry "${manager}" "${query}"
2679
2692
  } || true
2680
2693
  ;;
2681
2694
  esac | awk -F'\t' 'NF >= 1 { if ($2 == "") $2 = "-"; print $1 "\t" $2 }' | awk -F'\t' '!seen[$1]++' | {
@@ -2707,7 +2720,7 @@ manager_search_entries() {
2707
2720
 
2708
2721
  flags="$(query_cache_flags)"
2709
2722
  query_cache_setting="$(trim_whitespace "${query_cache_setting}")"
2710
- query_cache_setting="$(printf "%s" "${query_cache_setting}" | tr '[:upper:]' '[:lower:]')"
2723
+ query_cache_setting="${query_cache_setting,,}"
2711
2724
  query_cache_ttl="$(query_cache_ttl_seconds_for_manager "${manager}")"
2712
2725
 
2713
2726
  if [[ "${manager}" == "bun" ]]; then
@@ -3331,29 +3344,15 @@ build_dynamic_reload_command() {
3331
3344
  local manager_override="$1"
3332
3345
  local fallback_file="$2"
3333
3346
  local script_path="${BASH_SOURCE[0]}"
3334
- local min_chars="${FPF_RELOAD_MIN_CHARS:-2}"
3335
- local reload_debounce="${FPF_RELOAD_DEBOUNCE:-0.12}"
3336
3347
  local bypass_query_cache="1"
3337
3348
 
3338
- if ! [[ "${min_chars}" =~ ^[0-9]+$ ]]; then
3339
- min_chars=2
3340
- fi
3341
-
3342
- if ! [[ "${reload_debounce}" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
3343
- reload_debounce=0.12
3344
- fi
3345
-
3346
3349
  bypass_query_cache="$(dynamic_reload_query_cache_bypass_value)"
3347
3350
 
3348
3351
  if [[ "${script_path}" != /* ]]; then
3349
3352
  script_path="$(pwd)/${script_path}"
3350
3353
  fi
3351
3354
 
3352
- if [[ -n "${manager_override}" ]]; then
3353
- printf 'q={q}; if [ ${#q} -lt %s ]; then cat %q; else sleep %s; FPF_SKIP_INSTALLED_MARKERS=1 FPF_BYPASS_QUERY_CACHE=%s FPF_IPC_MANAGER_OVERRIDE=%q FPF_IPC_FALLBACK_FILE=%q %q --feed-search --manager %q -- "$q" 2>/dev/null || cat %q; fi' "${min_chars}" "${fallback_file}" "${reload_debounce}" "${bypass_query_cache}" "${manager_override}" "${fallback_file}" "${script_path}" "${manager_override}" "${fallback_file}"
3354
- else
3355
- printf 'q={q}; if [ ${#q} -lt %s ]; then cat %q; else sleep %s; FPF_SKIP_INSTALLED_MARKERS=1 FPF_BYPASS_QUERY_CACHE=%s FPF_IPC_MANAGER_OVERRIDE= FPF_IPC_FALLBACK_FILE=%q %q --feed-search -- "$q" 2>/dev/null || cat %q; fi' "${min_chars}" "${fallback_file}" "${reload_debounce}" "${bypass_query_cache}" "${fallback_file}" "${script_path}" "${fallback_file}"
3356
- fi
3355
+ printf 'FPF_SKIP_INSTALLED_MARKERS=1 FPF_BYPASS_QUERY_CACHE=%s FPF_IPC_MANAGER_OVERRIDE=%q FPF_IPC_FALLBACK_FILE=%q %q --dynamic-reload -- "{q}"' "${bypass_query_cache}" "${manager_override}" "${fallback_file}" "${script_path}"
3357
3356
  }
3358
3357
 
3359
3358
  build_dynamic_reload_command_for_query() {
@@ -3361,34 +3360,15 @@ build_dynamic_reload_command_for_query() {
3361
3360
  local fallback_file="$2"
3362
3361
  local query_value="$3"
3363
3362
  local script_path="${BASH_SOURCE[0]}"
3364
- local min_chars="${FPF_RELOAD_MIN_CHARS:-2}"
3365
- local reload_debounce="${FPF_RELOAD_DEBOUNCE:-0.12}"
3366
3363
  local bypass_query_cache="1"
3367
3364
 
3368
- if ! [[ "${min_chars}" =~ ^[0-9]+$ ]]; then
3369
- min_chars=2
3370
- fi
3371
-
3372
- if ! [[ "${reload_debounce}" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
3373
- reload_debounce=0.12
3374
- fi
3375
-
3376
3365
  bypass_query_cache="$(dynamic_reload_query_cache_bypass_value)"
3377
3366
 
3378
3367
  if [[ "${script_path}" != /* ]]; then
3379
3368
  script_path="$(pwd)/${script_path}"
3380
3369
  fi
3381
3370
 
3382
- if [[ ${#query_value} -lt ${min_chars} ]]; then
3383
- printf 'cat %q' "${fallback_file}"
3384
- return
3385
- fi
3386
-
3387
- if [[ -n "${manager_override}" ]]; then
3388
- printf 'sleep %s; FPF_SKIP_INSTALLED_MARKERS=1 FPF_BYPASS_QUERY_CACHE=%s FPF_IPC_MANAGER_OVERRIDE=%q FPF_IPC_FALLBACK_FILE=%q %q --feed-search --manager %q -- %q 2>/dev/null || cat %q' "${reload_debounce}" "${bypass_query_cache}" "${manager_override}" "${fallback_file}" "${script_path}" "${manager_override}" "${query_value}" "${fallback_file}"
3389
- else
3390
- printf 'sleep %s; FPF_SKIP_INSTALLED_MARKERS=1 FPF_BYPASS_QUERY_CACHE=%s FPF_IPC_MANAGER_OVERRIDE= FPF_IPC_FALLBACK_FILE=%q %q --feed-search -- %q 2>/dev/null || cat %q' "${reload_debounce}" "${bypass_query_cache}" "${fallback_file}" "${script_path}" "${query_value}" "${fallback_file}"
3391
- fi
3371
+ printf 'FPF_SKIP_INSTALLED_MARKERS=1 FPF_BYPASS_QUERY_CACHE=%s FPF_IPC_MANAGER_OVERRIDE=%q FPF_IPC_FALLBACK_FILE=%q %q --dynamic-reload -- %q' "${bypass_query_cache}" "${manager_override}" "${fallback_file}" "${script_path}" "${query_value}"
3392
3372
  }
3393
3373
 
3394
3374
  build_dynamic_reload_ipc_command() {
@@ -3514,6 +3494,68 @@ send_fzf_prompt_action() {
3514
3494
  send_fzf_listen_action "${action_payload}"
3515
3495
  }
3516
3496
 
3497
+ run_dynamic_reload_action() {
3498
+ local query="$1"
3499
+ local manager_override="${FPF_IPC_MANAGER_OVERRIDE:-}"
3500
+ local fallback_file="${FPF_IPC_FALLBACK_FILE:-}"
3501
+ local min_chars="${FPF_RELOAD_MIN_CHARS:-2}"
3502
+ local reload_debounce="${FPF_RELOAD_DEBOUNCE:-0.12}"
3503
+ local output_file=""
3504
+ local detected_manager=""
3505
+ local -a managers=()
3506
+
3507
+ if [[ -z "${fallback_file}" || ! -r "${fallback_file}" ]]; then
3508
+ return 1
3509
+ fi
3510
+
3511
+ if ! [[ "${min_chars}" =~ ^[0-9]+$ ]]; then
3512
+ min_chars=2
3513
+ fi
3514
+
3515
+ if ! [[ "${reload_debounce}" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
3516
+ reload_debounce=0.12
3517
+ fi
3518
+
3519
+ if [[ ${#query} -lt ${min_chars} ]]; then
3520
+ cat "${fallback_file}"
3521
+ return 0
3522
+ fi
3523
+
3524
+ sleep "${reload_debounce}"
3525
+
3526
+ if [[ -n "${manager_override}" ]]; then
3527
+ manager_override="$(normalize_manager "${manager_override}")"
3528
+ if ! manager_supported "${manager_override}" || ! manager_command_ready "${manager_override}"; then
3529
+ cat "${fallback_file}"
3530
+ return 0
3531
+ fi
3532
+ managers+=("${manager_override}")
3533
+ else
3534
+ while IFS= read -r detected_manager; do
3535
+ [[ -n "${detected_manager}" ]] || continue
3536
+ if manager_supported "${detected_manager}" && manager_command_ready "${detected_manager}"; then
3537
+ managers+=("${detected_manager}")
3538
+ fi
3539
+ done < <(detect_default_managers)
3540
+ fi
3541
+
3542
+ if [[ "${#managers[@]}" -eq 0 ]]; then
3543
+ cat "${fallback_file}"
3544
+ return 0
3545
+ fi
3546
+
3547
+ output_file="$(mktemp "${SESSION_TMP_ROOT}/dynamic-reload.XXXXXX")"
3548
+ : >"${output_file}"
3549
+
3550
+ if collect_search_display_rows "${query}" "${output_file}" "${managers[@]-}"; then
3551
+ cat "${output_file}"
3552
+ else
3553
+ cat "${fallback_file}"
3554
+ fi
3555
+
3556
+ rm -f "${output_file}"
3557
+ }
3558
+
3517
3559
  run_ipc_reload_action() {
3518
3560
  local query="$1"
3519
3561
  local manager_override="${FPF_IPC_MANAGER_OVERRIDE:-}"
@@ -3628,7 +3670,7 @@ confirm_action() {
3628
3670
  printf "%s [y/N]: " "${prompt}" >&2
3629
3671
  read -r reply || true
3630
3672
  reply="$(trim_whitespace "${reply}")"
3631
- normalized_reply="$(printf "%s" "${reply}" | tr '[:upper:]' '[:lower:]')"
3673
+ normalized_reply="${reply,,}"
3632
3674
 
3633
3675
  case "${normalized_reply}" in
3634
3676
  y|yes)
@@ -3738,6 +3780,11 @@ main() {
3738
3780
  exit 0
3739
3781
  fi
3740
3782
 
3783
+ if [[ "${ACTION}" == "dynamic-reload" ]]; then
3784
+ run_dynamic_reload_action "$(join_query)" || true
3785
+ exit 0
3786
+ fi
3787
+
3741
3788
  if [[ "${ACTION}" == "preview-item" ]]; then
3742
3789
  local preview_manager="${MANAGER_OVERRIDE:-}"
3743
3790
  local preview_package
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fpf-cli",
3
- "version": "1.6.45",
3
+ "version": "1.6.47",
4
4
  "description": "Cross-platform fuzzy package finder powered by fzf",
5
5
  "bin": {
6
6
  "fpf": "fpf"