]> git.plutz.net Git - shellwiki/commitdiff
month calendar view, more modular architecture
authorPaul Hänsch <paul@plutz.net>
Thu, 25 Jan 2024 02:25:19 +0000 (03:25 +0100)
committerPaul Hänsch <paul@plutz.net>
Thu, 25 Jan 2024 02:25:19 +0000 (03:25 +0100)
macros/calendar

index 575662f253bfcde184ff178e2d8871e277b97b47..e2fa8aa6820b9bdd4e96068e35a355a91bd0c1ee 100755 (executable)
@@ -1,4 +1,5 @@
 #!/bin/sh
+# vi:syntax=bash
 
 # Copyright 2024 Paul Hänsch
 # 
@@ -14,6 +15,7 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+
 . "$_EXEC/cgilite/cgilite.sh"
 . "$_EXEC/acl.sh"
 . "$_EXEC/tools.sh"
@@ -28,10 +30,8 @@ while [ $# -gt 0 ]; do case $1 in
   --depth)  depth="$2" shift 2;;
   \#*) tags="${tags}${tags:+ }${1###}"; shift 1;;
   \!*) ntags="${ntags}${ntags:+ }${1##!}"; shift 1;;
-  --h1|--h2|--h3|--h4|--h5|--h6|--label)
-    labeltype="${1#--}" label="$2"; shift 2;;
-  --alt-label)
-    altlabel="$2"; shift 2;;
+  --date|--from) fromdate="$2"; shift 2;;
+  --weekstart|--ws|-ws) ws="$2"; shift 2;;
   --) shift 1; break;;
   *) if [ ! "$dir" ]; then
       dir="$1"
@@ -47,95 +47,129 @@ esac; done
 [ "$depth" -ge 0 -o "$depth" -le 0 ] 2>&- || depth=0
 
 read DY DM DD <<-EOF
-       $(date +"%Y %m %d")
+       $(isdate "$fromdate" \
+         && date -ud "$fromdate" +"%Y %m %d" \
+         || date -u +"%Y %m %d"
+       )
        EOF
 
-dstart="$(date -d "${DY}-${DM}-01" +%s)"
-[ "$DM" -lt 12 ] \
-&& dend="$(date -d "${DY}-$(( ${DM#0} + 1))-01" +%s)" \
-|| dend="$(date -d "$(( ${DY#0} + 1))-01-01" +%s)"
+case $ws in
+  0|[sS]*) ws=0;;
+  1|[mM]*) ws=1;;
+  *) ws=0;;
+esac
+
+rrexpand() {
+  # Recurrence Expansion
+  # read recurring event specifications and expand them to a list of
+  # single events within the specified time frame
 
-expand() {
-  local start="$1" end="$2" rrfreq="$3" rrint="$4" rrend="$5" evtitle="$6" evlink="$7"
-  local dstart dend
+  local dstart="$1" dend="$2"
+  local junk1 start end rrfreq rrint rrend evtitle evlink junk2
+
+  while read -r junk1 start end rrfreq rrint rrend evtitle evlink junk2; do
+    [ "$rrend" -eq -1 ] && rrend=9999999999
+
+    if [ "$start" -lt "$dend" ] &&
+       [ "$end" -gt "$dstart" -o "$rrend" -gt "$dstart" ]; then
+      case $rrint in
+        day) rrex_day;;
+        week) rrex_week;;
+        month) rrex_month;;
+        year) rrex_year;;
+        *):
+          printf '%i   %i      %s      %s\n' "$start" "$end" "$evtitle" "$evlink"
+          ;;
+      esac
+    fi
+  done
+}
+
+rrex_day() {
+  # helper for rrexpand daily/N-day expansion
   local nstart nend
 
-  [ "$rrend" -eq -1 ] && rrend=9999999999
-
-  case $rrint in
-    day)
-      nend=$(( rrfreq * 86400 - (dstart - end) % (rrfreq * 86400) + dstart ))
-      nstart=$(( start - end + nend))
-      debug "[ $nend -lt $dend -a $nstart -lt $rrend ]"
-      while [ "$nend" -lt "$dend" -a "$nstart" -lt "$rrend" ]; do
-        printf '%i     %i      %s      %s\n' "$nstart" "$nend" "$evtitle" "$evlink"
-        # printf '%i   %i      %s\n' "$nstart" "$nend" "$evlink"
-        nstart="$((nstart + rrfreq * 86400))"
-          nend="$((nstart - start + end))"
-      done
-      ;;
-    week)
-      nend=$(( rrfreq * 604800 - (dstart - end) % (rrfreq * 604800) + dstart ))
-      nstart=$(( start - end + nend))
-      while [ "$nend" -lt "$dend" -a "$nstart" -lt "$rrend" ]; do
-        printf '%i     %i      %s      %s\n' "$nstart" "$nend" "$evtitle" "$evlink"
-        nstart="$((nstart + rrfreq * 7 * 86400))"
-          nend="$((nstart - start + end))"
-      done
-      ;;
-    month)
-      { read _y _m _d; read y m d; } <<-EOF
-       $(date -d @$dstart +"%Y %_m %_d"
-         date -d @$start  +"%Y %_m %_d"
+  nend=$(( rrfreq * 86400 - (dstart - end) % (rrfreq * 86400) + dstart ))
+  nstart=$(( start - end + nend))
+  while [ "$nstart" -lt "$rrend" -a "$nstart" -lt "$dend" ]; do
+    [ "$nstart" -ge "$start" ] \
+    && printf '%i      %i      %s      %s\n' "$nstart" "$nend" "$evtitle" "$evlink"
+    nstart="$((nstart + rrfreq * 86400))"
+      nend="$((nstart - start + end))"
+  done
+}
+
+rrex_week() {
+  # helper for rrexpand weekly/N-week expansion
+  local nstart nend
+
+  nend=$(( 0 * 604800 - (dstart - end) % (rrfreq * 604800) + dstart ))
+  nstart=$(( start - end + nend))
+  while [ "$nstart" -lt "$rrend" -a "$nstart" -lt "$dend" ]; do
+    [ "$nstart" -ge "$start" -a "$nstart" -ge "$dstart" ] \
+    && printf '%i      %i      %s      %s\n' "$nstart" "$nend" "$evtitle" "$evlink"
+    nstart="$((nstart + rrfreq * 7 * 86400))"
+      nend="$((nstart - start + end))"
+  done
+}
+
+rrex_month() {
+  # helper for rrexpand monthly/N-month expansion
+  local nstart nend
+
+  { read _y _m _d; read y m d start_time; } <<-EOF
+       $(date -ud @$dstart +"%Y %_m %_d"
+         date -ud @$start  +"%Y %_m %_d %T"
        )
        EOF
-      _m=$((_y * 12 + _m)) m=$((y * 12 + m))
-      while :; do
-        m=$(( rrfreq - ((_m - m - 1) % rrfreq + 1) + _m ))
-        nstart="$(printf '%04i-%02i-%02i' "$(( (m - 1) / 12 ))" "$(( (m - 1) % 12 + 1 ))" "$d")"
-        if isdate "$nstart" && [ "$(date -d "$nstart" +%s)" -ge "$dstart" ]; then
-          break
-        fi >/dev/null
-        _m="$((_m + rrfreq))"
-      done
-      nstart="$(date -d "$nstart $start_time" +%s)"
-        nend="$((end - start + nstart))"
-      while [ "$nend" -lt "$dend" -a "$nstart" -lt "$rrend" ]; do
-        printf '%i     %i      %s      %s\n' "$nstart" "$nend" "$evtitle" "$evlink"
-        m="$((m + rrfreq))"
-        nstart="$(printf '%04i-%02i-%02i' "$(( (m - 1) / 12 ))" "$(( (m - 1) % 12 + 1 ))" "$d")"
-        nstart="$(date -d "$nstart $start_time" +%s)"
-          nend="$((nstart - start + end))"
-      done
-      ;;
-    year)
-      { read _y _m _d; read y m d; } <<-EOF
-       $(date -d @$dstart +"%Y %_m %_d"
-         date -d @$start  +"%Y %_m %_d"
+  _m=$((_y * 12 + _m)) m=$((y * 12 + m))
+  while :; do
+    m=$(( rrfreq - ((_m - m - 1) % rrfreq + 1) + _m ))
+    nstart="$(printf '%04i-%02i-%02i' "$(( (m - 1) / 12 ))" "$(( (m - 1) % 12 + 1 ))" "$d")"
+    if isdate "$nstart" && [ "$(date -ud "$nstart" +%s)" -ge "$dstart" ]; then
+      break
+    fi >/dev/null
+    _m="$((_m + rrfreq))"
+  done
+  nstart="$(date -ud "$nstart $start_time" +%s)"
+    nend="$((end - start + nstart))"
+  while [ "$nstart" -lt "$rrend" -a "$nstart" -lt "$dend" ]; do
+    [ "$nstart" -ge "$start" ] \
+    && printf '%i      %i      %s      %s\n' "$nstart" "$nend" "$evtitle" "$evlink"
+    m="$((m + rrfreq))"
+    nstart="$(printf '%04i-%02i-%02i' "$(( (m - 1) / 12 ))" "$(( (m - 1) % 12 + 1 ))" "$d")"
+    nstart="$(date -ud "$nstart $start_time" +%s)"
+      nend="$((nstart - start + end))"
+  done
+}
+
+rrex_year() {
+  # helper for rrexpand yearly/N-year expansion
+  local nstart nend
+
+  { read _y _m _d; read y m d start_time; } <<-EOF
+       $(date -ud @$dstart +"%Y %_m %_d"
+         date -ud @$start  +"%Y %_m %_d %T"
        )
        EOF
-      while :; do
-        y=$(( rrfreq - ((_y - y - 1) % rrfreq + 1) + _y ))
-        nstart="$(printf '%04i-%02i-%02i' "$y" "$m" "$d")"
-        if isdate "$nstart" && [ "$(date -d "$nstart" +%s)" -ge "$dstart" ]; then
-          break
-        fi >/dev/null
-        _y="$((_y + rrfreq))"
-      done
-      nstart="$(date -d "$nstart $start_time" +%s)"
-        nend="$((end - start + nstart))"
-      while [ "$nend" -lt "$dend" -a "$nstart" -lt "$rrend" ]; do
-        printf '%i     %i      %s      %s\n' "$nstart" "$nend" "$evtitle" "$evlink"
-        y="$((y + rrfreq))"
-        nstart="$(printf '%04i-%02i-%02i' "$y" "$m" "$d")"
-        nstart="$(date -d "$nstart $start_time" +%s)"
-          nend="$((nstart - start + end))"
-      done
-      ;;
-    *):
-      printf '%i       %i      %s      %s\n' "$start" "$end" "$evtitle" "$evlink"
-      ;;
-  esac
+  while :; do
+    y=$(( rrfreq - ((_y - y - 1) % rrfreq + 1) + _y ))
+    nstart="$(printf '%04i-%02i-%02i' "$y" "$m" "$d")"
+    if isdate "$nstart" && [ "$(date -ud "$nstart" +%s)" -ge "$dstart" ]; then
+      break
+    fi >/dev/null
+    _y="$((_y + rrfreq))"
+  done
+  nstart="$(date -ud "$nstart $start_time" +%s)"
+    nend="$((end - start + nstart))"
+  while [ "$nstart" -lt "$rrend" -a "$nstart" -lt "$dend" ]; do
+    [ "$nstart" -ge "$start" ] \
+    && printf '%i      %i      %s      %s\n' "$nstart" "$nend" "$evtitle" "$evlink"
+    y="$((y + rrfreq))"
+    nstart="$(printf '%04i-%02i-%02i' "$y" "$m" "$d")"
+    nstart="$(date -ud "$nstart $start_time" +%s)"
+      nend="$((nstart - start + end))"
+  done
 }
 
 events="$(
