#!/usr/bin/env zsh [[ -v _z4h_tty_fd ]] || return autoload +X -Uz -- -z4h-present-files -z4h-cursor-show -z4h-find -z4h-fzf local -i dot_glob list_types [[ -o dot_glob ]] && dot_glob=1 [[ -o list_types ]] && list_types=1 -z4h-set-list-colors :complete:cd:: $list_types local -i list_colors=$((!$?)) (( ${+_z4h_dir_hist_fd} )) && -z4h-update-dir-history { -z4h-cursor-hide local -i first=1 while true; do local -i redraw=0 again=0 () { eval "$_z4h_opt" if (( first )); then local -i num_dirs=$#_z4h_dir_history local -i num_non_empty=0 else if (( dot_glob )); then local dirs=(*(-/DN)) else local dirs=(*(-/N)) fi local non_empty=(${^${dirs}}/*(D-/Y1N:h:t)) (( $#dirs )) || return 0 local -i num_dirs=$#dirs local -i num_non_empty=$#non_empty fi { -z4h-show-dots '' local -i pct=60 (( _z4h_can_save_restore_screen )) && pct=100 local -i height=$(( ! num_non_empty && 100 * (num_dirs + 4) < pct * LINES ? num_dirs + 4 : pct * LINES / 100 )) (( height >= 6 )) || (( height = 6 )) (( height <= LINES - 1 )) || (( height = LINES - 1 )) local opts=( --color=hl:201,hl+:201 --with-nth=2 --delimiter='\000' --ansi --exact --no-mouse --tiebreak=length,begin,index --no-multi --border=horizontal ) if (( first )); then opts+=(--no-sort) else () { emulate -L zsh # Set dot_glob in case the value of find-flags depends on it (via `zstyle -e`). # Ideally we should run this with user options. (( dot_glob )) && setopt dot_glob local -a bin zstyle -a :z4h:${WIDGET#z4h-} find-command bin if (( ! $#bin )) && (( $+commands[bfs] )); then opts+=(--no-sort) fi } fi local cursor_y cursor_x -z4h-get-cursor-pos || return if (( _z4h_can_save_restore_screen )); then opts+=(--no-clear) if { (( height <= cursor_y - 1 )) && zstyle -T :z4h: prompt-at-bottom } || (( cursor_y - 1 > LINES - cursor_y && cursor_y - 1 > 4 )) && { (( height > LINES - cursor_y )) || zstyle -T :z4h: prompt-at-bottom }; then (( height <= cursor_y - 1 )) || (( height = cursor_y - 1 )) local move=$'\e[0m\e['$((cursor_y-height))';1H' opts+=(--layout=default) elif (( LINES - cursor_y > 4 )); then (( height <= LINES - cursor_y )) || (( height = LINES - cursor_y )) local move=$'\e[0m\n\r' opts+=(--layout=reverse) else local -i extra=$((height - LINES + cursor_y)) print -rnu $_z4h_tty_fd -- ${(pl:$height::\n:)} || return (( cursor_y += LINES - cursor_y - height )) local move=$'\e[0m\e['$((cursor_y+1))';1H' opts+=(--layout=reverse) fi local _z4h_saved_screen -z4h-save-screen || return else print -u $_z4h_tty_fd || return local move= opts+=(--layout=reverse) fi opts+=(--height=$height) { local choice choice=$( unsetopt pipe_fail exec 2>/dev/null { print -r -- $sysparams[pid] if (( first )); then local dir for dir in $_z4h_dir_history; do { # There is a bug in zsh that triggers if these two # expansions are combined: ${(g:oce:)${~dir}}. dir=${~dir} if [[ -d ${dir::=${(g:oce:)dir}} && $dir != *$'\n'* ]]; then print -r -- $dir fi } always { TRY_BLOCK_ERROR=0 } done 2>/dev/null else print -rC1 -- $dirs -z4h-find $dot_glob 1 $non_empty | command sed -n '/\/.*\// s/^..//p' fi } | { local -a pids IFS=' ' builtin read -rA pids || exit print -r -- $pids $sysparams[pid] || exit -z4h-present-files $list_colors $list_types 1 } | { local -a pids IFS=' ' builtin read -rA pids || pids=() print -rnu $_z4h_tty_fd -- $move -z4h-cursor-show 2>&$_z4h_tty_fd -z4h-fzf $opts (( $#pids )) && builtin kill -- $pids } always { -z4h-cursor-hide }) [[ -n $choice ]] || return choice=("${(@f)choice}") [[ -n $choice[1] ]] && again=1 # Weird chars don't roundtrip, so the directory may not exist. cd -- ${choice[2]%%$'\0'*} 2>/dev/null || return redraw=1 } always { if (( _z4h_can_save_restore_screen )); then -z4h-restore-screen print -rn -- $'\e[0m\e['$cursor_y';'$cursor_x'H' else builtin echoti cuu 1 (( cursor_x > 1 )) && builtin echoti cuf $((cursor_x-1)) fi } } always { zle -R } } || return (( redraw )) && -z4h-redraw-prompt 1 (( again )) || break first=0 done } always { -z4h-cursor-show }