From 2e079dd7788c0b35210b07d856084c3c166c50c8 Mon Sep 17 00:00:00 2001 From: Sinkerine Date: Sun, 28 Jan 2018 11:46:21 -0500 Subject: [PATCH] [+] zce --- custom/plugins/zce/zce.plugin.zsh | 1 + custom/plugins/zce/zce.zsh | 280 ++++++++++++++++++++++++++++++ 2 files changed, 281 insertions(+) create mode 100644 custom/plugins/zce/zce.plugin.zsh create mode 100644 custom/plugins/zce/zce.zsh diff --git a/custom/plugins/zce/zce.plugin.zsh b/custom/plugins/zce/zce.plugin.zsh new file mode 100644 index 000000000..feac4199e --- /dev/null +++ b/custom/plugins/zce/zce.plugin.zsh @@ -0,0 +1 @@ +source ${0:A:h}/zce.zsh diff --git a/custom/plugins/zce/zce.zsh b/custom/plugins/zce/zce.zsh new file mode 100644 index 000000000..45f652aa9 --- /dev/null +++ b/custom/plugins/zce/zce.zsh @@ -0,0 +1,280 @@ +# vim's EasyMotion / Emacs's ace-jump-mode for zsh. + +# Author: Takeshi Banse +# License: BSD-3 + +# Thank you very much, Kim Silkebækken and winterTTr! +# I want to use the EasyMotion/ace-jump-mode in zsh. + +# Code + +zce-genh-loop-key () { + local place="$1"; shift + local keys="$1"; shift + local val="${(P)place}" + local k= l=; for k l in ${@}; do + local -i i=l; while ((i>0)); do + val="$val ${${:-${k}${keys[i]}}# }" + ((i--)) + done + : ${(P)place::=${val# }} + done +} + +zce-genh-loop () { + local succ="$1"; shift + local posstr="$1"; shift + local qchar="$1"; shift + local buffer="$1"; shift + local keyfun="$1"; shift + local keystr="$1"; shift + local -i n="$1"; shift + local -i m="$1"; shift + local a="$1"; shift + local -a as; : ${(A)as::=${(s. .)a}} + local -a kns; : ${(A)kns::=${(@)@}} + + if ((n == 0)); then + local tmp=; + ${keyfun} tmp ${keystr} ${kns[@]} + ${succ} ${qchar} $buffer ${tmp# }${a:+" "}${a} "$posstr"; return $? + elif [[ -z "$a" ]]; then + ${keyfun} a ${keystr} ${kns[@]} + ${0} ${succ} ${posstr} ${qchar} ${buffer} ${keyfun} ${keystr} \ + ${n} ${m} $a; return $? + else + local k=${as[1]}; shift as + local -i len; ((len=n $#keys)); then + zce-genh-loop "$kont" ${(j. .)ps} $c $b zce-genh-loop-key "$keys" \ + $(($#ps - $#keys + 1)) $#keys '' ' ' $#keys + else + zce-genh-loop "$kont" ${(j. .)ps} $c $b zce-genh-loop-key "$keys" \ + 0 $#keys '' ' ' $#ps + fi +} + +zce-2 () { + local c="$1" + local b="$2" + local oks="$3" + local ops="$4" + zce-2-raw "$c" "$b" "$oks" "$ops" \ + zce-move-cursor zce-keyin-loop zce-keyin-read +} + +zce-2-raw () { + setopt localoptions extendedglob + local c="$1"; shift + local b="$1"; shift + local oks="$1"; local -a ks; : ${(A)ks::=${=1}}; shift + local ops="$1"; local -a ps; : ${(A)ps::=${(Oa)${=1}}}; shift + local movecfun="$1"; shift + local keyinfun="$1"; shift + local kreadfun="$1"; shift + local -i i; ((i=$#ps)) + + if (($i==0)); then + zce-fail; return $? + elif (($i==1)); then + $movecfun $ps[1]; return $? + fi + + local -i n=1 + local null=$'\0' + local MATCH MBEGIN MEND + ${keyinfun} '' "$b" "${b//(#m)${c}/${ks[i--][1]}}" \ + "${movecfun}" "${keyinfun}" "${kreadfun}" \ + -- ${(s. .)${:-"${oks//(#m)$'\t'/$null$ps[((n++))] }$null$ps[n]"}} +} + +zce-fail () { + return -1 +} + +zce-move-cursor () { + ((CURSOR = $1 - 1)) + return 0 +} + +zce-readc () { + if [[ "${3-}" == "t" ]] && + {[[ -z "${POSTDISPLAY-}" ]] || [[ "${POSTDISPLAY-}" != *"\n"* ]]}; then + echoti cud1 + echoti cuu1 + zle reset-prompt + fi + echoti sc + echoti cud 1 + echoti hpa 0 2>/dev/null || echo -n '\x1b[1G' + echoti el + print -Pn $2 + read -s -k 1 $1 + local ret=$? + echoti hpa 0 2>/dev/null || echo -n '\x1b[1G' + echoti el + echoti rc + return $ret +} + +zce-keyin-read () { + local s=; zstyle -s ':zce:*' prompt-key s || \ + s='%{\e[1;32m%}Target key:%{\e[0m%} ' + zce-readc "$1" "$s" +} + +zce-keyin-loop () { + local -a region_highlight + local fg=; zstyle -s ':zce:*' fg fg || fg='fg=196,bold' + local bg=; zstyle -s ':zce:*' bg bg || bg='fg=black,bold' + zce-keyin-loop-raw "$fg" "$bg" "$@" +} + +zce-keyin-loop-raw () { + setopt localoptions extendedglob + local hispec="$1"; shift + local dimspec="$1"; shift + local key="$1"; shift + local ob="$1"; shift + local nb="$1"; shift + local movecfun="$1"; shift + local keyinfun="$1"; shift + local kreadfun="$1"; shift + shift; # dashdash + + local -i c=0; ((c=$#@)) + if ((c == 0)); then + zce-fail; return -1 + elif ((c == 1)); then + zce-move-cursor ${1#*$'\0'}; return 0 + fi + + local MATCH MBEGIN MEND + if [[ -z "$key" ]]; then + BUFFER="$nb" + region_highlight=("0 $#BUFFER $dimspec") + region_highlight+=(${${@#*$'\0'}/(#m)[[:digit:]]##/$((MATCH-1)) $MATCH $hispec}) + else + nb="$ob" + local tmp; for tmp in ${(M)@:#${key}*}; do + nb[${tmp#*$'\0'}]="${${tmp%$'\0'*}[(($#key+1))]}" + done + BUFFER="$nb" + region_highlight=("0 $#BUFFER $dimspec") + region_highlight+=(${${${(M)@:#${key}*}#*$'\0'}/(#m)[[:digit:]]##/$((MATCH-1)) $MATCH $hispec}) + fi + zle -R + + local key2=; ${kreadfun} key2 && \ + ${0} $hispec $dimspec "${key}${key2}" "$ob" "$nb" \ + "$movecfun" "$keyinfun" "$kreadfun" \ + -- "${(M)@:#${key}${key2}*}" || { + zce-fail; return -1 + } +} + +with-zce () { + zmodload zsh/terminfo 2>/dev/null + setopt localoptions extendedglob braceccl + local orig_buffer="$BUFFER" + local -i orig_cursor; ((orig_cursor=CURSOR)) + ((CURSOR=$#BUFFER)); zle -R + local -a region_highlight + { + local keys=; zstyle -s ':zce:*' keys keys || \ + keys=${(j..)$(print {a-z} {A-Z})} + "$@" "$keys" || { ((CURSOR=orig_cursor)) } + } always { + BUFFER="$orig_buffer" + zle redisplay + } +} + +zce-searchin-read () { + local s=; zstyle -s ':zce:*' prompt-char s || \ + s='%{\e[1;32m%}Search for character:%{\e[0m%} ' + zce-readc "$1" "$s" t +} + +zce-raw () { + local c=; "$1" c + [[ "$c" == [[:print:]] ]] && { + zce-1 "$c" "$BUFFER" zce-2 "$2" + } +} + +zce () { with-zce zce-raw zce-searchin-read } + +zle -N zce + +# zcompiling code. + +zce-zcompile-clean () { + local d=${1:-~/.zsh/zfunc} + rm -f ${d}/zce{,zwc*(N)} +} + +zce-zcompile () { + local s=${1:?Please specify the source file itself.} + local d=${2:?Please specify the directory for the zcompiled file.} + setopt localoptions extendedglob no_shwordsplit + + echo "** zcompiling zce in ${d} for a little faster startups..." + echo "mkdir -p ${d}" | sh -x + zce-zcompile-clean + + local g=${d}/zce + echo "* writing code ${g}" + { + local - fs + : ${(A)fs::=${(Mk)functions:#(*zce*)}} + echo "#!zsh" + echo "# NOTE: Generated from zce.zsh ($0). Please DO NOT EDIT."; echo + local -a es; es=('zce-zcompile*') + echo "$(functions ${fs:#${~${(j.|.)es}}})" + echo "\nzce" + } >| ${g} + + [[ -z ${ZCE_NOZCOMPILE-} ]] || return + autoload -U zrecompile && { + echo -n "* "; zrecompile -p -R ${g} + } && { + zmodload zsh/datetime + touch --date="$(strftime "%F %T" $((EPOCHSECONDS + 10)))" ${g}.zwc + [[ -z ${ZCE_ZCOMPILE_NOKEEP-} ]] || { echo "rm -f ${g} ${g}.zwc.*" | sh -x } + echo "** All done." + echo "** Please update your .zshrc to load the zcompiled file like this," + cat <8 -- +## zce.zsh stuff. +# source ${s/$HOME/~} +autoload -w ${g}; zle -N zce +# bindkey "^Xz" zce +-- 8< -- +EOT + } +}