optimise mdcat and fix trruncated files rendering
This commit is contained in:
@@ -353,7 +353,7 @@ mdcat()
|
|||||||
local _mdcat_print_hr
|
local _mdcat_print_hr
|
||||||
_mdcat_print_hr()
|
_mdcat_print_hr()
|
||||||
{
|
{
|
||||||
local cols="${COLUMNS:-}"
|
local cols="${_mdcat_cols:-}"
|
||||||
if [[ -z "$cols" || ! "$cols" =~ ^[0-9]+$ || "$cols" -lt 20 ]]; then
|
if [[ -z "$cols" || ! "$cols" =~ ^[0-9]+$ || "$cols" -lt 20 ]]; then
|
||||||
cols=$(tput cols 2>/dev/null)
|
cols=$(tput cols 2>/dev/null)
|
||||||
fi
|
fi
|
||||||
@@ -376,7 +376,7 @@ mdcat()
|
|||||||
shift
|
shift
|
||||||
local -a lines=("$@")
|
local -a lines=("$@")
|
||||||
|
|
||||||
local cols="${COLUMNS:-}"
|
local cols="${_mdcat_cols:-}"
|
||||||
if [[ -z "$cols" || ! "$cols" =~ ^[0-9]+$ || "$cols" -lt 20 ]]; then
|
if [[ -z "$cols" || ! "$cols" =~ ^[0-9]+$ || "$cols" -lt 20 ]]; then
|
||||||
cols=$(tput cols 2>/dev/null)
|
cols=$(tput cols 2>/dev/null)
|
||||||
fi
|
fi
|
||||||
@@ -472,11 +472,14 @@ mdcat()
|
|||||||
local -a lines=("$@")
|
local -a lines=("$@")
|
||||||
local -a table_rows=()
|
local -a table_rows=()
|
||||||
local -a col_widths=()
|
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'
|
local sep=$'\x1f'
|
||||||
|
|
||||||
# Parse header and data rows, skipping the Markdown separator row.
|
# 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
|
for ((i=0; i<${#lines[@]}; ++i)); do
|
||||||
(( i == 1 )) && continue
|
(( i == 1 )) && continue
|
||||||
local parsed
|
local parsed
|
||||||
@@ -487,13 +490,15 @@ mdcat()
|
|||||||
IFS="$sep" read -r -a row <<< "$parsed"
|
IFS="$sep" read -r -a row <<< "$parsed"
|
||||||
(( ncols < ${#row[@]} )) && ncols=${#row[@]}
|
(( ncols < ${#row[@]} )) && ncols=${#row[@]}
|
||||||
for ((j=0; j<${#row[@]}; ++j)); do
|
for ((j=0; j<${#row[@]}; ++j)); do
|
||||||
local vis
|
local styled visible key="$orow:$j"
|
||||||
vis=$(_mdcat_style_inline "${row[j]}")
|
styled=$(_mdcat_style_inline "${row[j]}")
|
||||||
vis=$(printf '%b' "$vis" | sed -E 's/\x1B\[[0-9;]*[mK]//g')
|
visible=$(printf '%b' "$styled" | sed -E 's/\x1B\[[0-9;]*[mK]//g')
|
||||||
local cell_len=${#vis}
|
cell_styled["$key"]="$styled"
|
||||||
|
cell_vislen["$key"]=${#visible}
|
||||||
[[ -z "${col_widths[j]}" ]] && col_widths[j]=0
|
[[ -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
|
done
|
||||||
|
orow=$((orow + 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
# Ensure all width slots are initialized before drawing borders.
|
# Ensure all width slots are initialized before drawing borders.
|
||||||
@@ -509,17 +514,12 @@ mdcat()
|
|||||||
done
|
done
|
||||||
printf "%b\n" "$IBlack$border$RESETCOL"
|
printf "%b\n" "$IBlack$border$RESETCOL"
|
||||||
|
|
||||||
# Print header row
|
# Print header row (cached styled cells)
|
||||||
local -a header=()
|
|
||||||
IFS="$sep" read -r -a header <<< "${table_rows[0]}"
|
|
||||||
printf "%b|" "$IBlack"
|
printf "%b|" "$IBlack"
|
||||||
for ((j=0; j<ncols; ++j)); do
|
for ((j=0; j<ncols; ++j)); do
|
||||||
local raw_cell="${header[j]:-}"
|
local hkey="0:$j"
|
||||||
local styled_cell
|
local styled_cell="${cell_styled[$hkey]:-}"
|
||||||
styled_cell=$(_mdcat_style_inline "$raw_cell")
|
local pad=$((col_widths[j] - ${cell_vislen[$hkey]:-0}))
|
||||||
local visible
|
|
||||||
visible=$(printf '%b' "$styled_cell" | sed -E 's/\x1B\[[0-9;]*[mK]//g')
|
|
||||||
local pad=$((col_widths[j] - ${#visible}))
|
|
||||||
(( pad < 0 )) && pad=0
|
(( pad < 0 )) && pad=0
|
||||||
printf " %b%b%*s%b |" "$BBlue" "$styled_cell" "$pad" "" "$IBlack"
|
printf " %b%b%*s%b |" "$BBlue" "$styled_cell" "$pad" "" "$IBlack"
|
||||||
done
|
done
|
||||||
@@ -532,18 +532,13 @@ mdcat()
|
|||||||
done
|
done
|
||||||
printf "%b\n" "$RESETCOL"
|
printf "%b\n" "$RESETCOL"
|
||||||
|
|
||||||
# Print data rows
|
# Print data rows (cached styled cells)
|
||||||
for ((i=1; i<${#table_rows[@]}; ++i)); do
|
for ((i=1; i<${#table_rows[@]}; ++i)); do
|
||||||
local -a row=()
|
|
||||||
IFS="$sep" read -r -a row <<< "${table_rows[i]}"
|
|
||||||
printf "%b|" "$IBlack"
|
printf "%b|" "$IBlack"
|
||||||
for ((j=0; j<ncols; ++j)); do
|
for ((j=0; j<ncols; ++j)); do
|
||||||
local raw_cell="${row[j]:-}"
|
local key="$i:$j"
|
||||||
local styled_cell
|
local styled_cell="${cell_styled[$key]:-}"
|
||||||
styled_cell=$(_mdcat_style_inline "$raw_cell")
|
local pad=$((col_widths[j] - ${cell_vislen[$key]:-0}))
|
||||||
local visible
|
|
||||||
visible=$(printf '%b' "$styled_cell" | sed -E 's/\x1B\[[0-9;]*[mK]//g')
|
|
||||||
local pad=$((col_widths[j] - ${#visible}))
|
|
||||||
(( pad < 0 )) && pad=0
|
(( pad < 0 )) && pad=0
|
||||||
printf " %b%b%*s%b |" "$RESETCOL" "$styled_cell" "$pad" "" "$IBlack"
|
printf " %b%b%*s%b |" "$RESETCOL" "$styled_cell" "$pad" "" "$IBlack"
|
||||||
done
|
done
|
||||||
@@ -607,19 +602,42 @@ mdcat()
|
|||||||
local -a code_lines=()
|
local -a code_lines=()
|
||||||
local in_table=0
|
local in_table=0
|
||||||
local -a table_lines=()
|
local -a table_lines=()
|
||||||
while IFS= read -r raw || [[ -n "$raw" ]]; do
|
|
||||||
|
# Resolve the terminal width once for the whole render instead of shelling
|
||||||
|
# out to tput for every printed line.
|
||||||
|
local _mdcat_cols="${COLUMNS:-}"
|
||||||
|
if [[ -z "$_mdcat_cols" || ! "$_mdcat_cols" =~ ^[0-9]+$ || "$_mdcat_cols" -lt 20 ]]; then
|
||||||
|
_mdcat_cols=$(tput cols 2>/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'}"
|
line="${raw%$'\r'}"
|
||||||
|
|
||||||
# Table detection: line with |, next line with | and ---
|
# Table detection: line with |, next line with | and ---
|
||||||
if [[ $in_table -eq 0 && "$line" =~ ^[[:space:]]*\|.*\|[[:space:]]*$ ]]; then
|
if [[ $in_table -eq 0 && "$line" =~ ^[[:space:]]*\|.*\|[[:space:]]*$ ]]; then
|
||||||
local next
|
local next="" next_ok=1
|
||||||
IFS= read -r next || true
|
IFS= read -r next || next_ok=0
|
||||||
# Accept: | --- | --- | or |:---|---:| etc.
|
# Accept: | --- | --- | or |:---|---:| etc.
|
||||||
if [[ "$next" =~ ^[[:space:]]*\|[[:space:]]*:?[-]+:?([[:space:]]*\|[[:space:]]*:?[ -]+:?)*\|[[:space:]]*$ ]]; then
|
if [[ "$next" =~ ^[[:space:]]*\|[[:space:]]*:?[-]+:?([[:space:]]*\|[[:space:]]*:?[ -]+:?)*\|[[:space:]]*$ ]]; then
|
||||||
in_table=1
|
in_table=1
|
||||||
table_lines=("$line" "$next")
|
table_lines=("$line" "$next")
|
||||||
continue
|
continue
|
||||||
fi
|
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
|
fi
|
||||||
if [[ $in_table -eq 1 ]]; then
|
if [[ $in_table -eq 1 ]]; then
|
||||||
# Accept table row if it starts and ends with |
|
# Accept table row if it starts and ends with |
|
||||||
@@ -709,9 +727,13 @@ mdcat()
|
|||||||
printf "%b\n" "$(_mdcat_style_inline "$line")"
|
printf "%b\n" "$(_mdcat_style_inline "$line")"
|
||||||
done < "${input_file:-/dev/stdin}"
|
done < "${input_file:-/dev/stdin}"
|
||||||
|
|
||||||
|
# Flush any block still open at end-of-input.
|
||||||
if [[ $in_code -eq 1 ]]; then
|
if [[ $in_code -eq 1 ]]; then
|
||||||
_mdcat_print_code_block "$code_lang" "${code_lines[@]}"
|
_mdcat_print_code_block "$code_lang" "${code_lines[@]}"
|
||||||
fi
|
fi
|
||||||
|
if [[ $in_table -eq 1 ]]; then
|
||||||
|
_mdcat_print_table "${table_lines[@]}"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
export -f mdcat
|
export -f mdcat
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user