You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pkgsearch 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #!/usr/bin/env bash
  2. declare -r esc=$'\033'
  3. declare -r c_reset="${esc}[0m"
  4. declare -r c_red="${esc}[31m"
  5. declare -r c_green="${esc}[32m"
  6. declare -r c_blue="${esc}[34m"
  7. declare distro
  8. declare preview_pos='right:hidden'
  9. usage() {
  10. LESS=-FEXR less <<HELP
  11. pkgsearch [options] [query]
  12. lists and installs packages from your distro's repositories
  13. without any arguments pkgsearch will list all available packages from your cache
  14. note: on Arch Linux you must pass a string to query the AUR
  15. HELP
  16. }
  17. err() {
  18. printf "${c_red}%s${c_reset}\n" "$*" >&2
  19. }
  20. die() {
  21. exit 1
  22. }
  23. has() {
  24. local verbose=0
  25. if [[ $1 = '-v' ]]; then
  26. verbose=1
  27. shift
  28. fi
  29. for c; do c="${c%% *}"
  30. if ! command -v "$c" &> /dev/null; then
  31. (( "$verbose" > 0 )) && err "$c not found"
  32. return 1
  33. fi
  34. done
  35. }
  36. select_from() {
  37. local cmd='command -v'
  38. for a; do
  39. case "$a" in
  40. -c)
  41. cmd="$2"
  42. shift 2
  43. ;;
  44. esac
  45. done
  46. for c; do
  47. if $cmd "${c%% *}" &> /dev/null; then
  48. echo "$c"
  49. return 0
  50. fi
  51. done
  52. return 1
  53. }
  54. fzf() {
  55. command fzf -e +s --multi --cycle --ansi \
  56. --bind='Ctrl-X:toggle-preview' \
  57. --no-hscroll --inline-info \
  58. --header='tab to select multiple packages, Ctrl-X for more info on a package' "$@"
  59. }
  60. install() {
  61. local pkgs count
  62. mapfile -t pkgs
  63. (( ${#pkgs} > 0 )) || exit
  64. count="${#pkgs[@]} package"
  65. (( ${#pkgs[@]} > 1 )) && count+='s'
  66. printf "installing %s: %s\n" "$count" "${pkgs[*]}"
  67. $1 "${pkgs[@]}" < /dev/tty
  68. }
  69. debian() {
  70. fzf --preview='apt-cache show {1}' \
  71. --query="$1" \
  72. < <(apt-cache search '.*' | sort |
  73. sed -u -r "s|^([^ ]+)|${c_green}\1${c_reset}|") |
  74. cut -d' ' -f1 |
  75. install "sudo $(select_from 'apt' 'aptitude' 'apt-get') install"
  76. }
  77. arch() {
  78. local search packages
  79. search='pacman'
  80. [[ -n "$1" ]] && search=$(select_from 'pacaur' 'trizen' 'yaourt' 'packer' 'apacman' 'pacman')
  81. packages=$(fzf --preview="$search -Si {2}" \
  82. < <( $search -Ss "$1" |
  83. gawk '{
  84. getline descr;
  85. sub(/ */,"", descr);
  86. repo = blue "[" gensub(/\/.*/, "", 1) "]" reset;
  87. name = green gensub(/.*\//, "", 1, $1) reset;
  88. info = gensub(/[^ ]* /, "", 1);
  89. print repo, name, info, descr;
  90. }' blue="$c_blue" green="$c_green" reset="$c_reset"
  91. ) | cut -d' ' -f2)
  92. [[ "$search" = "pacman" ]] && search="sudo pacman"
  93. install "$search -S" <<< "$packages"
  94. }
  95. void() {
  96. local package_list packagename='{ sub(/-[^\-]*$/, "", $2); print $2 }'
  97. package_list=$(xbps-query -Rs '' | sort)
  98. fzf --preview="p=\$(awk \"$packagename\" <<< {}); xbps-query -Rx \$p" \
  99. --query="$1" <<< "$package_list" |
  100. awk "$packagename" |
  101. install 'xbps-install -S'
  102. }
  103. fedora() {
  104. fzf --query="$*" --preview='p={}; p="${p%% *}"; dnf -q info "${p%.*}"' \
  105. < <(dnf -qC repoquery --qf "${c_green}%{name} ${c_reset} - %{summary}" \*) |
  106. awk '{ package=$1; sub(/\.\S+/, "", package); print package }' |
  107. install 'sudo dnf install'
  108. }
  109. while true; do
  110. case "$1" in
  111. -h|--help) usage; exit ;;
  112. -p|--preview) preview_pos="$2"; shift 2 ;;
  113. *) break
  114. esac
  115. done
  116. has -v fzf gawk || die
  117. request="$*"
  118. if [[ -r /etc/os-release ]]; then
  119. distro=$(awk -F'=' '"NAME" == $1 { gsub("\"", "", $2); print tolower($2); }' /etc/os-release)
  120. distro="${distro%% *}"
  121. fi
  122. case "$distro" in
  123. debian|ubuntu) debian "$request" ;;
  124. arch) arch "$request" ;;
  125. void) void "$request" ;;
  126. fedora) fedora "$request" ;;
  127. *) die 'unknown distro :(' ;;
  128. esac
  129. # TODO: homebrew: brew desc -s
  130. # sample output: https://pastebin.com/raw/3frRf6C7