fpf-cli 1.6.44 → 1.6.46

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 (3) hide show
  1. package/README.md +2 -2
  2. package/fpf +126 -114
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -105,8 +105,8 @@ Installed packages are marked with `*` in the result list.
105
105
  - `FPF_DYNAMIC_RELOAD_BYPASS_QUERY_CACHE=1`: bypass query cache during live reloads (default `1` for freshest results); set `0` to prefer cached reloads
106
106
  - `FPF_SEARCH_CATALOG_ASYNC_PREWARM`: async warmup for `apt`/`brew` catalog caches during interactive reload/search paths (default `1`, set `0` for synchronous legacy behavior)
107
107
  - `FPF_ENABLE_QUERY_CACHE`: `auto` (default), `1`, or `0` (`auto` enables query cache for `apt`, `brew`, `pacman`, and `bun`)
108
- - `FPF_QUERY_CACHE_TTL`: default query-cache TTL seconds for heavy manager caches (default `300`)
108
+ - `FPF_QUERY_CACHE_TTL`: global query-cache TTL override seconds for heavy managers (defaults: `apt=180`, `brew=120`, `pacman=180`; set `0` to always refresh)
109
109
  - `FPF_APT_QUERY_CACHE_TTL`, `FPF_BREW_QUERY_CACHE_TTL`, `FPF_PACMAN_QUERY_CACHE_TTL`: per-manager query-cache TTL overrides
110
- - `FPF_BUN_QUERY_CACHE_TTL`: Bun query-cache TTL (default `900`)
110
+ - `FPF_BUN_QUERY_CACHE_TTL`: Bun query-cache TTL (default `300`)
111
111
  - `FPF_DISABLE_INSTALLED_CACHE=1` disables installed-package marker cache
112
112
  - `FPF_INSTALLED_CACHE_TTL`: installed-package marker cache freshness window in seconds (default `300`, set `0` to always refresh)
package/fpf CHANGED
@@ -3,7 +3,7 @@
3
3
  set -euo pipefail
4
4
 
5
5
  SCRIPT_NAME="fpf"
6
- SCRIPT_VERSION="1.6.44"
6
+ SCRIPT_VERSION="1.6.46"
7
7
  TMP_ROOT="${TMPDIR:-/tmp}/fpf"
8
8
  SESSION_TMP_ROOT=""
9
9
  HELP_FILE=""
@@ -40,18 +40,36 @@ query_cache_default_enabled_for_manager() {
40
40
 
41
41
  query_cache_ttl_seconds_for_manager() {
42
42
  local manager="$1"
43
- local default_ttl="${FPF_QUERY_CACHE_TTL:-300}"
43
+ local default_ttl="0"
44
+ local global_ttl="${FPF_QUERY_CACHE_TTL:-}"
44
45
  local manager_ttl="0"
45
46
 
46
- if ! [[ "${default_ttl}" =~ ^[0-9]+$ ]]; then
47
- default_ttl=300
47
+ case "${manager}" in
48
+ apt)
49
+ default_ttl="180"
50
+ ;;
51
+ brew)
52
+ default_ttl="120"
53
+ ;;
54
+ pacman)
55
+ default_ttl="180"
56
+ ;;
57
+ bun)
58
+ default_ttl="300"
59
+ ;;
60
+ esac
61
+
62
+ if [[ -n "${global_ttl}" ]]; then
63
+ if [[ "${global_ttl}" =~ ^[0-9]+$ ]]; then
64
+ default_ttl="${global_ttl}"
65
+ fi
48
66
  fi
49
67
 
50
68
  case "${manager}" in
51
69
  bun)
52
- manager_ttl="${FPF_BUN_QUERY_CACHE_TTL:-900}"
70
+ manager_ttl="${FPF_BUN_QUERY_CACHE_TTL:-${default_ttl}}"
53
71
  if ! [[ "${manager_ttl}" =~ ^[0-9]+$ ]]; then
54
- manager_ttl=900
72
+ manager_ttl="${default_ttl}"
55
73
  fi
56
74
  ;;
57
75
  apt)
@@ -84,7 +102,7 @@ dynamic_reload_query_cache_bypass_value() {
84
102
  local bypass_setting="${FPF_DYNAMIC_RELOAD_BYPASS_QUERY_CACHE:-1}"
85
103
 
86
104
  bypass_setting="$(trim_whitespace "${bypass_setting}")"
87
- bypass_setting="$(printf "%s" "${bypass_setting}" | tr '[:upper:]' '[:lower:]')"
105
+ bypass_setting="${bypass_setting,,}"
88
106
 
89
107
  case "${bypass_setting}" in
90
108
  1|true|yes|on)
@@ -104,7 +122,7 @@ loading_indicator_enabled() {
104
122
  local indicator_setting=""
105
123
 
106
124
  indicator_setting="$(trim_whitespace "${FPF_LOADING_INDICATOR:-1}")"
107
- indicator_setting="$(printf "%s" "${indicator_setting}" | tr '[:upper:]' '[:lower:]')"
125
+ indicator_setting="${indicator_setting,,}"
108
126
 
109
127
  case "${indicator_setting}" in
110
128
  0|false|no|off)
@@ -412,7 +430,7 @@ assume_yes_enabled() {
412
430
  fi
413
431
 
414
432
  env_assume_yes="$(trim_whitespace "${FPF_ASSUME_YES:-0}")"
415
- env_assume_yes="$(printf "%s" "${env_assume_yes}" | tr '[:upper:]' '[:lower:]')"
433
+ env_assume_yes="${env_assume_yes,,}"
416
434
 
417
435
  case "${env_assume_yes}" in
418
436
  1|true|yes|on)
@@ -473,13 +491,14 @@ initialize_cache_root() {
473
491
  }
474
492
 
475
493
  normalize_cache_query() {
476
- printf "%s" "$1" |
477
- awk '{
478
- line=$0
479
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", line)
480
- gsub(/[[:space:]]+/, " ", line)
481
- print tolower(line)
482
- }'
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}"
483
502
  }
484
503
 
485
504
  trim_whitespace() {
@@ -513,7 +532,10 @@ log_selection_parse_skip() {
513
532
  }
514
533
 
515
534
  platform_cache_token() {
516
- uname -s | tr '[:upper:]' '[:lower:]'
535
+ local os
536
+
537
+ os="$(uname -s)"
538
+ printf "%s" "${os,,}"
517
539
  }
518
540
 
519
541
  cache_fingerprint() {
@@ -1061,7 +1083,7 @@ search_catalog_async_prewarm_enabled() {
1061
1083
  fi
1062
1084
 
1063
1085
  setting="$(trim_whitespace "${setting}")"
1064
- setting="$(printf "%s" "${setting}" | tr '[:upper:]' '[:lower:]')"
1086
+ setting="${setting,,}"
1065
1087
 
1066
1088
  case "${setting}" in
1067
1089
  0|false|no|off)
@@ -1753,7 +1775,7 @@ normalize_manager() {
1753
1775
  local manager="$1"
1754
1776
 
1755
1777
  manager="$(trim_whitespace "${manager}")"
1756
- manager="$(printf "%s" "${manager}" | tr '[:upper:]' '[:lower:]')"
1778
+ manager="${manager,,}"
1757
1779
 
1758
1780
  case "${manager}" in
1759
1781
  homebrew)
@@ -2068,6 +2090,9 @@ parse_args() {
2068
2090
  --feed-search)
2069
2091
  ACTION="feed-search"
2070
2092
  ;;
2093
+ --dynamic-reload)
2094
+ ACTION="dynamic-reload"
2095
+ ;;
2071
2096
  --ipc-reload)
2072
2097
  ACTION="ipc-reload"
2073
2098
  ;;
