fpf-cli 1.6.15 → 1.6.17
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 +1 -0
- package/fpf +1311 -72
- package/package.json +1 -1
package/fpf
CHANGED
|
@@ -3,16 +3,24 @@
|
|
|
3
3
|
set -euo pipefail
|
|
4
4
|
|
|
5
5
|
SCRIPT_NAME="fpf"
|
|
6
|
-
SCRIPT_VERSION="1.6.
|
|
6
|
+
SCRIPT_VERSION="1.6.17"
|
|
7
7
|
TMP_ROOT="${TMPDIR:-/tmp}/fpf"
|
|
8
8
|
SESSION_TMP_ROOT=""
|
|
9
9
|
HELP_FILE=""
|
|
10
10
|
KBINDS_FILE=""
|
|
11
|
+
CACHE_FORMAT_VERSION="1"
|
|
12
|
+
CACHE_ROOT=""
|
|
11
13
|
|
|
12
14
|
ACTION="search"
|
|
13
15
|
MANAGER_OVERRIDE=""
|
|
16
|
+
IPC_MANAGER_OVERRIDE=""
|
|
17
|
+
IPC_FALLBACK_FILE=""
|
|
14
18
|
declare -a QUERY_PARTS=()
|
|
15
19
|
|
|
20
|
+
query_cache_flags() {
|
|
21
|
+
printf "%s" "query_limit=${FPF_QUERY_RESULT_LIMIT:-0};per_manager_limit=${FPF_QUERY_PER_MANAGER_LIMIT:-40};no_query_limit=${FPF_NO_QUERY_RESULT_LIMIT:-120};no_query_npm_limit=${FPF_NO_QUERY_NPM_LIMIT:-120}"
|
|
22
|
+
}
|
|
23
|
+
|
|
16
24
|
log() {
|
|
17
25
|
printf "%s\n" "$*" >&2
|
|
18
26
|
}
|
|
@@ -30,16 +38,672 @@ ensure_tmp_root() {
|
|
|
30
38
|
mkdir -p "${TMP_ROOT}"
|
|
31
39
|
}
|
|
32
40
|
|
|
41
|
+
resolve_cache_root() {
|
|
42
|
+
local os
|
|
43
|
+
os="$(uname -s)"
|
|
44
|
+
|
|
45
|
+
if [[ -n "${FPF_CACHE_DIR:-}" ]]; then
|
|
46
|
+
printf "%s" "${FPF_CACHE_DIR}"
|
|
47
|
+
return
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
case "${os}" in
|
|
51
|
+
Darwin)
|
|
52
|
+
printf "%s" "${HOME}/Library/Caches/fpf"
|
|
53
|
+
;;
|
|
54
|
+
Linux)
|
|
55
|
+
if [[ -n "${XDG_CACHE_HOME:-}" ]]; then
|
|
56
|
+
printf "%s" "${XDG_CACHE_HOME}/fpf"
|
|
57
|
+
else
|
|
58
|
+
printf "%s" "${HOME}/.cache/fpf"
|
|
59
|
+
fi
|
|
60
|
+
;;
|
|
61
|
+
MINGW*|MSYS*|CYGWIN*|Windows_NT)
|
|
62
|
+
if [[ -n "${LOCALAPPDATA:-}" ]]; then
|
|
63
|
+
printf "%s" "${LOCALAPPDATA}/fpf"
|
|
64
|
+
elif [[ -n "${APPDATA:-}" ]]; then
|
|
65
|
+
printf "%s" "${APPDATA}/fpf"
|
|
66
|
+
else
|
|
67
|
+
printf "%s" "${HOME}/.cache/fpf"
|
|
68
|
+
fi
|
|
69
|
+
;;
|
|
70
|
+
*)
|
|
71
|
+
printf "%s" "${HOME}/.cache/fpf"
|
|
72
|
+
;;
|
|
73
|
+
esac
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
initialize_cache_root() {
|
|
77
|
+
if [[ -n "${CACHE_ROOT}" ]]; then
|
|
78
|
+
return
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
CACHE_ROOT="$(resolve_cache_root)"
|
|
82
|
+
mkdir -p "${CACHE_ROOT}"
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
normalize_cache_query() {
|
|
86
|
+
printf "%s" "$1" |
|
|
87
|
+
awk '{
|
|
88
|
+
line=$0
|
|
89
|
+
gsub(/^[[:space:]]+|[[:space:]]+$/, "", line)
|
|
90
|
+
gsub(/[[:space:]]+/, " ", line)
|
|
91
|
+
print tolower(line)
|
|
92
|
+
}'
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
platform_cache_token() {
|
|
96
|
+
uname -s | tr '[:upper:]' '[:lower:]'
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
cache_fingerprint() {
|
|
100
|
+
local manager="$1"
|
|
101
|
+
local query="$2"
|
|
102
|
+
local flags="$3"
|
|
103
|
+
local normalized_query
|
|
104
|
+
|
|
105
|
+
normalized_query="$(normalize_cache_query "${query}")"
|
|
106
|
+
printf "%s|%s|%s|%s|%s" "${CACHE_FORMAT_VERSION}" "${manager}" "$(platform_cache_token)" "${normalized_query}" "${flags}"
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
cache_cksum() {
|
|
110
|
+
local input="$1"
|
|
111
|
+
printf "%s" "${input}" | cksum | awk '{ print $1 }'
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
cache_catalog_key() {
|
|
115
|
+
local manager="$1"
|
|
116
|
+
printf "catalog/%s.tsv" "${manager}"
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
cache_search_catalog_fingerprint() {
|
|
120
|
+
local manager="$1"
|
|
121
|
+
local command_path=""
|
|
122
|
+
local extra_token=""
|
|
123
|
+
|
|
124
|
+
case "${manager}" in
|
|
125
|
+
apt)
|
|
126
|
+
command_path="$(command -v apt-cache 2>/dev/null || printf "missing")"
|
|
127
|
+
if [[ "${FPF_TEST_FIXTURES:-0}" == "1" ]]; then
|
|
128
|
+
extra_token="|fixtures=${FPF_TEST_FIXTURE_DIR:-enabled}"
|
|
129
|
+
fi
|
|
130
|
+
;;
|
|
131
|
+
brew)
|
|
132
|
+
command_path="$(command -v brew 2>/dev/null || printf "missing")"
|
|
133
|
+
if [[ "${FPF_TEST_FIXTURES:-0}" == "1" ]]; then
|
|
134
|
+
extra_token="|fixtures=${FPF_TEST_FIXTURE_DIR:-enabled}"
|
|
135
|
+
fi
|
|
136
|
+
;;
|
|
137
|
+
*)
|
|
138
|
+
command_path="n/a"
|
|
139
|
+
;;
|
|
140
|
+
esac
|
|
141
|
+
|
|
142
|
+
printf "%s|cmd=%s%s" "$(cache_fingerprint "${manager}" "" "search-catalog")" "${command_path}" "${extra_token}"
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
cache_search_catalog_key() {
|
|
146
|
+
local manager="$1"
|
|
147
|
+
local fingerprint="$2"
|
|
148
|
+
local checksum
|
|
149
|
+
|
|
150
|
+
checksum="$(cache_cksum "${fingerprint}")"
|
|
151
|
+
printf "search-catalog/%s/%s.tsv" "${manager}" "${checksum}"
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
cache_query_key() {
|
|
155
|
+
local manager="$1"
|
|
156
|
+
local query="$2"
|
|
157
|
+
local flags="$3"
|
|
158
|
+
local fingerprint
|
|
159
|
+
local checksum
|
|
160
|
+
|
|
161
|
+
fingerprint="$(cache_fingerprint "${manager}" "${query}" "${flags}")"
|
|
162
|
+
checksum="$(cache_cksum "${fingerprint}")"
|
|
163
|
+
printf "query/%s/%s.tsv" "${manager}" "${checksum}"
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
cache_meta_key() {
|
|
167
|
+
local key="$1"
|
|
168
|
+
printf "meta/%s.meta" "${key}"
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
cache_path_for_key() {
|
|
172
|
+
local key="$1"
|
|
173
|
+
printf "%s/%s" "${CACHE_ROOT}" "${key}"
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
cache_atomic_write_from_file() {
|
|
177
|
+
local source_file="$1"
|
|
178
|
+
local destination_file="$2"
|
|
179
|
+
local destination_dir
|
|
180
|
+
local destination_base
|
|
181
|
+
local temp_file
|
|
182
|
+
|
|
183
|
+
destination_dir="$(dirname "${destination_file}")"
|
|
184
|
+
destination_base="$(basename "${destination_file}")"
|
|
185
|
+
|
|
186
|
+
mkdir -p "${destination_dir}"
|
|
187
|
+
temp_file="$(mktemp "${destination_dir}/.${destination_base}.tmp.XXXXXX")"
|
|
188
|
+
cp "${source_file}" "${temp_file}"
|
|
189
|
+
mv "${temp_file}" "${destination_file}"
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
cache_write_meta() {
|
|
193
|
+
local key="$1"
|
|
194
|
+
local fingerprint="$2"
|
|
195
|
+
local item_count="$3"
|
|
196
|
+
local refresh_status="${4:-}"
|
|
197
|
+
local generation="${5:-}"
|
|
198
|
+
local last_error_at="${6:-}"
|
|
199
|
+
local last_error="${7:-}"
|
|
200
|
+
local created_at
|
|
201
|
+
local created_epoch
|
|
202
|
+
local meta_key
|
|
203
|
+
local meta_file
|
|
204
|
+
local temp_meta
|
|
205
|
+
|
|
206
|
+
created_at="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
|
207
|
+
created_epoch="$(date +%s)"
|
|
208
|
+
meta_key="$(cache_meta_key "${key}")"
|
|
209
|
+
meta_file="$(cache_path_for_key "${meta_key}")"
|
|
210
|
+
temp_meta="$(mktemp "${SESSION_TMP_ROOT}/meta.XXXXXX")"
|
|
211
|
+
|
|
212
|
+
{
|
|
213
|
+
printf "format_version=%s\n" "${CACHE_FORMAT_VERSION}"
|
|
214
|
+
printf "created_at=%s\n" "${created_at}"
|
|
215
|
+
printf "created_epoch=%s\n" "${created_epoch}"
|
|
216
|
+
printf "fingerprint=%s\n" "${fingerprint}"
|
|
217
|
+
printf "item_count=%s\n" "${item_count}"
|
|
218
|
+
if [[ -n "${refresh_status}" ]]; then
|
|
219
|
+
printf "refresh_status=%s\n" "${refresh_status}"
|
|
220
|
+
fi
|
|
221
|
+
if [[ -n "${generation}" ]]; then
|
|
222
|
+
printf "generation=%s\n" "${generation}"
|
|
223
|
+
fi
|
|
224
|
+
if [[ -n "${last_error_at}" ]]; then
|
|
225
|
+
printf "last_error_at=%s\n" "${last_error_at}"
|
|
226
|
+
fi
|
|
227
|
+
if [[ -n "${last_error}" ]]; then
|
|
228
|
+
printf "last_error=%s\n" "${last_error}"
|
|
229
|
+
fi
|
|
230
|
+
} >"${temp_meta}"
|
|
231
|
+
|
|
232
|
+
cache_atomic_write_from_file "${temp_meta}" "${meta_file}"
|
|
233
|
+
rm -f "${temp_meta}"
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
cache_store_key_from_file() {
|
|
237
|
+
local key="$1"
|
|
238
|
+
local fingerprint="$2"
|
|
239
|
+
local source_file="$3"
|
|
240
|
+
local refresh_status="${4:-}"
|
|
241
|
+
local generation="${5:-}"
|
|
242
|
+
local last_error_at="${6:-}"
|
|
243
|
+
local last_error="${7:-}"
|
|
244
|
+
local cache_file
|
|
245
|
+
local item_count
|
|
246
|
+
|
|
247
|
+
cache_file="$(cache_path_for_key "${key}")"
|
|
248
|
+
item_count="$(awk 'END { print NR + 0 }' "${source_file}")"
|
|
249
|
+
|
|
250
|
+
cache_atomic_write_from_file "${source_file}" "${cache_file}"
|
|
251
|
+
cache_write_meta "${key}" "${fingerprint}" "${item_count}" "${refresh_status}" "${generation}" "${last_error_at}" "${last_error}"
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
cache_meta_value_for_key() {
|
|
255
|
+
local key="$1"
|
|
256
|
+
local field_name="$2"
|
|
257
|
+
local meta_file
|
|
258
|
+
|
|
259
|
+
meta_file="$(cache_path_for_key "$(cache_meta_key "${key}")")"
|
|
260
|
+
if [[ ! -r "${meta_file}" ]]; then
|
|
261
|
+
return 1
|
|
262
|
+
fi
|
|
263
|
+
|
|
264
|
+
awk -F'=' -v key="${field_name}" '$1 == key { value=substr($0, index($0, "=") + 1); print value; exit }' "${meta_file}"
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
cache_is_fresh_with_ttl() {
|
|
268
|
+
local key="$1"
|
|
269
|
+
local ttl_seconds="$2"
|
|
270
|
+
local created_epoch
|
|
271
|
+
local now_epoch
|
|
272
|
+
local age_seconds
|
|
273
|
+
|
|
274
|
+
if ! [[ "${ttl_seconds}" =~ ^[0-9]+$ ]]; then
|
|
275
|
+
return 1
|
|
276
|
+
fi
|
|
277
|
+
|
|
278
|
+
if [[ "${ttl_seconds}" -eq 0 ]]; then
|
|
279
|
+
return 1
|
|
280
|
+
fi
|
|
281
|
+
|
|
282
|
+
created_epoch="$(cache_meta_value_for_key "${key}" "created_epoch" 2>/dev/null || true)"
|
|
283
|
+
if ! [[ "${created_epoch}" =~ ^[0-9]+$ ]]; then
|
|
284
|
+
return 1
|
|
285
|
+
fi
|
|
286
|
+
|
|
287
|
+
now_epoch="$(date +%s)"
|
|
288
|
+
if ! [[ "${now_epoch}" =~ ^[0-9]+$ ]]; then
|
|
289
|
+
return 1
|
|
290
|
+
fi
|
|
291
|
+
|
|
292
|
+
age_seconds=$((now_epoch - created_epoch))
|
|
293
|
+
if [[ "${age_seconds}" -lt 0 ]]; then
|
|
294
|
+
return 1
|
|
295
|
+
fi
|
|
296
|
+
|
|
297
|
+
[[ "${age_seconds}" -lt "${ttl_seconds}" ]]
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
cache_emit_query_rows_if_valid() {
|
|
301
|
+
local cache_file="$1"
|
|
302
|
+
|
|
303
|
+
[[ -s "${cache_file}" ]] || return 1
|
|
304
|
+
|
|
305
|
+
if ! awk -F'\t' 'NF >= 2 && $1 != "" { next } { exit 1 } END { if (NR == 0) exit 1 }' "${cache_file}" >/dev/null 2>&1; then
|
|
306
|
+
return 1
|
|
307
|
+
fi
|
|
308
|
+
|
|
309
|
+
awk -F'\t' 'NF >= 2 && $1 != "" { desc=$2; if (desc == "") desc="-"; print $1 "\t" desc }' "${cache_file}"
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
bun_generation_state_key() {
|
|
313
|
+
local key="$1"
|
|
314
|
+
printf "state/%s.generation" "${key}"
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
bun_generation_read() {
|
|
318
|
+
local key="$1"
|
|
319
|
+
local state_file
|
|
320
|
+
local current="0"
|
|
321
|
+
|
|
322
|
+
state_file="$(cache_path_for_key "$(bun_generation_state_key "${key}")")"
|
|
323
|
+
if [[ -r "${state_file}" ]]; then
|
|
324
|
+
current="$(awk 'NR == 1 { print $1; exit }' "${state_file}")"
|
|
325
|
+
fi
|
|
326
|
+
|
|
327
|
+
if ! [[ "${current}" =~ ^[0-9]+$ ]]; then
|
|
328
|
+
current="0"
|
|
329
|
+
fi
|
|
330
|
+
|
|
331
|
+
printf "%s" "${current}"
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
bun_generation_write() {
|
|
335
|
+
local key="$1"
|
|
336
|
+
local generation="$2"
|
|
337
|
+
local state_key
|
|
338
|
+
local state_file
|
|
339
|
+
local temp_file
|
|
340
|
+
|
|
341
|
+
state_key="$(bun_generation_state_key "${key}")"
|
|
342
|
+
state_file="$(cache_path_for_key "${state_key}")"
|
|
343
|
+
temp_file="$(mktemp "${SESSION_TMP_ROOT}/bun-generation.XXXXXX")"
|
|
344
|
+
printf "%s\n" "${generation}" >"${temp_file}"
|
|
345
|
+
cache_atomic_write_from_file "${temp_file}" "${state_file}"
|
|
346
|
+
rm -f "${temp_file}"
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
bun_generation_next() {
|
|
350
|
+
local key="$1"
|
|
351
|
+
local current
|
|
352
|
+
local next
|
|
353
|
+
|
|
354
|
+
current="$(bun_generation_read "${key}")"
|
|
355
|
+
next=$((current + 1))
|
|
356
|
+
bun_generation_write "${key}" "${next}"
|
|
357
|
+
printf "%s" "${next}"
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
bun_refresh_idle_seconds() {
|
|
361
|
+
local idle_seconds="${FPF_BUN_REFRESH_IDLE:-0.12}"
|
|
362
|
+
if ! [[ "${idle_seconds}" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
|
|
363
|
+
idle_seconds="0.12"
|
|
364
|
+
fi
|
|
365
|
+
printf "%s" "${idle_seconds}"
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
bun_emit_refresh_failure_meta() {
|
|
369
|
+
local key="$1"
|
|
370
|
+
local fingerprint="$2"
|
|
371
|
+
local generation="$3"
|
|
372
|
+
local last_error="$4"
|
|
373
|
+
local cache_file
|
|
374
|
+
local item_count="0"
|
|
375
|
+
local last_error_at
|
|
376
|
+
|
|
377
|
+
cache_file="$(cache_path_for_key "${key}")"
|
|
378
|
+
if [[ -s "${cache_file}" ]]; then
|
|
379
|
+
item_count="$(awk 'END { print NR + 0 }' "${cache_file}")"
|
|
380
|
+
fi
|
|
381
|
+
|
|
382
|
+
last_error_at="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
|
383
|
+
cache_write_meta "${key}" "${fingerprint}" "${item_count}" "error" "${generation}" "${last_error_at}" "${last_error}"
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
bun_try_hot_reload_after_refresh() {
|
|
387
|
+
local query="$1"
|
|
388
|
+
|
|
389
|
+
if [[ -n "${FPF_BUN_REFRESH_MANAGER_OVERRIDE:-}" || -n "${FPF_BUN_REFRESH_FALLBACK_FILE:-}" ]]; then
|
|
390
|
+
FPF_BUN_SKIP_REFRESH_SCHEDULE=1 \
|
|
391
|
+
FPF_IPC_MANAGER_OVERRIDE="${FPF_BUN_REFRESH_MANAGER_OVERRIDE:-}" \
|
|
392
|
+
FPF_IPC_FALLBACK_FILE="${FPF_BUN_REFRESH_FALLBACK_FILE:-}" \
|
|
393
|
+
run_ipc_reload_action "${query}" || true
|
|
394
|
+
fi
|
|
395
|
+
|
|
396
|
+
if [[ -n "${FPF_TEST_CACHE_REFRESH_SIGNAL_FILE:-}" ]] && command_exists fpf-refresh-signal; then
|
|
397
|
+
fpf-refresh-signal >/dev/null 2>&1 || true
|
|
398
|
+
fi
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
bun_run_refresh_worker() {
|
|
402
|
+
local manager="$1"
|
|
403
|
+
local query="$2"
|
|
404
|
+
local flags="$3"
|
|
405
|
+
local key="$4"
|
|
406
|
+
local fingerprint="$5"
|
|
407
|
+
local generation="$6"
|
|
408
|
+
local output_tmp
|
|
409
|
+
|
|
410
|
+
sleep "$(bun_refresh_idle_seconds)"
|
|
411
|
+
|
|
412
|
+
if [[ "${generation}" != "$(bun_generation_read "${key}")" ]]; then
|
|
413
|
+
return 0
|
|
414
|
+
fi
|
|
415
|
+
|
|
416
|
+
output_tmp="$(mktemp "${SESSION_TMP_ROOT}/bun-refresh.XXXXXX")"
|
|
417
|
+
if ! manager_bun_search_entries_strict "${query}" >"${output_tmp}"; then
|
|
418
|
+
rm -f "${output_tmp}"
|
|
419
|
+
bun_emit_refresh_failure_meta "${key}" "${fingerprint}" "${generation}" "bun_search_failed"
|
|
420
|
+
send_fzf_prompt_action "Search> " || true
|
|
421
|
+
return 1
|
|
422
|
+
fi
|
|
423
|
+
|
|
424
|
+
if [[ "${generation}" != "$(bun_generation_read "${key}")" ]]; then
|
|
425
|
+
rm -f "${output_tmp}"
|
|
426
|
+
return 0
|
|
427
|
+
fi
|
|
428
|
+
|
|
429
|
+
cache_store_key_from_file "${key}" "${fingerprint}" "${output_tmp}" "success" "${generation}"
|
|
430
|
+
rm -f "${output_tmp}"
|
|
431
|
+
bun_try_hot_reload_after_refresh "${query}"
|
|
432
|
+
return 0
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
start_bun_refresh_worker_async() {
|
|
436
|
+
local manager="$1"
|
|
437
|
+
local query="$2"
|
|
438
|
+
local flags="$3"
|
|
439
|
+
local key="$4"
|
|
440
|
+
local fingerprint="$5"
|
|
441
|
+
local generation="$6"
|
|
442
|
+
local fallback_file="$7"
|
|
443
|
+
local manager_override="$8"
|
|
444
|
+
local script_path="${BASH_SOURCE[0]}"
|
|
445
|
+
|
|
446
|
+
if [[ "${script_path}" != /* ]]; then
|
|
447
|
+
script_path="$(pwd)/${script_path}"
|
|
448
|
+
fi
|
|
449
|
+
|
|
450
|
+
FPF_BUN_REFRESH_FLAGS="${flags}" \
|
|
451
|
+
FPF_BUN_REFRESH_KEY="${key}" \
|
|
452
|
+
FPF_BUN_REFRESH_FINGERPRINT="${fingerprint}" \
|
|
453
|
+
FPF_BUN_REFRESH_GENERATION="${generation}" \
|
|
454
|
+
FPF_BUN_REFRESH_FALLBACK_FILE="${fallback_file}" \
|
|
455
|
+
FPF_BUN_REFRESH_MANAGER_OVERRIDE="${manager_override}" \
|
|
456
|
+
"${script_path}" --bun-refresh-worker --manager "${manager}" -- "${query}" >/dev/null 2>&1 &
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
build_apt_catalog_entries() {
|
|
460
|
+
apt-cache dumpavail 2>/dev/null |
|
|
461
|
+
awk '
|
|
462
|
+
function flush_entry() {
|
|
463
|
+
if (pkg == "") {
|
|
464
|
+
return
|
|
465
|
+
}
|
|
466
|
+
desc_out = desc
|
|
467
|
+
gsub(/^[[:space:]]+|[[:space:]]+$/, "", desc_out)
|
|
468
|
+
if (desc_out == "") {
|
|
469
|
+
desc_out = "-"
|
|
470
|
+
}
|
|
471
|
+
print pkg "\t" desc_out
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/^Package:[[:space:]]*/ {
|
|
475
|
+
flush_entry()
|
|
476
|
+
pkg = $0
|
|
477
|
+
sub(/^Package:[[:space:]]*/, "", pkg)
|
|
478
|
+
desc = ""
|
|
479
|
+
next
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/^Description:[[:space:]]*/ {
|
|
483
|
+
desc = $0
|
|
484
|
+
sub(/^Description:[[:space:]]*/, "", desc)
|
|
485
|
+
next
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/^[[:space:]]+/ {
|
|
489
|
+
if (desc != "") {
|
|
490
|
+
line = $0
|
|
491
|
+
sub(/^[[:space:]]+/, "", line)
|
|
492
|
+
if (line != "") {
|
|
493
|
+
desc = desc " " line
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
next
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/^$/ {
|
|
500
|
+
flush_entry()
|
|
501
|
+
pkg = ""
|
|
502
|
+
desc = ""
|
|
503
|
+
next
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
END {
|
|
507
|
+
flush_entry()
|
|
508
|
+
}
|
|
509
|
+
' |
|
|
510
|
+
awk -F'\t' 'NF >= 1 && $1 != "" { if ($2 == "") $2 = "-"; print $1 "\t" $2 }' |
|
|
511
|
+
awk -F'\t' '!seen[$1]++'
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
build_brew_catalog_entries() {
|
|
515
|
+
{
|
|
516
|
+
brew formulae 2>/dev/null || true
|
|
517
|
+
brew casks 2>/dev/null || true
|
|
518
|
+
} |
|
|
519
|
+
awk 'NF >= 1 && $1 != "" { print $1 "\t-" }' |
|
|
520
|
+
awk -F'\t' '!seen[$1]++'
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
ensure_search_catalog_cache() {
|
|
524
|
+
local manager="$1"
|
|
525
|
+
local cache_fingerprint_value
|
|
526
|
+
local cache_key
|
|
527
|
+
local cache_file
|
|
528
|
+
local output_tmp
|
|
529
|
+
|
|
530
|
+
initialize_cache_root
|
|
531
|
+
|
|
532
|
+
cache_fingerprint_value="$(cache_search_catalog_fingerprint "${manager}")"
|
|
533
|
+
cache_key="$(cache_search_catalog_key "${manager}" "${cache_fingerprint_value}")"
|
|
534
|
+
cache_file="$(cache_path_for_key "${cache_key}")"
|
|
535
|
+
|
|
536
|
+
if [[ -s "${cache_file}" ]]; then
|
|
537
|
+
return 0
|
|
538
|
+
fi
|
|
539
|
+
|
|
540
|
+
output_tmp="$(mktemp "${SESSION_TMP_ROOT}/search-catalog.XXXXXX")"
|
|
541
|
+
|
|
542
|
+
case "${manager}" in
|
|
543
|
+
apt)
|
|
544
|
+
build_apt_catalog_entries >"${output_tmp}" || true
|
|
545
|
+
;;
|
|
546
|
+
brew)
|
|
547
|
+
build_brew_catalog_entries >"${output_tmp}" || true
|
|
548
|
+
;;
|
|
549
|
+
*)
|
|
550
|
+
rm -f "${output_tmp}"
|
|
551
|
+
return 1
|
|
552
|
+
;;
|
|
553
|
+
esac
|
|
554
|
+
|
|
555
|
+
if [[ -s "${output_tmp}" ]]; then
|
|
556
|
+
cache_store_key_from_file "${cache_key}" "${cache_fingerprint_value}" "${output_tmp}"
|
|
557
|
+
rm -f "${output_tmp}"
|
|
558
|
+
return 0
|
|
559
|
+
fi
|
|
560
|
+
|
|
561
|
+
rm -f "${output_tmp}"
|
|
562
|
+
return 1
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
search_entries_from_catalog_cache() {
|
|
566
|
+
local manager="$1"
|
|
567
|
+
local query="$2"
|
|
568
|
+
local cache_fingerprint_value
|
|
569
|
+
local cache_key
|
|
570
|
+
local cache_file
|
|
571
|
+
|
|
572
|
+
initialize_cache_root
|
|
573
|
+
|
|
574
|
+
cache_fingerprint_value="$(cache_search_catalog_fingerprint "${manager}")"
|
|
575
|
+
cache_key="$(cache_search_catalog_key "${manager}" "${cache_fingerprint_value}")"
|
|
576
|
+
cache_file="$(cache_path_for_key "${cache_key}")"
|
|
577
|
+
|
|
578
|
+
if [[ ! -s "${cache_file}" ]]; then
|
|
579
|
+
return 1
|
|
580
|
+
fi
|
|
581
|
+
|
|
582
|
+
awk -F'\t' -v query="${query}" '
|
|
583
|
+
BEGIN {
|
|
584
|
+
normalized = tolower(query)
|
|
585
|
+
token_count = split(normalized, raw_tokens, /[[:space:]]+/)
|
|
586
|
+
token_index = 0
|
|
587
|
+
for (i = 1; i <= token_count; i++) {
|
|
588
|
+
if (raw_tokens[i] != "") {
|
|
589
|
+
token_index++
|
|
590
|
+
tokens[token_index] = raw_tokens[i]
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
{
|
|
595
|
+
haystack = tolower($1 " " $2)
|
|
596
|
+
matched = 1
|
|
597
|
+
for (i = 1; i <= token_index; i++) {
|
|
598
|
+
if (index(haystack, tokens[i]) == 0) {
|
|
599
|
+
matched = 0
|
|
600
|
+
break
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
if (matched) {
|
|
604
|
+
desc = $2
|
|
605
|
+
if (desc == "") {
|
|
606
|
+
desc = "-"
|
|
607
|
+
}
|
|
608
|
+
print $1 "\t" desc
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
' "${cache_file}" || return 1
|
|
612
|
+
}
|
|
613
|
+
|
|
33
614
|
initialize_session_tmp_root() {
|
|
34
615
|
if [[ -n "${SESSION_TMP_ROOT}" ]]; then
|
|
35
616
|
return
|
|
36
617
|
fi
|
|
37
618
|
|
|
38
|
-
|
|
619
|
+
if [[ -n "${FPF_SESSION_TMP_ROOT:-}" ]]; then
|
|
620
|
+
SESSION_TMP_ROOT="${FPF_SESSION_TMP_ROOT}"
|
|
621
|
+
mkdir -p "${SESSION_TMP_ROOT}"
|
|
622
|
+
else
|
|
623
|
+
SESSION_TMP_ROOT="$(mktemp -d "${TMP_ROOT}/session.XXXXXX")"
|
|
624
|
+
fi
|
|
39
625
|
HELP_FILE="${SESSION_TMP_ROOT}/help"
|
|
40
626
|
KBINDS_FILE="${SESSION_TMP_ROOT}/keybinds"
|
|
41
627
|
}
|
|
42
628
|
|
|
629
|
+
run_preview_manager_output() {
|
|
630
|
+
local manager="$1"
|
|
631
|
+
local package="$2"
|
|
632
|
+
|
|
633
|
+
case "${manager}" in
|
|
634
|
+
apt)
|
|
635
|
+
apt-cache show "${package}" 2>/dev/null || true
|
|
636
|
+
printf "\n"
|
|
637
|
+
dpkg -L "${package}" 2>/dev/null || true
|
|
638
|
+
;;
|
|
639
|
+
dnf)
|
|
640
|
+
dnf info "${package}" 2>/dev/null || true
|
|
641
|
+
printf "\n"
|
|
642
|
+
rpm -ql "${package}" 2>/dev/null || true
|
|
643
|
+
;;
|
|
644
|
+
pacman)
|
|
645
|
+
pacman -Si "${package}" 2>/dev/null || true
|
|
646
|
+
printf "\n"
|
|
647
|
+
pacman -Fl "${package}" 2>/dev/null | awk '{print $2}' || true
|
|
648
|
+
;;
|
|
649
|
+
zypper)
|
|
650
|
+
zypper --non-interactive info "${package}" 2>/dev/null || true
|
|
651
|
+
;;
|
|
652
|
+
emerge)
|
|
653
|
+
emerge --search --color=n "${package}" 2>/dev/null || true
|
|
654
|
+
;;
|
|
655
|
+
brew)
|
|
656
|
+
brew info "${package}" 2>/dev/null || true
|
|
657
|
+
;;
|
|
658
|
+
winget)
|
|
659
|
+
winget show --id "${package}" --exact --source winget --accept-source-agreements --disable-interactivity 2>/dev/null || true
|
|
660
|
+
;;
|
|
661
|
+
choco)
|
|
662
|
+
choco info "${package}" 2>/dev/null || true
|
|
663
|
+
;;
|
|
664
|
+
scoop)
|
|
665
|
+
scoop info "${package}" 2>/dev/null || true
|
|
666
|
+
;;
|
|
667
|
+
snap)
|
|
668
|
+
snap info "${package}" 2>/dev/null || true
|
|
669
|
+
;;
|
|
670
|
+
flatpak)
|
|
671
|
+
flatpak info "${package}" 2>/dev/null || flatpak remote-info flathub "${package}" 2>/dev/null || true
|
|
672
|
+
;;
|
|
673
|
+
npm)
|
|
674
|
+
npm view "${package}" 2>/dev/null || true
|
|
675
|
+
;;
|
|
676
|
+
bun)
|
|
677
|
+
bun info "${package}" 2>/dev/null || npm view "${package}" 2>/dev/null || true
|
|
678
|
+
;;
|
|
679
|
+
esac
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
run_preview_item_action() {
|
|
683
|
+
local manager="$1"
|
|
684
|
+
local package="$2"
|
|
685
|
+
local cache_dir="${SESSION_TMP_ROOT}/preview-cache"
|
|
686
|
+
local cache_key=""
|
|
687
|
+
local cache_file=""
|
|
688
|
+
local temp_file=""
|
|
689
|
+
|
|
690
|
+
[[ -n "${manager}" && -n "${package}" ]] || return 0
|
|
691
|
+
|
|
692
|
+
mkdir -p "${cache_dir}"
|
|
693
|
+
cache_key="$(cache_cksum "${manager}|${package}")"
|
|
694
|
+
cache_file="${cache_dir}/${manager}.${cache_key}.txt"
|
|
695
|
+
|
|
696
|
+
if [[ -f "${cache_file}" ]]; then
|
|
697
|
+
cat "${cache_file}"
|
|
698
|
+
return 0
|
|
699
|
+
fi
|
|
700
|
+
|
|
701
|
+
temp_file="$(mktemp "${SESSION_TMP_ROOT}/preview.XXXXXX")"
|
|
702
|
+
run_preview_manager_output "${manager}" "${package}" >"${temp_file}"
|
|
703
|
+
mv -f "${temp_file}" "${cache_file}"
|
|
704
|
+
cat "${cache_file}"
|
|
705
|
+
}
|
|
706
|
+
|
|
43
707
|
cleanup_session_tmp_root() {
|
|
44
708
|
if [[ -n "${SESSION_TMP_ROOT}" && -d "${SESSION_TMP_ROOT}" ]]; then
|
|
45
709
|
rm -rf "${SESSION_TMP_ROOT}"
|
|
@@ -124,6 +788,125 @@ manager_command_ready() {
|
|
|
124
788
|
esac
|
|
125
789
|
}
|
|
126
790
|
|
|
791
|
+
flatpak_has_any_remotes() {
|
|
792
|
+
if ! manager_command_ready flatpak; then
|
|
793
|
+
return 1
|
|
794
|
+
fi
|
|
795
|
+
|
|
796
|
+
if flatpak remotes --columns=name 2>/dev/null | awk 'NF > 0 { found=1; exit } END { exit (found ? 0 : 1) }'; then
|
|
797
|
+
return 0
|
|
798
|
+
fi
|
|
799
|
+
|
|
800
|
+
if flatpak remote-list --columns=name 2>/dev/null | awk 'NF > 0 { found=1; exit } END { exit (found ? 0 : 1) }'; then
|
|
801
|
+
return 0
|
|
802
|
+
fi
|
|
803
|
+
|
|
804
|
+
return 1
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
winget_has_default_source() {
|
|
808
|
+
if ! manager_command_ready winget; then
|
|
809
|
+
return 1
|
|
810
|
+
fi
|
|
811
|
+
|
|
812
|
+
if winget source list 2>/dev/null | awk '
|
|
813
|
+
{
|
|
814
|
+
line=$0
|
|
815
|
+
sub(/^[[:space:]]+/, "", line)
|
|
816
|
+
if (line == "") {
|
|
817
|
+
next
|
|
818
|
+
}
|
|
819
|
+
split(line, cols, /[[:space:]]+/)
|
|
820
|
+
if (tolower(cols[1]) == "winget") {
|
|
821
|
+
found=1
|
|
822
|
+
exit
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
END { exit (found ? 0 : 1) }
|
|
826
|
+
'; then
|
|
827
|
+
return 0
|
|
828
|
+
fi
|
|
829
|
+
|
|
830
|
+
return 1
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
choco_has_any_sources() {
|
|
834
|
+
if ! manager_command_ready choco; then
|
|
835
|
+
return 1
|
|
836
|
+
fi
|
|
837
|
+
|
|
838
|
+
if choco source list --limit-output 2>/dev/null | awk -F'|' 'NF >= 2 && $1 != "" { found=1; exit } END { exit (found ? 0 : 1) }'; then
|
|
839
|
+
return 0
|
|
840
|
+
fi
|
|
841
|
+
|
|
842
|
+
return 1
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
scoop_has_any_buckets() {
|
|
846
|
+
if ! manager_command_ready scoop; then
|
|
847
|
+
return 1
|
|
848
|
+
fi
|
|
849
|
+
|
|
850
|
+
if scoop bucket list 2>/dev/null | awk '
|
|
851
|
+
{
|
|
852
|
+
line=$0
|
|
853
|
+
sub(/^[[:space:]]+/, "", line)
|
|
854
|
+
if (line == "") {
|
|
855
|
+
next
|
|
856
|
+
}
|
|
857
|
+
if (tolower(line) ~ /^name[[:space:]]+/) {
|
|
858
|
+
next
|
|
859
|
+
}
|
|
860
|
+
if (line ~ /^[-[:space:]]+$/) {
|
|
861
|
+
next
|
|
862
|
+
}
|
|
863
|
+
split(line, cols, /[[:space:]]+/)
|
|
864
|
+
if (length(cols[2]) > 0 && (cols[2] ~ /^https?:\/\// || cols[2] ~ /^git@/ || cols[2] ~ /^ssh:\/\// || cols[2] ~ /^file:\/\// || cols[2] ~ /^\//)) {
|
|
865
|
+
found=1
|
|
866
|
+
exit
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
END { exit (found ? 0 : 1) }
|
|
870
|
+
'; then
|
|
871
|
+
return 0
|
|
872
|
+
fi
|
|
873
|
+
|
|
874
|
+
return 1
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
manager_no_query_setup_message() {
|
|
878
|
+
local manager="$1"
|
|
879
|
+
|
|
880
|
+
case "${manager}" in
|
|
881
|
+
flatpak)
|
|
882
|
+
if ! flatpak_has_any_remotes; then
|
|
883
|
+
printf "%s" "Flatpak has no remotes configured. Add Flathub with: flatpak remote-add --if-not-exists --user flathub https://flathub.org/repo/flathub.flatpakrepo"
|
|
884
|
+
return 0
|
|
885
|
+
fi
|
|
886
|
+
;;
|
|
887
|
+
winget)
|
|
888
|
+
if ! winget_has_default_source; then
|
|
889
|
+
printf "%s" "WinGet source 'winget' is not configured. Restore it with: winget source reset --force"
|
|
890
|
+
return 0
|
|
891
|
+
fi
|
|
892
|
+
;;
|
|
893
|
+
choco)
|
|
894
|
+
if ! choco_has_any_sources; then
|
|
895
|
+
printf "%s" "Chocolatey has no package sources configured. Add the default source with: choco source add -n=chocolatey -s=https://community.chocolatey.org/api/v2/"
|
|
896
|
+
return 0
|
|
897
|
+
fi
|
|
898
|
+
;;
|
|
899
|
+
scoop)
|
|
900
|
+
if ! scoop_has_any_buckets; then
|
|
901
|
+
printf "%s" "Scoop has no buckets configured. Add the default bucket with: scoop bucket add main"
|
|
902
|
+
return 0
|
|
903
|
+
fi
|
|
904
|
+
;;
|
|
905
|
+
esac
|
|
906
|
+
|
|
907
|
+
return 1
|
|
908
|
+
}
|
|
909
|
+
|
|
127
910
|
manager_can_install_fzf() {
|
|
128
911
|
local manager="$1"
|
|
129
912
|
case "${manager}" in
|
|
@@ -214,7 +997,7 @@ ensure_fzf() {
|
|
|
214
997
|
local candidates=()
|
|
215
998
|
local manager
|
|
216
999
|
|
|
217
|
-
if command_exists fzf; then
|
|
1000
|
+
if [[ "${FPF_TEST_FORCE_FZF_MISSING:-0}" != "1" ]] && command_exists fzf; then
|
|
218
1001
|
return
|
|
219
1002
|
fi
|
|
220
1003
|
|
|
@@ -533,6 +1316,18 @@ parse_args() {
|
|
|
533
1316
|
--feed-search)
|
|
534
1317
|
ACTION="feed-search"
|
|
535
1318
|
;;
|
|
1319
|
+
--ipc-reload)
|
|
1320
|
+
ACTION="ipc-reload"
|
|
1321
|
+
;;
|
|
1322
|
+
--ipc-query-notify)
|
|
1323
|
+
ACTION="ipc-query-notify"
|
|
1324
|
+
;;
|
|
1325
|
+
--preview-item)
|
|
1326
|
+
ACTION="preview-item"
|
|
1327
|
+
;;
|
|
1328
|
+
--bun-refresh-worker)
|
|
1329
|
+
ACTION="bun-refresh-worker"
|
|
1330
|
+
;;
|
|
536
1331
|
-ap|--apt)
|
|
537
1332
|
MANAGER_OVERRIDE="apt"
|
|
538
1333
|
;;
|
|
@@ -806,7 +1601,59 @@ exact_match_entry() {
|
|
|
806
1601
|
done < <(exact_query_candidates "${query}" | awk '!seen[$0]++')
|
|
807
1602
|
}
|
|
808
1603
|
|
|
809
|
-
|
|
1604
|
+
manager_bun_search_entries_strict() {
|
|
1605
|
+
local query="$1"
|
|
1606
|
+
local effective_query="${query}"
|
|
1607
|
+
local line_limit=0
|
|
1608
|
+
local query_line_limit=40
|
|
1609
|
+
local effective_limit=0
|
|
1610
|
+
local bun_search_file
|
|
1611
|
+
|
|
1612
|
+
if [[ -z "${query}" ]]; then
|
|
1613
|
+
line_limit="${FPF_NO_QUERY_RESULT_LIMIT:-120}"
|
|
1614
|
+
else
|
|
1615
|
+
query_line_limit="${FPF_QUERY_PER_MANAGER_LIMIT:-40}"
|
|
1616
|
+
fi
|
|
1617
|
+
|
|
1618
|
+
if ! [[ "${line_limit}" =~ ^[0-9]+$ ]]; then
|
|
1619
|
+
line_limit=0
|
|
1620
|
+
fi
|
|
1621
|
+
|
|
1622
|
+
if ! [[ "${query_line_limit}" =~ ^[0-9]+$ ]]; then
|
|
1623
|
+
query_line_limit=40
|
|
1624
|
+
fi
|
|
1625
|
+
|
|
1626
|
+
if [[ "${line_limit}" -gt 0 ]]; then
|
|
1627
|
+
effective_limit="${line_limit}"
|
|
1628
|
+
else
|
|
1629
|
+
effective_limit="${query_line_limit}"
|
|
1630
|
+
fi
|
|
1631
|
+
|
|
1632
|
+
if [[ -z "${effective_query}" ]]; then
|
|
1633
|
+
effective_query="aa"
|
|
1634
|
+
fi
|
|
1635
|
+
|
|
1636
|
+
bun_search_file="$(mktemp "${SESSION_TMP_ROOT}/bun-search-strict.XXXXXX")"
|
|
1637
|
+
if ! bun search "${effective_query}" >"${bun_search_file}" 2>/dev/null; then
|
|
1638
|
+
rm -f "${bun_search_file}"
|
|
1639
|
+
return 1
|
|
1640
|
+
fi
|
|
1641
|
+
|
|
1642
|
+
{
|
|
1643
|
+
awk 'NR > 1 && NF > 0 { name=$1; $1=""; sub(/^[[:space:]]+/, "", $0); if ($0 == "") $0="-"; print name "\t" $0 }' "${bun_search_file}"
|
|
1644
|
+
exact_match_entry "bun" "${query}"
|
|
1645
|
+
} | awk -F'\t' 'NF >= 1 { if ($2 == "") $2 = "-"; print $1 "\t" $2 }' | awk -F'\t' '!seen[$1]++' | {
|
|
1646
|
+
if [[ "${effective_limit}" -gt 0 ]]; then
|
|
1647
|
+
awk -v limit="${effective_limit}" 'NR <= limit'
|
|
1648
|
+
else
|
|
1649
|
+
cat
|
|
1650
|
+
fi
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
rm -f "${bun_search_file}"
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
manager_search_entries_uncached() {
|
|
810
1657
|
local manager="$1"
|
|
811
1658
|
local query="$2"
|
|
812
1659
|
local effective_query="${query}"
|
|
@@ -856,8 +1703,12 @@ manager_search_entries() {
|
|
|
856
1703
|
|
|
857
1704
|
case "${manager}" in
|
|
858
1705
|
apt)
|
|
859
|
-
|
|
860
|
-
|
|
1706
|
+
if ensure_search_catalog_cache "${manager}"; then
|
|
1707
|
+
search_entries_from_catalog_cache "${manager}" "${effective_query}" || true
|
|
1708
|
+
else
|
|
1709
|
+
apt-cache search -- "${effective_query}" 2>/dev/null |
|
|
1710
|
+
awk -F' - ' '{ name=$1; desc=$2; gsub(/^[[:space:]]+|[[:space:]]+$/, "", name); if (desc == "") desc="-"; print name "\t" desc }'
|
|
1711
|
+
fi
|
|
861
1712
|
;;
|
|
862
1713
|
dnf)
|
|
863
1714
|
local pattern="*"
|
|
@@ -914,11 +1765,18 @@ manager_search_entries() {
|
|
|
914
1765
|
'
|
|
915
1766
|
;;
|
|
916
1767
|
brew)
|
|
917
|
-
{
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
1768
|
+
if ensure_search_catalog_cache "${manager}"; then
|
|
1769
|
+
{
|
|
1770
|
+
search_entries_from_catalog_cache "${manager}" "${effective_query}" || true
|
|
1771
|
+
exact_match_entry "${manager}" "${query}"
|
|
1772
|
+
}
|
|
1773
|
+
else
|
|
1774
|
+
{
|
|
1775
|
+
brew search "${effective_query}" 2>/dev/null |
|
|
1776
|
+
awk 'NF > 0 && $1 != "==>" { print $1 "\t-" }'
|
|
1777
|
+
exact_match_entry "${manager}" "${query}"
|
|
1778
|
+
}
|
|
1779
|
+
fi
|
|
922
1780
|
;;
|
|
923
1781
|
winget)
|
|
924
1782
|
winget search "${effective_query}" --source winget --accept-source-agreements --disable-interactivity 2>/dev/null |
|
|
@@ -1017,6 +1875,83 @@ manager_search_entries() {
|
|
|
1017
1875
|
} || true
|
|
1018
1876
|
}
|
|
1019
1877
|
|
|
1878
|
+
manager_search_entries() {
|
|
1879
|
+
local manager="$1"
|
|
1880
|
+
local query="$2"
|
|
1881
|
+
local query_cache_enabled="${FPF_ENABLE_QUERY_CACHE:-0}"
|
|
1882
|
+
local bun_cache_ttl="${FPF_BUN_QUERY_CACHE_TTL:-900}"
|
|
1883
|
+
local flags
|
|
1884
|
+
local key
|
|
1885
|
+
local fingerprint
|
|
1886
|
+
local cache_file
|
|
1887
|
+
local output_tmp
|
|
1888
|
+
local generation
|
|
1889
|
+
local should_async_refresh=0
|
|
1890
|
+
|
|
1891
|
+
initialize_cache_root
|
|
1892
|
+
|
|
1893
|
+
flags="$(query_cache_flags)"
|
|
1894
|
+
|
|
1895
|
+
if ! [[ "${bun_cache_ttl}" =~ ^[0-9]+$ ]]; then
|
|
1896
|
+
bun_cache_ttl=900
|
|
1897
|
+
fi
|
|
1898
|
+
|
|
1899
|
+
if [[ "${manager}" == "bun" ]]; then
|
|
1900
|
+
query_cache_enabled="1"
|
|
1901
|
+
fi
|
|
1902
|
+
|
|
1903
|
+
key="$(cache_query_key "${manager}" "${query}" "${flags}")"
|
|
1904
|
+
fingerprint="$(cache_fingerprint "${manager}" "${query}" "${flags}")"
|
|
1905
|
+
cache_file="$(cache_path_for_key "${key}")"
|
|
1906
|
+
|
|
1907
|
+
if [[ "${manager}" == "bun" && ( "${ACTION}" == "feed-search" || "${ACTION}" == "ipc-query-notify" ) ]]; then
|
|
1908
|
+
if [[ -s "${cache_file}" ]]; then
|
|
1909
|
+
cache_emit_query_rows_if_valid "${cache_file}" || true
|
|
1910
|
+
fi
|
|
1911
|
+
|
|
1912
|
+
if cache_is_fresh_with_ttl "${key}" "${bun_cache_ttl}"; then
|
|
1913
|
+
return
|
|
1914
|
+
fi
|
|
1915
|
+
|
|
1916
|
+
generation="$(bun_generation_next "${key}")"
|
|
1917
|
+
if [[ -n "${FZF_PORT:-}" && "${FPF_BUN_SKIP_REFRESH_SCHEDULE:-0}" != "1" ]]; then
|
|
1918
|
+
should_async_refresh=1
|
|
1919
|
+
fi
|
|
1920
|
+
|
|
1921
|
+
if [[ "${FPF_BUN_TEST_SYNC_REFRESH:-0}" == "1" ]]; then
|
|
1922
|
+
should_async_refresh=0
|
|
1923
|
+
fi
|
|
1924
|
+
|
|
1925
|
+
if [[ "${should_async_refresh}" -eq 1 ]]; then
|
|
1926
|
+
start_bun_refresh_worker_async "${manager}" "${query}" "${flags}" "${key}" "${fingerprint}" "${generation}" "${FPF_IPC_FALLBACK_FILE:-}" "${FPF_IPC_MANAGER_OVERRIDE:-}"
|
|
1927
|
+
return
|
|
1928
|
+
fi
|
|
1929
|
+
|
|
1930
|
+
bun_run_refresh_worker "${manager}" "${query}" "${flags}" "${key}" "${fingerprint}" "${generation}" || true
|
|
1931
|
+
if [[ -s "${cache_file}" ]]; then
|
|
1932
|
+
cache_emit_query_rows_if_valid "${cache_file}" || true
|
|
1933
|
+
fi
|
|
1934
|
+
return
|
|
1935
|
+
fi
|
|
1936
|
+
|
|
1937
|
+
if [[ "${query_cache_enabled}" == "1" && -s "${cache_file}" ]]; then
|
|
1938
|
+
if [[ "${manager}" != "bun" ]] || cache_is_fresh_with_ttl "${key}" "${bun_cache_ttl}"; then
|
|
1939
|
+
cat "${cache_file}"
|
|
1940
|
+
return
|
|
1941
|
+
fi
|
|
1942
|
+
fi
|
|
1943
|
+
|
|
1944
|
+
output_tmp="$(mktemp "${SESSION_TMP_ROOT}/query-cache.XXXXXX")"
|
|
1945
|
+
manager_search_entries_uncached "${manager}" "${query}" >"${output_tmp}" || true
|
|
1946
|
+
|
|
1947
|
+
if [[ "${query_cache_enabled}" == "1" ]]; then
|
|
1948
|
+
cache_store_key_from_file "${key}" "${fingerprint}" "${output_tmp}"
|
|
1949
|
+
fi
|
|
1950
|
+
|
|
1951
|
+
cat "${output_tmp}"
|
|
1952
|
+
rm -f "${output_tmp}"
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1020
1955
|
manager_installed_entries() {
|
|
1021
1956
|
local manager="$1"
|
|
1022
1957
|
|
|
@@ -1137,34 +2072,35 @@ manager_installed_entries() {
|
|
|
1137
2072
|
;;
|
|
1138
2073
|
bun)
|
|
1139
2074
|
{
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
2075
|
+
local bun_pm_file
|
|
2076
|
+
bun_pm_file="$(mktemp "${SESSION_TMP_ROOT}/bun-pm.XXXXXX")"
|
|
2077
|
+
if bun pm ls --global >"${bun_pm_file}" 2>/dev/null; then
|
|
2078
|
+
awk '
|
|
2079
|
+
NR > 1 {
|
|
2080
|
+
line = $0
|
|
2081
|
+
gsub(/\r/, "", line)
|
|
2082
|
+
sub(/^[[:space:]]*[^[:alnum:]@]*/, "", line)
|
|
2083
|
+
sub(/^[[:space:]]+/, "", line)
|
|
2084
|
+
sub(/[[:space:]]+$/, "", line)
|
|
2085
|
+
|
|
2086
|
+
if (line == "") next
|
|
2087
|
+
if (line ~ /[[:space:]]node_modules([[:space:]]|$)/) next
|
|
2088
|
+
|
|
2089
|
+
split(line, fields, /[[:space:]]+/)
|
|
2090
|
+
pkg = fields[1]
|
|
2091
|
+
if (pkg == "") next
|
|
2092
|
+
|
|
2093
|
+
pkg_copy = pkg
|
|
2094
|
+
at_count = gsub(/@/, "@", pkg_copy)
|
|
2095
|
+
if ((substr(pkg, 1, 1) == "@" && at_count >= 2) || (substr(pkg, 1, 1) != "@" && at_count >= 1)) {
|
|
2096
|
+
sub(/@[^@[:space:]]*$/, "", pkg)
|
|
2097
|
+
}
|
|
1162
2098
|
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
}
|
|
2099
|
+
if (pkg != "") {
|
|
2100
|
+
print pkg "\tglobal"
|
|
1166
2101
|
}
|
|
1167
|
-
|
|
2102
|
+
}
|
|
2103
|
+
' "${bun_pm_file}"
|
|
1168
2104
|
elif command_exists npm; then
|
|
1169
2105
|
npm ls -g --depth=0 --parseable 2>/dev/null |
|
|
1170
2106
|
awk '
|
|
@@ -1188,6 +2124,7 @@ manager_installed_entries() {
|
|
|
1188
2124
|
}
|
|
1189
2125
|
'
|
|
1190
2126
|
fi
|
|
2127
|
+
rm -f "${bun_pm_file}"
|
|
1191
2128
|
} || true
|
|
1192
2129
|
;;
|
|
1193
2130
|
esac | sort -u || true
|
|
@@ -1202,8 +2139,15 @@ manager_installed_names_cached() {
|
|
|
1202
2139
|
local manager="$1"
|
|
1203
2140
|
local output_file="$2"
|
|
1204
2141
|
local cache_enabled="${FPF_DISABLE_INSTALLED_CACHE:-0}"
|
|
1205
|
-
local
|
|
1206
|
-
local cache_file
|
|
2142
|
+
local cache_key
|
|
2143
|
+
local cache_file
|
|
2144
|
+
local cache_fingerprint_value
|
|
2145
|
+
|
|
2146
|
+
initialize_cache_root
|
|
2147
|
+
|
|
2148
|
+
cache_key="$(cache_catalog_key "${manager}")"
|
|
2149
|
+
cache_file="$(cache_path_for_key "${cache_key}")"
|
|
2150
|
+
cache_fingerprint_value="$(cache_fingerprint "${manager}" "" "installed")"
|
|
1207
2151
|
|
|
1208
2152
|
if [[ "${cache_enabled}" != "1" && -s "${cache_file}" ]]; then
|
|
1209
2153
|
cp "${cache_file}" "${output_file}"
|
|
@@ -1213,47 +2157,82 @@ manager_installed_names_cached() {
|
|
|
1213
2157
|
manager_installed_names "${manager}" >"${output_file}" 2>/dev/null || true
|
|
1214
2158
|
|
|
1215
2159
|
if [[ "${cache_enabled}" != "1" && -s "${output_file}" ]]; then
|
|
1216
|
-
|
|
1217
|
-
cp "${output_file}" "${cache_file}"
|
|
2160
|
+
cache_store_key_from_file "${cache_key}" "${cache_fingerprint_value}" "${output_file}"
|
|
1218
2161
|
fi
|
|
1219
2162
|
}
|
|
1220
2163
|
|
|
1221
2164
|
mark_installed_packages() {
|
|
1222
|
-
local
|
|
1223
|
-
local
|
|
1224
|
-
local output_file="$3"
|
|
2165
|
+
local source_file="$1"
|
|
2166
|
+
local output_file="$2"
|
|
1225
2167
|
local installed_file
|
|
2168
|
+
local installed_map_file
|
|
2169
|
+
local manager
|
|
1226
2170
|
|
|
1227
2171
|
if [[ "${FPF_SKIP_INSTALLED_MARKERS:-0}" == "1" ]]; then
|
|
1228
2172
|
awk -F'\t' '
|
|
1229
2173
|
{
|
|
1230
|
-
desc = $
|
|
2174
|
+
desc = $3
|
|
1231
2175
|
if (desc == "") desc = "-"
|
|
1232
|
-
print $1 "\t " desc
|
|
2176
|
+
print $1 "\t" $2 "\t " desc
|
|
1233
2177
|
}
|
|
1234
2178
|
' "${source_file}" >"${output_file}"
|
|
1235
2179
|
return
|
|
1236
2180
|
fi
|
|
1237
2181
|
|
|
1238
|
-
|
|
1239
|
-
|
|
2182
|
+
installed_map_file="$(mktemp "${SESSION_TMP_ROOT}/installed-map.XXXXXX")"
|
|
2183
|
+
: >"${installed_map_file}"
|
|
2184
|
+
|
|
2185
|
+
while IFS= read -r manager; do
|
|
2186
|
+
[[ -n "${manager}" ]] || continue
|
|
2187
|
+
installed_file="$(mktemp "${SESSION_TMP_ROOT}/installed.${manager}.XXXXXX")"
|
|
2188
|
+
manager_installed_names_cached "${manager}" "${installed_file}"
|
|
2189
|
+
if [[ -s "${installed_file}" ]]; then
|
|
2190
|
+
awk -F'\t' -v mgr="${manager}" 'NF > 0 && $1 != "" { print mgr "\t" $1 }' "${installed_file}" >>"${installed_map_file}"
|
|
2191
|
+
fi
|
|
2192
|
+
rm -f "${installed_file}"
|
|
2193
|
+
done < <(awk -F'\t' 'NF >= 1 && $1 != "" { print $1 }' "${source_file}" | awk '!seen[$0]++')
|
|
1240
2194
|
|
|
1241
2195
|
awk -F'\t' '
|
|
1242
2196
|
FILENAME == ARGV[1] {
|
|
1243
|
-
|
|
1244
|
-
|
|
2197
|
+
key = $1 "\t" $2
|
|
2198
|
+
if ($1 != "" && $2 != "") {
|
|
2199
|
+
installed[key] = 1
|
|
1245
2200
|
}
|
|
1246
2201
|
next
|
|
1247
2202
|
}
|
|
1248
2203
|
{
|
|
1249
|
-
|
|
1250
|
-
|
|
2204
|
+
key = $1 "\t" $2
|
|
2205
|
+
mark = (installed[key] ? "* " : " ")
|
|
2206
|
+
desc = $3
|
|
1251
2207
|
if (desc == "") desc = "-"
|
|
1252
|
-
print $1 "\t" mark desc
|
|
2208
|
+
print $1 "\t" $2 "\t" mark desc
|
|
1253
2209
|
}
|
|
1254
|
-
' "${
|
|
2210
|
+
' "${installed_map_file}" "${source_file}" >"${output_file}"
|
|
2211
|
+
|
|
2212
|
+
rm -f "${installed_map_file}"
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
merge_search_display_rows() {
|
|
2216
|
+
local source_file="$1"
|
|
2217
|
+
local output_file="$2"
|
|
2218
|
+
|
|
2219
|
+
if [[ ! -s "${source_file}" ]]; then
|
|
2220
|
+
: >"${output_file}"
|
|
2221
|
+
return
|
|
2222
|
+
fi
|
|
1255
2223
|
|
|
1256
|
-
|
|
2224
|
+
sort -t $'\t' -k1,1 -k2,2 -k3,3 "${source_file}" |
|
|
2225
|
+
awk -F'\t' '
|
|
2226
|
+
NF >= 2 {
|
|
2227
|
+
key = $1 "\t" $2
|
|
2228
|
+
if (seen[key]++) {
|
|
2229
|
+
next
|
|
2230
|
+
}
|
|
2231
|
+
desc = $3
|
|
2232
|
+
if (desc == "") desc = "-"
|
|
2233
|
+
print $1 "\t" $2 "\t" desc
|
|
2234
|
+
}
|
|
2235
|
+
' >"${output_file}"
|
|
1257
2236
|
}
|
|
1258
2237
|
|
|
1259
2238
|
collect_search_display_rows() {
|
|
@@ -1270,6 +2249,8 @@ collect_search_display_rows() {
|
|
|
1270
2249
|
local manager
|
|
1271
2250
|
local part_file
|
|
1272
2251
|
local gather_pid
|
|
2252
|
+
local merged_source_file
|
|
2253
|
+
local merged_marked_file
|
|
1273
2254
|
|
|
1274
2255
|
for manager in "${managers[@]-}"; do
|
|
1275
2256
|
part_file="$(mktemp "${SESSION_TMP_ROOT}/part.XXXXXX")"
|
|
@@ -1277,19 +2258,17 @@ collect_search_display_rows() {
|
|
|
1277
2258
|
|
|
1278
2259
|
(
|
|
1279
2260
|
local_source_file="$(mktemp "${SESSION_TMP_ROOT}/source.XXXXXX")"
|
|
1280
|
-
local_marked_file="$(mktemp "${SESSION_TMP_ROOT}/marked.XXXXXX")"
|
|
1281
2261
|
manager_search_entries "${manager}" "${query}" >"${local_source_file}" || true
|
|
1282
2262
|
if [[ -s "${local_source_file}" ]]; then
|
|
1283
|
-
mark_installed_packages "${manager}" "${local_source_file}" "${local_marked_file}"
|
|
1284
2263
|
awk -F'\t' -v mgr="${manager}" '
|
|
1285
2264
|
NF >= 1 {
|
|
1286
2265
|
desc = $2
|
|
1287
2266
|
if (desc == "") desc = "-"
|
|
1288
2267
|
print mgr "\t" $1 "\t" desc
|
|
1289
2268
|
}
|
|
1290
|
-
' "${
|
|
2269
|
+
' "${local_source_file}" >"${part_file}"
|
|
1291
2270
|
fi
|
|
1292
|
-
rm -f "${local_source_file}"
|
|
2271
|
+
rm -f "${local_source_file}"
|
|
1293
2272
|
) &
|
|
1294
2273
|
gather_pids+=("$!")
|
|
1295
2274
|
done
|
|
@@ -1298,15 +2277,19 @@ collect_search_display_rows() {
|
|
|
1298
2277
|
wait "${gather_pid}" || true
|
|
1299
2278
|
done
|
|
1300
2279
|
|
|
2280
|
+
merged_source_file="$(mktemp "${SESSION_TMP_ROOT}/merged-source.XXXXXX")"
|
|
2281
|
+
merged_marked_file="$(mktemp "${SESSION_TMP_ROOT}/merged-marked.XXXXXX")"
|
|
2282
|
+
|
|
1301
2283
|
for part_file in "${part_files[@]-}"; do
|
|
1302
2284
|
if [[ -s "${part_file}" ]]; then
|
|
1303
|
-
cat "${part_file}" >>"${
|
|
2285
|
+
cat "${part_file}" >>"${merged_source_file}"
|
|
1304
2286
|
fi
|
|
1305
2287
|
rm -f "${part_file}"
|
|
1306
2288
|
done
|
|
1307
2289
|
|
|
1308
|
-
if [[ -s "${
|
|
1309
|
-
|
|
2290
|
+
if [[ -s "${merged_source_file}" ]]; then
|
|
2291
|
+
merge_search_display_rows "${merged_source_file}" "${merged_marked_file}"
|
|
2292
|
+
mark_installed_packages "${merged_marked_file}" "${output_file}"
|
|
1310
2293
|
rank_display_rows_by_query "${query}" "${output_file}"
|
|
1311
2294
|
|
|
1312
2295
|
if [[ -n "${query}" && "${query_limit}" =~ ^[0-9]+$ && "${query_limit}" -gt 0 ]]; then
|
|
@@ -1314,6 +2297,8 @@ collect_search_display_rows() {
|
|
|
1314
2297
|
mv "${output_file}.limited" "${output_file}"
|
|
1315
2298
|
fi
|
|
1316
2299
|
fi
|
|
2300
|
+
|
|
2301
|
+
rm -f "${merged_source_file}" "${merged_marked_file}"
|
|
1317
2302
|
}
|
|
1318
2303
|
|
|
1319
2304
|
build_dynamic_reload_command() {
|
|
@@ -1336,10 +2321,195 @@ build_dynamic_reload_command() {
|
|
|
1336
2321
|
fi
|
|
1337
2322
|
|
|
1338
2323
|
if [[ -n "${manager_override}" ]]; then
|
|
1339
|
-
printf 'q={q}; if [ ${#q} -lt %s ]; then cat %q; else sleep %s; FPF_SKIP_INSTALLED_MARKERS=1 %q --feed-search --manager %q -- "$q" 2>/dev/null || cat %q; fi' "${min_chars}" "${fallback_file}" "${reload_debounce}" "${script_path}" "${manager_override}" "${fallback_file}"
|
|
2324
|
+
printf 'q={q}; if [ ${#q} -lt %s ]; then cat %q; else sleep %s; FPF_SKIP_INSTALLED_MARKERS=1 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}" "${manager_override}" "${fallback_file}" "${script_path}" "${manager_override}" "${fallback_file}"
|
|
2325
|
+
else
|
|
2326
|
+
printf 'q={q}; if [ ${#q} -lt %s ]; then cat %q; else sleep %s; FPF_SKIP_INSTALLED_MARKERS=1 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}" "${fallback_file}" "${script_path}" "${fallback_file}"
|
|
2327
|
+
fi
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
build_dynamic_reload_command_for_query() {
|
|
2331
|
+
local manager_override="$1"
|
|
2332
|
+
local fallback_file="$2"
|
|
2333
|
+
local query_value="$3"
|
|
2334
|
+
local script_path="${BASH_SOURCE[0]}"
|
|
2335
|
+
local min_chars="${FPF_RELOAD_MIN_CHARS:-2}"
|
|
2336
|
+
local reload_debounce="${FPF_RELOAD_DEBOUNCE:-0.12}"
|
|
2337
|
+
|
|
2338
|
+
if ! [[ "${min_chars}" =~ ^[0-9]+$ ]]; then
|
|
2339
|
+
min_chars=2
|
|
2340
|
+
fi
|
|
2341
|
+
|
|
2342
|
+
if ! [[ "${reload_debounce}" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
|
|
2343
|
+
reload_debounce=0.12
|
|
2344
|
+
fi
|
|
2345
|
+
|
|
2346
|
+
if [[ "${script_path}" != /* ]]; then
|
|
2347
|
+
script_path="$(pwd)/${script_path}"
|
|
2348
|
+
fi
|
|
2349
|
+
|
|
2350
|
+
if [[ ${#query_value} -lt ${min_chars} ]]; then
|
|
2351
|
+
printf 'cat %q' "${fallback_file}"
|
|
2352
|
+
return
|
|
2353
|
+
fi
|
|
2354
|
+
|
|
2355
|
+
if [[ -n "${manager_override}" ]]; then
|
|
2356
|
+
printf 'sleep %s; FPF_SKIP_INSTALLED_MARKERS=1 FPF_IPC_MANAGER_OVERRIDE=%q FPF_IPC_FALLBACK_FILE=%q %q --feed-search --manager %q -- %q 2>/dev/null || cat %q' "${reload_debounce}" "${manager_override}" "${fallback_file}" "${script_path}" "${manager_override}" "${query_value}" "${fallback_file}"
|
|
2357
|
+
else
|
|
2358
|
+
printf 'sleep %s; FPF_SKIP_INSTALLED_MARKERS=1 FPF_IPC_MANAGER_OVERRIDE= FPF_IPC_FALLBACK_FILE=%q %q --feed-search -- %q 2>/dev/null || cat %q' "${reload_debounce}" "${fallback_file}" "${script_path}" "${query_value}" "${fallback_file}"
|
|
2359
|
+
fi
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
build_dynamic_reload_ipc_command() {
|
|
2363
|
+
local manager_override="$1"
|
|
2364
|
+
local fallback_file="$2"
|
|
2365
|
+
local script_path="${BASH_SOURCE[0]}"
|
|
2366
|
+
|
|
2367
|
+
if [[ "${script_path}" != /* ]]; then
|
|
2368
|
+
script_path="$(pwd)/${script_path}"
|
|
2369
|
+
fi
|
|
2370
|
+
|
|
2371
|
+
printf 'FPF_IPC_MANAGER_OVERRIDE=%q FPF_IPC_FALLBACK_FILE=%q %q --ipc-reload -- "{q}"' "${manager_override}" "${fallback_file}" "${script_path}"
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
build_dynamic_query_notify_ipc_command() {
|
|
2375
|
+
local manager_override="$1"
|
|
2376
|
+
local fallback_file="$2"
|
|
2377
|
+
local script_path="${BASH_SOURCE[0]}"
|
|
2378
|
+
|
|
2379
|
+
if [[ "${script_path}" != /* ]]; then
|
|
2380
|
+
script_path="$(pwd)/${script_path}"
|
|
2381
|
+
fi
|
|
2382
|
+
|
|
2383
|
+
printf 'FPF_IPC_MANAGER_OVERRIDE=%q FPF_IPC_FALLBACK_FILE=%q %q --ipc-query-notify -- "{q}"' "${manager_override}" "${fallback_file}" "${script_path}"
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
fzf_supports_listen() {
|
|
2387
|
+
local fzf_help
|
|
2388
|
+
fzf_help="$(fzf --help 2>&1 || true)"
|
|
2389
|
+
[[ "${fzf_help}" == *"--listen"* ]]
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
send_fzf_listen_action() {
|
|
2393
|
+
local action_payload="$1"
|
|
2394
|
+
local port="${FZF_PORT:-}"
|
|
2395
|
+
local host="127.0.0.1"
|
|
2396
|
+
local payload_size
|
|
2397
|
+
|
|
2398
|
+
if ! [[ "${port}" =~ ^[0-9]+$ ]] || [[ "${port}" -le 0 || "${port}" -gt 65535 ]]; then
|
|
2399
|
+
return 1
|
|
2400
|
+
fi
|
|
2401
|
+
|
|
2402
|
+
payload_size="$(printf "%s" "${action_payload}" | wc -c | tr -d '[:space:]')"
|
|
2403
|
+
|
|
2404
|
+
if command_exists curl; then
|
|
2405
|
+
curl --silent --show-error --fail --max-time 2 \
|
|
2406
|
+
--request POST \
|
|
2407
|
+
--header 'Content-Type: text/plain' \
|
|
2408
|
+
--data-binary "${action_payload}" \
|
|
2409
|
+
"http://${host}:${port}" >/dev/null 2>&1
|
|
2410
|
+
return
|
|
2411
|
+
fi
|
|
2412
|
+
|
|
2413
|
+
if command_exists nc; then
|
|
2414
|
+
{
|
|
2415
|
+
printf 'POST / HTTP/1.1\r\n'
|
|
2416
|
+
printf 'Host: %s:%s\r\n' "${host}" "${port}"
|
|
2417
|
+
printf 'Content-Type: text/plain\r\n'
|
|
2418
|
+
printf 'Content-Length: %s\r\n' "${payload_size}"
|
|
2419
|
+
printf '\r\n'
|
|
2420
|
+
printf '%s' "${action_payload}"
|
|
2421
|
+
} | nc -w 2 "${host}" "${port}" >/dev/null 2>&1
|
|
2422
|
+
return
|
|
2423
|
+
fi
|
|
2424
|
+
|
|
2425
|
+
if exec 9<>"/dev/tcp/${host}/${port}" 2>/dev/null; then
|
|
2426
|
+
printf 'POST / HTTP/1.1\r\n' >&9
|
|
2427
|
+
printf 'Host: %s:%s\r\n' "${host}" "${port}" >&9
|
|
2428
|
+
printf 'Content-Type: text/plain\r\n' >&9
|
|
2429
|
+
printf 'Content-Length: %s\r\n' "${payload_size}" >&9
|
|
2430
|
+
printf '\r\n' >&9
|
|
2431
|
+
printf '%s' "${action_payload}" >&9
|
|
2432
|
+
exec 9>&-
|
|
2433
|
+
return 0
|
|
2434
|
+
fi
|
|
2435
|
+
|
|
2436
|
+
return 1
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
send_fzf_prompt_action() {
|
|
2440
|
+
local prompt_text="$1"
|
|
2441
|
+
local action_payload
|
|
2442
|
+
|
|
2443
|
+
action_payload="change-prompt(${prompt_text})"
|
|
2444
|
+
send_fzf_listen_action "${action_payload}"
|
|
2445
|
+
}
|
|
2446
|
+
|
|
2447
|
+
run_ipc_reload_action() {
|
|
2448
|
+
local query="$1"
|
|
2449
|
+
local manager_override="${FPF_IPC_MANAGER_OVERRIDE:-}"
|
|
2450
|
+
local fallback_file="${FPF_IPC_FALLBACK_FILE:-}"
|
|
2451
|
+
local reload_command
|
|
2452
|
+
local action_payload
|
|
2453
|
+
|
|
2454
|
+
if [[ -z "${fallback_file}" || ! -r "${fallback_file}" ]]; then
|
|
2455
|
+
return 1
|
|
2456
|
+
fi
|
|
2457
|
+
|
|
2458
|
+
if [[ -n "${manager_override}" ]]; then
|
|
2459
|
+
manager_override="$(normalize_manager "${manager_override}")"
|
|
2460
|
+
manager_supported "${manager_override}" || return 1
|
|
2461
|
+
fi
|
|
2462
|
+
|
|
2463
|
+
reload_command="$(build_dynamic_reload_command_for_query "${manager_override}" "${fallback_file}" "${query}")"
|
|
2464
|
+
action_payload="reload(${reload_command})+change-prompt(Search> )"
|
|
2465
|
+
send_fzf_listen_action "${action_payload}"
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2468
|
+
run_ipc_query_notify_action() {
|
|
2469
|
+
local query="$1"
|
|
2470
|
+
local manager_override="${FPF_IPC_MANAGER_OVERRIDE:-}"
|
|
2471
|
+
local fallback_file="${FPF_IPC_FALLBACK_FILE:-}"
|
|
2472
|
+
local min_chars="${FPF_RELOAD_MIN_CHARS:-2}"
|
|
2473
|
+
local target_manager=""
|
|
2474
|
+
|
|
2475
|
+
if ! [[ "${min_chars}" =~ ^[0-9]+$ ]]; then
|
|
2476
|
+
min_chars=2
|
|
2477
|
+
fi
|
|
2478
|
+
|
|
2479
|
+
if [[ ${#query} -lt ${min_chars} ]]; then
|
|
2480
|
+
send_fzf_prompt_action "Search> " || true
|
|
2481
|
+
return 0
|
|
2482
|
+
fi
|
|
2483
|
+
|
|
2484
|
+
if [[ -z "${fallback_file}" || ! -r "${fallback_file}" ]]; then
|
|
2485
|
+
return 1
|
|
2486
|
+
fi
|
|
2487
|
+
|
|
2488
|
+
if [[ -n "${manager_override}" ]]; then
|
|
2489
|
+
manager_override="$(normalize_manager "${manager_override}")"
|
|
2490
|
+
manager_supported "${manager_override}" || return 1
|
|
2491
|
+
target_manager="${manager_override}"
|
|
1340
2492
|
else
|
|
1341
|
-
|
|
2493
|
+
target_manager="bun"
|
|
2494
|
+
fi
|
|
2495
|
+
|
|
2496
|
+
if [[ "${target_manager}" != "bun" ]]; then
|
|
2497
|
+
send_fzf_prompt_action "Search> " || true
|
|
2498
|
+
return 0
|
|
2499
|
+
fi
|
|
2500
|
+
|
|
2501
|
+
if ! manager_command_ready bun; then
|
|
2502
|
+
send_fzf_prompt_action "Search> " || true
|
|
2503
|
+
return 0
|
|
1342
2504
|
fi
|
|
2505
|
+
|
|
2506
|
+
send_fzf_prompt_action "Loading> " || true
|
|
2507
|
+
|
|
2508
|
+
FPF_IPC_MANAGER_OVERRIDE="${manager_override}" \
|
|
2509
|
+
FPF_IPC_FALLBACK_FILE="${fallback_file}" \
|
|
2510
|
+
manager_search_entries "bun" "${query}" >/dev/null 2>&1 || {
|
|
2511
|
+
send_fzf_prompt_action "Search> " || true
|
|
2512
|
+
}
|
|
1343
2513
|
}
|
|
1344
2514
|
|
|
1345
2515
|
manager_install() {
|
|
@@ -1572,9 +2742,15 @@ run_fuzzy_selector() {
|
|
|
1572
2742
|
local input_file="$2"
|
|
1573
2743
|
local header_line="$3"
|
|
1574
2744
|
local reload_cmd="${4:-}"
|
|
2745
|
+
local reload_ipc_cmd="${5:-}"
|
|
2746
|
+
local script_path="${BASH_SOURCE[0]}"
|
|
1575
2747
|
local preview_cmd
|
|
1576
2748
|
|
|
1577
|
-
|
|
2749
|
+
if [[ "${script_path}" != /* ]]; then
|
|
2750
|
+
script_path="$(pwd)/${script_path}"
|
|
2751
|
+
fi
|
|
2752
|
+
|
|
2753
|
+
preview_cmd="FPF_SESSION_TMP_ROOT=$(printf '%q' "${SESSION_TMP_ROOT}") ${script_path} --preview-item --manager {1} -- {2}"
|
|
1578
2754
|
|
|
1579
2755
|
local -a fzf_args=()
|
|
1580
2756
|
fzf_args=(-q "${query}" -m \
|
|
@@ -1597,8 +2773,14 @@ run_fuzzy_selector() {
|
|
|
1597
2773
|
--bind=ctrl-n:next-selected,ctrl-b:prev-selected \
|
|
1598
2774
|
--bind='focus:transform-preview-label:echo [{1}] {2}')
|
|
1599
2775
|
|
|
1600
|
-
if [[ -n "${
|
|
1601
|
-
fzf_args+=(--
|
|
2776
|
+
if [[ -n "${reload_ipc_cmd}" ]]; then
|
|
2777
|
+
fzf_args+=(--listen=0)
|
|
2778
|
+
fzf_args+=(--bind="change:execute-silent:${reload_ipc_cmd}")
|
|
2779
|
+
if [[ -n "${reload_cmd}" ]]; then
|
|
2780
|
+
fzf_args+=(--bind="ctrl-r:reload:${reload_cmd}")
|
|
2781
|
+
fi
|
|
2782
|
+
elif [[ -n "${reload_cmd}" ]]; then
|
|
2783
|
+
fzf_args+=(--bind="ctrl-r:reload:${reload_cmd}")
|
|
1602
2784
|
fi
|
|
1603
2785
|
|
|
1604
2786
|
fzf "${fzf_args[@]}" <"${input_file}"
|
|
@@ -1607,10 +2789,54 @@ run_fuzzy_selector() {
|
|
|
1607
2789
|
main() {
|
|
1608
2790
|
ensure_tmp_root
|
|
1609
2791
|
initialize_session_tmp_root
|
|
1610
|
-
|
|
2792
|
+
if [[ -z "${FPF_SESSION_TMP_ROOT:-}" ]]; then
|
|
2793
|
+
trap cleanup_session_tmp_root EXIT
|
|
2794
|
+
fi
|
|
1611
2795
|
|
|
1612
2796
|
parse_args "$@"
|
|
1613
2797
|
|
|
2798
|
+
if [[ "${ACTION}" == "ipc-reload" ]]; then
|
|
2799
|
+
run_ipc_reload_action "$(join_query)" || true
|
|
2800
|
+
exit 0
|
|
2801
|
+
fi
|
|
2802
|
+
|
|
2803
|
+
if [[ "${ACTION}" == "ipc-query-notify" ]]; then
|
|
2804
|
+
run_ipc_query_notify_action "$(join_query)" || true
|
|
2805
|
+
exit 0
|
|
2806
|
+
fi
|
|
2807
|
+
|
|
2808
|
+
if [[ "${ACTION}" == "preview-item" ]]; then
|
|
2809
|
+
local preview_manager="${MANAGER_OVERRIDE:-}"
|
|
2810
|
+
local preview_package
|
|
2811
|
+
|
|
2812
|
+
preview_package="$(join_query)"
|
|
2813
|
+
run_preview_item_action "${preview_manager}" "${preview_package}" || true
|
|
2814
|
+
exit 0
|
|
2815
|
+
fi
|
|
2816
|
+
|
|
2817
|
+
if [[ "${ACTION}" == "bun-refresh-worker" ]]; then
|
|
2818
|
+
local worker_manager="${MANAGER_OVERRIDE:-bun}"
|
|
2819
|
+
local worker_query
|
|
2820
|
+
local worker_flags
|
|
2821
|
+
local worker_key
|
|
2822
|
+
local worker_fingerprint
|
|
2823
|
+
local worker_generation
|
|
2824
|
+
|
|
2825
|
+
worker_query="$(join_query)"
|
|
2826
|
+
worker_flags="${FPF_BUN_REFRESH_FLAGS:-$(query_cache_flags)}"
|
|
2827
|
+
worker_key="${FPF_BUN_REFRESH_KEY:-$(cache_query_key "${worker_manager}" "${worker_query}" "${worker_flags}")}"
|
|
2828
|
+
worker_fingerprint="${FPF_BUN_REFRESH_FINGERPRINT:-$(cache_fingerprint "${worker_manager}" "${worker_query}" "${worker_flags}")}"
|
|
2829
|
+
worker_generation="${FPF_BUN_REFRESH_GENERATION:-0}"
|
|
2830
|
+
|
|
2831
|
+
if ! [[ "${worker_generation}" =~ ^[0-9]+$ ]] || [[ "${worker_generation}" -le 0 ]]; then
|
|
2832
|
+
exit 0
|
|
2833
|
+
fi
|
|
2834
|
+
|
|
2835
|
+
initialize_cache_root
|
|
2836
|
+
bun_run_refresh_worker "${worker_manager}" "${worker_query}" "${worker_flags}" "${worker_key}" "${worker_fingerprint}" "${worker_generation}" || true
|
|
2837
|
+
exit 0
|
|
2838
|
+
fi
|
|
2839
|
+
|
|
1614
2840
|
if [[ "${ACTION}" == "version" ]]; then
|
|
1615
2841
|
print_version
|
|
1616
2842
|
exit 0
|
|
@@ -1739,6 +2965,15 @@ main() {
|
|
|
1739
2965
|
|
|
1740
2966
|
if [[ ! -s "${display_file}" ]]; then
|
|
1741
2967
|
rm -f "${display_file}"
|
|
2968
|
+
|
|
2969
|
+
if [[ "${ACTION}" == "search" && -z "${query}" && "${#managers[@]}" -eq 1 ]]; then
|
|
2970
|
+
local setup_message=""
|
|
2971
|
+
setup_message="$(manager_no_query_setup_message "${managers[0]}" || true)"
|
|
2972
|
+
if [[ -n "${setup_message}" ]]; then
|
|
2973
|
+
die "${setup_message}"
|
|
2974
|
+
fi
|
|
2975
|
+
fi
|
|
2976
|
+
|
|
1742
2977
|
if [[ -n "${query}" ]]; then
|
|
1743
2978
|
die "No packages found for ${manager_display} matching '${query}'. Try a broader query or --manager."
|
|
1744
2979
|
fi
|
|
@@ -1762,14 +2997,18 @@ main() {
|
|
|
1762
2997
|
esac
|
|
1763
2998
|
|
|
1764
2999
|
local reload_cmd=""
|
|
3000
|
+
local reload_ipc_cmd=""
|
|
1765
3001
|
if [[ "${ACTION}" == "search" && -z "${query}" ]]; then
|
|
1766
3002
|
if dynamic_reload_enabled "${#managers[@]}"; then
|
|
1767
3003
|
reload_cmd="$(build_dynamic_reload_command "${MANAGER_OVERRIDE}" "${display_file}")"
|
|
3004
|
+
if fzf_supports_listen; then
|
|
3005
|
+
reload_ipc_cmd="$(build_dynamic_query_notify_ipc_command "${MANAGER_OVERRIDE}" "${display_file}")"
|
|
3006
|
+
fi
|
|
1768
3007
|
fi
|
|
1769
3008
|
fi
|
|
1770
3009
|
|
|
1771
3010
|
local selected
|
|
1772
|
-
selected="$(run_fuzzy_selector "${query}" "${display_file}" "${header}" "${reload_cmd}" || true)"
|
|
3011
|
+
selected="$(run_fuzzy_selector "${query}" "${display_file}" "${header}" "${reload_cmd}" "${reload_ipc_cmd}" || true)"
|
|
1773
3012
|
|
|
1774
3013
|
rm -f "${display_file}"
|
|
1775
3014
|
|
|
@@ -1824,7 +3063,7 @@ main() {
|
|
|
1824
3063
|
if confirm_action "Install ${#selected_packages[@]} package(s) with ${selected_manager_display}?"; then
|
|
1825
3064
|
for manager in "${unique_managers[@]-}"; do
|
|
1826
3065
|
mgr_packages=()
|
|
1827
|
-
for idx in "${!selected_packages[@]
|
|
3066
|
+
for idx in "${!selected_packages[@]}"; do
|
|
1828
3067
|
if [[ "${selected_managers[$idx]}" == "${manager}" ]]; then
|
|
1829
3068
|
mgr_packages+=("${selected_packages[$idx]}")
|
|
1830
3069
|
fi
|
|
@@ -1842,7 +3081,7 @@ main() {
|
|
|
1842
3081
|
if confirm_action "Remove ${#selected_packages[@]} package(s) with ${selected_manager_display}?"; then
|
|
1843
3082
|
for manager in "${unique_managers[@]-}"; do
|
|
1844
3083
|
mgr_packages=()
|
|
1845
|
-
for idx in "${!selected_packages[@]
|
|
3084
|
+
for idx in "${!selected_packages[@]}"; do
|
|
1846
3085
|
if [[ "${selected_managers[$idx]}" == "${manager}" ]]; then
|
|
1847
3086
|
mgr_packages+=("${selected_packages[$idx]}")
|
|
1848
3087
|
fi
|
|
@@ -1857,7 +3096,7 @@ main() {
|
|
|
1857
3096
|
fi
|
|
1858
3097
|
;;
|
|
1859
3098
|
list)
|
|
1860
|
-
for idx in "${!selected_packages[@]
|
|
3099
|
+
for idx in "${!selected_packages[@]}"; do
|
|
1861
3100
|
printf "\n=== %s (%s) ===\n" "${selected_packages[$idx]}" "$(manager_label "${selected_managers[$idx]}")"
|
|
1862
3101
|
manager_show_info "${selected_managers[$idx]}" "${selected_packages[$idx]}" || true
|
|
1863
3102
|
done
|