@@ -152,29 +186,96 @@ events="$(
     then
       cat "$_DATA/pages/${pagedir}/#events"
     fi
-  done \
-  | while read -r junk1 tstart tend rrfreq rrint rrend evtitle evlink junk2; do
-    if [ "$tend" -gt "$dstart" -a "$tstart" -lt "$dend" ] \
-       || [ "$rrend" -gt "$dstart" -o "$rrend" -eq -1 ]; then
-      expand "$tstart" "$tend" "$rrfreq" "$rrint" "$rrend" "$evtitle" "$evlink"
-    fi
-  done \
-  | debug \
-  | sort -n
+  done
 )"
 
-lday=''
-
-printf '<ul class="macro calendar">\n'
-printf '%s\n' "${events}" \
-| while read start end name link; do
-  day="$((start / 86400))"
-  if [ "$day" != "$lday" ]; then
-    [ "$lday" ] && printf '</ul></li>'
-    date -d "@$start" +'<li><label>%A, %F</label><ul class="day">'
-    lday="$day"
-  fi
-  printf '<li>%s: <a href="%s">%s</a></li>' \
-         "$(date -d "@$start" +"%T")" "$(URL "${link%%#*}")#$(URL "${link#*#}")" "$(HTML "${name}")"
-done
-printf '</ul></li></ul>'
+cal_list() {
+  # Print list view for upcoming events
+  local lday='' events sdate=$(date -ud "${DY}-${DM}-${DD}" +%s)
+
+  events="$(
+    printf %s\\n "$events" \
+    | rrexpand "$sdate" "$((sdate + 42 * 86400))" \
+    | sort -n
+  )"
+  
+  printf '<ul class="macro calendar cal_list">\n'
+  printf '%s\n' "${events}" \
+  | while read start end name link; do
+    day="$((start / 86400))"
+    if [ "$day" != "$lday" ]; then
+      [ "$lday" ] && printf '</ul></li>'
+      date -ud "@$start" +'<li><label>%A, %F</label><ul class="day">'
+      lday="$day"
+    fi
+    printf '<li>%s - <a href="%s">%s</a></li>' \
+           "$(date -ud "@$start" +"%H:%M")" "$(URL "${link%%#*}")#$(URL "${link#*#}")" "$(HTML "${name}")"
+  done
+  printf '</ul></li></ul>'
+}
+
+cal_month() {
+  local ws events calmonth
+  local iday idow mname dcnt dow dcal start end title link n
+
+  calmonth="$(GET calmonth || printf %i "$((DY * 12 + DM))")"
+  DY="$(( (calmonth - 1) / 12 ))"
+  DM="$(( (calmonth - 1) % 12 + 1 ))"
+
+  read -r iday idow mname <<-EOF
+       $(date -ud "${DY}-${DM}-01" +"%s        %u      %B")
+       EOF
+  dcnt=$((iday - idow * 86400 + ws * 86400))
+   dow=$ws
+  dcal="$(date -ud @"$dcnt" +%d)"
+
+  events="$(
+    printf %s\\n "$events" \
+    | rrexpand "$dcnt" "$((dcnt + 42 * 86400))" \
+    | sort -n
+  )"
+
+  printf '<table class="macro calendar cal_month">'
+  printf '<thead><tr><th><a href="%s">&lt;</a></th><th colspan=5>%s</th><th><a href="%s">&gt;</a></th></tr><tr>' \
+    "./?calmonth=$((DY * 12 + DM -1))" "$mname" "./?calmonth=$((DY * 12 + DM + 1))"
+  for n in 0 1 2 3 4 5 6; do date -ud @"$((dcnt + n * 86400))" +'<th>%a</th>'; done
+  printf '</tr></thead><tbody>'
+  while :; do
+    [ $dow = $ws ] && printf '<tr>'
+    printf '<td><label>%02i</label>' "$dcal"
+
+    evlist="$(
+      printf %s\\n "$events" \
+      | while read start end title link; do
+        if [ "$((start / 86400))" -lt "$((dcnt / 86400))" -a "$end" -gt "$dcnt" ]; then
+          printf '<li><a href="%s\#%s">%s</a></li>' \
+            "$(UNSTRING "${link%%#*}" |URL)" \
+            "$(UNSTRING "${link#*#}" |URL)" \
+            "$(UNSTRING "$title" |HTML)"
+        elif [ "$((start / 86400))" -eq "$((dcnt / 86400))" ]; then
+          printf '<li>%s - <a href="%s\#%s">%s</a></li>' \
+            "$(date -ud @"$start" +%H:%M)" \
+            "$(UNSTRING "${link%%#*}" |URL)" \
+            "$(UNSTRING "${link#*#}" |URL)" \
+            "$(UNSTRING "$title" |HTML)"
+        fi
+      done
+    )"
+    [ "$evlist" ] && printf '<ul>%s</ul>' "$evlist"
+
+    printf '</td>\n'
+    [ $dow = $(( (ws + 6) % 7)) ] && printf '</tr>\n'
+
+    dcnt=$(( dcnt + 86400 ))
+     dow=$(( (dow + 1) % 7 ))
+    [ $dcal -lt 28 ] \
+    && dcal=$((dcal + 1)) \
+    || dcal=$(date -ud @"$dcnt" +%d)
+    [ $dcnt -gt $((iday + 28 * 86400)) -a $dcal -le 7 -a $dow = $ws ] \
+    && break
+  done
+  printf '</tbody></table>'
+}
+
+%rem cal_list
+cal_month