#!/usr/bin/env zsh # # -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*- # # Copyright (c) 2016-2020 Sebastian Gniazdowski and contributors # Copyright (c) 2021-2022 zdharma-continuum and contributors __hsmw_ctx_prev_idx="$__hsmw_ctx_idx" [[ "$WIDGET" = *-word ]] && (( __hsmw_ctx_idx -- )) [[ "$WIDGET" = *-backwards ]] && (( __hsmw_ctx_idx ++ )) [[ "$WIDGET" = *-pforwards ]] && (( __hsmw_ctx_idx = __hsmw_ctx_idx - __hsmw_page_size )) [[ "$WIDGET" = *-pbackwards ]] && (( __hsmw_ctx_idx = __hsmw_ctx_idx + __hsmw_page_size )) _hsmw_ctx_up() { (( __hsmw_ctx_which -- )) (( __hsmw_ctx_which < 0 )) && __hsmw_ctx_which=${#__hsmw_ctx_found}-1 __hsmw_ctx_idx=0 _hsmw_ctx_main } _hsmw_ctx_down() { (( __hsmw_ctx_which ++ )) (( __hsmw_ctx_which >= ${#__hsmw_ctx_found} )) && __hsmw_ctx_which=0 __hsmw_ctx_idx=0 _hsmw_ctx_main } _hsmw_ctx_off() { __hsmw_ctx=0 __hsmw_ctx_found=( ) __hsmw_ctx_idx=0 __hsmw_ctx_page_start_idx=0 __hsmw_ctx_prev_offset=0 __hsmw_ctx_to_search="" __hsmw_ctx_which=0 # Reset main state so that it re-highlights __hsmw_prev_offset=0 zle -la _hsmw_ctx_down && zle -D _hsmw_ctx_down zle -la _hsmw_ctx_up && zle -D _hsmw_ctx_up bindkey -M hsmw '^N' "history-search-multi-word" bindkey -M hsmw '^P' "history-search-multi-word-backwards" (( ${1}+0 )) && _hsmw_simulate_widget } if [[ "$WIDGET" = "hsmw-context-main" ]]; then __hsmw_ctx=1-__hsmw_ctx if (( __hsmw_ctx == 0 )); then _hsmw_ctx_off 1 return fi zle -N _hsmw_ctx_down zle -N _hsmw_ctx_up bindkey -M hsmw '^N' "_hsmw_ctx_down" bindkey -M hsmw '^P' "_hsmw_ctx_up" fi _hsmw_ctx_main() { # The repeat will make the matching work on a fresh heap arena local to_search="${__hsmw_hcw_found[__hsmw_hcw_index]}" nl=$'\n' to_search="${to_search//(#m)[][*?|#~^()><\\]/\\$MATCH}" if [[ "$to_search" != "$__hsmw_ctx_to_search" ]]; then __hsmw_ctx_to_search="$to_search" repeat 1; do __hsmw_ctx_found=( "${(@kv)history[(R)$to_search]}" ) __hsmw_ctx_text_idx="${__hsmw_ctx_found[(I)$to_search]}" if [[ "$__hsmw_ctx_text_idx" = "0" ]]; then _hsmw_ctx_off 1 return 0 fi __hsmw_ctx_found[__hsmw_ctx_text_idx]=() done fi integer final_hist_found_idx final_hist_found_idx=__hsmw_ctx_text_idx+__hsmw_ctx_which-1 integer the_index="${__hsmw_ctx_found[final_hist_found_idx]}" the_index=the_index+__hsmw_ctx_idx integer max_index=$(( ${${(k)history[@]}[1]} + 1 )) if [[ "$max_index" -le "0" ]]; then POSTDISPLAY=$'\n'"No matches found" return 0 fi # # Pagination, index value guards # integer page_size="$__hsmw_page_size" [[ "$page_size" -gt "$max_index" ]] && page_size="$max_index" [[ "$the_index" -le 0 ]] && { __hsmw_ctx_idx="$__hsmw_ctx_prev_idx"; the_index=1; } [[ "$the_index" -gt "$(( max_index - 1))" ]] && { __hsmw_ctx_idx="$__hsmw_ctx_prev_idx"; the_index="$(( max_index - 1 ))"; } integer page_start_idx=$(( ((the_index-1)/page_size)*page_size+1 )) integer on_page_idx=$(( page_size - (the_index - page_start_idx) )) # # Prepare display # if [[ "$page_start_idx" != "$__hsmw_ctx_page_start_idx" ]]; then integer idx __hsmw_ctx_disp_list=( ) for (( idx = page_start_idx + page_size - 1; idx >= page_start_idx ; idx -- )); do __hsmw_ctx_disp_list+=( "${history[$idx]}" ) done # Don't do @ splitting, it's slower __hsmw_ctx_disp_list_newlines=( "${__hsmw_ctx_disp_list[@]}" ) # Replace all new lines with "\n" text __hsmw_ctx_disp_list=( "${(@)__hsmw_ctx_disp_list//$'\n'/\\n}" ) # Truncate to display width, preceede by two spaces __hsmw_ctx_disp_list=( "${(@)__hsmw_ctx_disp_list/(#m)*/ ${MATCH[1,COLUMNS-8]}}" ) # The same with newlines adapted for syntax highlighting __hsmw_ctx_disp_list_newlines=( "${(@)__hsmw_ctx_disp_list_newlines//$'\n'/ $nl}" ) __hsmw_ctx_disp_list_newlines=( "${(@)__hsmw_ctx_disp_list_newlines/(#m)*/ ${MATCH[1,COLUMNS-8]}}" ) fi # # Detect where "> .." entry starts, add the ">" mark # local txt_before="${(F)${(@)__hsmw_ctx_disp_list[1,on_page_idx-1]}}" local entry="${__hsmw_ctx_disp_list[on_page_idx]}" local text="${(F)__hsmw_ctx_disp_list}" integer replace_idx=${#txt_before}+2 (( replace_idx == 2 )) && replace_idx=1 text[replace_idx]=">" # # Colorify # local preamble=$'\n'"Showing context of history entry. Ctrl-K to return to search." local preamble2=$'\n'"Ctrl-N/P: next/previous occurence. Occurence #$(( __hsmw_ctx_which + 1 )) of ${#__hsmw_ctx_found}" preamble2=${(r:${#preamble}:: :)preamble2}$'\n' preamble+=$preamble2 integer offset=${#preamble}+${#BUFFER} POSTDISPLAY="$preamble$text" if (( page_start_idx != __hsmw_ctx_page_start_idx || offset != __hsmw_ctx_prev_offset )); then region_highlight=( "${#BUFFER} $offset bg=22" ) if (( __hsmw_synhl )); then integer pre_index=$offset local line for line in "${__hsmw_ctx_disp_list_newlines[@]}"; do reply=( ) -hsmw-highlight-process "$line" "$pre_index" region_highlight+=( $reply ) pre_index+=${#line}+1 done fi else region_highlight[-1]=() fi __hsmw_ctx_page_start_idx=page_start_idx __hsmw_ctx_prev_offset=offset region_highlight+=( "$(( offset + ${#txt_before} )) $(( offset + ${#txt_before} + ${#entry} + 1 )) $__hsmw_active" ) } _hsmw_ctx_main