diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | Doc/Zsh/calsys.yo | 35 | ||||
-rw-r--r-- | Functions/Calendar/age | 13 | ||||
-rw-r--r-- | Functions/Calendar/calendar_add | 2 | ||||
-rw-r--r-- | Functions/Calendar/calendar_scandate | 177 |
5 files changed, 176 insertions, 61 deletions
diff --git a/ChangeLog b/ChangeLog index 8aabed72e..b487f40d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2006-12-04 Peter Stephenson <pws@csr.com> + + * unposted: Doc/Zsh/calsys.yo, Functions/Calendar/age, + Functions/Calendar/calendar_add, + Functions/Calendar/calendar_scandate: autoload missing in + calendar_add; add some date shortcuts for the use of age. + + * 23027: Vin Shelton: Doc/Zsh/calsys.yo: texinfo links were + reversed. + 2006-12-03 Peter Stephenson <p.w.stephenson@ntlworld.com> * 22026: Src/exec.c, Src/subst.c, Src/utils.c, Src/zsh.h, diff --git a/Doc/Zsh/calsys.yo b/Doc/Zsh/calsys.yo index 543bf0935..b2196e448 100644 --- a/Doc/Zsh/calsys.yo +++ b/Doc/Zsh/calsys.yo @@ -172,8 +172,17 @@ in the list above. Otherwise, a time is only recognised as being associated with a date if there is only whitespace in between, or if the time was embedded in the date. -Days of the week are not scanned, but will be ignored if they occur -at the start of the date pattern only. +Days of the week are not normally scanned, but will be ignored if they +occur at the start of the date pattern only. However, in contexts where it +is useful to specify dates relative to today, days of the week with no +other date specification may be given. The day is assumed to be either +today or within the past week. Likewise, the words tt(yesterday), +tt(today) and tt(tomorrow) are handled. All matches are case-insensitive. +Hence if today is Monday, then tt(Sunday) is equivalent to tt(yesterday), +tt(Monday) is equivalent to tt(today), but tt(Tuesday) gives a date six +days ago. This is not generally useful within the calendar file. +Dates in this format may be combined with a time specification; for +example tt(Tomorrow, 8 p.m.). For example, the standard date format: @@ -379,7 +388,20 @@ directly as command or arguments, or separately as shell parameters. example(print *+LPAR()e:age 2006/10/04 2006/10/09:+RPAR()) The example above matches all files modified between the start of those -dates. +dates. The second argument may alternatively be a relative time +introduced by a tt(PLUS()): + +example(print *+LPAR()e:age 2006/10/04 +5d:+RPAR()) + +The example above is equivalent to the previous example. + +In addition to the special use of days of the week, tt(today) and +tt(yesterday), times with no date may be specified; these apply to today. +Obviously such uses become problematic around midnight. + +example(print *+LPAR()e-age 12:00 13:30-+RPAR()) + +The example above shows files modified between 12:00 and 13:00 today. example(print *+LPAR()e:age 2006/10/04:+RPAR()) @@ -508,6 +530,11 @@ In addition to setting tt(REPLY), set tt(REPLY2) to the remainder of the argument after the date and time have been stripped. This is empty if the option tt(-A) was given. ) +item(tt(-t))( +Allow a time with no date specification. The date is assumed to be +today. The behaviour is unspecified if the iron tongue of midnight +is tolling twelve. +) enditem() ) ) @@ -526,7 +553,7 @@ command tt(xmessage) to display a window with the event details. ) enditem() -texinode(Calendar Bugs)(Calendar Utility Functions)()(Calendar Function System) +texinode(Calendar Bugs)()(Calendar Utility Functions)(Calendar Function System) sect(Bugs) There is no tt(calendar_delete) function. diff --git a/Functions/Calendar/age b/Functions/Calendar/age index 2d193f473..b6f648adb 100644 --- a/Functions/Calendar/age +++ b/Functions/Calendar/age @@ -55,11 +55,18 @@ fi integer mtime=$vals[1] date1 date2 local REPLY -if calendar_scandate $AGEREF; then +# allow a time only (meaning today) +if calendar_scandate -t $AGEREF; then date1=$REPLY - if [[ -n $AGEREF2 ]] && calendar_scandate $AGEREF2; then - date2=$REPLY + if [[ -n $AGEREF2 ]]; then + if [[ $AGEREF2 = +* ]]; then + calendar_scandate -rt $AGEREF2[2,-1] || return 1 + (( date2 = date1 + REPLY )) + else + calendar_scandate -t $AGEREF2 || return 1 + date2=$REPLY + fi else (( date2 = date1 + 24 * 60 * 60 )) fi diff --git a/Functions/Calendar/calendar_add b/Functions/Calendar/calendar_add index 2a00811fd..f7f60e136 100644 --- a/Functions/Calendar/calendar_add +++ b/Functions/Calendar/calendar_add @@ -14,7 +14,7 @@ local calendar newfile REPLY lastline local -a calendar_entries lockfiles integer newdate done rstat -autoload -U calendar_{read,lockfiles} +autoload -U calendar_{read,lockfiles,scandate} # Read the calendar file from the calendar-file style zstyle -s ':datetime:calendar_add:' calendar-file calendar || diff --git a/Functions/Calendar/calendar_scandate b/Functions/Calendar/calendar_scandate index f0024b89a..825aaf65b 100644 --- a/Functions/Calendar/calendar_scandate +++ b/Functions/Calendar/calendar_scandate @@ -161,6 +161,7 @@ local daypat="${schars}#(sun|mon|tue|wed|thu|fri|sat)[a-z]#${schars}#" # the day of the week is greedy, so the day of the week gets ignored # if it's optional.) local dspat_anchor="(|(#B)${daypat}(#b)${schars}#)" +local dspat_anchor_noday="(|${schars}#)" # Date start pattern when not anchored at the start. local dspat_noanchor="(|*${schars})" # end pattern for relative times: similar remark about use of $schars. @@ -171,18 +172,20 @@ local repat="(|s)(|${schars}*)" local monthpat="(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]#" # days, not handled but we need to ignore them. also not localized. -integer year month day hour minute second +integer year month day hour minute second then local opt line orig_line mname MATCH MBEGIN MEND tz local -a match mbegin mend # Flags that we found a date or a time (maybe a relative time) integer date_found time_found +# Flag that it's OK to have a time only +integer time_ok # Indices of positions of start and end of time and dates found. # These are actual character indices as zsh would normally use, i.e. # line[time_start,time_end] is the string for the time. integer time_start time_end date_start date_end integer anchor anchor_end debug relative reladd setvar -while getopts "aAdrs" opt; do +while getopts "aAdrst" opt; do case $opt in (a) # anchor @@ -207,6 +210,10 @@ while getopts "aAdrs" opt; do (( setvar = 1 )) ;; + (t) + (( time_ok = 1 )) + ;; + (*) return 1 ;; @@ -216,10 +223,11 @@ shift $(( OPTIND - 1 )) line=$1 orig_line=$1 -local dspat tspat +local dspat dspat_noday tspat if (( anchor )); then # Anchored at the start. dspat=$dspat_anchor + dspat_noday=$dspat_anchor_noday if (( relative )); then tspat=$tspat_anchor else @@ -228,6 +236,7 @@ if (( anchor )); then fi else dspat=$dspat_noanchor + dspat_noday=$dspat_noanchor tspat=$tspat_noanchor fi @@ -370,70 +379,132 @@ if (( relative == 0 )); then date_start=$mbegin[2] date_end=$mend[7] date_found=1 ;; + + # Look for WEEKDAY + ((#bi)${~dspat_noday}(${~daypat})*) + integer wday_now wday + local wdaystr=${(L)match[3]} + date_start=$mbegin[2] date_end=$mend[2] + + # Find the day number. + local -a wdays + # This is the ordering of %w in strtfime (zero-offset). + wdays=(sun mon tue wed thu fri sat sun) + (( wday = ${wdays[(i)$wdaystr]} - 1 )) + + # Find the date for that day. + (( then = EPOCHSECONDS )) + strftime -s wday_now "%w" $then + # Day is either today or in the past. + (( wday_now < wday )) && (( wday_now += 7 )) + (( then -= (wday_now - wday) * 24 * 60 * 60 )) + strftime -s year "%Y" $then + strftime -s month "%m" $then + strftime -s day "%d" $then + date_found=1 + ;; + + # Look for "today", "yesterday", "tomorrow" + ((#bi)${~dspat_noday}(yesterday|today|tomorrow)(|${schars})*) + (( then = EPOCHSECONDS )) + case ${(L)match[2]} in + (yesterday) + (( then -= 24 * 60 * 60 )) + ;; + + (tomorrow) + (( then += 24 * 60 * 60 )) + ;; + esac + strftime -s year "%Y" $then + strftime -s month "%m" $then + strftime -s day "%d" $then + date_start=$mbegin[2] date_end=$mend[2] + date_found=1 + ;; esac fi -if (( date_found )); then +if (( date_found || (time_ok && time_found) )); then # date found # see if there's a day at the start - if [[ ${line[1,$date_start-1]} = (#bi)${~daypat} ]]; then - date_start=$mbegin[1] + if (( date_found )); then + if [[ ${line[1,$date_start-1]} = (#bi)${~daypat} ]]; then + date_start=$mbegin[1] + fi + line=${line[1,$date_start-1]}${line[$date_end+1,-1]} fi - line=${line[1,$date_start-1]}${line[$date_end+1,-1]} if (( time_found )); then - # If we found a time, it must be associated with the date, - # or we can't use it. Since we removed the time from the - # string to find the date, however, it's complicated to - # know where both were found. Reconstruct the date indices of - # the original string. - if (( time_start <= date_start )); then - # Time came before start of date; add length in. - (( date_start += time_end - time_start + 1 )) - fi - if (( time_start <= date_end )); then - (( date_end += time_end - time_start + 1 )) - fi + if (( date_found )); then + # If we found a time, it must be associated with the date, + # or we can't use it. Since we removed the time from the + # string to find the date, however, it's complicated to + # know where both were found. Reconstruct the date indices of + # the original string. + if (( time_start <= date_start )); then + # Time came before start of date; add length in. + (( date_start += time_end - time_start + 1 )) + fi + if (( time_start <= date_end )); then + (( date_end += time_end - time_start + 1 )) + fi - if (( time_end + 1 < date_start )); then - # If time wholly before date, OK if only separator characters - # in between. (This allows some illogical stuff with commas - # but that's probably not important.) - if [[ ${orig_line[time_end+1,date_start-1]} != ${~schars}# ]]; then - # Clearly this can't work if anchor is set. In principle, - # we could match the date and ignore the time if it wasn't. - # However, that seems dodgy. - return 1 - else - # Form massaged line by removing the entire date/time chunk. - line="${orig_line[1,time_start-1]}${orig_line[date_end+1,-1]}" + if (( time_end + 1 < date_start )); then + # If time wholly before date, OK if only separator characters + # in between. (This allows some illogical stuff with commas + # but that's probably not important.) + if [[ ${orig_line[time_end+1,date_start-1]} != ${~schars}# ]]; then + # Clearly this can't work if anchor is set. In principle, + # we could match the date and ignore the time if it wasn't. + # However, that seems dodgy. + return 1 + else + # Form massaged line by removing the entire date/time chunk. + line="${orig_line[1,time_start-1]}${orig_line[date_end+1,-1]}" + fi + elif (( date_end + 1 < time_start )); then + # If date wholly before time, OK if only time separator characters + # in between. This allows 2006/10/12:13:43 etc. + if [[ ${orig_line[date_end+1,time_start-1]} != ${~tschars}# ]]; then + # Here, we assume the time is associated with something later + # in the line. This is pretty much inevitable for the sort + # of use we are expecting. For example, + # 2006/10/24 Meeting from early, may go on till 12:00. + # or with some uses of the calendar system, + # 2006/10/24 MR 1 Another pointless meeting WARN 01:00 + # The 01:00 says warn an hour before, not that the meeting starts + # at 1 am. About the only safe way round would be to force + # a time to be present, but that's not how the traditional + # calendar programme works. + # + # Hence we need to reconstruct. + (( time_found = 0, hour = 0, minute = 0, second = 0 )) + line="${orig_line[1,date_start-1]}${orig_line[date_end+1,-1]}" + else + # As above. + line="${orig_line[1,date_start-1]}${orig_line[time_end+1,-1]}" + fi fi - elif (( date_end + 1 < time_start )); then - # If date wholly before time, OK if only time separator characters - # in between. This allows 2006/10/12:13:43 etc. - if [[ ${orig_line[date_end+1,time_start-1]} != ${~tschars}# ]]; then - # Here, we assume the time is associated with something later - # in the line. This is pretty much inevitable for the sort - # of use we are expecting. For example, - # 2006/10/24 Meeting from early, may go on till 12:00. - # or with some uses of the calendar system, - # 2006/10/24 MR 1 Another pointless meeting WARN 01:00 - # The 01:00 says warn an hour before, not that the meeting starts - # at 1 am. About the only safe way round would be to force - # a time to be present, but that's not how the traditional - # calendar programme works. - # - # Hence we need to reconstruct. - (( time_found = 0, hour = 0, minute = 0, second = 0 )) - line="${orig_line[1,date_start-1]}${orig_line[date_end+1,-1]}" - else - # As above. - line="${orig_line[1,date_start-1]}${orig_line[time_end+1,-1]}" + else + # Time only. + # We didn't test anchors for time originally, since it + # might have been embedded in the date. If there's no date, + # we need to test specially. + if (( anchor )) && + [[ ${orig_line[1,time_start-1]} != ${~tschars}# ]]; then + # Anchor at start failed. + return 1 fi + strftime -s year "%Y" $EPOCHSECONDS + strftime -s month "%m" $EPOCHSECONDS + strftime -s day "%d" $EPOCHSECONDS + # Date now handled. + (( date_found = 1 )) fi if (( debug )); then print "Time string: $time_start,$time_end:" \ "'$orig_line[time_start,time_end]'" - print "Date string: $date_start,$date_end:" \ + (( date_ok )) && print "Date string: $date_start,$date_end:" \ "'$orig_line[date_start,date_end]'" print "Remaining line: '$line'" fi |