Browse Source

npmsearch -> js (rewrite)

master
DanielFGray 8 months ago
parent
commit
66c8303008
2 changed files with 163 additions and 144 deletions
  1. 163
    0
      js
  2. 0
    144
      npmsearch

+ 163
- 0
js View File

@@ -0,0 +1,163 @@
#!/usr/bin/env bash

declare -A aliases
declare -A helptext

err() { printf '%s\n' "$@" >&2; return 1; }

die() {
(( $# > 0 )) && err "$@"
exit 1
}

select_from() {
local cmd='command -v'
for a; do
case "$a" in
-c) cmd="$2"; shift 2 ;;
esac
done
for c; do
if $cmd "${c%% *}" &> /dev/null; then
echo "$c"
return 0
fi
done
return 1
}

has() {
local v c
if [[ $1 = '-v' ]]; then
v=1
shift
fi
for c; do c="${c%% *}"
if ! command -v "$c" &> /dev/null; then
(( v > 0 )) && err "$c not found"
return 1
fi
done
}
export -f has
aliases[s]=search
helptext['search']="search and install packages"
subcmd_search() {
local choices init
if [[ -n $1 ]]; then init=$(npm --json search "$*" | pretty_npm_search); fi
# SHELL is needed to use exported functions if default shell is not bash
SHELL=$(which bash) fzf \
--inline-info \
--query="$*" \
--phony \
--multi \
--preview-window=hidden \
--header='enter to install, C-d saves as devDependency, C-v to pick versions' \
--bind='?:toggle-preview' \
--bind='change:reload:npm --json search {q} | pretty_npm_search' \
--bind='ctrl-v:execute:subcmd_ls-versions {1} <> /dev/tty' \
--bind="enter:execute:subcmd_install {+1} <> /dev/tty" \
--bind="ctrl-d:execute:subcmd_install -D {+1} <> /dev/tty" \
--preview="npm view {1}" \
<<< "$init"
}

aliases[lsv]='ls-versions'
helptext['ls-versions']='list and install versions'
subcmd_ls-versions() {
local package="$1"
npm --json view "$package" |
jq -r '.versions[]' | # label with .dist-tags?
fzf --tac --preview="npm view ${package}@{1}" \
--header="choose version for $package | C-d saves as devDependency" \
--bind="enter:execute:subcmd_install '${package}@{1}' <> /dev/tty" \
--bind="ctrl-d:execute:subcmd_install -D '${package}@{1}' <> /dev/tty"
}
export -f subcmd_ls-versions

aliases[un]=uninstall
helptext[uninstall]='uninstall packages'
subcmd_uninstall() {
local rm
mapfile -t rm < <(
jq -r '{dependencies, devDependencies}[] | keys[]' package.json |
fzf -m --query="$*")
(( ${#rm} > 0 )) || return
$(select_from 'yarn remove' 'npm uninstall') "${rm[@]}"
}

aliases[i]=install
helptext[install]='install packages'
subcmd_install() {
if [[ -e yarn.lock ]] && has yarn; then
yarn add "$@"
else
npm i -S "$@"
fi
}
export -f subcmd_install

helptext[init]='guided project setup'
subcmd_init() {
$(select_from 'git-flow init -d' 'git init') > /dev/null
npm init -y > /dev/null
[[ -e .gitignore ]] || curl -sL https://raw.githubusercontent.com/toptal/gitignore/master/templates/Node.gitignore > .gitignore
# install typescript? eslint? prettier? husky + lint-staged?
# react? vue? bundlers etc
}

helptext[lint]='setup or use eslint'
subcmd_lint() { # TODO
# should check if typescript, react, babel is installed, use relevant plugins
if [[ $(jq '.devDependencies.eslint' package.json) = null ]]; then
npx eslint --init
fi
npx eslint --ignore-path=.gitignore "$@"
}

aliases[fmt]=format
helptext[format]='setup or use prettier'
subcmd_format() { # TODO
if [[ $(jq '.devDependencies.prettier' package.json) = null ]]; then
subcmd_install -D prettier # eslint-{config,plugin}-prettier
fi
npx prettier --ignore-path .gitignore --write "$@"
}

aliases[-h]=help
helptext[help]='show this help '
subcmd_help() {
LESS=-FEXR less <<-HELP
js [subcmd] [options]

$(for c in "${subcmds_avail[@]}"; do
printf " %s\n %s\n" "$c" "${helptext[$c]}"
done)
HELP
}

pretty_npm_search() { jq -r '.[] | "\(.name) \(.version)\t\(.description[0:80])\t\(.author.name // .publisher.username)\t\((.keywords // []) | join(" "))"' | column -t -s $'\t'; }
export -f pretty_npm_search

has -v fzf jq npm || die

mapfile -t subcmds_avail < <(compgen -A function | awk '/^subcmd_/{ sub(/^subcmd_/, "", $0); print }')

if (( $# < 1 )); then
err 'missing command'
subcmd_help
exit 1
elif has "subcmd_$1"; then
subcmd="subcmd_$1"
shift
"$subcmd" "$@"
elif [[ -v aliases[$1] ]]; then
subcmd=subcmd_${aliases[$1]}
shift
"$subcmd" "$@"
else
err 'unknown command'
subcmd_help
exit 1
fi

+ 0
- 144
npmsearch View File

@@ -1,144 +0,0 @@
#!/usr/bin/env bash

declare -a args
declare -a packages
declare savedev=0
declare global=0

declare -A colors
colors[red]=$(tput setaf 1)
colors[green]=$(tput setaf 2)
colors[reset]=$(tput sgr0)

usage() {
LESS=-FEXR less <<-HELP
npmsearch [options] [packages]
searches npm for packages

-r, --remove
list and remove packages from package.json

to increase the amount of packages shown when searching, try:
npm config set searchlimit 40

HELP
}

color() {
local color="$1"; shift
printf '%s' "${colors[$color]}"
printf '%s\n' "$@"
printf '%s' "${colors[reset]}"
}

err() { color red "$@" >&2; return 1; }

die() {
(( $# > 0 )) && err "$@"
exit 1
}

has() {
local v c
if [[ $1 = '-v' ]]; then
v=1
shift
fi
for c; do c="${c%% *}"
if ! command -v "$c" &> /dev/null; then
(( v > 0 )) && err "$c not found"
return 1
fi
done
}

select_from() {
local cmd='command -v'
for a; do
case "$a" in
-c) cmd="$2"; shift 2 ;;
esac
done
for c; do
if $cmd "${c%% *}" &> /dev/null; then
echo "$c"
return 0
fi
done
return 1
}

has -v fzf npm || die

fzf() {
command fzf --inline-info --ansi --reverse +s --no-hscroll "$@"
}

if [[ $1 = '-h' || $1 = '--help' ]]; then
usage
exit
fi

if [[ $1 = '-r' || $1 = '--remove' ]]; then
shift
mapfile -t rm < <(
jq -r '{dependencies, devDependencies} | .[] | keys | .[]' package.json |
fzf -m --cycle -e --reverse --query="$*")
(( ${#rm} > 0 )) && $(select_from 'yarn remove' 'npm uninstall') "${rm[@]}"
die
fi

printf '%ssearching...%s\r' "${colors[green]}" "${colors[reset]}"
search=$(npm search --json "$*") || exit

search=$(jq -r '.[] | "\(.name)|\(.version)|\(.description)"' <<< "$search" | column -t -s'|')

mapfile -t packages < <(fzf --multi \
--bind='ctrl-x:toggle-preview' \
--expect='ctrl-g,ctrl-d,enter,ctrl-v,esc' \
--preview-window='hidden:down' \
--preview="npm -s --json view {1} | jq -C \"del(.users, .time, .versions)\"" \
--header='C-d saves as devDependency, C-g installs globally, C-v for specific version, C-x for more info, ' \
<<< "$search")

key="${packages[0]}"
case "${key,,}" in
esc) die ;;
ctrl-d) savedev=1 ;;
ctrl-g) global=1 ;;
ctrl-v)
package="${packages[1]%% *}"
mapfile -t version < <(
npm -s --json view "$package" |
jq -r '.versions[]' | # label with .dist-tags?
fzf --header="choose version for $package | C-d saves as devDependency" --tac --expect='ctrl-d,esc')
key="${version[0]}"
case "${key,,}" in
esc) die ;;
ctrl-d) savedev=1 ;;
esac
packages=( "${package}@${version[1]}" )
;;
esac

(( ${#packages[@]} > 0 )) || die 'no packages to install'

if (( ${#packages[@]} > 1 )); then
packages=( "${packages[@]:1}" )
packages=( "${packages[@]%% *}" )
fi

printf '%sinstalling...%s\r' "${colors[green]}" "${colors[reset]}"
if (( global > 0 )); then
npm install -g "${args[@]}" "${packages[@]}"
elif has yarn; then
(( savedev > 0 )) && args+=( -D )
yarn add "${args[@]}" "${packages[@]}"
else
if (( savedev > 0 )); then
args+=( -D )
else
args+=( -S )
fi
npm i "${args[@]}" "${packages[@]}"
fi

Loading…
Cancel
Save