選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

447 行
14 KiB

8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
  1. # Fish-like fast/unobtrusive autosuggestions for zsh.
  2. # https://github.com/zsh-users/zsh-autosuggestions
  3. # v0.3.1
  4. # Copyright (c) 2013 Thiago de Arruda
  5. # Copyright (c) 2016 Eric Freese
  6. #
  7. # Permission is hereby granted, free of charge, to any person
  8. # obtaining a copy of this software and associated documentation
  9. # files (the "Software"), to deal in the Software without
  10. # restriction, including without limitation the rights to use,
  11. # copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. # copies of the Software, and to permit persons to whom the
  13. # Software is furnished to do so, subject to the following
  14. # conditions:
  15. #
  16. # The above copyright notice and this permission notice shall be
  17. # included in all copies or substantial portions of the Software.
  18. #
  19. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  20. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  21. # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  22. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  23. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  24. # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  26. # OTHER DEALINGS IN THE SOFTWARE.
  27. #--------------------------------------------------------------------#
  28. # Global Configuration Variables #
  29. #--------------------------------------------------------------------#
  30. # Color to use when highlighting suggestion
  31. # Uses format of `region_highlight`
  32. # More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets
  33. ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'
  34. # Prefix to use when saving original versions of bound widgets
  35. ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
  36. ZSH_AUTOSUGGEST_STRATEGY=default
  37. # Widgets that clear the suggestion
  38. ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
  39. history-search-forward
  40. history-search-backward
  41. history-beginning-search-forward
  42. history-beginning-search-backward
  43. history-substring-search-up
  44. history-substring-search-down
  45. up-line-or-history
  46. down-line-or-history
  47. accept-line
  48. )
  49. # Widgets that accept the entire suggestion
  50. ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
  51. forward-char
  52. end-of-line
  53. vi-forward-char
  54. vi-end-of-line
  55. vi-add-eol
  56. )
  57. # Widgets that accept the entire suggestion and execute it
  58. ZSH_AUTOSUGGEST_EXECUTE_WIDGETS=(
  59. )
  60. # Widgets that accept the suggestion as far as the cursor moves
  61. ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
  62. forward-word
  63. vi-forward-word
  64. vi-forward-word-end
  65. vi-forward-blank-word
  66. vi-forward-blank-word-end
  67. )
  68. #--------------------------------------------------------------------#
  69. # Handle Deprecated Variables/Widgets #
  70. #--------------------------------------------------------------------#
  71. _zsh_autosuggest_deprecated_warning() {
  72. >&2 echo "zsh-autosuggestions: $@"
  73. }
  74. _zsh_autosuggest_check_deprecated_config() {
  75. if [ -n "$AUTOSUGGESTION_HIGHLIGHT_COLOR" ]; then
  76. _zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_HIGHLIGHT_COLOR is deprecated. Use ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE instead."
  77. [ -z "$ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE" ] && ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE=$AUTOSUGGESTION_HIGHLIGHT_STYLE
  78. unset AUTOSUGGESTION_HIGHLIGHT_STYLE
  79. fi
  80. if [ -n "$AUTOSUGGESTION_HIGHLIGHT_CURSOR" ]; then
  81. _zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_HIGHLIGHT_CURSOR is deprecated."
  82. unset AUTOSUGGESTION_HIGHLIGHT_CURSOR
  83. fi
  84. if [ -n "$AUTOSUGGESTION_ACCEPT_RIGHT_ARROW" ]; then
  85. _zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_ACCEPT_RIGHT_ARROW is deprecated. The right arrow now accepts the suggestion by default."
  86. unset AUTOSUGGESTION_ACCEPT_RIGHT_ARROW
  87. fi
  88. }
  89. _zsh_autosuggest_deprecated_start_widget() {
  90. _zsh_autosuggest_deprecated_warning "The autosuggest-start widget is deprecated. For more info, see the README at https://github.com/zsh-users/zsh-autosuggestions."
  91. zle -D autosuggest-start
  92. eval "zle-line-init() {
  93. $(echo $functions[${widgets[zle-line-init]#*:}] | sed -e 's/zle autosuggest-start//g')
  94. }"
  95. }
  96. zle -N autosuggest-start _zsh_autosuggest_deprecated_start_widget
  97. #--------------------------------------------------------------------#
  98. # Widget Helpers #
  99. #--------------------------------------------------------------------#
  100. # Bind a single widget to an autosuggest widget, saving a reference to the original widget
  101. _zsh_autosuggest_bind_widget() {
  102. local widget=$1
  103. local autosuggest_action=$2
  104. local prefix=$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX
  105. # Save a reference to the original widget
  106. case $widgets[$widget] in
  107. # Already bound
  108. user:_zsh_autosuggest_(bound|orig)_*);;
  109. # User-defined widget
  110. user:*)
  111. zle -N $prefix$widget ${widgets[$widget]#*:}
  112. ;;
  113. # Built-in widget
  114. builtin)
  115. eval "_zsh_autosuggest_orig_$widget() { zle .$widget }"
  116. zle -N $prefix$widget _zsh_autosuggest_orig_$widget
  117. ;;
  118. # Completion widget
  119. completion:*)
  120. eval "zle -C $prefix$widget ${${widgets[$widget]#*:}/:/ }"
  121. ;;
  122. esac
  123. # Pass the original widget's name explicitly into the autosuggest
  124. # function. Use this passed in widget name to call the original
  125. # widget instead of relying on the $WIDGET variable being set
  126. # correctly. $WIDGET cannot be trusted because other plugins call
  127. # zle without the `-w` flag (e.g. `zle self-insert` instead of
  128. # `zle self-insert -w`).
  129. eval "_zsh_autosuggest_bound_$widget() {
  130. _zsh_autosuggest_widget_$autosuggest_action $prefix$widget \$@
  131. }"
  132. # Create the bound widget
  133. zle -N $widget _zsh_autosuggest_bound_$widget
  134. }
  135. # Map all configured widgets to the right autosuggest widgets
  136. _zsh_autosuggest_bind_widgets() {
  137. local widget;
  138. # Find every widget we might want to bind and bind it appropriately
  139. for widget in ${${(f)"$(builtin zle -la)"}:#(.*|_*|orig-*|autosuggest-*|$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX*|zle-line-*|run-help|which-command|beep|set-local-history|yank)}; do
  140. if [ ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]; then
  141. _zsh_autosuggest_bind_widget $widget clear
  142. elif [ ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]; then
  143. _zsh_autosuggest_bind_widget $widget accept
  144. elif [ ${ZSH_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]; then
  145. _zsh_autosuggest_bind_widget $widget execute
  146. elif [ ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]; then
  147. _zsh_autosuggest_bind_widget $widget partial_accept
  148. else
  149. # Assume any unspecified widget might modify the buffer
  150. _zsh_autosuggest_bind_widget $widget modify
  151. fi
  152. done
  153. }
  154. # Given the name of an original widget and args, invoke it, if it exists
  155. _zsh_autosuggest_invoke_original_widget() {
  156. # Do nothing unless called with at least one arg
  157. [ $# -gt 0 ] || return
  158. local original_widget_name="$1"
  159. shift
  160. if [ $widgets[$original_widget_name] ]; then
  161. zle $original_widget_name -- $@
  162. fi
  163. }
  164. #--------------------------------------------------------------------#
  165. # Highlighting #
  166. #--------------------------------------------------------------------#
  167. # If there was a highlight, remove it
  168. _zsh_autosuggest_highlight_reset() {
  169. typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
  170. if [ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]; then
  171. region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}")
  172. unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
  173. fi
  174. }
  175. # If there's a suggestion, highlight it
  176. _zsh_autosuggest_highlight_apply() {
  177. typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
  178. if [ $#POSTDISPLAY -gt 0 ]; then
  179. _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
  180. region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT")
  181. else
  182. unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
  183. fi
  184. }
  185. #--------------------------------------------------------------------#
  186. # Autosuggest Widget Implementations #
  187. #--------------------------------------------------------------------#
  188. # Clear the suggestion
  189. _zsh_autosuggest_clear() {
  190. # Remove the suggestion
  191. unset POSTDISPLAY
  192. _zsh_autosuggest_invoke_original_widget $@
  193. }
  194. # Modify the buffer and get a new suggestion
  195. _zsh_autosuggest_modify() {
  196. local -i retval
  197. # Original widget modifies the buffer
  198. _zsh_autosuggest_invoke_original_widget $@
  199. retval=$?
  200. # Get a new suggestion if the buffer is not empty after modification
  201. local suggestion
  202. if [ $#BUFFER -gt 0 ]; then
  203. suggestion="$(_zsh_autosuggest_suggestion "$BUFFER")"
  204. fi
  205. # Add the suggestion to the POSTDISPLAY
  206. if [ -n "$suggestion" ]; then
  207. POSTDISPLAY="${suggestion#$BUFFER}"
  208. else
  209. unset POSTDISPLAY
  210. fi
  211. return $retval
  212. }
  213. # Accept the entire suggestion
  214. _zsh_autosuggest_accept() {
  215. local -i max_cursor_pos=$#BUFFER
  216. # When vicmd keymap is active, the cursor can't move all the way
  217. # to the end of the buffer
  218. if [ "$KEYMAP" = "vicmd" ]; then
  219. max_cursor_pos=$((max_cursor_pos - 1))
  220. fi
  221. # Only accept if the cursor is at the end of the buffer
  222. if [ $CURSOR -eq $max_cursor_pos ]; then
  223. # Add the suggestion to the buffer
  224. BUFFER="$BUFFER$POSTDISPLAY"
  225. # Remove the suggestion
  226. unset POSTDISPLAY
  227. # Move the cursor to the end of the buffer
  228. CURSOR=${#BUFFER}
  229. fi
  230. _zsh_autosuggest_invoke_original_widget $@
  231. }
  232. # Accept the entire suggestion and execute it
  233. _zsh_autosuggest_execute() {
  234. # Add the suggestion to the buffer
  235. BUFFER="$BUFFER$POSTDISPLAY"
  236. # Remove the suggestion
  237. unset POSTDISPLAY
  238. # Call the original `accept-line` to handle syntax highlighting or
  239. # other potential custom behavior
  240. _zsh_autosuggest_invoke_original_widget "accept-line"
  241. }
  242. # Partially accept the suggestion
  243. _zsh_autosuggest_partial_accept() {
  244. local -i retval
  245. # Save the contents of the buffer so we can restore later if needed
  246. local original_buffer="$BUFFER"
  247. # Temporarily accept the suggestion.
  248. BUFFER="$BUFFER$POSTDISPLAY"
  249. # Original widget moves the cursor
  250. _zsh_autosuggest_invoke_original_widget $@
  251. retval=$?
  252. # If we've moved past the end of the original buffer
  253. if [ $CURSOR -gt $#original_buffer ]; then
  254. # Set POSTDISPLAY to text right of the cursor
  255. POSTDISPLAY="$RBUFFER"
  256. # Clip the buffer at the cursor
  257. BUFFER="$LBUFFER"
  258. else
  259. # Restore the original buffer
  260. BUFFER="$original_buffer"
  261. fi
  262. return $retval
  263. }
  264. for action in clear modify accept partial_accept execute; do
  265. eval "_zsh_autosuggest_widget_$action() {
  266. local -i retval
  267. _zsh_autosuggest_highlight_reset
  268. _zsh_autosuggest_$action \$@
  269. retval=\$?
  270. _zsh_autosuggest_highlight_apply
  271. return \$retval
  272. }"
  273. done
  274. zle -N autosuggest-accept _zsh_autosuggest_widget_accept
  275. zle -N autosuggest-clear _zsh_autosuggest_widget_clear
  276. zle -N autosuggest-execute _zsh_autosuggest_widget_execute
  277. #--------------------------------------------------------------------#
  278. # Suggestion #
  279. #--------------------------------------------------------------------#
  280. # Delegate to the selected strategy to determine a suggestion
  281. _zsh_autosuggest_suggestion() {
  282. local prefix="$1"
  283. local strategy_function="_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY"
  284. if [ -n "$functions[$strategy_function]" ]; then
  285. echo -E "$($strategy_function "$prefix")"
  286. fi
  287. }
  288. _zsh_autosuggest_escape_command() {
  289. setopt localoptions EXTENDED_GLOB
  290. # Escape special chars in the string (requires EXTENDED_GLOB)
  291. echo -E "${1//(#m)[\\()\[\]|*?]/\\$MATCH}"
  292. }
  293. # Get the previously executed command
  294. _zsh_autosuggest_prev_command() {
  295. echo -E "${history[$((HISTCMD-1))]}"
  296. }
  297. #--------------------------------------------------------------------#
  298. # Default Suggestion Strategy #
  299. #--------------------------------------------------------------------#
  300. # Suggests the most recent history item that matches the given
  301. # prefix.
  302. #
  303. _zsh_autosuggest_strategy_default() {
  304. local prefix="$(_zsh_autosuggest_escape_command "$1")"
  305. # Get the keys of the history items that match
  306. local -a histkeys
  307. histkeys=(${(k)history[(r)$prefix*]})
  308. # Echo the value of the first key
  309. echo -E "${history[$histkeys[1]]}"
  310. }
  311. #--------------------------------------------------------------------#
  312. # Match Previous Command Suggestion Strategy #
  313. #--------------------------------------------------------------------#
  314. # Suggests the most recent history item that matches the given
  315. # prefix and whose preceding history item also matches the most
  316. # recently executed command.
  317. #
  318. # For example, suppose your history has the following entries:
  319. # - pwd
  320. # - ls foo
  321. # - ls bar
  322. # - pwd
  323. #
  324. # Given the history list above, when you type 'ls', the suggestion
  325. # will be 'ls foo' rather than 'ls bar' because your most recently
  326. # executed command (pwd) was previously followed by 'ls foo'.
  327. #
  328. _zsh_autosuggest_strategy_match_prev_cmd() {
  329. local prefix="$(_zsh_autosuggest_escape_command "$1")"
  330. # Get all history event numbers that correspond to history
  331. # entries that match pattern $prefix*
  332. local history_match_keys
  333. history_match_keys=(${(k)history[(R)$prefix*]})
  334. # By default we use the first history number (most recent history entry)
  335. local histkey="${history_match_keys[1]}"
  336. # Get the previously executed command
  337. local prev_cmd="$(_zsh_autosuggest_prev_command)"
  338. prev_cmd="$(_zsh_autosuggest_escape_command "$prev_cmd")"
  339. # Iterate up to the first 200 history event numbers that match $prefix
  340. for key in "${(@)history_match_keys[1,200]}"; do
  341. # Stop if we ran out of history
  342. [[ $key -gt 1 ]] || break
  343. # See if the history entry preceding the suggestion matches the
  344. # previous command, and use it if it does
  345. if [[ "${history[$((key - 1))]}" == "$prev_cmd" ]]; then
  346. histkey="$key"
  347. break
  348. fi
  349. done
  350. # Echo the matched history entry
  351. echo -E "$history[$histkey]"
  352. }
  353. #--------------------------------------------------------------------#
  354. # Start #
  355. #--------------------------------------------------------------------#
  356. # Start the autosuggestion widgets
  357. _zsh_autosuggest_start() {
  358. _zsh_autosuggest_check_deprecated_config
  359. _zsh_autosuggest_bind_widgets
  360. }
  361. autoload -Uz add-zsh-hook
  362. add-zsh-hook precmd _zsh_autosuggest_start