fpf-cli 1.6.4 → 1.6.6

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 +162 -51
  2. package/package.json +1 -1
package/fpf CHANGED
@@ -494,6 +494,9 @@ parse_args() {
494
494
  -U|--update)
495
495
  ACTION="update"
496
496
  ;;
497
+ --feed-search)
498
+ ACTION="feed-search"
499
+ ;;
497
500
  -ap|--apt)
498
501
  MANAGER_OVERRIDE="apt"
499
502
  ;;
@@ -579,11 +582,38 @@ join_query() {
579
582
  printf "%s" "${query}"
580
583
  }
581
584
 
585
+ query_is_single_token() {
586
+ local query="$1"
587
+ [[ -n "${query}" && "${query}" != *[[:space:]]* ]]
588
+ }
589
+
590
+ exact_match_entry() {
591
+ local manager="$1"
592
+ local query="$2"
593
+
594
+ if ! query_is_single_token "${query}"; then
595
+ return 0
596
+ fi
597
+
598
+ case "${manager}" in
599
+ brew)
600
+ if brew info --formula "${query}" >/dev/null 2>&1 || brew info --cask "${query}" >/dev/null 2>&1; then
601
+ printf "%s\t-\n" "${query}"
602
+ fi
603
+ ;;
604
+ npm|bun)
605
+ if command_exists npm && npm view "${query}" name >/dev/null 2>&1; then
606
+ printf "%s\t-\n" "${query}"
607
+ fi
608
+ ;;
609
+ esac
610
+ }
611
+
582
612
  manager_search_entries() {
583
613
  local manager="$1"
584
614
  local query="$2"
585
615
  local effective_query="${query}"
586
- local npm_search_limit=200
616
+ local npm_search_limit=500
587
617
  local line_limit=0
588
618
 
589
619
  if [[ -z "${query}" ]]; then
@@ -592,7 +622,7 @@ manager_search_entries() {
592
622
  fi
593
623
 
594
624
  if ! [[ "${npm_search_limit}" =~ ^[0-9]+$ ]] || [[ "${npm_search_limit}" -eq 0 ]]; then
595
- npm_search_limit=200
625
+ npm_search_limit=500
596
626
  fi
597
627
 
598
628
  if ! [[ "${line_limit}" =~ ^[0-9]+$ ]]; then
@@ -673,8 +703,11 @@ manager_search_entries() {
673
703
  '
674
704
  ;;
675
705
  brew)
676
- brew search "${effective_query}" 2>/dev/null |
677
- awk 'NF > 0 { print $1 "\t-" }'
706
+ {
707
+ brew search "${effective_query}" 2>/dev/null |
708
+ awk 'NF > 0 && $1 != "==>" { print $1 "\t-" }'
709
+ exact_match_entry "${manager}" "${query}"
710
+ }
678
711
  ;;
679
712
  winget)
680
713
  winget search "${effective_query}" --source winget --accept-source-agreements --disable-interactivity 2>/dev/null |
@@ -744,8 +777,11 @@ manager_search_entries() {
744
777
  fi
745
778
  ;;
746
779
  npm)
747
- npm search "${effective_query}" --searchlimit="${npm_search_limit}" --parseable 2>/dev/null |
748
- awk -F'\t' 'NF >= 2 { print $1 "\t" $2 }'
780
+ {
781
+ npm search "${effective_query}" --searchlimit="${npm_search_limit}" --parseable 2>/dev/null |
782
+ awk -F'\t' 'NF >= 2 { print $1 "\t" $2 }'
783
+ exact_match_entry "${manager}" "${query}"
784
+ }
749
785
  ;;
750
786
  bun)
