From 136b99839bcca45d21c444b799412698ca107c0d Mon Sep 17 00:00:00 2001 From: Fabian Boehm Date: Tue, 22 Aug 2023 22:17:22 +0200 Subject: [PATCH] print_apt_packages: Go back to apt-cache for non-installed packages Unfortunately, /var/lib/dpkg/status on recent-ish Debian versions at least only contains the *installed* packages, rendering this solution broken. What we do instead is: 1. Remove a useless newline from each package, so our limit would now let more full package data sets through 2. Increase the limit by 5x This yields a completion that runs in ~800ms instead of ~700ms on a raspberry pi, but gives ~10x the candidates, compared to the old apt-cache version. This partially reverts 96deaae7d86edfbc16e411bdb73bf54ced7fb447 (cherry picked from commit 81cd0359509621bd8fb11556bdfd65462ede54a9) --- .../functions/__fish_print_apt_packages.fish | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/share/functions/__fish_print_apt_packages.fish b/share/functions/__fish_print_apt_packages.fish index c8d578c9e..102895b1b 100644 --- a/share/functions/__fish_print_apt_packages.fish +++ b/share/functions/__fish_print_apt_packages.fish @@ -7,7 +7,12 @@ function __fish_print_apt_packages return end - type -q -f apt-cache || return 1 + set -l search_term (commandline -ct | string replace -ar '[\'"\\\\]' '' | string lower) + + if ! test -f /var/lib/dpkg/status + return 1 + end + if not set -q _flag_installed # Do not generate the cache as apparently sometimes this is slow. # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=547550 @@ -28,11 +33,32 @@ function __fish_print_apt_packages # The `head -n 500` causes us to stop once we have 500 lines. We do it after the `sed` because # Debian package descriptions can be extremely long and are hard-wrapped: texlive-latex-extra # has about 2700 lines on Debian 11. - apt-cache --no-generate show '.*'(commandline -ct)'.*' 2>/dev/null | sed -r '/^(Package|Description-?[a-zA-Z_]*):/!d;s/Package: (.*)/\1\t/g;s/Description-?[^:]*: (.*)/\1\x1a\n/g' | head -n 500 | string join "" | string replace --all --regex \x1a+ \n | uniq + apt-cache --no-generate show '.*'(commandline -ct)'.*' 2>/dev/null | sed -r '/^(Package|Description-?[a-zA-Z_]*):/!d;s/Package: (.*)/\1\t/g;s/Description-?[^:]*: (.*)/\1\x1a/g' | head -n 2500 | string join "" | string replace --all --regex \x1a+ \n | uniq return 0 else - set -l packages (dpkg --get-selections | string replace -fr '(\S+)\s+install' "\$1" | string match -e (commandline -ct)) - apt-cache --no-generate show $packages 2>/dev/null | sed -r '/^(Package|Description-?[a-zA-Z_]*):/!d;s/Package: (.*)/\1\t/g;s/Description-?[^:]*: (.*)/\1\x1a\n/g' | head -n 500 | string join "" | string replace --all --regex \x1a+ \n | uniq - return 0 + # Do not not use `apt-cache` as it is sometimes inexplicably slow (by multiple orders of magnitude). + awk ' +BEGIN { + FS=": " +} + +/^Package/ { + pkg=$2 +} + +/^Status/ { + installed=0 + if ($2 ~ /(^|\s)installed/) { + installed=1 + } +} + +/^Description(-[a-zA-Z]+)?:/ { + desc=$2 + if (installed == 1 && index(pkg, "'$search_term'") > 0) { + print pkg "\t" desc + installed=0 # Prevent multiple description translations from being printed + } +}'