n-list-draw 4.3 KB

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