fpf-cli 1.6.34 → 1.6.36
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/README.md +2 -0
- package/fpf +292 -42
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -98,6 +98,8 @@ Installed packages are marked with `*` in the result list.
|
|
|
98
98
|
- `FPF_DYNAMIC_RELOAD`: `always` (default), `single`, or `never`
|
|
99
99
|
- Live reload uses `change:reload` by default for reliability (`ctrl-r` uses the same reload command).
|
|
100
100
|
- Set `FPF_DYNAMIC_RELOAD_TRANSPORT=ipc` to opt into `--listen` + IPC query notifications on supported `fzf` builds.
|
|
101
|
+
- Startup now shows a dynamic pre-search loader with per-manager progress + elapsed time.
|
|
102
|
+
- Set `FPF_LOADING_INDICATOR=0` to disable the pre-search loading indicator.
|
|
101
103
|
- `FPF_RELOAD_MIN_CHARS`: minimum query length before live reload (default `2`)
|
|
102
104
|
- `FPF_RELOAD_DEBOUNCE`: reload debounce seconds (default `0.12`)
|
|
103
105
|
- `FPF_DISABLE_INSTALLED_CACHE=1` disables installed-package marker cache
|
package/fpf
CHANGED
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
set -euo pipefail
|
|
4
4
|
|
|
5
5
|
SCRIPT_NAME="fpf"
|
|
6
|
-
SCRIPT_VERSION="1.6.
|
|
6
|
+
SCRIPT_VERSION="1.6.36"
|
|
7
7
|
TMP_ROOT="${TMPDIR:-/tmp}/fpf"
|
|
8
8
|
SESSION_TMP_ROOT=""
|
|
9
9
|
HELP_FILE=""
|
|
10
10
|
KBINDS_FILE=""
|
|
11
11
|
CACHE_FORMAT_VERSION="1"
|
|
12
12
|
CACHE_ROOT=""
|
|
13
|
+
LOADING_INDICATOR_PID=""
|
|
14
|
+
LOADING_PROGRESS_DIR=""
|
|
13
15
|
|
|
14
16
|
ACTION="search"
|
|
15
17
|
MANAGER_OVERRIDE=""
|
|
@@ -27,6 +29,208 @@ log() {
|
|
|
27
29
|
printf "%s\n" "$*" >&2
|
|
28
30
|
}
|
|
29
31
|
|
|
32
|
+
loading_indicator_enabled() {
|
|
33
|
+
local indicator_setting=""
|
|
34
|
+
|
|
35
|
+
indicator_setting="$(trim_whitespace "${FPF_LOADING_INDICATOR:-1}")"
|
|
36
|
+
indicator_setting="$(printf "%s" "${indicator_setting}" | tr '[:upper:]' '[:lower:]')"
|
|
37
|
+
|
|
38
|
+
case "${indicator_setting}" in
|
|
39
|
+
0|false|no|off)
|
|
40
|
+
return 1
|
|
41
|
+
;;
|
|
42
|
+
esac
|
|
43
|
+
|
|
44
|
+
[[ -t 2 ]]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
loading_progress_begin() {
|
|
48
|
+
local managers=("$@")
|
|
49
|
+
local manager=""
|
|
50
|
+
local progress_file=""
|
|
51
|
+
|
|
52
|
+
loading_progress_end
|
|
53
|
+
loading_indicator_enabled || return 0
|
|
54
|
+
[[ "${#managers[@]}" -gt 0 ]] || return 0
|
|
55
|
+
|
|
56
|
+
LOADING_PROGRESS_DIR="$(mktemp -d "${SESSION_TMP_ROOT}/loading-progress.XXXXXX")"
|
|
57
|
+
for manager in "${managers[@]-}"; do
|
|
58
|
+
progress_file="${LOADING_PROGRESS_DIR}/${manager}.status"
|
|
59
|
+
printf "pending\tqueued\n" >"${progress_file}"
|
|
60
|
+
done
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
loading_progress_end() {
|
|
64
|
+
if [[ -z "${LOADING_PROGRESS_DIR}" ]]; then
|
|
65
|
+
return 0
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
if [[ -d "${LOADING_PROGRESS_DIR}" ]]; then
|
|
69
|
+
rm -rf "${LOADING_PROGRESS_DIR}" >/dev/null 2>&1 || true
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
LOADING_PROGRESS_DIR=""
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
loading_progress_mark_state() {
|
|
76
|
+
local manager="$1"
|
|
77
|
+
local state="$2"
|
|
78
|
+
local detail="${3:-}"
|
|
79
|
+
local progress_file=""
|
|
80
|
+
|
|
81
|
+
if [[ -z "${LOADING_PROGRESS_DIR}" || ! -d "${LOADING_PROGRESS_DIR}" ]]; then
|
|
82
|
+
return 0
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
progress_file="${LOADING_PROGRESS_DIR}/${manager}.status"
|
|
86
|
+
printf "%s\t%s\n" "${state}" "${detail}" >"${progress_file}" 2>/dev/null || true
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
loading_progress_mark_running() {
|
|
90
|
+
local manager="$1"
|
|
91
|
+
local detail="${2:-working}"
|
|
92
|
+
loading_progress_mark_state "${manager}" "running" "${detail}"
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
loading_progress_mark_done() {
|
|
96
|
+
local manager="$1"
|
|
97
|
+
local detail="${2:-done}"
|
|
98
|
+
loading_progress_mark_state "${manager}" "done" "${detail}"
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
loading_progress_snapshot() {
|
|
102
|
+
local status_file=""
|
|
103
|
+
local manager=""
|
|
104
|
+
local status=""
|
|
105
|
+
local detail=""
|
|
106
|
+
local total=0
|
|
107
|
+
local done=0
|
|
108
|
+
local running=0
|
|
109
|
+
local queued=0
|
|
110
|
+
local -a active_details=()
|
|
111
|
+
local active_display=""
|
|
112
|
+
local idx
|
|
113
|
+
|
|
114
|
+
if [[ -z "${LOADING_PROGRESS_DIR}" || ! -d "${LOADING_PROGRESS_DIR}" ]]; then
|
|
115
|
+
return 0
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
for status_file in "${LOADING_PROGRESS_DIR}"/*.status; do
|
|
119
|
+
[[ -f "${status_file}" ]] || continue
|
|
120
|
+
total=$((total + 1))
|
|
121
|
+
manager="$(basename "${status_file}" .status)"
|
|
122
|
+
IFS=$'\t' read -r status detail <"${status_file}" || true
|
|
123
|
+
case "${status}" in
|
|
124
|
+
done)
|
|
125
|
+
done=$((done + 1))
|
|
126
|
+
;;
|
|
127
|
+
running)
|
|
128
|
+
running=$((running + 1))
|
|
129
|
+
if [[ "${#active_details[@]}" -lt 2 ]]; then
|
|
130
|
+
active_details+=("$(manager_label "${manager}"): ${detail:-working}")
|
|
131
|
+
fi
|
|
132
|
+
;;
|
|
133
|
+
*)
|
|
134
|
+
queued=$((queued + 1))
|
|
135
|
+
;;
|
|
136
|
+
esac
|
|
137
|
+
done
|
|
138
|
+
|
|
139
|
+
[[ "${total}" -gt 0 ]] || return 0
|
|
140
|
+
|
|
141
|
+
active_display=""
|
|
142
|
+
for idx in "${!active_details[@]}"; do
|
|
143
|
+
if [[ -n "${active_display}" ]]; then
|
|
144
|
+
active_display+=", "
|
|
145
|
+
fi
|
|
146
|
+
active_display+="${active_details[$idx]}"
|
|
147
|
+
done
|
|
148
|
+
if [[ "${running}" -gt "${#active_details[@]}" ]]; then
|
|
149
|
+
if [[ -n "${active_display}" ]]; then
|
|
150
|
+
active_display+=", "
|
|
151
|
+
fi
|
|
152
|
+
active_display+="+$((running - ${#active_details[@]})) more"
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
printf "%s/%s done" "${done}" "${total}"
|
|
156
|
+
if [[ -n "${active_display}" ]]; then
|
|
157
|
+
printf " | active: %s" "${active_display}"
|
|
158
|
+
fi
|
|
159
|
+
if [[ "${queued}" -gt 0 ]]; then
|
|
160
|
+
printf " | queued: %s" "${queued}"
|
|
161
|
+
fi
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
start_loading_indicator() {
|
|
165
|
+
local message="${1:-Loading}"
|
|
166
|
+
|
|
167
|
+
if [[ -n "${LOADING_INDICATOR_PID}" ]]; then
|
|
168
|
+
stop_loading_indicator
|
|
169
|
+
fi
|
|
170
|
+
|
|
171
|
+
loading_indicator_enabled || return 0
|
|
172
|
+
|
|
173
|
+
(
|
|
174
|
+
trap 'exit 0' TERM INT
|
|
175
|
+
local frames='|/-\'
|
|
176
|
+
local frame_index=0
|
|
177
|
+
local started_epoch
|
|
178
|
+
local elapsed_seconds=0
|
|
179
|
+
local snapshot=""
|
|
180
|
+
|
|
181
|
+
started_epoch="$(date +%s)"
|
|
182
|
+
if ! [[ "${started_epoch}" =~ ^[0-9]+$ ]]; then
|
|
183
|
+
started_epoch=0
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
while true; do
|
|
187
|
+
elapsed_seconds="$(( $(date +%s) - started_epoch ))"
|
|
188
|
+
if [[ "${elapsed_seconds}" -lt 0 ]]; then
|
|
189
|
+
elapsed_seconds=0
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
snapshot="$(loading_progress_snapshot)"
|
|
193
|
+
if [[ -n "${snapshot}" ]]; then
|
|
194
|
+
printf "\r\033[2K%s [%s] %s | elapsed: %ss" "${message}" "${frames:frame_index:1}" "${snapshot}" "${elapsed_seconds}" >&2
|
|
195
|
+
else
|
|
196
|
+
printf "\r\033[2K%s [%s] elapsed: %ss" "${message}" "${frames:frame_index:1}" "${elapsed_seconds}" >&2
|
|
197
|
+
fi
|
|
198
|
+
frame_index=$(((frame_index + 1) % 4))
|
|
199
|
+
sleep 0.1
|
|
200
|
+
done
|
|
201
|
+
) &
|
|
202
|
+
LOADING_INDICATOR_PID="$!"
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
stop_loading_indicator() {
|
|
206
|
+
if [[ -z "${LOADING_INDICATOR_PID}" ]]; then
|
|
207
|
+
return 0
|
|
208
|
+
fi
|
|
209
|
+
|
|
210
|
+
kill "${LOADING_INDICATOR_PID}" >/dev/null 2>&1 || true
|
|
211
|
+
wait "${LOADING_INDICATOR_PID}" >/dev/null 2>&1 || true
|
|
212
|
+
LOADING_INDICATOR_PID=""
|
|
213
|
+
|
|
214
|
+
if loading_indicator_enabled; then
|
|
215
|
+
printf "\r\033[2K" >&2
|
|
216
|
+
fi
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
run_with_loading_indicator() {
|
|
220
|
+
local message="$1"
|
|
221
|
+
shift
|
|
222
|
+
|
|
223
|
+
start_loading_indicator "${message}"
|
|
224
|
+
if "$@"; then
|
|
225
|
+
stop_loading_indicator
|
|
226
|
+
return 0
|
|
227
|
+
fi
|
|
228
|
+
|
|
229
|
+
local status="$?"
|
|
230
|
+
stop_loading_indicator
|
|
231
|
+
return "${status}"
|
|
232
|
+
}
|
|
233
|
+
|
|
30
234
|
die() {
|
|
31
235
|
log "Error: $*"
|
|
32
236
|
exit 1
|
|
@@ -861,6 +1065,9 @@ run_preview_item_action() {
|
|
|
861
1065
|
}
|
|
862
1066
|
|
|
863
1067
|
cleanup_session_tmp_root() {
|
|
1068
|
+
stop_loading_indicator
|
|
1069
|
+
loading_progress_end
|
|
1070
|
+
|
|
864
1071
|
if [[ -n "${SESSION_TMP_ROOT}" && -d "${SESSION_TMP_ROOT}" ]]; then
|
|
865
1072
|
rm -rf "${SESSION_TMP_ROOT}"
|
|
866
1073
|
fi
|
|
@@ -2711,6 +2918,10 @@ collect_search_display_rows() {
|
|
|
2711
2918
|
part_files+=("${part_file}")
|
|
2712
2919
|
|
|
2713
2920
|
(
|
|
2921
|
+
local local_source_file
|
|
2922
|
+
local result_count=0
|
|
2923
|
+
|
|
2924
|
+
loading_progress_mark_running "${manager}" "searching package index"
|
|
2714
2925
|
local_source_file="$(mktemp "${SESSION_TMP_ROOT}/source.XXXXXX")"
|
|
2715
2926
|
manager_search_entries "${manager}" "${query}" >"${local_source_file}" || true
|
|
2716
2927
|
if [[ -s "${local_source_file}" ]]; then
|
|
@@ -2723,6 +2934,11 @@ collect_search_display_rows() {
|
|
|
2723
2934
|
' "${local_source_file}" >"${part_file}"
|
|
2724
2935
|
fi
|
|
2725
2936
|
rm -f "${local_source_file}"
|
|
2937
|
+
|
|
2938
|
+
if [[ -s "${part_file}" ]]; then
|
|
2939
|
+
result_count="$(awk 'END { print NR + 0 }' "${part_file}")"
|
|
2940
|
+
fi
|
|
2941
|
+
loading_progress_mark_done "${manager}" "${result_count} results indexed"
|
|
2726
2942
|
) &
|
|
2727
2943
|
gather_pids+=("$!")
|
|
2728
2944
|
done
|
|
@@ -2755,6 +2971,64 @@ collect_search_display_rows() {
|
|
|
2755
2971
|
rm -f "${merged_source_file}" "${merged_marked_file}"
|
|
2756
2972
|
}
|
|
2757
2973
|
|
|
2974
|
+
collect_installed_display_rows() {
|
|
2975
|
+
local output_file="$1"
|
|
2976
|
+
shift
|
|
2977
|
+
local managers=("$@")
|
|
2978
|
+
local part_files=()
|
|
2979
|
+
local gather_pids=()
|
|
2980
|
+
local manager
|
|
2981
|
+
local part_file
|
|
2982
|
+
local gather_pid
|
|
2983
|
+
|
|
2984
|
+
: >"${output_file}"
|
|
2985
|
+
|
|
2986
|
+
for manager in "${managers[@]-}"; do
|
|
2987
|
+
part_file="$(mktemp "${SESSION_TMP_ROOT}/part.XXXXXX")"
|
|
2988
|
+
part_files+=("${part_file}")
|
|
2989
|
+
|
|
2990
|
+
(
|
|
2991
|
+
local local_source_file
|
|
2992
|
+
local result_count=0
|
|
2993
|
+
|
|
2994
|
+
loading_progress_mark_running "${manager}" "reading installed packages"
|
|
2995
|
+
local_source_file="$(mktemp "${SESSION_TMP_ROOT}/source.XXXXXX")"
|
|
2996
|
+
manager_installed_entries "${manager}" >"${local_source_file}" || true
|
|
2997
|
+
if [[ -s "${local_source_file}" ]]; then
|
|
2998
|
+
awk -F'\t' -v mgr="${manager}" '
|
|
2999
|
+
NF >= 1 {
|
|
3000
|
+
desc = $2
|
|
3001
|
+
if (desc == "") desc = "-"
|
|
3002
|
+
print mgr "\t" $1 "\t" desc
|
|
3003
|
+
}
|
|
3004
|
+
' "${local_source_file}" >"${part_file}"
|
|
3005
|
+
fi
|
|
3006
|
+
rm -f "${local_source_file}"
|
|
3007
|
+
|
|
3008
|
+
if [[ -s "${part_file}" ]]; then
|
|
3009
|
+
result_count="$(awk 'END { print NR + 0 }' "${part_file}")"
|
|
3010
|
+
fi
|
|
3011
|
+
loading_progress_mark_done "${manager}" "${result_count} installed entries"
|
|
3012
|
+
) &
|
|
3013
|
+
gather_pids+=("$!")
|
|
3014
|
+
done
|
|
3015
|
+
|
|
3016
|
+
for gather_pid in "${gather_pids[@]-}"; do
|
|
3017
|
+
wait "${gather_pid}" || true
|
|
3018
|
+
done
|
|
3019
|
+
|
|
3020
|
+
for part_file in "${part_files[@]-}"; do
|
|
3021
|
+
if [[ -s "${part_file}" ]]; then
|
|
3022
|
+
cat "${part_file}" >>"${output_file}"
|
|
3023
|
+
fi
|
|
3024
|
+
rm -f "${part_file}"
|
|
3025
|
+
done
|
|
3026
|
+
|
|
3027
|
+
if [[ -s "${output_file}" ]]; then
|
|
3028
|
+
sort -u "${output_file}" -o "${output_file}"
|
|
3029
|
+
fi
|
|
3030
|
+
}
|
|
3031
|
+
|
|
2758
3032
|
build_dynamic_reload_command() {
|
|
2759
3033
|
local manager_override="$1"
|
|
2760
3034
|
local fallback_file="$2"
|
|
@@ -3286,48 +3560,19 @@ main() {
|
|
|
3286
3560
|
ensure_fzf "${managers[@]-}"
|
|
3287
3561
|
|
|
3288
3562
|
if [[ "${ACTION}" == "search" ]]; then
|
|
3289
|
-
|
|
3563
|
+
loading_progress_begin "${managers[@]-}"
|
|
3564
|
+
if ! run_with_loading_indicator "Loading packages from ${manager_display}" collect_search_display_rows "${query}" "${display_file}" "${managers[@]-}"; then
|
|
3565
|
+
loading_progress_end
|
|
3566
|
+
die "Failed to load package search results."
|
|
3567
|
+
fi
|
|
3568
|
+
loading_progress_end
|
|
3290
3569
|
else
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
for manager in "${managers[@]-}"; do
|
|
3297
|
-
part_file="$(mktemp "${SESSION_TMP_ROOT}/part.XXXXXX")"
|
|
3298
|
-
part_files+=("${part_file}")
|
|
3299
|
-
|
|
3300
|
-
(
|
|
3301
|
-
local_source_file="$(mktemp "${SESSION_TMP_ROOT}/source.XXXXXX")"
|
|
3302
|
-
manager_installed_entries "${manager}" >"${local_source_file}" || true
|
|
3303
|
-
if [[ -s "${local_source_file}" ]]; then
|
|
3304
|
-
awk -F'\t' -v mgr="${manager}" '
|
|
3305
|
-
NF >= 1 {
|
|
3306
|
-
desc = $2
|
|
3307
|
-
if (desc == "") desc = "-"
|
|
3308
|
-
print mgr "\t" $1 "\t" desc
|
|
3309
|
-
}
|
|
3310
|
-
' "${local_source_file}" >"${part_file}"
|
|
3311
|
-
fi
|
|
3312
|
-
rm -f "${local_source_file}"
|
|
3313
|
-
) &
|
|
3314
|
-
gather_pids+=("$!")
|
|
3315
|
-
done
|
|
3316
|
-
|
|
3317
|
-
for gather_pid in "${gather_pids[@]-}"; do
|
|
3318
|
-
wait "${gather_pid}" || true
|
|
3319
|
-
done
|
|
3320
|
-
|
|
3321
|
-
for part_file in "${part_files[@]-}"; do
|
|
3322
|
-
if [[ -s "${part_file}" ]]; then
|
|
3323
|
-
cat "${part_file}" >>"${display_file}"
|
|
3324
|
-
fi
|
|
3325
|
-
rm -f "${part_file}"
|
|
3326
|
-
done
|
|
3327
|
-
|
|
3328
|
-
if [[ -s "${display_file}" ]]; then
|
|
3329
|
-
sort -u "${display_file}" -o "${display_file}"
|
|
3570
|
+
loading_progress_begin "${managers[@]-}"
|
|
3571
|
+
if ! run_with_loading_indicator "Loading installed packages from ${manager_display}" collect_installed_display_rows "${display_file}" "${managers[@]-}"; then
|
|
3572
|
+
loading_progress_end
|
|
3573
|
+
die "Failed to load installed package results."
|
|
3330
3574
|
fi
|
|
3575
|
+
loading_progress_end
|
|
3331
3576
|
fi
|
|
3332
3577
|
|
|
3333
3578
|
if [[ ! -s "${display_file}" ]]; then
|
|
@@ -3370,7 +3615,12 @@ main() {
|
|
|
3370
3615
|
if dynamic_reload_enabled "${#managers[@]}"; then
|
|
3371
3616
|
if [[ -n "${query}" ]]; then
|
|
3372
3617
|
reload_fallback_file="$(mktemp "${SESSION_TMP_ROOT}/reload-fallback.XXXXXX")"
|
|
3373
|
-
|
|
3618
|
+
loading_progress_begin "${managers[@]-}"
|
|
3619
|
+
if ! run_with_loading_indicator "Preparing baseline search results" collect_search_display_rows "" "${reload_fallback_file}" "${managers[@]-}"; then
|
|
3620
|
+
loading_progress_end
|
|
3621
|
+
die "Failed to prepare baseline search results."
|
|
3622
|
+
fi
|
|
3623
|
+
loading_progress_end
|
|
3374
3624
|
if [[ ! -s "${reload_fallback_file}" ]]; then
|
|
3375
3625
|
cp "${display_file}" "${reload_fallback_file}"
|
|
3376
3626
|
fi
|