From 439b661cb8e92c83e6523b47afc44476ed78fe6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=84min=20Baumeler?= Date: Thu, 19 Mar 2026 12:10:46 +0100 Subject: [PATCH] as per gh c65d8ae5fe6bafefe8182613f7f9f79983e12a78 --- README.md | 38 ++++++++++++++++++++++++++++++++++++-- src/awk/new.awk | 11 ++++++++++- src/awk/update.awk | 15 +++++++++++++-- src/main.sh | 4 ++-- src/sh/cli.sh | 40 +++++++++++++++++++++------------------- src/sh/icalendar.sh | 14 ++++++++++---- 6 files changed, 92 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index bb99e75..ea8a040 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ item_types = ["VJOURNAL", "VTODO"] You may also specify the location of the configuration file with the environment `CONFIGFILE`. By default, `fzf-vjour` sets a descriptive terminal title. -This can be bypassed by specyfing `SET_TERMINAL_TITLE="no"` in the configuration file. +This can be bypassed by specifying `SET_TERMINAL_TITLE="no"` in the configuration file. Usage ----- @@ -88,7 +88,7 @@ In addition, there are the following keybindings: | Key | Action | | --- | ------ | | `enter` | Open note/journal/task in your `$EDITOR` | -| `ctrl-alt-d` | Delete the seleted entry | +| `ctrl-alt-d` | Delete the selected entry | | `ctrl-n` | Make a new entry | | `ctrl-r` | Refresh the view | | `ctrl-s` | Run the synchronization command | @@ -117,6 +117,40 @@ In the attachment view, you may use the following keys: | `ctrl-a` | Add attachment | | `ctrl-alt-d` | Delete attachment | +Entry types +----------- +This applications, as well as [jtx Board](https://jtx.techbee.at/), distinguishes among three entry types. + +**Notes** are VJOURNAL entries without dates. Here is an example of a note: +```md +# Related research +> research + +Lorem ipsum +``` + +**Journal** entries are notes associated to a date (typically to _today_). An example of a journal entry is: +```md +::: |> today +# Alignment for Bell experiment +> lab + +Lorem ipsum +``` + +**Tasks** are VTODO entries with an optional due date. An example of a task _with_ a due date is: +```md +::: <| next Sunday +# Finish manuscript +> research +``` +Another example of a task _without_ due date is +```md +::: <| +# Acquire Epist. Lett +> research +``` + Git support ----------- You can track your entries with `git` by simply running `fzf-vjour --git-init`. diff --git a/src/awk/new.awk b/src/awk/new.awk index bf18dfc..1d14be5 100644 --- a/src/awk/new.awk +++ b/src/awk/new.awk @@ -5,7 +5,8 @@ BEGIN { zulu = strftime("%Y%m%dT%H%M%SZ", systime(), 1); } desc { desc = desc "\\n" escape($0); next; } -/^::: \|>/ && !start { gsub("\"", ""); start = substr(zulu, 1, 8); next; } +/^::: \|>/ && !start { gsub("\"", ""); i = index($0, "<"); + start = i ? substr($0, 8, 8-i) : substr($0, 8); next; } /^::: <\|/ && !due { gsub("\"", ""); due = "D" substr($0, 8); next; } /^# / && !summary { summary = "S" escape(substr($0, 3)); next; } /^> / && !categories { categories = "C" escape_but_commas(substr($0, 3)); next; } @@ -27,6 +28,14 @@ END { categories = categories "," a[i] categories = substr(categories, 2) } + if (start) { + # Use command line `date` for parsing + cmd = "date -d \"" start "\" +\"%Y%m%d\""; + suc = cmd | getline start + close(cmd) + if (suc != 1) + exit 1 + } if (due) { # Use command line `date` for parsing cmd = "date -d \"" due "\" +\"%Y%m%d\""; diff --git a/src/awk/update.awk b/src/awk/update.awk index e58d9d9..edc10a9 100644 --- a/src/awk/update.awk +++ b/src/awk/update.awk @@ -19,6 +19,14 @@ ENDFILE { categories = categories "," a[i] categories = substr(categories, 2) } + if (start) { + # Use command line `date` for parsing + cmd = "date -d \"" start "\" +\"%Y%m%d\""; + suc = cmd | getline start + close(cmd) + if (suc != 1) + exit 1 + } if (due) { # Use command line `date` for parsing cmd = "date -d \"" due "\" +\"%Y%m%d\""; @@ -31,7 +39,8 @@ ENDFILE { } NR == FNR && desc { desc = desc "\\n" escape($0); next; } -NR == FNR && /^::: <\|/ && !due { gsub("\"",""); due = "D" substr($0, 8); next; } +NR == FNR && /^::: \|>/ && !start { gsub("\"", ""); start = substr($0, 8); next; } +NR == FNR && /^::: <\|/ && !due { gsub("\"", ""); due = "D" substr($0, 8); next; } NR == FNR && /^# / && !summary { summary = "S" escape(substr($0, 3)); next; } NR == FNR && /^> / && !categories { categories = "C" escape_but_commas(substr($0, 3)); next; } NR == FNR && !$0 && !el { el = 1; next; } @@ -41,13 +50,15 @@ due && type == "VJOURNAL" { print "Notes and journal entries do not have /^BEGIN:(VJOURNAL|VTODO)/ { type = $2; print; next; } /^ / && drop { next; } # drop this folded line /^X-ALT-DESC/ && type { drop = 1; next; } # drop this alternative description -/^(DUE|SUMMARY|CATEGORIES|DESCRIPTION|LAST-MODIFIED)/ && type { drop = 1; next; } # skip for now, we will write updated fields at the end +/^(DTSTART|DUE|SUMMARY|CATEGORIES|DESCRIPTION|LAST-MODIFIED)/ && type { drop = 1; next; } # skip for now, we will write updated fields at the end { drop = 0 } # keep everything else /^SEQUENCE/ && type { seq = $2; next; } # store sequence number and skip /^END:/ && type == $2 { seq = seq ? seq + 1 : 1; print_cr("SEQUENCE:" seq); print_cr("LAST-MODIFIED:" zulu); + if (start && due && due < start) {print "Due date cannot be earlier than the start date." > "/dev/stderr"; exit 1;} + if (start) print_cr("DTSTART;VALUE=DATE:" start); if (due) print_cr("DUE;VALUE=DATE:" due); print_fold("SUMMARY:", summary); print_fold("CATEGORIES:", categories); diff --git a/src/main.sh b/src/main.sh index bc771a1..caf3d7b 100644 --- a/src/main.sh +++ b/src/main.sh @@ -66,8 +66,8 @@ if [ "${1:-}" = "--help" ]; then specified summary --add-task [] Read task from stdin and add it with the specified summary and optional due date - --add-jour Read journal from stdin and add it with the - specified summary + --add-jour [] Read journal from stdin and add it with the + specified summary and optional date --collection Select collection to which the note, task, or journal entry is added non-interactively. The argument is the ordinal describing the diff --git a/src/sh/cli.sh b/src/sh/cli.sh index f7737e5..7fec974 100644 --- a/src/sh/cli.sh +++ b/src/sh/cli.sh @@ -37,7 +37,7 @@ esac if [ -z "${next_filter:-}" ]; then # else [FILTER] are the next options - # Here, we have --add-xyz with --collection or nothign + # Here, we have --add-xyz with --collection or nothing case "${1:-}" in "--add-note" | "--add-task" | "--add-jour" | "--collection") noninteractive=1 @@ -53,27 +53,29 @@ if [ -z "${next_filter:-}" ]; then fi add_option="$1" shift - summary=${1-} + summary=${1:-} if [ -z "$summary" ]; then err "You did not give a summary" exit 1 fi shift - if [ "$add_option" = "--add-task" ] && [ -n "${1:-}" ]; then - case "$1" in - "--"*) - continue - ;; - *) - due=$(printf "%s" "$1" | tr -dc "[:alnum:][:blank:]") - shift - if [ -z "$due" ] || ! date -d "$due" >/dev/null 2>&1; then - err "Invalid due date" - exit 1 - fi - ;; - esac - fi + if [ -n "${1:-}" ]; then + case "$1" in + "--"*) continue ;; + *) + case "$add_option" in + "--add-task" | "--add-jour") + dueorstartdate=$(printf "%s" "$1" | tr -dc "[:alnum:][:blank:]") + shift + if [ -z "$dueorstartdate" ] || ! date -d "$dueorstartdate" >/dev/null 2>&1; then + err "Invalid date" + exit 1 + fi + ;; + esac + ;; + esac + fi ;; "--collection") shift @@ -112,10 +114,10 @@ if [ -n "${noninteractive:-}" ]; then __add_note "$collection" "$summary" ;; "--add-task") - __add_task "$collection" "$summary" "${due:-}" + __add_task "$collection" "$summary" "${dueorstartdate:-}" ;; "--add-jour") - __add_jour "$collection" "$summary" + __add_jour "$collection" "$summary" "${dueorstartdate:-}" ;; esac exit 0 diff --git a/src/sh/icalendar.sh b/src/sh/icalendar.sh index f8e8db2..e4f66f7 100644 --- a/src/sh/icalendar.sh +++ b/src/sh/icalendar.sh @@ -74,18 +74,20 @@ __add_task() { __add_from_md "$tmpmd" "$collection" } -# Noninteractively add jounral, and fill description from stdin +# Noninteractively add journal, and fill description from stdin # # @input $1: Collection # @input $2: Summary +# @input $3: start date (optional, defaults to "today") __add_jour() { collection="$1" shift summary="$1" shift + [ "${1:-}" ] && start=$1 || start="today" tmpmd=$(mktemp --suffix='.md') { - echo "::: |> " + echo "::: |> $start" echo "# $summary" echo "" } >"$tmpmd" @@ -137,9 +139,13 @@ __edit() { file="$1" shift tmpmd=$(mktemp --suffix='.md') + start=$(awk -v field="DTSTART" -v format="date" "$AWK_GET" "$file") + if [ -n "$start" ]; then + echo "::: |> $start" >>"$tmpmd" + fi due=$(awk -v field="DUE" -v format="date" "$AWK_GET" "$file") if [ -n "$due" ]; then - echo "::: <| $due" >"$tmpmd" + echo "::: <| $due" >>"$tmpmd" fi { echo "# $(awk -v field="SUMMARY" -v oneline=1 "$AWK_GET" "$file")" @@ -228,7 +234,7 @@ __new() { done tmpmd=$(mktemp --suffix='.md') { - echo "::: |> " + echo "::: |> today " echo "::: <| " echo "# " echo "> "