n-list-input 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. # Copy this file into /usr/share/zsh/site-functions/
  2. # and add 'autoload n-list-input` to .zshrc
  3. #
  4. # This is an internal function not for direct use
  5. emulate -L zsh
  6. zmodload zsh/curses
  7. setopt typesetsilent
  8. # Compute first to show index
  9. _nlist_compute_first_to_show_idx() {
  10. from_what_idx_list_is_shown=0+((current_idx-1)/page_height)*page_height+1
  11. }
  12. _nlist_update_from_keywords() {
  13. keywordisfresh="1"
  14. if [ "$nkeywords" -gt 0 ]; then
  15. curkeyword=$(( (curkeyword+1) % (nkeywords+1) ))
  16. if [ "$curkeyword" -eq "0" ]; then
  17. buffer=""
  18. else
  19. buffer="${keywords[curkeyword]}"
  20. fi
  21. fi
  22. }
  23. _nlist_iterate_theme() {
  24. themeisfresh="1"
  25. if [ "$1" = "1" ]; then
  26. curtheme=$(( (curtheme+1) % (nthemes+1) ))
  27. else
  28. curtheme=curtheme-1
  29. [ "$curtheme" -lt 0 ] && curtheme=nthemes
  30. fi
  31. if [ "$nthemes" -gt 0 ]; then
  32. local theme=${themes[curtheme]}
  33. [ "$curtheme" -eq "0" ] && theme="$backuptheme"
  34. colorpair="${theme%/*}"
  35. bold="${theme##*/}"
  36. background="${colorpair#*/}"
  37. zcurses bg main "$colorpair"
  38. zcurses bg inner "$colorpair"
  39. fi
  40. }
  41. _nlist_rotate_buffer() {
  42. setopt localoptions noglob
  43. local -a words
  44. words=( ${(s: :)buffer} )
  45. words=( ${words[-1]} ${words[1,-2]} )
  46. local space=""
  47. [ "${buffer[-1]}" = " " ] && space=" "
  48. buffer="${(j: :)words}$space"
  49. }
  50. typeset -ga reply
  51. reply=( -1 '' )
  52. integer current_idx="$1"
  53. integer from_what_idx_list_is_shown="$2"
  54. integer page_height="$3"
  55. integer page_width="$4"
  56. integer last_element="$5"
  57. integer hscroll="$6"
  58. local key="$7"
  59. integer search="$8"
  60. local buffer="$9"
  61. integer uniq_mode="$10"
  62. integer f_mode="$11"
  63. #
  64. # Listening for input
  65. #
  66. if [ "$search" = "0" ]; then
  67. case "$key" in
  68. (UP|k|$'\C-P')
  69. # Are there any elements before the current one?
  70. [ "$current_idx" -gt 1 ] && current_idx=current_idx-1;
  71. _nlist_compute_first_to_show_idx
  72. ;;
  73. (DOWN|j|$'\C-N')
  74. # Are there any elements after the current one?
  75. [ "$current_idx" -lt "$last_element" ] && current_idx=current_idx+1;
  76. _nlist_compute_first_to_show_idx
  77. ;;
  78. (PPAGE|$'\b'|$'\C-?'|BACKSPACE)
  79. current_idx=current_idx-page_height
  80. [ "$current_idx" -lt 1 ] && current_idx=1;
  81. _nlist_compute_first_to_show_idx
  82. ;;
  83. (NPAGE|" ")
  84. current_idx=current_idx+page_height
  85. [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
  86. _nlist_compute_first_to_show_idx
  87. ;;
  88. ($'\C-U')
  89. current_idx=current_idx-page_height/2
  90. [ "$current_idx" -lt 1 ] && current_idx=1;
  91. _nlist_compute_first_to_show_idx
  92. ;;
  93. ($'\C-D')
  94. current_idx=current_idx+page_height/2
  95. [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
  96. _nlist_compute_first_to_show_idx
  97. ;;
  98. (HOME|g)
  99. current_idx=1
  100. _nlist_compute_first_to_show_idx
  101. ;;
  102. (END|G)
  103. current_idx=last_element
  104. _nlist_compute_first_to_show_idx
  105. ;;
  106. ($'\n'|ENTER)
  107. # Is that element selectable?
  108. # Check for this only when there is no search
  109. if [[ "$NLIST_SEARCH_BUFFER" != "" || "$NLIST_IS_UNIQ_MODE" -eq 1 ||
  110. ${NLIST_NONSELECTABLE_ELEMENTS[(r)$current_idx]} != $current_idx ]]
  111. then
  112. # Save current element in the result variable
  113. reply=( $current_idx "SELECT" )
  114. fi
  115. ;;
  116. (H|'?')
  117. # This event needs to be enabled
  118. if [[ "${NLIST_ENABLED_EVENTS[(r)HELP]}" = "HELP" ]]; then
  119. reply=( -1 "HELP" )
  120. fi
  121. ;;
  122. (F1)
  123. # This event needs to be enabled
  124. if [[ "${NLIST_ENABLED_EVENTS[(r)F1]}" = "F1" ]]; then
  125. reply=( -1 "$key" )
  126. fi
  127. ;;
  128. (F4|F5|F6|F7|F8|F9|F10|DC)
  129. # ignore; F2, F3 are used below
  130. ;;
  131. (q)
  132. reply=( -1 "QUIT" )
  133. ;;
  134. (/)
  135. search=1
  136. _nlist_cursor_visibility 1
  137. ;;
  138. ($'\t')
  139. reply=( $current_idx "LEAVE" )
  140. ;;
  141. ($'\C-L')
  142. reply=( -1 "REDRAW" )
  143. ;;
  144. (\])
  145. [[ "${(t)NLIST_HOP_INDEXES}" = "array" || "${(t)NLIST_HOP_INDEXES}" = "array-local" ]] &&
  146. [ -z "$NLIST_SEARCH_BUFFER" ] && [ "$NLIST_IS_UNIQ_MODE" -eq 0 ] &&
  147. for idx in "${(n)NLIST_HOP_INDEXES[@]}"; do
  148. if [ "$idx" -gt "$current_idx" ]; then
  149. current_idx=$idx
  150. _nlist_compute_first_to_show_idx
  151. break
  152. fi
  153. done
  154. ;;
  155. (\[)
  156. [[ "${(t)NLIST_HOP_INDEXES}" = "array" || "${(t)NLIST_HOP_INDEXES}" = "array-local" ]] &&
  157. [ -z "$NLIST_SEARCH_BUFFER" ] && [ "$NLIST_IS_UNIQ_MODE" -eq 0 ] &&
  158. for idx in "${(nO)NLIST_HOP_INDEXES[@]}"; do
  159. if [ "$idx" -lt "$current_idx" ]; then
  160. current_idx=$idx
  161. _nlist_compute_first_to_show_idx
  162. break
  163. fi
  164. done
  165. ;;
  166. ('<'|'{'|LEFT|'h')
  167. hscroll=hscroll-7
  168. [ "$hscroll" -lt 0 ] && hscroll=0
  169. ;;
  170. ('>'|'}'|RIGHT|'l')
  171. hscroll+=7
  172. ;;
  173. ($'\E')
  174. buffer=""
  175. ;;
  176. (F3)
  177. if [ "$search" = "1" ]; then
  178. search=0
  179. _nlist_cursor_visibility 0
  180. else
  181. search=1
  182. _nlist_cursor_visibility 1
  183. fi
  184. ;;
  185. (o|$'\C-O')
  186. uniq_mode=1-uniq_mode
  187. ;;
  188. (f|$'\C-F')
  189. (( f_mode=(f_mode+1) % 3 ))
  190. ;;
  191. ($'\x1F'|F2|$'\C-X')
  192. search=1
  193. _nlist_cursor_visibility 1
  194. _nlist_update_from_keywords
  195. ;;
  196. ($'\C-T')
  197. _nlist_iterate_theme 1
  198. ;;
  199. ($'\C-G')
  200. _nlist_iterate_theme 0
  201. ;;
  202. ($'\C-E'|e)
  203. # This event needs to be enabled
  204. if [[ "${NLIST_ENABLED_EVENTS[(r)EDIT]}" = "EDIT" ]]; then
  205. reply=( -1 "EDIT" )
  206. fi
  207. ;;
  208. ($'\C-A')
  209. _nlist_rotate_buffer
  210. ;;
  211. (*)
  212. ;;
  213. esac
  214. else
  215. case "$key" in
  216. ($'\n'|ENTER)
  217. if [ "$NLIST_INSTANT_SELECT" = "1" ]; then
  218. if [[ "$NLIST_SEARCH_BUFFER" != "" || "$NLIST_IS_UNIQ_MODE" -eq 1 ||
  219. ${NLIST_NONSELECTABLE_ELEMENTS[(r)$current_idx]} != $current_idx ]]
  220. then
  221. reply=( $current_idx "SELECT" )
  222. fi
  223. else
  224. search=0
  225. _nlist_cursor_visibility 0
  226. fi
  227. ;;
  228. ($'\C-L')
  229. reply=( -1 "REDRAW" )
  230. ;;
  231. #
  232. # Slightly limited navigation
  233. #
  234. (UP|$'\C-P')
  235. [ "$current_idx" -gt 1 ] && current_idx=current_idx-1;
  236. _nlist_compute_first_to_show_idx
  237. ;;
  238. (DOWN|$'\C-N')
  239. [ "$current_idx" -lt "$last_element" ] && current_idx=current_idx+1;
  240. _nlist_compute_first_to_show_idx
  241. ;;
  242. (PPAGE)
  243. current_idx=current_idx-page_height
  244. [ "$current_idx" -lt 1 ] && current_idx=1;
  245. _nlist_compute_first_to_show_idx
  246. ;;
  247. (NPAGE)
  248. current_idx=current_idx+page_height
  249. [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
  250. _nlist_compute_first_to_show_idx
  251. ;;
  252. ($'\C-U')
  253. current_idx=current_idx-page_height/2
  254. [ "$current_idx" -lt 1 ] && current_idx=1;
  255. _nlist_compute_first_to_show_idx
  256. ;;
  257. ($'\C-D')
  258. current_idx=current_idx+page_height/2
  259. [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
  260. _nlist_compute_first_to_show_idx
  261. ;;
  262. (HOME)
  263. current_idx=1
  264. _nlist_compute_first_to_show_idx
  265. ;;
  266. (END)
  267. current_idx=last_element
  268. _nlist_compute_first_to_show_idx
  269. ;;
  270. (LEFT)
  271. hscroll=hscroll-7
  272. [ "$hscroll" -lt 0 ] && hscroll=0
  273. ;;
  274. (RIGHT)
  275. hscroll+=7
  276. ;;
  277. (F1)
  278. # This event needs to be enabled
  279. if [[ "${NLIST_ENABLED_EVENTS[(r)F1]}" = "F1" ]]; then
  280. reply=( -1 "$key" )
  281. fi
  282. ;;
  283. (F4|F5|F6|F7|F8|F9|F10|DC)
  284. # ignore; F2, F3 are used below
  285. ;;
  286. #
  287. # The input
  288. #
  289. ($'\b'|$'\C-?'|BACKSPACE)
  290. buffer="${buffer%?}"
  291. ;;
  292. ($'\C-W')
  293. [ "$buffer" = "${buffer% *}" ] && buffer="" || buffer="${buffer% *}"
  294. ;;
  295. ($'\C-K')
  296. buffer=""
  297. ;;
  298. ($'\E')
  299. buffer=""
  300. search=0
  301. _nlist_cursor_visibility 0
  302. ;;
  303. (F3)
  304. if [ "$search" = "1" ]; then
  305. search=0
  306. _nlist_cursor_visibility 0
  307. else
  308. search=1
  309. _nlist_cursor_visibility 1
  310. fi
  311. ;;
  312. ($'\C-O')
  313. uniq_mode=1-uniq_mode
  314. ;;
  315. ($'\C-F')
  316. (( f_mode=(f_mode+1) % 3 ))
  317. ;;
  318. ($'\x1F'|F2|$'\C-X')
  319. _nlist_update_from_keywords
  320. ;;
  321. ($'\C-T')
  322. _nlist_iterate_theme 1
  323. ;;
  324. ($'\C-G')
  325. _nlist_iterate_theme 0
  326. ;;
  327. ($'\C-E')
  328. # This event needs to be enabled
  329. if [[ "${NLIST_ENABLED_EVENTS[(r)EDIT]}" = "EDIT" ]]; then
  330. reply=( -1 "EDIT" )
  331. fi
  332. ;;
  333. ($'\C-A')
  334. _nlist_rotate_buffer
  335. ;;
  336. (*)
  337. if [[ $#key == 1 && $((#key)) -lt 31 ]]; then
  338. # ignore all other control keys
  339. else
  340. buffer+="$key"
  341. fi
  342. ;;
  343. esac
  344. fi
  345. reply[3]="$current_idx"
  346. reply[4]="$from_what_idx_list_is_shown"
  347. reply[5]="$hscroll"
  348. reply[6]="$search"
  349. reply[7]="$buffer"
  350. reply[8]="$uniq_mode"
  351. reply[9]="$f_mode"
  352. # vim: set filetype=zsh: