diff --git a/src/awk/new.awk b/src/awk/new.awk index 635b633..d1e52c1 100644 --- a/src/awk/new.awk +++ b/src/awk/new.awk @@ -2,36 +2,26 @@ BEGIN { FS=":"; - type = "VJOURNAL"; zulu = strftime("%Y%m%dT%H%M%SZ", systime(), 1); } -desc { desc = desc "\\n" escape($0); next; } -{ - if (substr($0, 1, 6) == "::: |>") - { - start = substr(zulu, 1, 8); - getline; - } - if (substr($0, 1, 6) == "::: <|") - { - type = "VTODO" - due = substr($0, 8); - getline; - } - summary = substr($0, 1, 2) != "# " ? "" : escape(substr($0, 3)); - getline; - categories = substr($0, 1, 1) != ">" ? "" : escape_but_commas(substr($0, 3)); - getline; # This line should be empty - getline; # First line of description - desc = "D" escape($0); - next; -} +desc { desc = desc "\\n" escape($0); next; } +/^::: \|>/ && !start { gsub("\"", ""); start = substr(zulu, 1, 8); next; } +/^::: <\| / && !due { gsub("\"", ""); due = substr($0, 8); next; } +/^# / && !summary { summary = escape(substr($0, 3)); next; } +/^> / && !categories { categories = escape_but_commas(substr($0, 3)); next; } +!$0 && !el { el = 1; next; } +!el { print "Unrecognized header on line "NR": " $0 > "/dev/stderr"; exit 1; } + { desc = "D" escape($0); next; } END { # Sanitize input + type = due ? "VTODO" : "VJOURNAL" if (due) { # Use command line `date` for parsing cmd = "date -d \"" due "\" +\"%Y%m%d\""; - cmd | getline res + suc = cmd | getline res + close(cmd) + if (suc != 1) + exit 1 due = res ? res : "" } diff --git a/src/awk/update.awk b/src/awk/update.awk index 69fb846..97b5ae5 100644 --- a/src/awk/update.awk +++ b/src/awk/update.awk @@ -6,39 +6,30 @@ BEGIN { } ENDFILE { - if (NR == FNR) - { - # Sanitize input - if (due) { - # Use command line `date` for parsing - cmd = "date -d \"" due "\" +\"%Y%m%d\""; - cmd | getline res - due = res ? res : "" - } + if (NR == FNR && due) { + # Use command line `date` for parsing + cmd = "date -d \"" due "\" +\"%Y%m%d\""; + suc = cmd | getline res + close(cmd) + if (suc != 1) + exit 1 + due = res ? res : "" } } -NR == FNR && desc { desc = desc "\\n" escape($0); next; } -NR == FNR { - if (substr($0, 1, 6) == "::: <|") - { - due = substr($0, 8); - getline; - } - summary = substr($0, 1, 2) != "# " ? "" : escape(substr($0, 3)); - getline; - categories = substr($0, 1, 1) != ">" ? "" : escape_but_commas(substr($0, 3)); - getline; # This line should be empty - getline; # First line of description - desc = "D" escape($0); - next; -} - -/^BEGIN:(VJOURNAL|VTODO)/ { type = $2; print; next } -/^X-ALT-DESC/ && type { next } # drop this alternative description -/^ / && type { next } # drop this folded line (the only content with folded lines will be updated) -/^(DUE|SUMMARY|CATEGORIES|DESCRIPTION|LAST-MODIFIED)/ && type { next } # skip for now, we will write updated fields at the end -/^SEQUENCE/ && type { seq = $2; next } # store sequence number and skip +NR == FNR && desc { desc = desc "\\n" escape($0); next; } +NR == FNR && /^::: <\| / && !due { gsub("\"",""); due = substr($0, 8); next; } +NR == FNR && /^# / && !summary { summary = escape(substr($0, 3)); next; } +NR == FNR && /^> / && !categories { categories = escape_but_commas(substr($0, 3)); next; } +NR == FNR && !$0 && !el { el = 1; next; } +NR == FNR && !el { print "Unrecognized header on line "NR": " $0 > "/dev/stderr"; exit 1; } +NR == FNR { desc = "D" escape($0); next; } +due && type == "VJOURNAL" { print "Notes and journal entries do not have due dates." > "/dev/stderr"; exit 1; } +/^BEGIN:(VJOURNAL|VTODO)/ { type = $2; print; next; } +/^X-ALT-DESC/ && type { next; } # drop this alternative description +/^ / && type { next; } # drop this folded line (the only content with folded lines will be updated) +/^(DUE|SUMMARY|CATEGORIES|DESCRIPTION|LAST-MODIFIED)/ && type { next; } # skip for now, we will write updated fields at the end +/^SEQUENCE/ && type { seq = $2; next; } # store sequence number and skip /^END:/ && type == $2 { seq = seq ? seq + 1 : 1; print "SEQUENCE:" seq; diff --git a/src/sh/icalendar.sh b/src/sh/icalendar.sh index ecd6c5f..27a4b9d 100644 --- a/src/sh/icalendar.sh +++ b/src/sh/icalendar.sh @@ -41,24 +41,32 @@ __change_priority() { __edit() { file="$1" shift - filetmp=$(mktemp --suffix='.md') - awk "$AWK_EXPORT" "$file" >"$filetmp" - checksum=$(cksum "$filetmp") + tmpmd=$(mktemp --suffix='.md') + awk "$AWK_EXPORT" "$file" >"$tmpmd" + checksum=$(cksum "$tmpmd") # Open in editor - $EDITOR "$filetmp" >/dev/tty + $EDITOR "$tmpmd" >/dev/tty # Update only if changes are detected - if [ "$checksum" != "$(cksum "$filetmp")" ]; then - file_new="$filetmp.ics" - awk "$AWK_UPDATE" "$filetmp" "$file" >"$file_new" - mv "$file_new" "$file" - if [ -n "${GIT:-}" ]; then - $GIT add "$file" - $GIT commit -q -m "File modified" -- "$file" + while [ "$checksum" != "$(cksum "$tmpmd")" ]; do + tmpfile="$tmpmd.ics" + if awk "$AWK_UPDATE" "$tmpmd" "$file" >"$tmpfile"; then + mv "$tmpfile" "$file" + if [ -n "${GIT:-}" ]; then + $GIT add "$file" + $GIT commit -q -m "File modified" -- "$file" + fi + break + else + rm -f "$tmpfile" + err "Failed to update entry. Press to continue." + read -r tmp + # Re-open in editor + $EDITOR "$tmpmd" >/dev/tty fi - fi - rm "$filetmp" + done + rm "$tmpmd" } # Delete file @@ -112,14 +120,22 @@ __new() { $EDITOR "$tmpmd" >/dev/tty # Update if changes are detected - if [ "$checksum" != "$(cksum "$tmpmd")" ]; then + while [ "$checksum" != "$(cksum "$tmpmd")" ]; do tmpfile="$tmpmd.ics" - awk -v uid="$uuid" "$AWK_NEW" "$tmpmd" >"$tmpfile" - mv "$tmpfile" "$file" - if [ -n "${GIT:-}" ]; then - $GIT add "$file" - $GIT commit -q -m "File added" -- "$file" + if awk -v uid="$uuid" "$AWK_NEW" "$tmpmd" >"$tmpfile"; then + mv "$tmpfile" "$file" + if [ -n "${GIT:-}" ]; then + $GIT add "$file" + $GIT commit -q -m "File added" -- "$file" + fi + break + else + rm -f "$tmpfile" + err "Failed to create new entry. Press to continue." + read -r tmp + # Re-open in editor + $EDITOR "$tmpmd" >/dev/tty fi - fi + done rm "$tmpmd" }