751
787
  {
@@ -756,6 +792,7 @@ manager_search_entries() {
756
792
  npm search "${effective_query}" --searchlimit="${npm_search_limit}" --parseable 2>/dev/null |
757
793
  awk -F'\t' 'NF >= 2 { print $1 "\t" $2 }'
758
794
  fi
795
+ exact_match_entry "${manager}" "${query}"
759
796
  } || true
760
797
  ;;
761
798
  esac | awk -F'\t' 'NF >= 1 { if ($2 == "") $2 = "-"; print $1 "\t" $2 }' | sort -u | {
@@ -912,6 +949,74 @@ mark_installed_packages() {
912
949
  rm -f "${installed_file}"
913
950
  }
914
951
 
952
+ collect_search_display_rows() {
953
+ local query="$1"
954
+ local output_file="$2"
955
+ shift 2
956
+ local managers=("$@")
957
+
958
+ : >"${output_file}"
959
+
960
+ local part_files=()
961
+ local gather_pids=()
962
+ local manager
963
+ local part_file
964
+ local gather_pid
965
+
966
+ for manager in "${managers[@]-}"; do
967
+ part_file="$(mktemp "${TMP_ROOT}/part.XXXXXX")"
968
+ part_files+=("${part_file}")
969
+
970
+ (
971
+ local_source_file="$(mktemp "${TMP_ROOT}/source.XXXXXX")"
972
+ local_marked_file="$(mktemp "${TMP_ROOT}/marked.XXXXXX")"
973
+ manager_search_entries "${manager}" "${query}" >"${local_source_file}" || true
974
+ if [[ -s "${local_source_file}" ]]; then
975
+ mark_installed_packages "${manager}" "${local_source_file}" "${local_marked_file}"
976
+ awk -F'\t' -v mgr="${manager}" '
977
+ NF >= 1 {
978
+ desc = $2
979
+ if (desc == "") desc = "-"
980
+ print mgr "\t" $1 "\t" desc
981
+ }
982
+ ' "${local_marked_file}" >"${part_file}"
983
+ fi
984
+ rm -f "${local_source_file}" "${local_marked_file}"
985
+ ) &
986
+ gather_pids+=("$!")
987
+ done
988
+
989
+ for gather_pid in "${gather_pids[@]-}"; do
990
+ wait "${gather_pid}" || true
991
+ done
992
+
993
+ for part_file in "${part_files[@]-}"; do
994
+ if [[ -s "${part_file}" ]]; then
995
+ cat "${part_file}" >>"${output_file}"
996
+ fi
997
+ rm -f "${part_file}"
998
+ done
999
+
1000
+ if [[ -s "${output_file}" ]]; then
1001
+ sort -u "${output_file}" -o "${output_file}"
1002
+ fi
1003
+ }
1004
+
1005
+ build_dynamic_reload_command() {
1006
+ local manager_override="$1"
1007
+ local script_path="${BASH_SOURCE[0]}"
1008
+
1009
+ if [[ "${script_path}" != /* ]]; then
1010
+ script_path="$(pwd)/${script_path}"
1011
+ fi
1012
+
1013
+ if [[ -n "${manager_override}" ]]; then
1014
+ printf "%q --feed-search --manager %q -- {q} 2>/dev/null || true" "${script_path}" "${manager_override}"
1015
+ else
1016
+ printf "%q --feed-search -- {q} 2>/dev/null || true" "${script_path}"
1017
+ fi
1018
+ }
1019
+
915
1020
  manager_preview_command() {
916
1021
  local manager="$1"
917
1022
 
@@ -1184,11 +1289,13 @@ run_fuzzy_selector() {
1184
1289
  local query="$1"
1185
1290
  local input_file="$2"
1186
1291
  local header_line="$3"
1292
+ local reload_cmd="${4:-}"
1187
1293
  local preview_cmd
1188
1294
 
1189
1295
  preview_cmd='bash -c '\''mgr="$1"; pkg="$2"; case "$mgr" in apt) apt-cache show "$pkg" 2>/dev/null; printf "\n"; dpkg -L "$pkg" 2>/dev/null ;; dnf) dnf info "$pkg" 2>/dev/null; printf "\n"; rpm -ql "$pkg" 2>/dev/null ;; pacman) pacman -Si "$pkg" 2>/dev/null; printf "\n"; pacman -Fl "$pkg" 2>/dev/null | awk "{print \$2}" ;; zypper) zypper --non-interactive info "$pkg" 2>/dev/null ;; emerge) emerge --search --color=n "$pkg" 2>/dev/null ;; brew) brew info "$pkg" 2>/dev/null ;; winget) winget show --id "$pkg" --exact --source winget --accept-source-agreements --disable-interactivity 2>/dev/null ;; choco) choco info "$pkg" 2>/dev/null ;; scoop) scoop info "$pkg" 2>/dev/null ;; snap) snap info "$pkg" 2>/dev/null ;; flatpak) flatpak info "$pkg" 2>/dev/null || flatpak remote-info flathub "$pkg" 2>/dev/null ;; npm) npm view "$pkg" 2>/dev/null ;; bun) bun info "$pkg" 2>/dev/null || npm view "$pkg" 2>/dev/null ;; esac'\'' _ {1} {2}'
1190
1296
 
1191
- fzf -q "${query}" -e -m \
1297
+ local -a fzf_args=()
1298
+ fzf_args=(-q "${query}" -m \
1192
1299
  --delimiter=$'\t' \
1193
1300
  --with-nth=1,2,3 \
1194
1301
  --preview="${preview_cmd}" \
@@ -1203,8 +1310,15 @@ run_fuzzy_selector() {
1203
1310
  --bind=ctrl-h:preview:"cat ${HELP_FILE}" \
1204
1311
  --bind='ctrl-/:change-preview-window(hidden|)' \
1205
1312
  --bind=ctrl-n:next-selected,ctrl-b:prev-selected \
1206
- --bind='focus:transform-preview-label:echo {1}: {2}' \
1207
- <"${input_file}"
1313
+ --bind='focus:transform-preview-label:echo {1}: {2}')
1314
+
1315
+ if [[ -n "${reload_cmd}" ]]; then
1316
+ fzf_args+=(--disabled --bind="start:reload:${reload_cmd}" --bind="change:reload:${reload_cmd}")
1317
+ else
1318
+ fzf_args+=(-e)
1319
+ fi
1320
+
1321
+ fzf "${fzf_args[@]}" <"${input_file}"
1208
1322
  }
1209
1323
 
1210
1324
  main() {
@@ -1270,22 +1384,33 @@ main() {
1270
1384
  exit 0
1271
1385
  fi
1272
1386
 
1273
- ensure_fzf "${managers[@]-}"
1274
-
1275
1387
  local display_file
1276
1388
  display_file="$(mktemp "${TMP_ROOT}/display.XXXXXX")"
1277
1389
  : >"${display_file}"
1278
1390
 
1279
- local part_files=()
1280
- local gather_pids=()
1281
- local part_file
1282
- local gather_pid
1391
+ if [[ "${ACTION}" == "feed-search" ]]; then
1392
+ collect_search_display_rows "${query}" "${display_file}" "${managers[@]-}"
1393
+ if [[ -s "${display_file}" ]]; then
1394
+ cat "${display_file}"
1395
+ fi
1396
+ rm -f "${display_file}"
1397
+ exit 0
1398
+ fi
1283
1399
 
1284
- for manager in "${managers[@]-}"; do
1285
- part_file="$(mktemp "${TMP_ROOT}/part.XXXXXX")"
1286
- part_files+=("${part_file}")
1400
+ ensure_fzf "${managers[@]-}"
1401
+
1402
+ if [[ "${ACTION}" == "search" ]]; then
1403
+ collect_search_display_rows "${query}" "${display_file}" "${managers[@]-}"
1404
+ else
1405
+ local part_files=()
1406
+ local gather_pids=()
1407
+ local part_file
1408
+ local gather_pid
1409
+
1410
+ for manager in "${managers[@]-}"; do
1411
+ part_file="$(mktemp "${TMP_ROOT}/part.XXXXXX")"
1412
+ part_files+=("${part_file}")
1287
1413
 
1288
- if [[ "${ACTION}" == "list" || "${ACTION}" == "remove" ]]; then
1289
1414
  (
1290
1415
  local_source_file="$(mktemp "${TMP_ROOT}/source.XXXXXX")"
1291
1416
  manager_installed_entries "${manager}" >"${local_source_file}" || true
@@ -1301,41 +1426,22 @@ main() {
1301
1426
  rm -f "${local_source_file}"
1302
1427
  ) &
1303
1428
  gather_pids+=("$!")
1304
- continue
1305
- fi
1429
+ done
1306
1430
 
1307
- (
1308
- local_source_file="$(mktemp "${TMP_ROOT}/source.XXXXXX")"
1309
- local_marked_file="$(mktemp "${TMP_ROOT}/marked.XXXXXX")"
1310
- manager_search_entries "${manager}" "${query}" >"${local_source_file}" || true
1311
- if [[ -s "${local_source_file}" ]]; then
1312
- mark_installed_packages "${manager}" "${local_source_file}" "${local_marked_file}"
1313
- awk -F'\t' -v mgr="${manager}" '
1314
- NF >= 1 {
1315
- desc = $2
1316
- if (desc == "") desc = "-"
1317
- print mgr "\t" $1 "\t" desc
1318
- }
1319
- ' "${local_marked_file}" >"${part_file}"
1320
- fi
1321
- rm -f "${local_source_file}" "${local_marked_file}"
1322
- ) &
1323
- gather_pids+=("$!")
1324
- done
1431
+ for gather_pid in "${gather_pids[@]-}"; do
1432
+ wait "${gather_pid}" || true
1433
+ done
1325
1434
 
1326
- for gather_pid in "${gather_pids[@]-}"; do
1327
- wait "${gather_pid}" || true
1328
- done
1435
+ for part_file in "${part_files[@]-}"; do
1436
+ if [[ -s "${part_file}" ]]; then
1437
+ cat "${part_file}" >>"${display_file}"
1438
+ fi
1439
+ rm -f "${part_file}"
1440
+ done
1329
1441
 
1330
- for part_file in "${part_files[@]-}"; do
1331
- if [[ -s "${part_file}" ]]; then
1332
- cat "${part_file}" >>"${display_file}"
1442
+ if [[ -s "${display_file}" ]]; then
1443
+ sort -u "${display_file}" -o "${display_file}"
1333
1444
  fi
1334
- rm -f "${part_file}"
1335
- done
1336
-
1337
- if [[ -s "${display_file}" ]]; then
1338
- sort -u "${display_file}" -o "${display_file}"
1339
1445
  fi
1340
1446
 
1341
1447
  if [[ ! -s "${display_file}" ]]; then
@@ -1359,8 +1465,13 @@ main() {
1359
1465
  ;;
1360
1466
  esac
1361
1467
 
1468
+ local reload_cmd=""
1469
+ if [[ "${ACTION}" == "search" && -z "${query}" ]]; then
1470
+ reload_cmd="$(build_dynamic_reload_command "${MANAGER_OVERRIDE}")"
1471
+ fi
1472
+
1362
1473
  local selected
1363
- selected="$(run_fuzzy_selector "${query}" "${display_file}" "${header}" || true)"
1474
+ selected="$(run_fuzzy_selector "${query}" "${display_file}" "${header}" "${reload_cmd}" || true)"
1364
1475
 
1365
1476
  rm -f "${display_file}"
1366
1477
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fpf-cli",
3
- "version": "1.6.4",
3
+ "version": "1.6.6",
4
4
  "description": "Cross-platform fuzzy package finder powered by fzf",
5
5
  "bin": {
6
6
  "fpf": "fpf"