@@ -2328,8 +2353,10 @@ exact_query_candidates() {
2328
2353
  local dashed_query=""
2329
2354
  local underscored_query=""
2330
2355
  local nospace_query=""
2356
+ local -a query_tokens=()
2331
2357
 
2332
- compact_query="$(printf "%s" "${query}" | awk '{$1=$1; print}')"
2358
+ read -r -a query_tokens <<<"${query}"
2359
+ compact_query="${query_tokens[*]}"
2333
2360
  [[ -n "${compact_query}" ]] || return 0
2334
2361
 
2335
2362
  printf "%s\n" "${compact_query}"
@@ -2344,41 +2371,6 @@ exact_query_candidates() {
2344
2371
  fi
2345
2372
  }
2346
2373
 
2347
- exact_match_entry() {
2348
- local manager="$1"
2349
- local query="$2"
2350
- local candidate
2351
-
2352
- if [[ -z "${query}" ]]; then
2353
- return 0
2354
- fi
2355
-
2356
- while IFS= read -r candidate; do
2357
- [[ -n "${candidate}" ]] || continue
2358
-
2359
- case "${manager}" in
2360
- brew)
2361
- if brew info --formula "${candidate}" >/dev/null 2>&1 || brew info --cask "${candidate}" >/dev/null 2>&1; then
2362
- printf "%s\t-\n" "${candidate}"
2363
- return 0
2364
- fi
2365
- ;;
2366
- npm)
2367
- if command_exists npm && npm view "${candidate}" name >/dev/null 2>&1; then
2368
- printf "%s\t-\n" "${candidate}"
2369
- return 0
2370
- fi
2371
- ;;
2372
- bun)
2373
- if bun info "${candidate}" >/dev/null 2>&1 || (command_exists npm && npm view "${candidate}" name >/dev/null 2>&1); then
2374
- printf "%s\t-\n" "${candidate}"
2375
- return 0
2376
- fi
2377
- ;;
2378
- esac
2379
- done < <(exact_query_candidates "${query}" | awk '!seen[$0]++')
2380
- }
2381
-
2382
2374
  manager_bun_search_entries_strict() {
2383
2375
  local query="$1"
2384
2376
  local effective_query="${query}"
@@ -2419,7 +2411,6 @@ manager_bun_search_entries_strict() {
2419
2411
 
2420
2412
  {
2421
2413
  awk 'NR > 1 && NF > 0 { name=$1; $1=""; sub(/^[[:space:]]+/, "", $0); if ($0 == "") $0="-"; print name "\t" $0 }' "${bun_search_file}"
2422
- exact_match_entry "bun" "${query}"
2423
2414
  } | awk -F'\t' 'NF >= 1 { if ($2 == "") $2 = "-"; print $1 "\t" $2 }' | awk -F'\t' '!seen[$1]++' | {
2424
2415
  if [[ "${effective_limit}" -gt 0 ]]; then
2425
2416
  awk -v limit="${effective_limit}" 'NR <= limit'
@@ -2550,25 +2541,16 @@ manager_search_entries_uncached() {
2550
2541
  ;;
2551
2542
  brew)
2552
2543
  if search_entries_from_catalog_cache "${manager}" "${effective_query}"; then
2553
- exact_match_entry "${manager}" "${query}"
2544
+ :
2554
2545
  elif [[ -n "${query}" ]] && search_catalog_async_prewarm_enabled; then
2555
2546
  start_search_catalog_prewarm_async "${manager}"
2556
- {
2557
- brew search "${effective_query}" 2>/dev/null |
2558
- awk 'NF >= 1 { print $1 "\t-" }'
2559
- exact_match_entry "${manager}" "${query}"
2560
- }
2547
+ brew search "${effective_query}" 2>/dev/null |
2548
+ awk 'NF >= 1 { print $1 "\t-" }'
2561
2549
  elif ensure_search_catalog_cache "${manager}"; then
2562
- {
2563
- search_entries_from_catalog_cache "${manager}" "${effective_query}" || true
2564
- exact_match_entry "${manager}" "${query}"
2565
- }
2550
+ search_entries_from_catalog_cache "${manager}" "${effective_query}" || true
2566
2551
  else
2567
- {
2568
- brew search "${effective_query}" 2>/dev/null |
2569
- awk 'NF > 0 && $1 != "==>" { print $1 "\t-" }'
2570
- exact_match_entry "${manager}" "${query}"
2571
- }
2552
+ brew search "${effective_query}" 2>/dev/null |
2553
+ awk 'NF > 0 && $1 != "==>" { print $1 "\t-" }'
2572
2554
  fi
2573
2555
  ;;
2574
2556
  winget)
@@ -2640,11 +2622,8 @@ manager_search_entries_uncached() {
2640
2622
  fi
2641
2623
  ;;
2642
2624
  npm)
2643
- {
2644
- npm search "${effective_query}" --searchlimit="${npm_search_limit}" --parseable 2>/dev/null |
2645
- awk -F'\t' 'NF >= 2 { print $1 "\t" $2 }'
2646
- exact_match_entry "${manager}" "${query}"
2647
- }
2625
+ npm search "${effective_query}" --searchlimit="${npm_search_limit}" --parseable 2>/dev/null |
2626
+ awk -F'\t' 'NF >= 2 { print $1 "\t" $2 }'
2648
2627
  ;;
2649
2628
  bun)
2650
2629
  {
@@ -2657,7 +2636,6 @@ manager_search_entries_uncached() {
2657
2636
  awk -F'\t' 'NF >= 2 { print $1 "\t" $2 }'
2658
2637
  fi
2659
2638
  rm -f "${bun_search_file}"
2660
- exact_match_entry "${manager}" "${query}"
2661
2639
  } || true
2662
2640
  ;;
2663
2641
  esac | awk -F'\t' 'NF >= 1 { if ($2 == "") $2 = "-"; print $1 "\t" $2 }' | awk -F'\t' '!seen[$1]++' | {
@@ -2689,7 +2667,7 @@ manager_search_entries() {
2689
2667
 
2690
2668
  flags="$(query_cache_flags)"
2691
2669
  query_cache_setting="$(trim_whitespace "${query_cache_setting}")"
2692
- query_cache_setting="$(printf "%s" "${query_cache_setting}" | tr '[:upper:]' '[:lower:]')"
2670
+ query_cache_setting="${query_cache_setting,,}"
2693
2671
  query_cache_ttl="$(query_cache_ttl_seconds_for_manager "${manager}")"
2694
2672
 
2695
2673
  if [[ "${manager}" == "bun" ]]; then
@@ -3313,29 +3291,15 @@ build_dynamic_reload_command() {
3313
3291
  local manager_override="$1"
3314
3292
  local fallback_file="$2"
3315
3293
  local script_path="${BASH_SOURCE[0]}"
3316
- local min_chars="${FPF_RELOAD_MIN_CHARS:-2}"
3317
- local reload_debounce="${FPF_RELOAD_DEBOUNCE:-0.12}"
3318
3294
  local bypass_query_cache="1"
3319
3295
 
3320
- if ! [[ "${min_chars}" =~ ^[0-9]+$ ]]; then
3321
- min_chars=2
3322
- fi
3323
-
3324
- if ! [[ "${reload_debounce}" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
3325
- reload_debounce=0.12
3326
- fi
3327
-
3328
3296
  bypass_query_cache="$(dynamic_reload_query_cache_bypass_value)"
3329
3297
 
3330
3298
  if [[ "${script_path}" != /* ]]; then
3331
3299
  script_path="$(pwd)/${script_path}"
3332
3300
  fi
3333
3301
 
3334
- if [[ -n "${manager_override}" ]]; then
3335
- 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}"
3336
- else
3337
- 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}"
3338
- fi
3302
+ 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}"
3339
3303
  }
3340
3304
 
3341
3305
  build_dynamic_reload_command_for_query() {
@@ -3343,34 +3307,15 @@ build_dynamic_reload_command_for_query() {
3343
3307
  local fallback_file="$2"
3344
3308
  local query_value="$3"
3345
3309
  local script_path="${BASH_SOURCE[0]}"
3346
- local min_chars="${FPF_RELOAD_MIN_CHARS:-2}"
3347
- local reload_debounce="${FPF_RELOAD_DEBOUNCE:-0.12}"
3348
3310
  local bypass_query_cache="1"
3349
3311
 
3350
- if ! [[ "${min_chars}" =~ ^[0-9]+$ ]]; then
3351
- min_chars=2
3352
- fi
3353
-
3354
- if ! [[ "${reload_debounce}" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
3355
- reload_debounce=0.12
3356
- fi
3357
-
3358
3312
  bypass_query_cache="$(dynamic_reload_query_cache_bypass_value)"
3359
3313
 
3360
3314
  if [[ "${script_path}" != /* ]]; then
3361
3315
  script_path="$(pwd)/${script_path}"
3362
3316
  fi
3363
3317
 
3364
- if [[ ${#query_value} -lt ${min_chars} ]]; then
3365
- printf 'cat %q' "${fallback_file}"
3366
- return
3367
- fi
3368
-
3369
- if [[ -n "${manager_override}" ]]; then
3370
- 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}"
3371
- else
3372
- 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}"
3373
- fi
3318
+ 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}"
3374
3319
  }
3375
3320
 
3376
3321
  build_dynamic_reload_ipc_command() {
@@ -3496,6 +3441,68 @@ send_fzf_prompt_action() {
3496
3441
  send_fzf_listen_action "${action_payload}"
3497
3442
  }
3498
3443
 
3444
+ run_dynamic_reload_action() {
3445
+ local query="$1"
3446
+ local manager_override="${FPF_IPC_MANAGER_OVERRIDE:-}"
3447
+ local fallback_file="${FPF_IPC_FALLBACK_FILE:-}"
3448
+ local min_chars="${FPF_RELOAD_MIN_CHARS:-2}"
3449
+ local reload_debounce="${FPF_RELOAD_DEBOUNCE:-0.12}"
3450
+ local output_file=""
3451
+ local detected_manager=""
3452
+ local -a managers=()
3453
+
3454
+ if [[ -z "${fallback_file}" || ! -r "${fallback_file}" ]]; then
3455
+ return 1
3456
+ fi
3457
+
3458
+ if ! [[ "${min_chars}" =~ ^[0-9]+$ ]]; then
3459
+ min_chars=2
3460
+ fi
3461
+
3462
+ if ! [[ "${reload_debounce}" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
3463
+ reload_debounce=0.12
3464
+ fi
3465
+
3466
+ if [[ ${#query} -lt ${min_chars} ]]; then
3467
+ cat "${fallback_file}"
3468
+ return 0
3469
+ fi
3470
+
3471
+ sleep "${reload_debounce}"
3472
+
3473
+ if [[ -n "${manager_override}" ]]; then
3474
+ manager_override="$(normalize_manager "${manager_override}")"
3475
+ if ! manager_supported "${manager_override}" || ! manager_command_ready "${manager_override}"; then
3476
+ cat "${fallback_file}"
3477
+ return 0
3478
+ fi
3479
+ managers+=("${manager_override}")
3480
+ else
3481
+ while IFS= read -r detected_manager; do
3482
+ [[ -n "${detected_manager}" ]] || continue
3483
+ if manager_supported "${detected_manager}" && manager_command_ready "${detected_manager}"; then
3484
+ managers+=("${detected_manager}")
3485
+ fi
3486
+ done < <(detect_default_managers)
3487
+ fi
3488
+
3489
+ if [[ "${#managers[@]}" -eq 0 ]]; then
3490
+ cat "${fallback_file}"
3491
+ return 0
3492
+ fi
3493
+
3494
+ output_file="$(mktemp "${SESSION_TMP_ROOT}/dynamic-reload.XXXXXX")"
3495
+ : >"${output_file}"
3496
+
3497
+ if collect_search_display_rows "${query}" "${output_file}" "${managers[@]-}"; then
3498
+ cat "${output_file}"
3499
+ else
3500
+ cat "${fallback_file}"
3501
+ fi
3502
+
3503
+ rm -f "${output_file}"
3504
+ }
3505
+
3499
3506
  run_ipc_reload_action() {
3500
3507
  local query="$1"
3501
3508
  local manager_override="${FPF_IPC_MANAGER_OVERRIDE:-}"
@@ -3610,7 +3617,7 @@ confirm_action() {
3610
3617
  printf "%s [y/N]: " "${prompt}" >&2
3611
3618
  read -r reply || true
3612
3619
  reply="$(trim_whitespace "${reply}")"
3613
- normalized_reply="$(printf "%s" "${reply}" | tr '[:upper:]' '[:lower:]')"
3620
+ normalized_reply="${reply,,}"
3614
3621
 
3615
3622
  case "${normalized_reply}" in
3616
3623
  y|yes)
@@ -3720,6 +3727,11 @@ main() {
3720
3727
  exit 0
3721
3728
  fi
3722
3729
 
3730
+ if [[ "${ACTION}" == "dynamic-reload" ]]; then
3731
+ run_dynamic_reload_action "$(join_query)" || true
3732
+ exit 0
3733
+ fi
3734
+
3723
3735
  if [[ "${ACTION}" == "preview-item" ]]; then
3724
3736
  local preview_manager="${MANAGER_OVERRIDE:-}"
3725
3737
  local preview_package
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fpf-cli",
3
- "version": "1.6.44",
3
+ "version": "1.6.46",
4
4
  "description": "Cross-platform fuzzy package finder powered by fzf",
5
5
  "bin": {
6
6
  "fpf": "fpf"