mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-01-08 19:36:57 +01:00
33b846810c
26075: fix repeated calendar events so that the next event is always in the future
95 lines
3.1 KiB
Text
95 lines
3.1 KiB
Text
# 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
|
|
integer now
|
|
|
|
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:]]#}"
|
|
(( now = EPOCHSECONDS ))
|
|
while (( ${reply[rpttime]} < now )); do
|
|
# let's hope the original appointment wasn't in 44 B.C.
|
|
if calendar_scandate -a -R ${reply[rpttime]} ${reply[rptstr]}; then
|
|
if (( REPLY <= ${reply[rpttime]} )); then
|
|
# pathological case
|
|
break;
|
|
fi
|
|
reply[rpttime]=$REPLY
|
|
fi
|
|
done
|
|
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
|