1# Copy this file into /usr/share/zsh/site-functions/ 2# and add 'autoload n-list-draw` to .zshrc 3# 4# This is an internal function not for direct use 5 6emulate -L zsh 7 8zmodload zsh/curses 9 10setopt typesetsilent extendedglob 11 12_nlist_print_with_ansi() { 13 local win="$1" text="$2" out col chunk Xout 14 integer text_offset="$3" max_text_len="$4" text_len=0 no_match=0 nochunk_text_len to_skip_from_chunk to_chop_off_from_chunk before_len 15 16 # 1 - non-escaped text, 2 - first number in the escaped text, with ; 17 # 3 - second number, 4 - text after whole escape text 18 19 typeset -a c 20 c=( black red green yellow blue magenta cyan white ) 21 22 while [[ -n "$text" && "$no_match" -eq 0 ]]; do 23 if [[ "$text" = (#b)([^$'\x1b']#)$'\x1b'\[([0-9](#c0,2))(#B)(\;|)(#b)([0-9](#c0,2))m(*) ]]; then 24 # Text for further processing 25 text="$match[4]" 26 # Text chunk to output now 27 out="$match[1]" 28 # Save color 29 col="$match[2]" 30 (( match[3] >= 30 && match[3] <= 37 )) && col="$match[3]" 31 else 32 out="$text" 33 no_match=1 34 fi 35 36 if [ -n "$out" ]; then 37################ Expand tabs ################ 38 chunk="$out" 39 before_len="$text_len" 40 Xout="" 41 42 while [ -n "$chunk" ]; do 43 [[ "$chunk" = (#b)([^$'\t']#)$'\t'(*) ]] && { 44 (( all_text_len=((before_len+${#match[1]})/8+1)*8 )) 45 46 Xout+="${(r:all_text_len-before_len:: :)match[1]}" 47 48 before_len+=all_text_len-before_len 49 chunk="$match[2]" 50 } || { 51 Xout+="$chunk" 52 break 53 } 54 done 55############################################# 56 57 # Input text length without the current chunk 58 nochunk_text_len=text_len 59 # Input text length up to current chunk 60 text_len+="$#Xout" 61 62 # Should start displaying with this chunk? 63 # I.e. stop skipping left part of the input text? 64 if (( text_len > text_offset )); then 65 to_skip_from_chunk=text_offset-nochunk_text_len 66 67 # LEFT - is chunk off the left skip boundary? +1 for 1-based index in string 68 (( to_skip_from_chunk > 0 )) && Xout="${Xout[to_skip_from_chunk+1,-1]}" 69 70 # RIGHT - is text off the screen? 71 if (( text_len-text_offset > max_text_len )); then 72 to_chop_off_from_chunk=0+(text_len-text_offset)-max_text_len 73 Xout="${Xout[1,-to_chop_off_from_chunk-1]}" 74 fi 75 76 [ -n "$Xout" ] && zcurses string "$win" "$Xout" 77 fi 78 fi 79 80 if (( no_match == 0 )); then 81 if (( col >= 30 && col <= 37 )); then 82 zcurses attr "$win" $c[col-29]/"$background" 83 elif [[ "$col" -eq 0 ]]; then 84 zcurses attr "$win" "$colorpair" 85 fi 86 fi 87 done 88} 89 90integer highlight="$1" 91integer page_height="$2" 92integer page_width="$3" 93local y_offset="$4" 94local x_offset="$5" 95local text_offset="$6" 96local win="$7" 97shift 7 98integer max_text_len=page_width-x_offset 99 100[[ "$bold" = "0" || "$bold" = "-bold" ]] && bold="-bold" || bold="+bold" 101[[ "$active_text" = "underline" || "$active_text" = "reverse" ]] || local active_text="reverse" 102# Linux has ncv 18, screen* has ncv 3 - underline won't work properly 103(( ${terminfo[ncv]:-0} & 2 )) && active_text="reverse" 104# FreeBSD uses TERM=xterm for newcons but doesn't actually support underline 105[[ "$TERM" = "xterm" && -z "$DISPLAY" ]] && active_text="reverse" 106 107integer max_idx=page_height 108integer end_idx=max_idx 109[ "$end_idx" -gt "$#" ] && end_idx="$#" 110integer y=y_offset 111 112zcurses attr "$win" "$bold" "$colorpair" 113 114integer i text_len 115local text 116for (( i=1; i<=end_idx; i++ )); do 117 zcurses move "$win" $y "$x_offset" 118 119 [ "$i" = "$highlight" ] && zcurses attr "$win" +"$active_text" 120 _nlist_print_with_ansi "$win" "$@[i]" "$text_offset" "$max_text_len" 121 zcurses clear "$win" eol 122 [ "$i" = "$highlight" ] && zcurses attr "$win" -"$active_text" 123 124 y+=1 125done 126 127if [ "$end_idx" -lt "$max_idx" ]; then 128 zcurses move "$win" $y "$x_offset" 129 zcurses clear "$win" eol 130fi 131 132zcurses attr "$win" white/black 133# vim: set filetype=zsh: 134