fpf-cli 1.6.11 → 1.6.12
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.
- package/fpf +145 -43
- 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.
|
|
6
|
+
SCRIPT_VERSION="1.6.12"
|
|
7
7
|
TMP_ROOT="${TMPDIR:-/tmp}/fpf"
|
|
8
8
|
SESSION_TMP_ROOT=""
|
|
9
9
|
HELP_FILE=""
|
|
@@ -642,85 +642,168 @@ rank_display_rows_by_query() {
|
|
|
642
642
|
local query="$1"
|
|
643
643
|
local input_file="$2"
|
|
644
644
|
local ranked_file
|
|
645
|
+
local has_exact=0
|
|
646
|
+
local candidate
|
|
645
647
|
|
|
646
648
|
[[ -n "${query}" ]] || return 0
|
|
647
649
|
|
|
650
|
+
while IFS= read -r candidate; do
|
|
651
|
+
[[ -n "${candidate}" ]] || continue
|
|
652
|
+
if awk -F'\t' -v cand="${candidate}" 'tolower($2) == tolower(cand) { found=1; exit } END { exit (found ? 0 : 1) }' "${input_file}"; then
|
|
653
|
+
has_exact=1
|
|
654
|
+
break
|
|
655
|
+
fi
|
|
656
|
+
done < <(exact_query_candidates "${query}" | awk '!seen[$0]++')
|
|
657
|
+
|
|
648
658
|
ranked_file="$(mktemp "${SESSION_TMP_ROOT}/ranked.XXXXXX")"
|
|
649
659
|
|
|
650
|
-
awk -F'\t' -v query="${query}" '
|
|
660
|
+
awk -F'\t' -v query="${query}" -v has_exact="${has_exact}" '
|
|
651
661
|
function lower(s) { return tolower(s) }
|
|
662
|
+
function normalize(s, t) {
|
|
663
|
+
t = lower(s)
|
|
664
|
+
gsub(/[^[:alnum:]]+/, "", t)
|
|
665
|
+
return t
|
|
666
|
+
}
|
|
652
667
|
BEGIN {
|
|
653
668
|
q = lower(query)
|
|
669
|
+
gsub(/^[[:space:]]+|[[:space:]]+$/, "", q)
|
|
670
|
+
q_norm = normalize(q)
|
|
671
|
+
|
|
672
|
+
token_total = split(q, raw_tokens, /[^[:alnum:]]+/)
|
|
673
|
+
query_token_count = 0
|
|
674
|
+
for (i = 1; i <= token_total; i++) {
|
|
675
|
+
if (raw_tokens[i] != "") {
|
|
676
|
+
query_tokens[++query_token_count] = raw_tokens[i]
|
|
677
|
+
}
|
|
678
|
+
}
|
|
654
679
|
}
|
|
655
680
|
{
|
|
656
|
-
mgr = $1
|
|
657
681
|
pkg = $2
|
|
658
682
|
desc = $3
|
|
659
683
|
|
|
660
684
|
pkg_l = lower(pkg)
|
|
661
685
|
desc_l = lower(desc)
|
|
686
|
+
pkg_norm = normalize(pkg_l)
|
|
687
|
+
desc_norm = normalize(desc_l)
|
|
688
|
+
|
|
689
|
+
pkg_token_hits = 0
|
|
690
|
+
desc_token_hits = 0
|
|
691
|
+
for (i = 1; i <= query_token_count; i++) {
|
|
692
|
+
token = query_tokens[i]
|
|
693
|
+
if (index(pkg_l, token) > 0 || index(pkg_norm, token) > 0) {
|
|
694
|
+
pkg_token_hits++
|
|
695
|
+
}
|
|
696
|
+
if (index(desc_l, token) > 0 || index(desc_norm, token) > 0) {
|
|
697
|
+
desc_token_hits++
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
pkg_token_count = 0
|
|
702
|
+
split(pkg_l, pkg_parts, /[^[:alnum:]]+/)
|
|
703
|
+
for (i in pkg_parts) {
|
|
704
|
+
if (pkg_parts[i] != "") {
|
|
705
|
+
pkg_token_count++
|
|
706
|
+
}
|
|
707
|
+
}
|
|
662
708
|
|
|
663
|
-
score =
|
|
709
|
+
score = 12
|
|
664
710
|
if (q != "") {
|
|
665
|
-
if (pkg_l == q) {
|
|
711
|
+
if (pkg_l == q || (q_norm != "" && pkg_norm == q_norm)) {
|
|
666
712
|
score = 0
|
|
667
|
-
} else if (index(
|
|
713
|
+
} else if (q_norm != "" && index(pkg_norm, q_norm) == 1) {
|
|
668
714
|
score = 1
|
|
669
|
-
} else if (
|
|
715
|
+
} else if (query_token_count > 1 && pkg_token_hits == query_token_count) {
|
|
670
716
|
score = 2
|
|
671
|
-
} else if (index(
|
|
717
|
+
} else if (q_norm != "" && index(pkg_norm, q_norm) > 0) {
|
|
672
718
|
score = 3
|
|
719
|
+
} else if (query_token_count > 0 && pkg_token_hits > 0) {
|
|
720
|
+
score = 4
|
|
721
|
+
} else if (query_token_count > 0 && desc_token_hits == query_token_count) {
|
|
722
|
+
score = 5
|
|
723
|
+
} else if (query_token_count > 0 && desc_token_hits > 0) {
|
|
724
|
+
score = 6
|
|
673
725
|
}
|
|
674
726
|
}
|
|
675
727
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
mgr_score = 0
|
|
679
|
-
} else if (mgr == "npm") {
|
|
680
|
-
mgr_score = 1
|
|
681
|
-
} else if (mgr == "brew") {
|
|
682
|
-
mgr_score = 2
|
|
728
|
+
if (q != "" && has_exact == 1 && pkg_token_hits == query_token_count && query_token_count > 0 && pkg_token_count > query_token_count) {
|
|
729
|
+
score += 5
|
|
683
730
|
}
|
|
684
731
|
|
|
685
|
-
|
|
732
|
+
if (q != "" && desc_l ~ /(plugin|template|starter|boilerplate|router|hooks?|mcp|integration)/) {
|
|
733
|
+
score += 2
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
mgr_bias = 0
|
|
737
|
+
if (mgr == "npm") {
|
|
738
|
+
mgr_bias = 4
|
|
739
|
+
} else if (mgr == "bun") {
|
|
740
|
+
mgr_bias = 3
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
print score "\t" mgr_bias "\t" (99 - pkg_token_hits) "\t" (99 - desc_token_hits) "\t" length(pkg) "\t" pkg_l "\t" $0
|
|
686
744
|
}
|
|
687
745
|
' "${input_file}" |
|
|
688
|
-
sort -t $'\t' -k1,1n -k2,2n -k3,3n -k4,
|
|
689
|
-
awk -F'\t' '{ print $
|
|
746
|
+
sort -t $'\t' -k1,1n -k2,2n -k3,3n -k4,4n -k5,5n -k6,6 |
|
|
747
|
+
awk -F'\t' '{ print $7 "\t" $8 "\t" $9 }' >"${ranked_file}"
|
|
690
748
|
|
|
691
749
|
mv "${ranked_file}" "${input_file}"
|
|
692
750
|
}
|
|
693
751
|
|
|
694
|
-
|
|
752
|
+
exact_query_candidates() {
|
|
695
753
|
local query="$1"
|
|
696
|
-
|
|
754
|
+
local compact_query=""
|
|
755
|
+
local dashed_query=""
|
|
756
|
+
local underscored_query=""
|
|
757
|
+
local nospace_query=""
|
|
758
|
+
|
|
759
|
+
compact_query="$(printf "%s" "${query}" | awk '{$1=$1; print}')"
|
|
760
|
+
[[ -n "${compact_query}" ]] || return 0
|
|
761
|
+
|
|
762
|
+
printf "%s\n" "${compact_query}"
|
|
763
|
+
|
|
764
|
+
if [[ "${compact_query}" == *[[:space:]]* ]]; then
|
|
765
|
+
dashed_query="${compact_query// /-}"
|
|
766
|
+
underscored_query="${compact_query// /_}"
|
|
767
|
+
nospace_query="${compact_query// /}"
|
|
768
|
+
printf "%s\n" "${dashed_query}"
|
|
769
|
+
printf "%s\n" "${underscored_query}"
|
|
770
|
+
printf "%s\n" "${nospace_query}"
|
|
771
|
+
fi
|
|
697
772
|
}
|
|
698
773
|
|
|
699
774
|
exact_match_entry() {
|
|
700
775
|
local manager="$1"
|
|
701
776
|
local query="$2"
|
|
777
|
+
local candidate
|
|
702
778
|
|
|
703
|
-
if
|
|
779
|
+
if [[ -z "${query}" ]]; then
|
|
704
780
|
return 0
|
|
705
781
|
fi
|
|
706
782
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
783
|
+
while IFS= read -r candidate; do
|
|
784
|
+
[[ -n "${candidate}" ]] || continue
|
|
785
|
+
|
|
786
|
+
case "${manager}" in
|
|
787
|
+
brew)
|
|
788
|
+
if brew info --formula "${candidate}" >/dev/null 2>&1 || brew info --cask "${candidate}" >/dev/null 2>&1; then
|
|
789
|
+
printf "%s\t-\n" "${candidate}"
|
|
790
|
+
return 0
|
|
791
|
+
fi
|
|
792
|
+
;;
|
|
793
|
+
npm)
|
|
794
|
+
if command_exists npm && npm view "${candidate}" name >/dev/null 2>&1; then
|
|
795
|
+
printf "%s\t-\n" "${candidate}"
|
|
796
|
+
return 0
|
|
797
|
+
fi
|
|
798
|
+
;;
|
|
799
|
+
bun)
|
|
800
|
+
if bun info "${candidate}" >/dev/null 2>&1 || (command_exists npm && npm view "${candidate}" name >/dev/null 2>&1); then
|
|
801
|
+
printf "%s\t-\n" "${candidate}"
|
|
802
|
+
return 0
|
|
803
|
+
fi
|
|
804
|
+
;;
|
|
805
|
+
esac
|
|
806
|
+
done < <(exact_query_candidates "${query}" | awk '!seen[$0]++')
|
|
724
807
|
}
|
|
725
808
|
|
|
726
809
|
manager_search_entries() {
|
|
@@ -729,10 +812,14 @@ manager_search_entries() {
|
|
|
729
812
|
local effective_query="${query}"
|
|
730
813
|
local npm_search_limit=500
|
|
731
814
|
local line_limit=0
|
|
815
|
+
local query_line_limit=40
|
|
816
|
+
local effective_limit=0
|
|
732
817
|
|
|
733
818
|
if [[ -z "${query}" ]]; then
|
|
734
819
|
npm_search_limit="${FPF_NO_QUERY_NPM_LIMIT:-120}"
|
|
735
820
|
line_limit="${FPF_NO_QUERY_RESULT_LIMIT:-120}"
|
|
821
|
+
else
|
|
822
|
+
query_line_limit="${FPF_QUERY_PER_MANAGER_LIMIT:-40}"
|
|
736
823
|
fi
|
|
737
824
|
|
|
738
825
|
if ! [[ "${npm_search_limit}" =~ ^[0-9]+$ ]] || [[ "${npm_search_limit}" -eq 0 ]]; then
|
|
@@ -743,6 +830,16 @@ manager_search_entries() {
|
|
|
743
830
|
line_limit=0
|
|
744
831
|
fi
|
|
745
832
|
|
|
833
|
+
if ! [[ "${query_line_limit}" =~ ^[0-9]+$ ]]; then
|
|
834
|
+
query_line_limit=40
|
|
835
|
+
fi
|
|
836
|
+
|
|
837
|
+
if [[ "${line_limit}" -gt 0 ]]; then
|
|
838
|
+
effective_limit="${line_limit}"
|
|
839
|
+
else
|
|
840
|
+
effective_limit="${query_line_limit}"
|
|
841
|
+
fi
|
|
842
|
+
|
|
746
843
|
if [[ -z "${effective_query}" ]]; then
|
|
747
844
|
case "${manager}" in
|
|
748
845
|
apt|dnf|pacman|zypper|emerge|choco|scoop|snap)
|
|
@@ -912,8 +1009,8 @@ manager_search_entries() {
|
|
|
912
1009
|
} || true
|
|
913
1010
|
;;
|
|
914
1011
|
esac | awk -F'\t' 'NF >= 1 { if ($2 == "") $2 = "-"; print $1 "\t" $2 }' | awk -F'\t' '!seen[$1]++' | {
|
|
915
|
-
if [[ "${
|
|
916
|
-
awk -v limit="${
|
|
1012
|
+
if [[ "${effective_limit}" -gt 0 ]]; then
|
|
1013
|
+
awk -v limit="${effective_limit}" 'NR <= limit'
|
|
917
1014
|
else
|
|
918
1015
|
cat
|
|
919
1016
|
fi
|
|
@@ -1101,6 +1198,7 @@ collect_search_display_rows() {
|
|
|
1101
1198
|
local output_file="$2"
|
|
1102
1199
|
shift 2
|
|
1103
1200
|
local managers=("$@")
|
|
1201
|
+
local query_limit="${FPF_QUERY_RESULT_LIMIT:-80}"
|
|
1104
1202
|
|
|
1105
1203
|
: >"${output_file}"
|
|
1106
1204
|
|
|
@@ -1147,6 +1245,11 @@ collect_search_display_rows() {
|
|
|
1147
1245
|
if [[ -s "${output_file}" ]]; then
|
|
1148
1246
|
sort -u "${output_file}" -o "${output_file}"
|
|
1149
1247
|
rank_display_rows_by_query "${query}" "${output_file}"
|
|
1248
|
+
|
|
1249
|
+
if [[ -n "${query}" && "${query_limit}" =~ ^[0-9]+$ && "${query_limit}" -gt 0 ]]; then
|
|
1250
|
+
awk -v limit="${query_limit}" 'NR <= limit' "${output_file}" >"${output_file}.limited"
|
|
1251
|
+
mv "${output_file}.limited" "${output_file}"
|
|
1252
|
+
fi
|
|
1150
1253
|
fi
|
|
1151
1254
|
}
|
|
1152
1255
|
|
|
@@ -1412,10 +1515,11 @@ run_fuzzy_selector() {
|
|
|
1412
1515
|
|
|
1413
1516
|
local -a fzf_args=()
|
|
1414
1517
|
fzf_args=(-q "${query}" -m \
|
|
1518
|
+
-e \
|
|
1415
1519
|
--delimiter=$'\t' \
|
|
1416
1520
|
--with-nth=1,2,3 \
|
|
1417
1521
|
--preview="${preview_cmd}" \
|
|
1418
|
-
--preview-window=55%:wrap:border-sharp
|
|
1522
|
+
--preview-window=55%:wrap:border-sharp \
|
|
1419
1523
|
--layout=reverse \
|
|
1420
1524
|
--marker='>>' \
|
|
1421
1525
|
--prompt='Search> ' \
|
|
@@ -1431,8 +1535,6 @@ run_fuzzy_selector() {
|
|
|
1431
1535
|
|
|
1432
1536
|
if [[ -n "${reload_cmd}" ]]; then
|
|
1433
1537
|
fzf_args+=(--bind="change:reload:${reload_cmd}")
|
|
1434
|
-
else
|
|
1435
|
-
fzf_args+=(-e)
|
|
1436
1538
|
fi
|
|
1437
1539
|
|
|
1438
1540
|
fzf "${fzf_args[@]}" <"${input_file}"
|