From 396f68971fef574160e780c01d12a58747f5d224 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Tue, 7 Jul 2015 22:59:00 +0200 Subject: 35718: new calendar style date completion --- ChangeLog | 5 ++ Completion/Unix/Command/_find | 21 +++++-- Completion/Unix/Type/_dates | 123 +++++++++++++++++++++++++++++++++++++++++ Completion/Zsh/Type/_globquals | 11 ++-- 4 files changed, 150 insertions(+), 10 deletions(-) create mode 100644 Completion/Unix/Type/_dates diff --git a/ChangeLog b/ChangeLog index 1f4e3f999..0c60eedf9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-07-06 Oliver Kiddle + + * 35718: Completion/Unix/Command/_find, Completion/Unix/Type/_dates, + Completion/Zsh/Type/_globquals: new calendar style date completion + 2015-07-07 Peter Stephenson * unposted: Src/Zle/complete.c: remove compiler warning. diff --git a/Completion/Unix/Command/_find b/Completion/Unix/Command/_find index 8f80e36cf..aefca34f2 100644 --- a/Completion/Unix/Command/_find +++ b/Completion/Unix/Command/_find @@ -1,6 +1,7 @@ #compdef find gfind -local variant args +local curcontext="$curcontext" state_descr variant +local -a state line args alts _pick_variant -r variant gnu=GNU $OSTYPE -version @@ -114,11 +115,11 @@ case $variant in ;; esac -_arguments $args \ +_arguments -C $args \ '(-L -P)-H[only follow symlinks when resolving command-line arguments]' \ '(-H -P)-L[follow symlinks]' \ - '*-atime:access time (days)' \ - '*-ctime:inode change time (days)' \ + '*-atime:access time (days):->times' \ + '*-ctime:inode change time (days):->times' \ '*-depth' \ '*-exec:program: _command_names -e:*\;::program arguments: _normal' \ '*-follow' \ @@ -128,7 +129,7 @@ _arguments $args \ '*-links:number of links:' \ '*-ls' \ '*-mount' \ - '*-mtime:modification time (days)' \ + '*-mtime:modification time (days):->times' \ '*-name:name pattern' \ '*-newer:file to compare (modification time):_files' \ '*-nogroup' \ @@ -143,3 +144,13 @@ _arguments $args \ '*-xdev' \ '*-a' '*-o' \ '*:directory:_files -/' + +if [[ $state = times ]]; then + if ! compset -P '[+-]' || [[ -prefix '[0-9]' ]]; then + disp=( 'before' 'exactly' 'since' ) + compstate[list]+=' packed' + alts=( "senses:sense:compadd -V times -S '' -d disp - + '' -" ) + fi + alts+=( "times:${state_descr}:_dates -f d" ) + _alternative $alts +fi diff --git a/Completion/Unix/Type/_dates b/Completion/Unix/Type/_dates new file mode 100644 index 000000000..486a2c229 --- /dev/null +++ b/Completion/Unix/Type/_dates @@ -0,0 +1,123 @@ +#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. +# 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 explain +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 X:=explain +(( 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 + +_message -e dates ${explain[2]:-date} +(( rows )) || return +_description -2V -x dates expl date +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 diff --git a/Completion/Zsh/Type/_globquals b/Completion/Zsh/Type/_globquals index 042b27400..5cdb8f7c4 100644 --- a/Completion/Zsh/Type/_globquals +++ b/Completion/Zsh/Type/_globquals @@ -1,7 +1,7 @@ #autoload local state=qual expl char delim timespec -local -a alts +local -a alts tdisp sdisp local -A specmap while [[ -n $PREFIX ]]; do @@ -117,14 +117,15 @@ while [[ -n $PREFIX ]]; do alts=() timespec=$PREFIX[1] if ! compset -P '[Mwhmsd]' && [[ -z $PREFIX ]]; then - alts+=("time-specifiers:time specifier:\ -((M\:months w\:weeks h\:hours m:\minutes s\:seconds d\:days))") + tdisp=( seconds minutes hours days weeks Months ) + alts+=( "time-specifiers:time specifier:compadd -E 0 -d tdisp -S '' - s m h d w M" ) fi if ! compset -P '[-+]' && [[ -z $PREFIX ]]; then - alts+=("senses:sense:((-\:less\ than +\:more\ than))") + sdisp=( before exactly since ) + alts+=("senses:sense:compadd -E 0 -d sdisp -S '' - + '' -") fi specmap=( M months w weeks h hours m minutes s seconds '(|+|-|d)' days) - alts+=('digits:digit ('${${specmap[(K)$timespec]}:-invalid time specifier}'):' ) + alts+=('digits:digit ('${${specmap[(K)$timespec]}:-invalid time specifier}'):_dates -f ${${timespec/[-+]/d}:-d} -S ""' ) _alternative $alts return fi -- cgit 1.4.1