feat(search): add optional plain output formatting

This allows to run the search command without bats, which is not used in
the default pretty output format.

Component: pkgctl search
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
This commit is contained in:
Levente Polyak 2024-01-05 19:23:52 +01:00
parent 0e538cf498
commit d0dc0e1a32
No known key found for this signature in database
GPG Key ID: FC1B547C8D8172C8
7 changed files with 135 additions and 20 deletions

View File

@ -67,7 +67,6 @@ Component: pkgctl db remove
- arch-install-scripts
- awk
- bash
- bats
- binutils
- coreutils
- diffutils
@ -87,6 +86,10 @@ Component: pkgctl db remove
- mercurial
- subversion
### Optional Dependencies
- bats (pretty printing)
### Development Dependencies
- asciidoc

View File

@ -9,6 +9,8 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
# shellcheck source=src/lib/valid-inspect.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh
# shellcheck source=src/lib/valid-search.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-search.sh
_binary_arch=${DEVTOOLS_VALID_ARCHES[*]:0:-1}
_colors=(never always auto)
@ -333,11 +335,15 @@ _pkgctl_repo_web_opts() { _filedir -d; }
_pkgctl_search_args=(
--json
--no-default-filter
--json
-F --format
-N --no-line-number
-h --help
)
_pkgctl_search_opts() { :; }
_pkgctl_search_args__format_opts() { _devtools_completions_search_format; }
_pkgctl_search_args_F_opts() { _devtools_completions_search_format; }
_pkgctl_diff_args=(
@ -391,6 +397,9 @@ _devtools_completions_protocol() {
_devtools_completions_inspect() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_INSPECT_MODES[*]}" -- "$cur")
}
_devtools_completions_search_format() {
mapfile -t COMPREPLY < <(compgen -W "${valid_search_output_format[*]}" -- "$cur")
}
__devtools_complete() {
local service=$1

View File

@ -9,6 +9,8 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
# shellcheck source=src/lib/valid-inspect.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh
# shellcheck source=src/lib/valid-search.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-search.sh
_binary_arch=${DEVTOOLS_VALID_ARCHES[*]:0:-1}
_colors=(never always auto)
@ -140,8 +142,10 @@ _pkgctl_repo_web_args=(
)
_pkgctl_search_args=(
'--json[Enable printing results in JSON]'
'--no-default-filter[Do not apply default filter (like -path:keys/pgp/*.asc)]'
'--json[Enable printing results in JSON]'
'(-F --format)'{-F,--format}"[Controls the formatting of the results]:format:($valid_search_output_format[*])"
'(-N --no-line-number)'{-N,--no-line-number}"[Don't show line numbers when formatting results]"
'(-h --help)'{-h,--help}'[Display usage]'
'1:query'
)

View File

@ -20,7 +20,7 @@ use glob matching.
Available filters for the blobs scope: path, extension
Every usage of the search command must be authenticated. Consult the
'pkgctl auth' command to authenticate with GitLab or view the authentication
`'pkgctl auth'` command to authenticate with GitLab or view the authentication
status.
Search Tips
@ -41,14 +41,27 @@ Search Tips
Options
-------
*--json*::
Enable printing results in JSON
*-h, --help*::
Show a help text
Filter Options
--------------
*--no-default-filter*::
Do not apply default filter (like -path:keys/pgp/*.asc)
*-h, --help*::
Show a help text
Output Options
--------------
*--json*::
Enable printing in JSON; Shorthand for `'--format json'`
*-F, --format* 'FORMAT'::
Controls the formatting of the results; `FORMAT` is `'pretty'`, `'plain'`,
or `'json'` (default `pretty`)
*-N, --no-line-number*::
Don't show line numbers when formatting results
See Also
--------

View File

@ -33,9 +33,11 @@ export PKGBASE_MAINTAINER_URL=https://archlinux.org/packages/pkgbase-maintainer
# check if messages are to be printed using color
if [[ -t 2 && "$TERM" != dumb ]] || [[ ${DEVTOOLS_COLOR} == always ]]; then
colorize
PURPLE="$(tput setaf 5)"
DARK_GREEN="$(tput setaf 2)"
else
# shellcheck disable=2034
declare -gr ALL_OFF='' BOLD='' BLUE='' GREEN='' RED='' YELLOW=''
declare -gr ALL_OFF='' BOLD='' BLUE='' GREEN='' RED='' YELLOW='' PURPLE=''
fi
stat_busy() {

View File

@ -12,7 +12,10 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/cache.sh
# shellcheck source=src/lib/api/gitlab.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/gitlab.sh
# shellcheck source=src/lib/valid-search.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-search.sh
source /usr/share/makepkg/util/util.sh
source /usr/share/makepkg/util/message.sh
set -eo pipefail
@ -48,16 +51,33 @@ pkgctl_search_usage() {
! Merge request !23456
OPTIONS
--json Enable printing results in JSON
--no-default-filter Do not apply default filter (like -path:keys/pgp/*.asc)
-h, --help Show this help text
-h, --help Show this help text
FILTER OPTIONS
--no-default-filter Do not apply default filter (like -path:keys/pgp/*.asc)
OUTPUT OPTIONS
--json Enable printing in JSON; Shorthand for '--format json'
-F, --format FORMAT Controls the formatting of the results; FORMAT is 'pretty',
'plain', or 'json' (default: pretty)
-N, --no-line-number Don't show line numbers when formatting results
EXAMPLES
$ ${COMMAND} linux
$ ${COMMAND} '"pytest -v" +PYTHONPATH'
$ ${COMMAND} --json '"pytest -v" +PYTHONPATH'
_EOF_
}
pkgctl_search_check_option_group_format() {
local option=$1
local output_format=$2
if [[ -n ${output_format} ]]; then
die "The argument '%s' cannot be used with one or more of the other specified arguments" "${option}"
exit 1
fi
return 0
}
pkgctl_search() {
if (( $# < 1 )); then
pkgctl_search_usage
@ -66,15 +86,17 @@ pkgctl_search() {
# options
local search
local formatter=pretty
local output_format=
local use_default_filter=1
local line_numbers=1
# variables
local bats_style="header,grid"
local default_filter="-path:keys/pgp/*.asc"
local graphql_lookup_batch=200
local output result query entries from until length
local project_name_cache_file project_name_lookup project_ids project_id project_name project_slice
local mapping_output path startline data
local mapping_output path startline currentline data line
while (( $# )); do
case $1 in
@ -82,14 +104,28 @@ pkgctl_search() {
pkgctl_search_usage
exit 0
;;
--json)
formatter=json
shift
;;
--no-default-filter)
use_default_filter=0
shift
;;
--json)
pkgctl_search_check_option_group_format "$1" "${output_format}"
output_format=json
shift
;;
-F|--format)
(( $# <= 1 )) && die "missing argument for %s" "$1"
pkgctl_search_check_option_group_format "$1" "${output_format}"
output_format="${2}"
if ! in_array "${output_format}" "${valid_search_output_format[@]}"; then
die "Unknown output format: %s" "${output_format}"
fi
shift 2
;;
-N|--no-line-number)
line_numbers=0
shift
;;
--)
shift
break
@ -114,16 +150,35 @@ pkgctl_search() {
search+=" ${default_filter}"
fi
# assign default output format
if [[ -z ${output_format} ]]; then
output_format=pretty
fi
# check for optional dependencies
if [[ ${output_format} == pretty ]] && ! command -v bats &>/dev/null; then
warning "Failed to find optional dependency 'bats': falling back to plain output"
output_format=plain
fi
# populate line numbers option
if (( line_numbers )); then
bats_style="numbers,${bats_style}"
fi
# call the gitlab search API
stat_busy "Querying gitlab search api"
output=$(gitlab_api_search "${search}")
stat_done
# collect project ids whose name needs to be looked up
project_name_cache_file=$(get_cache_file gitlab/project_id_to_name)
lock 11 "${project_name_cache_file}" "Locking project name cache"
mapfile -t project_ids < <(
jq --raw-output '[.[].project_id] | unique[]' <<< "${output}" | \
grep --invert-match --file <(awk '{ print $1 }' < "${project_name_cache_file}" ))
# look up project names
stat_busy "Querying project names"
local entries="${#project_ids[@]}"
local until=0
@ -171,7 +226,7 @@ pkgctl_search() {
lock_close 11
# output mode JSON
if [[ ${formatter} == json ]]; then
if [[ ${output_format} == json ]]; then
jq --from-file <(
for project_id in $(jq '.[].project_id' <<< "${output}"); do
project_name=${project_name_lookup[${project_id}]}
@ -197,6 +252,23 @@ pkgctl_search() {
unset "data[${#data[@]}-1]"
fi
# output mode plain
if [[ ${output_format} == plain ]]; then
printf "%s%s%s\n" "${PURPLE}" "${project_name}/${path}" "${ALL_OFF}"
currentline=${startline}
for line in "${data[@]}"; do
if (( line_numbers )); then
line="${DARK_GREEN}${currentline}${ALL_OFF}: ${line}"
currentline=$(( currentline + 1 ))
fi
printf "%s\n" "${line}"
done
printf "\n"
continue
fi
# prepend empty lines to match startline
if (( startline > 1 )); then
mapfile -t data < <(
@ -210,6 +282,7 @@ pkgctl_search() {
--line-range "${startline}:" \
--paging=never \
--force-colorization \
--style "${bats_style}" \
--map-syntax "PKGBUILD:Bourne Again Shell (bash)" \
--map-syntax ".SRCINFO:INI" \
--map-syntax "*install:Bourne Again Shell (bash)" \

11
src/lib/valid-search.sh Normal file
View File

@ -0,0 +1,11 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
:
# shellcheck disable=2034
valid_search_output_format=(
pretty
plain
json
)