From c96011d6b2f4527bd842afe67ca5808e209a6ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Chastanet?= Date: Mon, 15 Jan 2024 02:26:55 +0100 Subject: [PATCH] improved help message --- bin/doc | 13 ++ bin/postmanCli | 210 ++++++++----------- src/_binaries/Postman/command.postmanCli.tpl | 22 +- 3 files changed, 109 insertions(+), 136 deletions(-) diff --git a/bin/doc b/bin/doc index 17f60051..a7bf684b 100755 --- a/bin/doc +++ b/bin/doc @@ -976,6 +976,19 @@ UI::requireTheme() { UI::theme "${BASH_FRAMEWORK_THEME-default}" } +# @description remove ansi codes from input or files given as argument +# @arg $@ files:String[] the files to filter +# @exitcode * if one of the filter command fails +# @stdin you can use stdin as alternative to files argument +# @stdout the filtered content +# @see https://en.wikipedia.org/wiki/ANSI_escape_code +# shellcheck disable=SC2120 +Filters::removeAnsiCodes() { + # cspell:disable + sed -E 's/\x1b\[[0-9;]*[mGKHF]//g' "$@" + # cspell:enable +} + # @description Display message using skip color (yellow) # @arg $1 message:String the message to display Log::displaySkipped() { diff --git a/bin/postmanCli b/bin/postmanCli index 09f6440d..65abd4b7 100755 --- a/bin/postmanCli +++ b/bin/postmanCli @@ -101,10 +101,12 @@ trap cleanOnExit EXIT HUP QUIT ABRT TERM # @description concat each element of an array with a separator # but wrapping text when line length is more than provided argument # The algorithm will try not to cut the array element if it can. -# if an arg can be placed on current line it will be, +# - if an arg can be placed on current line it will be, # otherwise current line is printed and arg is added to the new # current line -# empty arg is interpreted as a new line. +# - Empty arg is interpreted as a new line. +# - Add \r to arg in order to force break line and avoid following +# arg to be concatenated with current arg. # # @arg $1 glue:String # @arg $2 maxLineLength:int @@ -126,117 +128,102 @@ Array::wrap2() { return 0 fi - eatNextSpaces() { - if [[ "${currentChar}" != [[:space:]] ]]; then - ((i--)) || true - return 0 - fi - for (( ; i < textLength; i++)); do - if [[ "${text:${i}:1}" != [[:space:]] ]]; then - ((i--)) || true - break - fi - done - } printCurrentLine() { - echo -e "${currentLine}" | sed -E -e 's/[[:blank:]]*$//' + if ((isNewline == 0)) || ((previousLineEmpty == 1)); then + echo + fi ((isNewline = 1)) - currentLine="${indentStr}" + echo -en "${indentStr}" ((currentLineLength = indentNextLine)) || true } - nextLine() { - printCurrentLine - eatNextSpaces - } - local currentLine currentChar ansiCode - local -i isAnsiCode currentLineLength=0 isNewline=1 textLength=0 - local text="" - local arg="" - while (($# > 0)); do - arg="$1" - shift || true - if ((${#arg} == 0)) || [[ "${arg}" = $'\n' ]]; then - if ((isNewline == 0)); then - # isNewline = 0 means currentLine is not empty - printCurrentLine - fi - echo - continue - fi - local textFirstLine="${arg%%$'\n'*}" - text="$(echo "${arg}" | sed -E '1d')" - ((textLength = ${#text})) || true - local textFirstLineNoAnsi - textFirstLineNoAnsi="$(echo "${textFirstLine}" | Filters::removeAnsiCodes)" - local -i textFirstLineNoAnsiLength=0 - ((textFirstLineNoAnsiLength = ${#textFirstLineNoAnsi})) || true - - if ((isNewline == 0)); then - glueLength="${#glue}" + appendToCurrentLine() { + local text="$1" + local -i length=$2 + ((currentLineLength += length)) || true + ((isNewline = 0)) || true + if [[ "${text: -1}" = $'\r' ]]; then + text="${text:0:-1}" + echo -en "${text%%+([[:blank:]])}" + printCurrentLine else - glueLength="0" + echo -en "${text%%+([[:blank:]])}" fi - if ((currentLineLength + textFirstLineNoAnsiLength + glueLength > maxLineLength)); then - if ((isNewline == 0)); then - # isNewline = 0 means currentLine is not empty + } + + ( + local currentLine + local -i currentLineLength=0 isNewline=1 argLength=0 + local -a additionalLines + local -i previousLineEmpty=0 + local arg="" + + while (($# > 0)); do + arg="$1" + shift || true + + # replace tab by 2 spaces + arg="${arg//$'\t'/ }" + # remove trailing spaces + arg="${arg%[[:blank:]]}" + if [[ "${arg}" = $'\n' || -z "${arg}" ]]; then printCurrentLine + ((previousLineEmpty = 1)) + continue + else + if ((previousLineEmpty == 1)); then + printCurrentLine + fi + ((previousLineEmpty = 0)) || true fi - # restore current arg without considering first line - text="${arg}" - ((textLength = ${#text})) || true - else - if ((isNewline == 0)); then - # isNewline = 0 means currentLine is not empty - currentLine+="${glue}" - ((currentLineLength += glueLength)) || true + # convert eol to args + mapfile -t additionalLines <<<"${arg}" + if ((${#additionalLines[@]} > 1)); then + set -- "${additionalLines[@]}" "$@" + continue fi - currentLine+="${textFirstLine}" - isNewline="0" - ((currentLineLength += ${#textFirstLine})) || true - fi - for ((i = 0; i < textLength; i++)); do - currentChar="${text:${i}:1}" - - if [[ "${currentChar}" = $'\r' ]]; then - # ignore - true - elif [[ "${currentChar}" = "\x1b" ]]; then - isAnsiCode=1 - ansiCode+="${currentChar}" - elif ((isAnsiCode == 1)); then - ansiCode+="${currentChar}" - if [[ "${currentChar}" =~ [mGKHF] ]]; then - isAnsiCode=0 - echo -e "${ansiCode}" - elif [[ "${currentChar}" = $'\n' ]]; then - # invalid ansi code, ignore it - isAnsiCode=0 - ansiCode="" + ((argLength = ${#arg})) || true + + # empty arg + if ((argLength == 0)); then + if ((isNewline == 0)); then + # isNewline = 0 means currentLine is not empty + printCurrentLine fi + continue + fi + + if ((isNewline == 0)); then + glueLength="${#glue}" else - # non ansi code - if [[ "${currentChar}" = $'\n' ]] || ((currentLineLength == maxLineLength)); then - nextLine - elif [[ "${currentChar}" = "\t" ]]; then - if ((currentLineLength + 2 <= maxLineLength)); then - currentLine+=" " - ((isNewline = 0)) || true - ((currentLineLength = currentLineLength + 2)) - else - nextLine - fi + glueLength="0" + fi + if ((currentLineLength + argLength + glueLength > maxLineLength)); then + if ((argLength + glueLength > maxLineLength)); then + # arg is too long to even fit on one line + # we have to split the arg on current and next line + local -i remainingLineLength + ((remainingLineLength = maxLineLength - currentLineLength - glueLength)) + appendToCurrentLine "${glue:0:${glueLength}}${arg:0:${remainingLineLength}}" "$((glueLength + remainingLineLength))" + printCurrentLine + arg="${arg:${remainingLineLength}}" + # remove leading spaces + arg="${arg##[[:blank:]]}" + + set -- "${arg}" "$@" else - currentLine+="${currentChar}" - ((isNewline = 0)) || true - ((++currentLineLength)) + # the arg can fit on next line + printCurrentLine + appendToCurrentLine "${arg}" "${argLength}" fi + else + appendToCurrentLine "${glue:0:${glueLength}}${arg}" "$((glueLength + argLength))" fi done - done - if [[ "${currentLine}" != "" ]] && [[ ! "${currentLine}" =~ ^[\ \t]+$ ]]; then - printCurrentLine - fi + if [[ "${currentLine}" != "" ]] && [[ ! "${currentLine}" =~ ^[\ \t]+$ ]]; then + printCurrentLine + fi + ) | sed -E -e 's/[[:blank:]]+$//' } # @description ensure env files are loaded @@ -798,19 +785,6 @@ Env::pathPrepend() { done } -# @description remove ansi codes from input or files given as argument -# @arg $@ files:String[] the files to filter -# @exitcode * if one of the filter command fails -# @stdin you can use stdin as alternative to files argument -# @stdout the filtered content -# @see https://en.wikipedia.org/wiki/ANSI_escape_code -# shellcheck disable=SC2120 -Filters::removeAnsiCodes() { - # cspell:disable - sed -E 's/\x1b\[[0-9;]*[mGKHF]//g' "$@" - # cspell:enable -} - # @description log message to file # @arg $1 message:String the message to display Log::logDebug() { @@ -1622,14 +1596,6 @@ commandOptionParseFinished() { displayConfig fi } -NBSP="\xc2\xa0" -NBSP2="${NBSP}${NBSP}" -argCommandHelp() { - echo -e "${__HELP_OPTION_COLOR}pull${__HELP_NORMAL}" - echo -e "${NBSP2}Pull collections from Postman back to repositories.\r" - echo -e "${__HELP_OPTION_COLOR}push${__HELP_NORMAL}" - echo -e "${NBSP2}Push repositories collections to Postman." -} postmanCliCommand() { local options_parse_cmd="$1" @@ -1963,20 +1929,20 @@ postmanCliCommand() { echo -e "${__HELP_TITLE_COLOR}ARGUMENTS:${__RESET_COLOR}" echo -e " [${__HELP_OPTION_COLOR}command${__HELP_NORMAL} {single}]" local -a helpArray - # shellcheck disable=SC2054,SC2206 - mapfile -t helpArray < <(argCommandHelp) + # shellcheck disable=SC2054 + helpArray=($'\e[1;34mpull\r\n Pull collections from Postman back to repositories.\r\n\e[1;34mpush\r\n Push repositories collections to Postman.') echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" echo -e " [${__HELP_OPTION_COLOR}commandArgs${__HELP_NORMAL} {list} (optional)]" local -a helpArray # shellcheck disable=SC2054 - helpArray=($'list of postman collection\'s references to pull or push\n\n or no argument to pull or push all the collections') + helpArray=($'list of postman collection\'s references to pull or push\r\nor no argument to pull or push all the collections') echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" echo echo -e "${__HELP_TITLE_COLOR}PUSH/PULL OPTIONS:${__RESET_COLOR}" echo -e " ${__HELP_OPTION_COLOR}--postman-model${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-m ${__HELP_NORMAL} {single}" local -a helpArray # shellcheck disable=SC2054 - helpArray=($'postmanCli model file to use\n\n Default value: /postmanCli.collections.json') + helpArray=($'postmanCli model file to use\r\nDefault value: /postmanCli.collections.json') echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" echo echo -e "${__HELP_TITLE_COLOR}GLOBAL OPTIONS:${__RESET_COLOR}" diff --git a/src/_binaries/Postman/command.postmanCli.tpl b/src/_binaries/Postman/command.postmanCli.tpl index eb87dccf..fcc11883 100644 --- a/src/_binaries/Postman/command.postmanCli.tpl +++ b/src/_binaries/Postman/command.postmanCli.tpl @@ -6,14 +6,6 @@ declare help="Push/Pull postman collections of all the configured repositories" % .INCLUDE "$(dynamicTemplateDir _binaries/options/options.base.tpl)" -NBSP="\xc2\xa0" -NBSP2="${NBSP}${NBSP}" -argCommandHelp() { - echo -e "${__HELP_OPTION_COLOR}pull${__HELP_NORMAL}" - echo -e "${NBSP2}Pull collections from Postman back to repositories." $'\r' - echo -e "${__HELP_OPTION_COLOR}push${__HELP_NORMAL}" - echo -e "${NBSP2}Push repositories collections to Postman." -} % @@ -26,22 +18,24 @@ source <( # shellcheck disable=SC2016 Options::generateOption \ --variable-type String \ - --help $'postmanCli model file to use\n - Default value: /postmanCli.collections.json' \ + --help $'postmanCli model file to use\r +Default value: /postmanCli.collections.json' \ --group groupPushPullFunction \ --alt "--postman-model" \ --alt "-m" \ --variable-name "optionPostmanModelConfig" \ --function-name optionPostmanModelConfigFunction - argCommandHelp() { :; } Options::generateArg \ --variable-name "argCommand" \ --min 0 \ --max 1 \ --name "command" \ --authorized-values 'pull|push' \ - --help argCommandHelp \ + --help $'${__HELP_OPTION_COLOR}pull${__HELP_NORMAL}\r + Pull collections from Postman back to repositories.\r +${__HELP_OPTION_COLOR}push${__HELP_NORMAL}\r + Push repositories collections to Postman.' \ --function-name argCommandFunction Options::generateArg \ @@ -50,8 +44,8 @@ source <( --max -1 \ --name "commandArgs" \ --help \ - $'list of postman collection\'s references to pull or push\n - or no argument to pull or push all the collections' \ + $'list of postman collection\'s references to pull or push\r +or no argument to pull or push all the collections' \ --function-name commandArgsFunction )