From 4673ad6c89bbdca632b22edfc2ef35486b7a635b Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 1 Jul 2023 15:21:32 +0200 Subject: feat(search): add subcommand to search across the packaging group Search for an expression across the GitLab packaging group. To use a filter, include it in your query. You may use wildcards (*) to 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 status. This command uses bats for pretty printing the results including line numbers and syntax highlighting. Component: pkgctl search Co-authored-by: Christian Heusel Co-authored-by: Levente Polyak --- doc/man/pkgctl-search.1.asciidoc | 58 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 doc/man/pkgctl-search.1.asciidoc (limited to 'doc/man/pkgctl-search.1.asciidoc') diff --git a/doc/man/pkgctl-search.1.asciidoc b/doc/man/pkgctl-search.1.asciidoc new file mode 100644 index 0000000..fb79b88 --- /dev/null +++ b/doc/man/pkgctl-search.1.asciidoc @@ -0,0 +1,58 @@ +pkgctl-search(1) +================ + +Name +---- +pkgctl-search - Search for an expression across the GitLab packaging group + +Synopsis +-------- +pkgctl search [OPTIONS] QUERY + +Description +----------- + +Search for an expression across the GitLab packaging group. + +To use a filter, include it in your query. You may use wildcards (*) to +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 +status. + +Search Tips +----------- + + Syntax Description Example + ─────────────────────────────────────── + " Exact search "gem sidekiq" + ~ Fuzzy search J~ Doe + | Or display | banner + + And display +banner + - Exclude display -banner + * Partial bug error 50* + \ Escape \*md + # Issue ID #23456 + ! 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 a help text + +See Also +-------- + +linkman:pkgctl-auth[1] + +include::include/footer.asciidoc[] -- cgit v1.2.3-54-g00ecf From d0dc0e1a32d6ed9b166eca777f7fb7071c4c2df1 Mon Sep 17 00:00:00 2001 From: Levente Polyak Date: Fri, 5 Jan 2024 19:23:52 +0100 Subject: 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 --- README.md | 5 +- contrib/completion/bash/devtools.in | 11 ++++- contrib/completion/zsh/_devtools.in | 6 ++- doc/man/pkgctl-search.1.asciidoc | 23 +++++++-- src/lib/common.sh | 4 +- src/lib/search.sh | 93 +++++++++++++++++++++++++++++++++---- src/lib/valid-search.sh | 11 +++++ 7 files changed, 134 insertions(+), 19 deletions(-) create mode 100644 src/lib/valid-search.sh (limited to 'doc/man/pkgctl-search.1.asciidoc') diff --git a/README.md b/README.md index 6c36a37..ca761db 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/contrib/completion/bash/devtools.in b/contrib/completion/bash/devtools.in index 155bb7e..4c7b73a 100644 --- a/contrib/completion/bash/devtools.in +++ b/contrib/completion/bash/devtools.in @@ -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 diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in index 120b47a..448fbed 100644 --- a/contrib/completion/zsh/_devtools.in +++ b/contrib/completion/zsh/_devtools.in @@ -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' ) diff --git a/doc/man/pkgctl-search.1.asciidoc b/doc/man/pkgctl-search.1.asciidoc index fb79b88..8172b00 100644 --- a/doc/man/pkgctl-search.1.asciidoc +++ b/doc/man/pkgctl-search.1.asciidoc @@ -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 -------- diff --git a/src/lib/common.sh b/src/lib/common.sh index 29b0343..17b91bc 100644 --- a/src/lib/common.sh +++ b/src/lib/common.sh @@ -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() { diff --git a/src/lib/search.sh b/src/lib/search.sh index cf64db3..862af25 100644 --- a/src/lib/search.sh +++ b/src/lib/search.sh @@ -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,12 +104,26 @@ pkgctl_search() { pkgctl_search_usage exit 0 ;; + --no-default-filter) + use_default_filter=0 + shift + ;; --json) - formatter=json + pkgctl_search_check_option_group_format "$1" "${output_format}" + output_format=json shift ;; - --no-default-filter) - use_default_filter=0 + -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 ;; --) @@ -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)" \ diff --git a/src/lib/valid-search.sh b/src/lib/valid-search.sh new file mode 100644 index 0000000..43799a5 --- /dev/null +++ b/src/lib/valid-search.sh @@ -0,0 +1,11 @@ +#!/hint/bash +# +# SPDX-License-Identifier: GPL-3.0-or-later +: + +# shellcheck disable=2034 +valid_search_output_format=( + pretty + plain + json +) -- cgit v1.2.3-54-g00ecf