From e3281996188d449c5dddaaf044c0426b5c3707f9 Mon Sep 17 00:00:00 2001 From: fatalerrors Date: Thu, 9 Jul 2026 14:56:30 +0200 Subject: [PATCH] fixed disp with escape sequence --- profile.d/disp.sh | 78 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 20 deletions(-) diff --git a/profile.d/disp.sh b/profile.d/disp.sh index 513879e..0297371 100644 --- a/profile.d/disp.sh +++ b/profile.d/disp.sh @@ -44,7 +44,7 @@ set_colors() export DEFAULTFG='\e[0;39m' export DEFAULTBG='\e[0;49m' export DEFAULTCOL="${DEFAULTBG}${DEFAULTFG}" - export RESETCOL=$'\e[0m' + export RESETCOL='\e[0m' # Regular Colors export Black='\e[0;30m' @@ -134,9 +134,8 @@ disp() _disp_print_wrapped() { local prefix="$1" - local prefix_len="$2" - local target_fd="$3" - shift 3 + local target_fd="$2" + shift 2 local message="$*" local cols="${COLUMNS:-}" @@ -145,14 +144,57 @@ disp() fi [[ -z "$cols" || ! "$cols" =~ ^[0-9]+$ || "$cols" -lt 20 ]] && cols=80 + # Match ANSI CSI sequences in real-ESC, literal \e and literal \033 forms + # so their on-screen width (zero) is excluded from all width calculations. + local ansi_re=$'\e\\[[0-9;]*[A-Za-z]' + ansi_re+='|\\e\[[0-9;]*[A-Za-z]' + ansi_re+='|\\033\[[0-9;]*[A-Za-z]' + + # The hanging-indent width is the prefix's VISIBLE length (ANSI stripped), + # so callers no longer need to pass a separate plain-text length. + local _pv=$prefix + while [[ $_pv =~ $ansi_re ]]; do _pv=${_pv/"${BASH_REMATCH[0]}"/}; done local indent_len=0 - [[ "$prefix_len" =~ ^[0-9]+$ && "$prefix_len" -gt 0 ]] && indent_len=$((prefix_len + 1)) + (( ${#_pv} > 0 )) && indent_len=$(( ${#_pv} + 1 )) local width=$((cols - indent_len)) (( width < 10 )) && width=10 - local wrapped - wrapped=$(printf "%s" "$message" | fold -s -w "$width") + # ANSI-aware soft wrap (fold -s semantics): break at the last space that + # keeps a line within `width` VISIBLE columns, hard-breaking only when a + # run has no space. ANSI escapes are copied through at zero width so they + # no longer inflate the measured width and cause premature wrapping. + local wrapped="" line="" line_vis=0 last_space=-1 + local _i=0 _n=${#message} + while (( _i < _n )); do + local _sub=${message:_i} + if [[ $_sub =~ ^($ansi_re) ]]; then + line+=${BASH_REMATCH[0]} + _i=$(( _i + ${#BASH_REMATCH[0]} )) + continue + fi + local _c=${message:_i:1} + _i=$(( _i + 1 )) + line+=$_c + (( line_vis++ )) + [[ $_c == ' ' ]] && last_space=${#line} + if (( line_vis > width )); then + if (( last_space > 0 )); then + wrapped+=${line:0:last_space-1}$'\n' + line=${line:last_space} + local _st=$line + while [[ $_st =~ $ansi_re ]]; do _st=${_st/"${BASH_REMATCH[0]}"/}; done + line_vis=${#_st} + else + local _keep=${line: -1} + wrapped+=${line:0:${#line}-1}$'\n' + line=$_keep + line_vis=1 + fi + last_space=-1 + fi + done + wrapped+=$line local first_line=1 local line @@ -188,50 +230,46 @@ disp() case ${1^^} in "I") - local heads_plain="[ info ]" if [[ $color_enabled -eq 1 ]]; then local heads="[ ${IGreen}info${DEFAULTFG} ]" else - local heads="$heads_plain" + local heads="[ info ]" fi shift [[ -z $QUIET || $QUIET -ne 1 ]] && \ - _disp_print_wrapped "$heads" "${#heads_plain}" 1 "$*" + _disp_print_wrapped "$heads" 1 "$*" ;; "W") - local heads_plain="[ Warning ]" if [[ $color_enabled -eq 1 ]]; then local heads="[ ${IYellow}Warning${DEFAULTFG} ]" else - local heads="$heads_plain" + local heads="[ Warning ]" fi shift - _disp_print_wrapped "$heads" "${#heads_plain}" 2 "$*" + _disp_print_wrapped "$heads" 2 "$*" ;; "E") - local heads_plain="[ ERROR ]" if [[ $color_enabled -eq 1 ]]; then local heads="[ ${IRed}ERROR${DEFAULTFG} ]" else - local heads="$heads_plain" + local heads="[ ERROR ]" fi shift - _disp_print_wrapped "$heads" "${#heads_plain}" 2 "$*" + _disp_print_wrapped "$heads" 2 "$*" ;; "D") - local heads_plain="[ debug ]" if [[ $color_enabled -eq 1 ]]; then local heads="[ ${ICyan}debug${DEFAULTFG} ]" else - local heads="$heads_plain" + local heads="[ debug ]" fi shift [[ -n $DEBUG && $DEBUG -gt 1 ]] && \ - _disp_print_wrapped "$heads" "${#heads_plain}" 1 "$*" + _disp_print_wrapped "$heads" 1 "$*" ;; * ) [[ -z $QUIET || $QUIET -ne 1 ]] && \ - _disp_print_wrapped "" 0 1 "$*" + _disp_print_wrapped "" 1 "$*" ;; esac }