summaryrefslogtreecommitdiff
path: root/Functions/Calendar
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2007-11-29 09:49:42 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2007-11-29 09:49:42 +0000
commitf518a387a8d7a1178b38943ffffe70b40dfc98ce (patch)
tree6b052fc58e0ad977cd513c8718ba53c653824472 /Functions/Calendar
parent5b887fa759f503ed854c44ecc759f1596ed8a104 (diff)
downloadzsh-f518a387a8d7a1178b38943ffffe70b40dfc98ce.tar.gz
zsh-f518a387a8d7a1178b38943ffffe70b40dfc98ce.zip
Kohsuke Kawaguchi: 24129: when completing ant targets,
skip those beginning - that cant be invoked from the command line
Diffstat (limited to 'Functions/Calendar')
-rw-r--r--Functions/Calendar/.distfiles23
-rw-r--r--Functions/Calendar/calendar45
-rw-r--r--Functions/Calendar/calendar_add62
-rw-r--r--Functions/Calendar/calendar_parse83
4 files changed, 169 insertions, 44 deletions
diff --git a/Functions/Calendar/.distfiles b/Functions/Calendar/.distfiles
index c49469431..7c14c384a 100644
--- a/Functions/Calendar/.distfiles
+++ b/Functions/Calendar/.distfiles
@@ -1,13 +1,14 @@
DISTFILES_SRC='
- .distfiles
- age
- calendar
- calendar_add
- calendar_edit
- calendar_lockfiles
- calendar_read
- calendar_scandate
- calendar_show
- calendar_showdate
- calendar_sort
+.distfiles
+age
+calendar
+calendar_add
+calendar_edit
+calendar_lockfiles
+calendar_parse
+calendar_read
+calendar_scandate
+calendar_show
+calendar_showdate
+calendar_sort
'
diff --git a/Functions/Calendar/calendar b/Functions/Calendar/calendar
index 7dec84e28..246cf2383 100644
--- a/Functions/Calendar/calendar
+++ b/Functions/Calendar/calendar
@@ -1,18 +1,19 @@
emulate -L zsh
setopt extendedglob
-local line showline restline REPLY REPLY2 userange pruned nobackup datefmt
+local line showline restline REPLY REPLY2 userange nobackup datefmt
local calendar donefile sched newfile warnstr mywarnstr newdate
integer time start stop today ndays y m d next=-1 shown done nodone
integer verbose warntime mywarntime t tcalc tsched i rstat remaining
integer showcount icount repeating repeattime resched showall brief
local -a calendar_entries calendar_addlines
local -a times calopts showprog lockfiles match mbegin mend
+local -A reply
zmodload -i zsh/datetime || return 1
zmodload -i zsh/zutil || return 1
-autoload -U calendar_{add,read,scandate,show,lockfiles}
+autoload -U calendar_{add,parse,read,scandate,show,lockfiles}
# Read the calendar file from the calendar-file style
zstyle -s ':datetime:calendar:' calendar-file calendar || calendar=~/calendar
@@ -254,31 +255,29 @@ fi
calendar_read $calendar
for line in $calendar_entries; do
- # This call sets REPLY to the date and time in seconds since the epoch,
- # REPLY2 to the line with the date and time removed.
- calendar_scandate -as $line || continue
- (( t = REPLY ))
- restline=$REPLY2
-
+ calendar_parse $line || continue
+
+ # Extract returned parameters from $reply
+ # Time of event
+ (( t = ${reply[time]} ))
+ # Remainder of line including RPT and WARN stuff: we need
+ # to keep these for rescheduling.
+ restline=$reply[text1]
# Look for specific warn time.
- pruned=${restline#(|*[[:space:],])WARN[[:space:]]}
- (( mywarntime = warntime ))
- mywarnstr=$warnstr
- if [[ $pruned != $restline ]]; then
- if calendar_scandate -asm -R $t $pruned; then
- (( mywarntime = t - REPLY ))
- mywarnstr=${pruned%%"$REPLY2"}
- fi
+ if [[ -n ${reply[warntime]} ]]; then
+ (( mywarntime = t - ${reply[warntime]} ))
+ mywarnstr=${reply[warnstr]}
+ else
+ (( mywarntime = warntime ))
+ mywarnstr=$warnstr
fi
-
# Look for a repeat time.
- (( repeating = 0 ))
- pruned=${restline#(|*[[:space:],])RPT[[:space:]]}
- if [[ $pruned != $restline ]]; then
- if calendar_scandate -a -R $t $pruned; then
- (( repeattime = REPLY, repeating = 1 ))
- fi
+ if [[ -n ${reply[rpttime]} ]]; then
+ (( repeattime = ${reply[rpttime]}, repeating = 1 ))
+ else
+ (( repeating = 0 ))
fi
+ # Finished extracting parameters from $reply
if (( verbose )); then
print "Examining: $line"
diff --git a/Functions/Calendar/calendar_add b/Functions/Calendar/calendar_add
index dc9f50c2b..6c61a3cba 100644
--- a/Functions/Calendar/calendar_add
+++ b/Functions/Calendar/calendar_add
@@ -11,10 +11,11 @@ emulate -L zsh
setopt extendedglob
local calendar newfile REPLY lastline opt
-local -a calendar_entries lockfiles
-integer my_date done rstat nolock nobackup
+local -a calendar_entries lockfiles reply
+integer my_date done rstat nolock nobackup new_recurring old_recurring
+local -A reply parse_new parse_old recurring_uids
-autoload -U calendar_{read,lockfiles,scandate}
+autoload -U calendar_{parse,read,lockfiles}
while getopts "BL" opt; do
case $opt in
@@ -38,11 +39,13 @@ zstyle -s ':datetime:calendar_add:' calendar-file calendar ||
calendar=~/calendar
newfile=$calendar.new.$HOST.$$
-if ! calendar_scandate -a "$*"; then
+if ! calendar_parse "$*"; then
print "$0: failed to parse date/time" >&2
return 1
fi
-(( my_date = $REPLY ))
+parse_new=("${(@kv)reply}")
+(( my_date = $parse_new[time] ))
+[[ -n $parse_new[rpttime] ]] && (( new_recurring = 1 ))
# $calendar doesn't necessarily exist yet.
@@ -53,7 +56,7 @@ local my_uid their_uid
# text/calendar format.
local uidpat='(|*[[:space:]])UID[[:space:]]##(#b)([[:xdigit:]]##)(|[[:space:]]*)'
if [[ "$*" = ${~uidpat} ]]; then
- my_uid=$match[1]
+ my_uid=${(U)match[1]}
fi
# start of block for following always to clear up lockfiles.
@@ -63,16 +66,55 @@ fi
if [[ -f $calendar ]]; then
calendar_read $calendar
+ if [[ -n $my_uid ]]; then
+ # Pre-scan to find recurring events with a UID
+ for line in $calendar_entries; do
+ calendar_parse $line || continue
+ # Recurring with a UID?
+ if [[ -n $reply[rpttime] && $line = ${~uidpat} ]]; then
+ # Yes, so record this as a recurring event.
+ their_uid=${(U)match[1]}
+ recurring_uids[$their_uid]=1
+ fi
+ done
+ fi
+
{
for line in $calendar_entries; do
- if (( ! done )) && calendar_scandate -a $line && (( REPLY > my_date )); then
+ calendar_parse $line || continue
+ parse_old=("${(@kv)reply}")
+ if (( ! done && ${parse_old[time]} > my_date )); then
print -r -- "$*"
(( done = 1 ))
fi
- # Don't save this entry if it has the same UID as the new one.
+ if [[ -n $parse_old[rpttime] ]]; then
+ (( old_recurring = 1 ))
+ else
+ (( old_recurring = 0 ))
+ fi
if [[ -n $my_uid && $line = ${~uidpat} ]]; then
- their_uid=$match[1]
- [[ ${(U)my_uid} = ${(U)their_uid} ]] && continue
+ their_uid=${(U)match[1]}
+ if [[ $my_uid = $their_uid ]]; then
+ # Deal with recurrences, being careful in case there
+ # are one-off variants that don't replace recurrences.
+ #
+ # Bug 1: "calendar" still doesn't know about one-off variants.
+ # Bug 2: neither do I; how do we know which occurrence
+ # it replaces?
+ # Bug 3: the code for calculating recurrences is awful anyway.
+
+ if (( old_recurring && new_recurring )); then
+ # Replacing a recurrence; there can be only one.
+ continue
+ elif (( ! new_recurring )); then
+ # Not recurring. See if we have previously found
+ # a recurrent version
+ [[ -n $recurring_uids[$their_uid] ]] && (( old_recurring = 1 ))
+ # No, so assume this is a straightforward replacement
+ # of a non-recurring event.
+ (( ! old_recurring )) && continue
+ fi
+ fi
fi
if [[ $REPLY -eq $my_date && $line = "$*" ]]; then
(( done )) && continue # paranoia: shouldn't happen
diff --git a/Functions/Calendar/calendar_parse b/Functions/Calendar/calendar_parse
new file mode 100644
index 000000000..f856a4f77
--- /dev/null
+++ b/Functions/Calendar/calendar_parse
@@ -0,0 +1,83 @@
+# Parse the line passed down in the first argument as a calendar entry.
+# Sets the values parsed into the associative array reply, consisting of:
+# time The time as an integer (as per EPOCHSECONDS)
+# text1 The text from the the line not including the date/time, but
+# including any WARN or RPT text. This is useful for rescheduling
+# events, since the keywords need to be retained in this case.
+# warntime Any warning time (WARN keyword) as an integer, else an empty
+# string. This is the time of the warning in units of EPOCHSECONDS,
+# not the parsed version of the original number (which was a time
+# difference).
+# warnstr Any warning time as the original string (e.g. "5 mins"), not
+# including the WARN keyword.
+# rpttime Any repeat/recurrence time (RPT keyword) as an integer, else empty.
+# This is the time of the recurrence itself in EPOCHSECONDS units
+# (as with a warning---not the difference between the events).
+# rptstr Any repeat/recurrence time as the original string.
+# text2 The text from the line with the date and keywords and values removed.
+#
+# Note that here an "integer" is a string of digits, not an internally
+# formatted integer.
+#
+# Return status 1 if parsing failed. reply is set to an empty
+# in this case. Note the caller is responsible for
+# making reply local.
+
+emulate -L zsh
+setopt extendedglob
+
+local REPLY REPLY2
+local -a match mbegin mend
+
+autoload -U calendar_scandate
+
+typeset -gA reply
+
+reply=()
+
+if (( $# != 1 )); then
+ print "Usage: $0 calendar-entry" >&2
+ return 2
+fi
+
+# This call sets REPLY to the date and time in seconds since the epoch,
+# REPLY2 to the line with the date and time removed.
+calendar_scandate -as $1 || return 1
+reply[time]=$(( REPLY ))
+reply[text1]=${REPLY2##[[:space:]]#}
+
+reply[text2]=$reply[text1]
+
+integer changed=1
+
+while (( changed )); do
+
+ (( changed = 0 ))
+
+ # Look for specific warn time.
+ if [[ $reply[text2] = (#b)(|*[[:space:],])WARN[[:space:]](*) ]]; then
+ if calendar_scandate -asm -R $reply[time] $match[2]; then
+ reply[warntime]=$REPLY
+ reply[warnstr]=${match[2]%%"$REPLY2"}
+ reply[text2]="${match[1]}${REPLY2##[[:space:]]#}"
+ else
+ # Just remove the keyword for further parsing
+ reply[text2]="${match[1]}${match[2]##[[:space:]]#}"
+ fi
+ (( changed = 1 ))
+ elif [[ $reply[text2] = (#b)(|*[[:space:],])RPT[[:space:]](*) ]]; then
+ if calendar_scandate -a -R $reply[time] $match[2]; then
+ reply[rpttime]=$REPLY
+ reply[rptstr]=${match[2]%%"$REPLY2"}
+ reply[text2]="${match[1]}${REPLY2##[[:space:]]#}"
+ else
+ # Just remove the keyword for further parsing
+ reply[text2]="${match[1]}${match[2]##[[:space:]]#}"
+ fi
+ (( changed = 1 ))
+ fi
+done
+
+reply[text2]="${reply[text2]##[[:space:],]#}"
+
+return 0