From e6607f07af28b26bd36bcd92f3373e27d7ada5fe Mon Sep 17 00:00:00 2001 From: fatalerrors Date: Thu, 9 Jul 2026 11:30:43 +0200 Subject: [PATCH] optimise mdcat and fix trruncated files rendering --- profile.d/disp.sh | 82 ++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/profile.d/disp.sh b/profile.d/disp.sh index 349c58f..513879e 100644 --- a/profile.d/disp.sh +++ b/profile.d/disp.sh @@ -353,7 +353,7 @@ mdcat() local _mdcat_print_hr _mdcat_print_hr() { - local cols="${COLUMNS:-}" + local cols="${_mdcat_cols:-}" if [[ -z "$cols" || ! "$cols" =~ ^[0-9]+$ || "$cols" -lt 20 ]]; then cols=$(tput cols 2>/dev/null) fi @@ -376,7 +376,7 @@ mdcat() shift local -a lines=("$@") - local cols="${COLUMNS:-}" + local cols="${_mdcat_cols:-}" if [[ -z "$cols" || ! "$cols" =~ ^[0-9]+$ || "$cols" -lt 20 ]]; then cols=$(tput cols 2>/dev/null) fi @@ -472,11 +472,14 @@ mdcat() local -a lines=("$@") local -a table_rows=() local -a col_widths=() - local i j ncols=0 + local -A cell_styled=() cell_vislen=() + local i j ncols=0 orow=0 local sep=$'\x1f' # Parse header and data rows, skipping the Markdown separator row. - # Width is computed from visible text length with ANSI escapes stripped. + # Each cell is styled exactly once here; the styled text and its visible + # width (ANSI stripped) are cached and reused when drawing, so the costly + # _mdcat_style_inline runs once per cell instead of twice. for ((i=0; i<${#lines[@]}; ++i)); do (( i == 1 )) && continue local parsed @@ -487,13 +490,15 @@ mdcat() IFS="$sep" read -r -a row <<< "$parsed" (( ncols < ${#row[@]} )) && ncols=${#row[@]} for ((j=0; j<${#row[@]}; ++j)); do - local vis - vis=$(_mdcat_style_inline "${row[j]}") - vis=$(printf '%b' "$vis" | sed -E 's/\x1B\[[0-9;]*[mK]//g') - local cell_len=${#vis} + local styled visible key="$orow:$j" + styled=$(_mdcat_style_inline "${row[j]}") + visible=$(printf '%b' "$styled" | sed -E 's/\x1B\[[0-9;]*[mK]//g') + cell_styled["$key"]="$styled" + cell_vislen["$key"]=${#visible} [[ -z "${col_widths[j]}" ]] && col_widths[j]=0 - (( col_widths[j] < cell_len )) && col_widths[j]=$cell_len + (( col_widths[j] < ${#visible} )) && col_widths[j]=${#visible} done + orow=$((orow + 1)) done # Ensure all width slots are initialized before drawing borders. @@ -509,17 +514,12 @@ mdcat() done printf "%b\n" "$IBlack$border$RESETCOL" - # Print header row - local -a header=() - IFS="$sep" read -r -a header <<< "${table_rows[0]}" + # Print header row (cached styled cells) printf "%b|" "$IBlack" for ((j=0; j/dev/null) + fi + [[ -z "$_mdcat_cols" || ! "$_mdcat_cols" =~ ^[0-9]+$ || "$_mdcat_cols" -lt 20 ]] && _mdcat_cols=80 + + # Single-line push-back buffer: table detection reads one line ahead, so a + # non-separator look-ahead line must be reprocessed rather than discarded. + local pending_line="" has_pending=0 + while :; do + if [[ $has_pending -eq 1 ]]; then + raw="$pending_line" + has_pending=0 + elif ! IFS= read -r raw; then + [[ -n "$raw" ]] || break + fi line="${raw%$'\r'}" # Table detection: line with |, next line with | and --- if [[ $in_table -eq 0 && "$line" =~ ^[[:space:]]*\|.*\|[[:space:]]*$ ]]; then - local next - IFS= read -r next || true + local next="" next_ok=1 + IFS= read -r next || next_ok=0 # Accept: | --- | --- | or |:---|---:| etc. if [[ "$next" =~ ^[[:space:]]*\|[[:space:]]*:?[-]+:?([[:space:]]*\|[[:space:]]*:?[ -]+:?)*\|[[:space:]]*$ ]]; then in_table=1 table_lines=("$line" "$next") continue fi + # Not a separator: push the look-ahead line back so it is not lost. + if [[ $next_ok -eq 1 || -n "$next" ]]; then + pending_line="$next" + has_pending=1 + fi fi if [[ $in_table -eq 1 ]]; then # Accept table row if it starts and ends with | @@ -709,9 +727,13 @@ mdcat() printf "%b\n" "$(_mdcat_style_inline "$line")" done < "${input_file:-/dev/stdin}" + # Flush any block still open at end-of-input. if [[ $in_code -eq 1 ]]; then _mdcat_print_code_block "$code_lang" "${code_lines[@]}" fi + if [[ $in_table -eq 1 ]]; then + _mdcat_print_table "${table_lines[@]}" + fi } export -f mdcat # ------------------------------------------------------------------------------