Advertisement
goku13l

Untitled

May 7th, 2022
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.74 KB | None | 0 0
  1. ## .zshrc
  2. source "$ZPLUGINS/zsh-autosuggestions/zsh-autosuggestions.zsh"
  3.  
  4. # Atuin (history replacement)
  5. # Keeps the history in a sqlite db (Needs to be after zsh-autosuggestions)
  6. source "$ZDOTDIR/plugins/atuin.zsh"
  7.  
  8. # bind UP and DOWN arrow keys to history search
  9. bindkey "$terminfo[kcuu1]" atuin_fzf_inline_up
  10. bindkey "$terminfo[kcud1]" atuin_fzf_inline_down
  11. bindkey '^[[A' atuin_fzf_inline_up
  12. bindkey '^[[B' atuin_fzf_inline_down
  13.  
  14. bindkey '^r' _atuin_search_widget # Default
  15. bindkey '^[r' _atuin_fzf # Using fzf interactively
  16.  
  17. ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=#555'
  18. ZSH_AUTOSUGGEST_STRATEGY=('atuin')
  19. ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE='20'
  20. ZSH_AUTOSUGGEST_USE_ASYNC='true'
  21. ZSH_AUTOSUGGEST_MANUAL_REBIND='true'
  22.  
  23.  
  24. ## plugins/atuin.zsh
  25. # Enable atuin history plugin
  26. # Import atuin history into zsh array
  27. # Support multiline commands
  28. # Support interactive atuin, interactive fzf,
  29. # inline history navigation with or without fzf filtering by query
  30. # Support zsh-autosuggestions using atuin history
  31. # Support highlighting of query terms
  32.  
  33. ## Source the atuin zsh plugin
  34. # Equivalent to `eval "$(atuin init zsh)"` but a little bit faster (~2ms)
  35. # Yeah, probably not worth it but it's already written so ¯\_(ツ)_/¯
  36. atuin_version="# $(atuin --version)"
  37. current_atuin_version="$(head -1 $ZCACHE/_atuin_init_zsh.zsh)"
  38. if [[ "$atuin_version" != "$current_atuin_version" ]]; then
  39. # Check for new atuin version and update the cache
  40. echo "$atuin_version" > "$ZCACHE/_atuin_init_zsh.zsh"
  41. atuin init zsh >> "$ZCACHE/_atuin_init_zsh.zsh"
  42. fi
  43. export ATUIN_NOBIND='true'
  44. source "$ZCACHE/_atuin_init_zsh.zsh"
  45.  
  46. ## Import atuin history into zsh array
  47. declare -U _history_atuin # -U indicates unique array so duplicates are not inserted
  48. # Get the last 1500 (More than the 'max_lenght' below, to account for duplicates) commands from the atuin history database
  49. # Separate each command with ';;\n;;' instead of '\n', this allows support for multiline commands.
  50. # Split them using the same separator and insert them into the array: (@pws:;;\n;;:).
  51. # Sort them by timestamp in descending order (Last executed command first), this helps with:
  52. # Limiting the number of sqlite rows (otherwise it woulds trim the latest rows)
  53. # As latest commands are inserted first they have preference to earlier ones when checking for duplicates.
  54. # Bonus points for simplifying 'Limit history array size' below.
  55. _history_atuin=("${(@pws:;;\n;;:)"$(sqlite3 --newline $';;\n;;' ~/.local/share/atuin/history.db 'SELECT command FROM history ORDER BY timestamp DESC LIMIT 2000')"}")
  56.  
  57. # Redeclare as normal array, this allows us to store new duplicate commands for keeping a better session history.
  58. # Ofc those duplicates get removed when opening a new terminal.
  59. declare -a history_atuin
  60.  
  61. ## Limit history array size to 1000
  62. # _history_atuin:0:1000, Get slice from 0 to 1000, effectively trimming it's size
  63. # (@Oa), Reverse the order so last executed commands are first
  64. history_atuin=(${(@Oa)_history_atuin:0:1000})
  65. unset _history_atuin
  66.  
  67. if [[ -z $history_atuin ]]; then
  68. echo 'Error: Atuin history array is empty'
  69. echo 'Atuin may not be installed, history not imported, wrong path for the database or something else.'
  70. exit
  71. fi
  72.  
  73. ## Keep history array updated with new executed commands
  74. _atuin_update_history_preexec(){
  75. if [[ $history_atuin[-1] != "$1" ]]; then
  76. # Store the new command in history if it's different than the last one
  77. # This basically avoids adding duplicate commands one right after the other
  78. history_atuin+=("$1") # Store the command in our zsh array (cache)
  79. fi
  80. }
  81. add-zsh-hook preexec _atuin_update_history_preexec
  82.  
  83. ## Set selected command as new buffer and move the cursor to the end
  84. __atuin_set_buffer() {
  85. BUFFER="$1"
  86. CURSOR=${#BUFFER}
  87. }
  88.  
  89. ## Invoque fzf with atuin history
  90. _atuin_fzf() {
  91. # Print history splitting commands with nulls `print -rNC1 -- $var`
  92. # Get the history inverted `${(@Oa)history_atuin}` for the print command.
  93. # Get and parse history using nulls as separators
  94. # Nulls are used as separators instead of newlines to keep support for multiline commands
  95. output=$(print -rNC1 -- "${(@Oa)history_atuin}" | fzf --read0)
  96. __atuin_set_buffer "$output"
  97. }
  98. zle -N _atuin_fzf
  99.  
  100. typeset -g _atuin_fzf_inline_query
  101. typeset -g _atuin_fzf_inline_query_matches
  102. typeset -g _atuin_fzf_inline_result
  103. typeset -i _atuin_fzf_inline_result_index=0
  104.  
  105. ## Emulate history-substring-search but with atuin results
  106. __atuin_fzf_inline() {
  107. typeset -g suggestion=''
  108. local add_or_substract="$1"
  109.  
  110. # Move the cursor instead of changing history command
  111. # but only if he current command is multiline, and we are not in the first or last line
  112. # (depending if we are moving up or downon the history)
  113. if (( $BUFFERLINES > 1 )); then
  114. local lines_before_end
  115. if [[ "$add_or_substract" == '+' ]]; then
  116. lines_before_end=(${(f)LBUFFER})
  117. else
  118. lines_before_end=(${(f)RBUFFER})
  119. fi
  120. if (( ${#lines_before_end} > 1 )); then
  121. if [[ "$add_or_substract" == '+' ]]; then
  122. zle up-line # zsh builtin, move cursor one line up
  123. else
  124. zle down-line # zsh builtin, move cursor one line down
  125. fi
  126. return
  127. fi
  128. fi
  129.  
  130. # Add or substract one from the index, depending if we are going up or down on the history
  131. _atuin_fzf_inline_result_index=$(( _atuin_fzf_inline_result_index $add_or_substract 1 ))
  132.  
  133. if (( _atuin_fzf_inline_result_index < 0 )); then
  134. # Drop the current query, clear the buffer.
  135. _atuin_fzf_inline_result_index=0
  136. unset _atuin_fzf_inline_query_matches
  137. __atuin_set_buffer ''
  138. return
  139. elif [[ "$BUFFER" == "$_atuin_fzf_inline_result" ]]; then
  140. if (( _atuin_fzf_inline_result_index == 0 )); then
  141. __atuin_set_buffer "$_atuin_fzf_inline_query"
  142. return
  143. fi
  144. else
  145. _atuin_fzf_inline_result_index=1
  146. unset _atuin_fzf_inline_query_matches
  147. _atuin_fzf_inline_query="$BUFFER"
  148. fi
  149.  
  150. ## Get the history array we are gonna use
  151. local query="$_atuin_fzf_inline_query"
  152. local index="$_atuin_fzf_inline_result_index"
  153. if [[ -n "$query" ]]; then # Filter commands by query using fzf
  154. # Create array of matches, filtered by fzf if not already created
  155. # Print history splitting commands with nulls `print -rNC1 -- $var`
  156. # Filter results with fzf, using nulls as separators for both input and output
  157. # Create array using nulls as separators `(@0)`
  158. # Nulls are used as separators instead of newlines to keep support for multiline commands
  159. if [[ -z "$_atuin_fzf_inline_query_matches" ]]; then
  160. _atuin_fzf_inline_query_matches=("${(@0)"$(print -rNC1 -- "$history_atuin[@]" | fzf --read0 --print0 --exact --no-sort --filter="$query")"}")
  161. shift -p _atuin_fzf_inline_query_matches # Pop the last item, it's an empty string
  162. fi
  163. matches='_atuin_fzf_inline_query_matches'
  164. else # No need to filter with fzf if there is no query, use the entire history array
  165. matches='history_atuin'
  166. fi
  167.  
  168. max_index=${#${(P)matches}} # Get size of array named $matches
  169. if (( index > max_index )); then
  170. _atuin_fzf_inline_result_index="$max_index"
  171. # We already reached the end of the history, do nothing
  172. return
  173. fi
  174.  
  175. ## Get next command from history
  176. # From array named $matches get element -$index, negative number to start from the last element
  177. _atuin_fzf_inline_result=${${(P)matches}[-$index]}
  178.  
  179. ## Set command as current edit buffer
  180. __atuin_set_buffer "$_atuin_fzf_inline_result"
  181.  
  182. # Find all matches of $query in $BUFFER and highlight them
  183. if [[ -n "$query" ]]; then
  184. _zsh_highlight # This needs to be before region_highlight+= or the added highlight will be ignored, does _zsh_highlight clear the region_highlight array?.
  185. local last_match_end=0
  186. while true; do
  187. # (i) Search $query inside $BUFFER and return the index of the first matching character
  188. # (e) Match using $query as a literal string (i.e. query=* will match the literal character `*`)
  189. # (b:last_match_end:) Start matching from index=$last_match_end
  190. local match_start="${BUFFER[(ieb:last_match_end:)${query}]}"
  191. if (( $match_start <= ${#BUFFER} )); then
  192. local match_end=$(( $match_start + ${#query} ))
  193. last_match_end=$match_end
  194. # Highlight from index $match_start to $match_end, they need an offset of 1
  195. region_highlight+=("$(($match_start - 1)) $(($match_end - 1)) underline") # bold
  196. else
  197. # The query didn't match anything
  198. break
  199. fi
  200. done
  201. fi
  202. }
  203.  
  204. atuin_fzf_inline_up() {
  205. __atuin_fzf_inline '+'
  206. }
  207. atuin_fzf_inline_down() {
  208. __atuin_fzf_inline '-'
  209. }
  210.  
  211. zle -N atuin_fzf_inline_up
  212. zle -N atuin_fzf_inline_down
  213.  
  214. ## Add compatibility with zsh-autosuggest
  215.  
  216. # Tell autosuggest to clear suggestions when atuin changes the edit buffer
  217. ZSH_AUTOSUGGEST_CLEAR_WIDGETS+=('atuin_fzf_inline_up')
  218. ZSH_AUTOSUGGEST_CLEAR_WIDGETS+=('atuin_fzf_inline_down')
  219.  
  220. _zsh_autosuggest_strategy_atuin() {
  221. # Straight copy from: https://github.com/zsh-users/zsh-autosuggestions/blob/master/src/strategies/history.zsh
  222. # Only changes are the history source and inverting the matching order.
  223. #
  224. # Copyright (c) 2013 Thiago de Arruda
  225. # Copyright (c) 2016-2021 Eric Freese
  226.  
  227. # Permission is hereby granted, free of charge, to any person
  228. # obtaining a copy of this software and associated documentation
  229. # files (the "Software"), to deal in the Software without
  230. # restriction, including without limitation the rights to use,
  231. # copy, modify, merge, publish, distribute, sublicense, and/or sell
  232. # copies of the Software, and to permit persons to whom the
  233. # Software is furnished to do so, subject to the following
  234. # conditions:
  235.  
  236. # The above copyright notice and this permission notice shall be
  237. # included in all copies or substantial portions of the Software.
  238.  
  239. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  240. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  241. # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  242. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  243. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  244. # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  245. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  246. # OTHER DEALINGS IN THE SOFTWARE.
  247. #
  248.  
  249. # Reset options to defaults and enable LOCAL_OPTIONS
  250. emulate -L zsh
  251.  
  252. # Enable globbing flags so that we can use (#m) and (x~y) glob operator
  253. setopt EXTENDED_GLOB
  254.  
  255. # Escape backslashes and all of the glob operators so we can use
  256. # this string as a pattern to search the $history associative array.
  257. # - (#m) globbing flag enables setting references for match data
  258. # TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
  259. local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
  260.  
  261. # Get the history items that match the prefix, excluding those that match
  262. # the ignore pattern
  263. local pattern="$prefix*"
  264. if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then
  265. pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)"
  266. fi
  267.  
  268. # Give the first history item matching the pattern as the suggestion
  269. # - (r) subscript flag makes the pattern match on values
  270. # - (R) same as r, but gives the last match
  271. typeset -g suggestion="${history_atuin[(R)$pattern]}"
  272. }
  273.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement