#autoload # Options: # -f format : specify strftime format for matches # -f s/m/h/d/w/M : specify relative format # -F : select a future rather than past date # Styles: # max-matches-length : maximum number or percentage of lines to use for # completion listing, if both are specified, the # lowest takes precedence. # date-format : override date format local -a disp cand expl local userformat format spacer=1 spacing month monstart skip match local d day daysecs extra preclude r ri col local -a starts skips local -i start now mult local -i columns=$(( (COLUMNS+4) / 32 )) rows=LINES-4 offset=0 local -a days=( Mo Tu We Th Fr Sa Su ) local future mlabel mfmt mlabels zparseopts -D -K -E f:=format F=future (( future = $#future ? 1 : -1 )) zstyle -s ":completion:${curcontext}:dates" date-format userformat format=${userformat:-${format[2]:-%F}} zstyle -a ":completion:${curcontext}:dates" max-matches-length r for ri in $r; do [[ $ri = [0-9]##% ]] && (( ri = LINES * .${ri%%%} )) (( ri < rows )) && (( rows=ri )) done (( rows = rows / 8 )) zmodload -i zsh/datetime || rows=0 _tags dates || return 0 _comp_mesg=yes _description -2V -x dates expl date compadd "${@:/-X/-x}" "$expl[@]" - [[ -z $MENUSELECT && $WIDGET != menu-select ]] && return [[ -n $PREFIX$SUFFIX ]] && return 0 (( rows )) || return 0 compstate[list]='packed rows' if [[ $WIDGET = _next_tags ]]; then typeset -g -i _next_tags_line typeset -g -i _next_tags_date=$(( HISTNO == _next_tags_line ? _next_tags_date+1 : 1)) _next_tags_line=HISTNO (( offset = _next_tags_date*rows*columns )) fi (( now=EPOCHSECONDS )) strftime -s year '%Y' $now strftime -s month '%m' $now (( offset = future*offset + year*12 + month + ((future == 1) ? rows*columns-2 : -1) )) for ((;rows;rows--)); do disp=() mlabels="" for ((col=1;col<=columns;col++)); do (( start = offset + col - rows * columns )) strftime -r -s monstart '%Y%m' $(( start/12 ))$(( 1 + start % 12 )) strftime -s skip '%w' $(( monstart-86400 )) starts[col]=$monstart skips[col]=$skip disp+=( $days ' ' ) mfmt='%B' strftime -s mlabel '%m' $monstart [[ $mlabel = 01 ]] && mfmt+=' %Y' strftime -s mlabel "$mfmt" $monstart mlabels+="${(r.(col == columns) ? 28 : 32.):-${(l.(26-$#mlabel)/2.)}$mlabel}" done (( spacing = COLUMNS - 32 * columns + 2 )) disp[-1]="${(l.spacing.)}" (( spacing < 2 )) && spacer=0 disp[-1]=() expl[1+expl[(i)-V]]=dates-$rows compadd -x "$mlabels" "$expl[@]" -d disp -E $(( $#disp )) for ((line=0;line<6;line++)); do for ((col=1;col<=columns;col++)); do if (( skips[col] && !line )); then disp=(); disp[skips[col]]='' compadd -x "$mlabels" "$expl[@]" -d disp -E $skips[col] (( skip=skips[col] )) else skip=0 fi disp=() cand=() (( extra = (col == columns) ? spacer : 1 )) (( preclude = 0 )) for ((d=1;d<=7-skip;d++)); do (( day = d+7*line+skip-skips[col] )) (( daysecs = starts[col] + 86400 * (day - 1) )) strftime -s realday '%d' $daysecs if (( realday != day )); then (( extra+=8-d )) break fi (( mult = -future * (now - daysecs) + (future == 1 ? 86400 : 0) )) case $format in s) (( match = mult )) ;; m) (( match = mult / 60 )) ;; h) (( match = mult / 3600 )) ;; d) (( match = mult / 86400 )) ;; w) (( match = mult / 604800 )) ;; M) (( match = mult / 2592000 )) ;; *) strftime -s match - $format $daysecs ;; esac disp+=( "${(l.2.)day}" ) if (( future < 0 && now < daysecs )); then (( extra++ )) elif (( future > 0 && (now - daysecs) > 86400 )); then (( preclude++ )) else (( (now - daysecs) < 86400 && (now - daysecs) > 0 )) && compstate[insert]=menu:$(( compstate[nmatches] + $#disp )) cand+=( "$match" ) fi done if (( preclude )); then compadd -x "$mlabels" "$expl[@]" -E $preclude -d disp shift preclude disp fi compadd -x "$mlabels" -U -i "$IPREFIX" -I "$ISUFFIX" "$expl[@]" "$@" -d disp -E $extra -a cand done done done