n-preview 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. # Copy this file into /usr/share/zsh/site-functions/
  2. # and add 'autoload n-preview` to .zshrc
  3. #
  4. # This is partially a test if n-list-draw and n-list-input can be
  5. # used multiple times to create multiple lists. It might become
  6. # more usable if someone adds more features like previewing of
  7. # archive contents.
  8. emulate -L zsh
  9. zmodload zsh/curses
  10. setopt typesetsilent extendedglob
  11. trap "return" TERM INT QUIT
  12. trap "_vpreview_exit" EXIT
  13. local IFS="
  14. "
  15. [ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
  16. [[ "$colorpair" = "" ]] && colorpair="white/black"
  17. local background="${colorpair#*/}"
  18. # Drawing and input
  19. autoload n-list-draw n-list-input
  20. # Cleanup before any exit
  21. _vpreview_exit() {
  22. zcurses 2>/dev/null delwin files
  23. zcurses 2>/dev/null delwin body
  24. zcurses 2>/dev/null delwin status
  25. zcurses 2>/dev/null refresh
  26. zcurses end
  27. }
  28. # Outputs a message in the bottom of the screen
  29. _vpreview_status_msg() {
  30. zcurses move status 1 2
  31. zcurses clear status eol
  32. zcurses string status "$1"
  33. }
  34. # Prefer tput, then module terminfo
  35. _nlist_cursor_visibility() {
  36. if type tput 2>/dev/null 1>&2; then
  37. [ "$1" = "1" ] && tput cvvis
  38. [ "$1" = "0" ] && tput civis
  39. elif [ "$has_termcap" = "1" ]; then
  40. [ "$1" = "1" ] && [ -n $terminfo[cvvis] ] && echo -n $terminfo[cvvis]
  41. [ "$1" = "0" ] && [ -n $terminfo[civis] ] && echo -n $terminfo[civis]
  42. fi
  43. }
  44. #
  45. # Main code
  46. #
  47. integer term_height="$LINES"
  48. integer term_width="$COLUMNS"
  49. if [[ "$term_height" -lt 1 || "$term_width" -lt 1 ]]; then
  50. local stty_out=$( stty size )
  51. term_height="${stty_out% *}"
  52. term_width="${stty_out#* }"
  53. fi
  54. integer status_height=3
  55. integer status_width=term_width
  56. integer status_page_height=1
  57. integer status_page_width=term_width-2
  58. integer files_height=term_height-status_height
  59. integer files_width=term_width/5
  60. integer files_page_height=files_height-2
  61. integer files_page_width=files_width-2
  62. integer body_height=term_height-status_height
  63. integer body_width=term_width-files_width
  64. integer body_page_height=body_height-2
  65. integer body_page_width=body_width
  66. integer _from_what_idx_list_is_shown_1=1
  67. integer current_1=1
  68. integer _from_what_idx_list_is_shown_2=1
  69. integer current_2=1
  70. integer hscroll_2=0
  71. integer active_window=0
  72. local ansi_mode="ansi"
  73. [ -f ~/.config/znt/n-preview.conf ] && . ~/.config/znt/n-preview.conf
  74. typeset -a hcmd
  75. #if type pygmentize 2>/dev/null 1>&2; then
  76. # hcmd=( pygmentize -g )
  77. if type highlight 2>/dev/null 1>&2; then
  78. hcmd=( highlight -q --force -O ansi )
  79. elif type source-highlight 2>/dev/null 1>&2; then
  80. # Warning: source-highlight can have problems
  81. hcmd=( source-highlight --failsafe -fesc -o STDOUT -i )
  82. else
  83. ansi_mode="noansi"
  84. fi
  85. zcurses init
  86. zcurses addwin status "$status_height" "$status_width" $(( term_height - status_height )) 0
  87. zcurses addwin files "$files_height" "$files_width" 0 0
  88. zcurses addwin body "$body_height" "$body_width" 0 "$files_width"
  89. zcurses bg status white/black
  90. zcurses bg files white/black
  91. zcurses bg body white/black
  92. #
  93. # Listening for input
  94. #
  95. local key keypad
  96. # Clear input buffer
  97. zcurses timeout status 0
  98. zcurses input status key keypad
  99. zcurses timeout status -1
  100. key=""
  101. keypad=""
  102. typeset -a filenames
  103. integer last_element_1
  104. typeset -a body
  105. integer last_element_2
  106. filenames=( *(N) )
  107. filenames=( "${(@M)filenames:#(#i)*$1*}" )
  108. local NLIST_GREP_STRING="$1"
  109. integer last_element_1="$#filenames"
  110. integer last_element_2=0
  111. local selection action final_key
  112. while (( 1 )); do
  113. # Output the lists
  114. integer end_idx=$(( _from_what_idx_list_is_shown_1 + files_page_height - 1 ))
  115. [ "$end_idx" -gt "$last_element_1" ] && end_idx=last_element_1
  116. n-list-draw "$(( (current_1 -1) % files_page_height + 1 ))" \
  117. "$files_page_height" "$files_page_width" 1 2 0 files \
  118. "${(@)filenames[_from_what_idx_list_is_shown_1, end_idx]}"
  119. if [ "$#body" -ge 1 ]; then
  120. end_idx=$(( _from_what_idx_list_is_shown_2 + body_page_height - 1 ))
  121. [ "$end_idx" -gt "$last_element_2" ] && end_idx=last_element_2
  122. n-list-draw "$(( (current_2 -1) % body_page_height + 1 ))" \
  123. "$body_page_height" "$body_page_width" 1 0 "$hscroll_2" body \
  124. "${(@)body[_from_what_idx_list_is_shown_2, end_idx]}"
  125. fi
  126. [[ "$active_window" -eq 0 ]] && zcurses border files
  127. zcurses border status
  128. zcurses refresh files body status
  129. # Wait for input
  130. zcurses input status key keypad
  131. # Get the special (i.e. "keypad") key or regular key
  132. if [ -n "$key" ]; then
  133. final_key="$key"
  134. elif [ -n "$keypad" ]; then
  135. final_key="$keypad"
  136. else
  137. _vpreview_status_msg "Inproper input detected"
  138. zcurses refresh status
  139. fi
  140. if [ "$active_window" -eq 0 ]; then
  141. zcurses clear files
  142. n-list-input "$current_1" "$_from_what_idx_list_is_shown_1" "$files_page_height" \
  143. "$files_page_width" "$last_element_1" 0 "$final_key"
  144. selection="$reply[1]"
  145. action="$reply[2]"
  146. current_1="$reply[3]"
  147. _from_what_idx_list_is_shown_1="$reply[4]"
  148. if [ "$action" = "SELECT" ]; then
  149. # Load new file and refresh the displaying window
  150. local filename="$filenames[$selection]"
  151. if [ "$ansi_mode" = "ansi" ]; then
  152. body=( "${(@f)"$( "$hcmd[@]" "$filename" )"}" )
  153. else
  154. body=( "${(@f)"$(<$filename)"}" )
  155. fi
  156. last_element_2="$#body"
  157. current_2=1
  158. _from_what_idx_list_is_shown_2=1
  159. zcurses clear body
  160. fi
  161. elif [ "$active_window" -eq 1 ]; then
  162. zcurses clear body
  163. n-list-input "$current_2" "$_from_what_idx_list_is_shown_2" "$body_page_height" \
  164. "$body_page_width" "$last_element_2" "$hscroll_2" "$final_key"
  165. selection="$reply[1]"
  166. action="$reply[2]"
  167. current_2="$reply[3]"
  168. _from_what_idx_list_is_shown_2="$reply[4]"
  169. hscroll_2="$reply[5]"
  170. fi
  171. if [ "$action" = "LEAVE" ]; then
  172. active_window=1-active_window
  173. elif [ "$action" = "QUIT" ]; then
  174. break
  175. elif [ "$action" = "REDRAW" ]; then
  176. zcurses clear files redraw
  177. zcurses clear body redraw
  178. zcurses clear status redraw
  179. fi
  180. done
  181. # vim: set filetype=zsh: