Compare commits
1 Commits
main
...
feat/built
| Author | SHA1 | Date | |
|---|---|---|---|
|
12ba1d3326
|
@@ -12,4 +12,11 @@ Initial release.
|
|||||||
- Edit, list todo notes by any date format understood by `date(1)`
|
- Edit, list todo notes by any date format understood by `date(1)`
|
||||||
- Write custom template programs to generate content for newly created notes
|
- Write custom template programs to generate content for newly created notes
|
||||||
|
|
||||||
|
## v0.2.0
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Builtin templates for the markdown and xit formats (`.md` and `.xit`
|
||||||
|
extensions); the templates carry over open tasks from previous agenda notes
|
||||||
|
|
||||||
[changelog.md]: https://changelog.md/
|
[changelog.md]: https://changelog.md/
|
||||||
|
|||||||
12
Makefile
12
Makefile
@@ -6,15 +6,19 @@ PREFIX := /usr/local
|
|||||||
.PHONY: install
|
.PHONY: install
|
||||||
install: ./agenda.1.gz
|
install: ./agenda.1.gz
|
||||||
install -m 755 -D ./agenda $(PREFIX)/bin/agenda
|
install -m 755 -D ./agenda $(PREFIX)/bin/agenda
|
||||||
|
mkdir -p $(PREFIX)/share/agenda/templates
|
||||||
|
install -m 755 ./templates/* $(PREFIX)/share/agenda/templates
|
||||||
install -m 644 -D ./agenda.1.gz $(PREFIX)/share/man/man1/agenda.1.gz
|
install -m 644 -D ./agenda.1.gz $(PREFIX)/share/man/man1/agenda.1.gz
|
||||||
install -m 644 -D ./completion.bash $(PREFIX)/share/bash-completion/completions/agenda
|
install -m 644 -D ./completion.bash $(PREFIX)/share/bash-completion/completions/agenda
|
||||||
|
|
||||||
.PHONY: uninstall
|
.PHONY: uninstall
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f $(PREFIX)/bin/agenda
|
$(RM) $(PREFIX)/bin/agenda
|
||||||
rm -f $(PREFIX)/share/man/man1/agenda.1.gz
|
$(RM) $(PREFIX)/share/agenda/templates/*
|
||||||
rm -f $(PREFIX)/share/bash-completion/completions/agenda
|
$(RM) $(PREFIX)/share/man/man1/agenda.1.gz
|
||||||
|
$(RM) $(PREFIX)/share/bash-completion/completions/agenda
|
||||||
|
rmdir $(PREFIX)/share/agenda/templates $(PREFIX)/share/agenda
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -f ./agenda.1.gz
|
$(RM) ./agenda.1.gz
|
||||||
|
|||||||
59
agenda
59
agenda
@@ -17,6 +17,9 @@ AGENDA_EDITOR=${AGENDA_EDITOR:-${VISUAL:-${EDITOR:-vi}}}
|
|||||||
#
|
#
|
||||||
AGENDA_DIR=${AGENDA_DIR:-}
|
AGENDA_DIR=${AGENDA_DIR:-}
|
||||||
|
|
||||||
|
# Location of additional files of an agenda installation.
|
||||||
|
AGENDA_DATA_DIRS=${AGENDA_DATA_DIRS:-}
|
||||||
|
|
||||||
# The default `-e` option.
|
# The default `-e` option.
|
||||||
AGENDA_EXTENSION=${AGENDA_EXTENSION:-"md"}
|
AGENDA_EXTENSION=${AGENDA_EXTENSION:-"md"}
|
||||||
|
|
||||||
@@ -24,7 +27,10 @@ AGENDA_EXTENSION=${AGENDA_EXTENSION:-"md"}
|
|||||||
AGENDA_DEFAULT=${AGENDA_DEFAULT:-"agenda"}
|
AGENDA_DEFAULT=${AGENDA_DEFAULT:-"agenda"}
|
||||||
|
|
||||||
# Command that provides the initial contents of new agenda files.
|
# Command that provides the initial contents of new agenda files.
|
||||||
AGENDA_TEMPLATE=${AGENDA_TEMPLATE:-"__agenda_default_template"}
|
#
|
||||||
|
# If this is null AGENDA_PATH is searched for an executable in the template
|
||||||
|
# subdirectory with the same name as AGENDA_EXTENSION.
|
||||||
|
AGENDA_TEMPLATE=${AGENDA_TEMPLATE:-}
|
||||||
|
|
||||||
__usage() {
|
__usage() {
|
||||||
fold -s <<-USAGE
|
fold -s <<-USAGE
|
||||||
@@ -56,7 +62,15 @@ __main() {
|
|||||||
"--version") __version && return ;;
|
"--version") __version && return ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
if [ -z "$AGENDA_DATA_DIRS" ]; then
|
||||||
|
# FIXME: As per spec only absolute paths should be accepted!
|
||||||
|
AGENDA_DATA_DIRS="${XDG_CONFIG_HOME:-"$HOME/.config"}/agenda"
|
||||||
|
AGENDA_DATA_DIRS="$AGENDA_DATA_DIRS:/usr/local/share/agenda"
|
||||||
|
AGENDA_DATA_DIRS="$AGENDA_DATA_DIRS:/usr/share/agenda"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -z "$AGENDA_DIR" ]; then
|
if [ -z "$AGENDA_DIR" ]; then
|
||||||
|
# FIXME: As per spec only absolute paths should be accepted!
|
||||||
AGENDA_DIR="${XDG_DATA_HOME:-"$HOME/.local/share"}/agenda"
|
AGENDA_DIR="${XDG_DATA_HOME:-"$HOME/.local/share"}/agenda"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -291,6 +305,7 @@ __list() {
|
|||||||
fi
|
fi
|
||||||
done < <(
|
done < <(
|
||||||
# Sort the paths by basename.
|
# Sort the paths by basename.
|
||||||
|
# TODO: Inline the prefix functions and explain this.
|
||||||
find "$dir" -type f \
|
find "$dir" -type f \
|
||||||
| __agenda_sort_prefix \
|
| __agenda_sort_prefix \
|
||||||
| sort \
|
| sort \
|
||||||
@@ -312,7 +327,18 @@ __agenda_create() {
|
|||||||
tmp_err=$(mktemp)
|
tmp_err=$(mktemp)
|
||||||
|
|
||||||
if [ "$backlog" = "no" ]; then
|
if [ "$backlog" = "no" ]; then
|
||||||
# Capture exit code of the template command.
|
# Search for a template program if the AGENDA_TEMPLATE variable is empty.
|
||||||
|
if [ -z "$AGENDA_TEMPLATE" ]; then
|
||||||
|
AGENDA_TEMPLATE=$(
|
||||||
|
__agenda_get_template_path "$AGENDA_EXTENSION" ||
|
||||||
|
__agenda_get_template_path "default" ||
|
||||||
|
true
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If a template program is set, attempt to use it to create the new agenda
|
||||||
|
# note file.
|
||||||
|
if [ -n "$AGENDA_TEMPLATE" ]; then
|
||||||
local code
|
local code
|
||||||
set +e
|
set +e
|
||||||
"$AGENDA_TEMPLATE" > "$tmp" 2> "$tmp_err"
|
"$AGENDA_TEMPLATE" > "$tmp" 2> "$tmp_err"
|
||||||
@@ -334,25 +360,15 @@ __agenda_create() {
|
|||||||
echo "${0##*/}: cannot create '$file': template error" >&2
|
echo "${0##*/}: cannot create '$file': template error" >&2
|
||||||
return $code
|
return $code
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
touch "$tmp"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "${file%/*}"
|
mkdir -p "${file%/*}"
|
||||||
mv "$tmp" "$file"
|
mv "$tmp" "$file"
|
||||||
}
|
}
|
||||||
|
|
||||||
__agenda_default_template() {
|
|
||||||
case $AGENDA_EXTENSION in
|
|
||||||
"md")
|
|
||||||
printf "# %s %s\n\n- [ ] " "$AGENDA_NAME" "$AGENDA_DATE"
|
|
||||||
;;
|
|
||||||
"txt"|"xit"|"")
|
|
||||||
printf "%s %s\n[ ] " "$AGENDA_NAME" "$AGENDA_DATE"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
__agenda_last() {
|
__agenda_last() {
|
||||||
local file=$1 name=$2
|
local file=$1 name=$2
|
||||||
|
|
||||||
@@ -375,6 +391,19 @@ __agenda_last() {
|
|||||||
echo "${last:-}"
|
echo "${last:-}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__agenda_get_template_path() {
|
||||||
|
local template=$1
|
||||||
|
|
||||||
|
local IFS=":" path
|
||||||
|
for path in $AGENDA_DATA_DIRS; do
|
||||||
|
if [ -x "$path/templates/$template" ]; then
|
||||||
|
AGENDA_TEMPLATE="$path/templates/$template"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
# https://stackoverflow.com/a/49035906
|
# https://stackoverflow.com/a/49035906
|
||||||
__slugify() {
|
__slugify() {
|
||||||
echo "$1" \
|
echo "$1" \
|
||||||
|
|||||||
54
agenda.1
54
agenda.1
@@ -1,4 +1,4 @@
|
|||||||
.TH AGENDA 1 "2024-06-07" "agenda 0.1.0"
|
.TH AGENDA 1 "2024-06-07" "agenda 0.2.0"
|
||||||
\#=============================================================================
|
\#=============================================================================
|
||||||
.SH NAME
|
.SH NAME
|
||||||
agenda \- Manage daily tasks and notes in any plain text format.
|
agenda \- Manage daily tasks and notes in any plain text format.
|
||||||
@@ -107,7 +107,26 @@ The editor process has access to certain environment variables.
|
|||||||
\fBAGENDA_DIR\fP
|
\fBAGENDA_DIR\fP
|
||||||
.RS 4
|
.RS 4
|
||||||
The home of all agenda note files read and written by agenda. If this is empty
|
The home of all agenda note files read and written by agenda. If this is empty
|
||||||
`${XDG_DATA_HOME:-"$HOME/.local/share"}/agenda` will be used.
|
\fBXDG_DATA_HOME\fP\fI/agenda\fP will be used.
|
||||||
|
.PP
|
||||||
|
.RE
|
||||||
|
\#
|
||||||
|
\fBAGENDA_DATA_DIRS\fP
|
||||||
|
.RS 4
|
||||||
|
Colon delimited Paths to additional files that come with an agenda installation
|
||||||
|
and custom overrides. Currently only used for template programs (located in the
|
||||||
|
\fItemplate/\fP sub-directory). If a file is searched in these paths the first file
|
||||||
|
that is found is used.
|
||||||
|
|
||||||
|
.nr PI 2n
|
||||||
|
If this variable is not set or empty it is set to include (in order)
|
||||||
|
.IP \[bu]
|
||||||
|
\fBXDG_CONFIG_HOME\fP\fI/agenda\fP
|
||||||
|
.IP \[bu]
|
||||||
|
\fI/usr/local/share/agenda\fP
|
||||||
|
.IP \[bu]
|
||||||
|
\fI/usr/share/agenda\fP
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
.RE
|
.RE
|
||||||
\#
|
\#
|
||||||
@@ -127,10 +146,14 @@ The default agenda name if the \fI-t\fP option is omitted. This falls back to
|
|||||||
\#
|
\#
|
||||||
\fBAGENDA_TEMPLATE\fP
|
\fBAGENDA_TEMPLATE\fP
|
||||||
.RS 4
|
.RS 4
|
||||||
If this is not empty the value is interpreted as a command and executed when
|
If this variable is not empty the value is interpreted as a command and
|
||||||
creating a new agenda note with the \fI-c\fP flag. Any std output of the
|
executed when creating a new agenda note with the \fI-c\fP flag. Any std output
|
||||||
command is written to the new file. The template process has access to certain
|
of the command is written to the new file. The template process has access to
|
||||||
environment variables.
|
certain environment variables.
|
||||||
|
.PP
|
||||||
|
If this variable is unset or empty \fBAGENDA_DATA_DIRS\fP is searched for an
|
||||||
|
executable in the \fItemplates\fP sub-directory that is named either like the
|
||||||
|
corresponding extension or "default".
|
||||||
.sp 1
|
.sp 1
|
||||||
The following example will copy the last agenda note to
|
The following example will copy the last agenda note to
|
||||||
the new agenda note file.
|
the new agenda note file.
|
||||||
@@ -153,6 +176,10 @@ Note however that this example is specific to \fBbash(1)\fP, since only bash
|
|||||||
can export functions this way. In general you should write your template as a
|
can export functions this way. In general you should write your template as a
|
||||||
script, save it, and set it as executable.
|
script, save it, and set it as executable.
|
||||||
.PP
|
.PP
|
||||||
|
To set/override a template for a certain extension (e.g. markdown), save the
|
||||||
|
program to one of the \fBAGENDA_DATA_DIRS\fP, e.g.
|
||||||
|
\fI\fBXDG_CONFIG_HOME\fP/agenda/templates/md\fP.
|
||||||
|
.PP
|
||||||
\#-----------------------------------------------------------------------------
|
\#-----------------------------------------------------------------------------
|
||||||
.SS "Templates and editor"
|
.SS "Templates and editor"
|
||||||
The template command and editor processes have access to certain environment
|
The template command and editor processes have access to certain environment
|
||||||
@@ -188,6 +215,21 @@ The file path of the agenda note.
|
|||||||
The last agenda file. Can be empty if no previous agenda note exists.
|
The last agenda file. Can be empty if no previous agenda note exists.
|
||||||
.PP
|
.PP
|
||||||
.RE
|
.RE
|
||||||
|
.SS "Other"
|
||||||
|
\#
|
||||||
|
\fBXDG_CONFIG_HOME\fP
|
||||||
|
.RS 4
|
||||||
|
The default user configuration path. If this is not set the default of
|
||||||
|
\fBHOME\fP\fI/.config\fP is assumed.
|
||||||
|
.PP
|
||||||
|
.RE
|
||||||
|
\#
|
||||||
|
\fBXDG_DATA_HOME\fP
|
||||||
|
.RS 4
|
||||||
|
The default user data path. If this is not set the default of
|
||||||
|
\fBHOME\fP\fI/.local/share\fP is assumed.
|
||||||
|
.PP
|
||||||
|
.RE
|
||||||
\#=============================================================================
|
\#=============================================================================
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
\fBdate(1)\fP
|
\fBdate(1)\fP
|
||||||
|
|||||||
6
templates/default
Executable file
6
templates/default
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
type agenda >/dev/null
|
||||||
|
|
||||||
|
# Capitalize the title.
|
||||||
|
echo "$AGENDA_NAME $AGENDA_DATE" | awk '{print toupper(substr($0,0,1))tolower(substr($0,2))}'
|
||||||
42
templates/md
Executable file
42
templates/md
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
type agenda >/dev/null
|
||||||
|
|
||||||
|
if [ "${AGENDA_EXTENSION:-}" != "md" ]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Capitalize the title.
|
||||||
|
echo "$AGENDA_NAME $AGENDA_DATE" | awk '{print "# "toupper(substr($0,0,1))tolower(substr($0,2))}'
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [ -n "${AGENDA_IS_BACKLOG:-}" ]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Carry over open tasks from the last agenda markdown file.
|
||||||
|
if [ -e "$AGENDA_LAST" ] && [ "${AGENDA_LAST#*.}" = "md" ]; then
|
||||||
|
while IFS= read -r REPLY; do
|
||||||
|
case ${state:-} in
|
||||||
|
"open_task")
|
||||||
|
case $REPLY in
|
||||||
|
"- [ ] "*|" "*)
|
||||||
|
# Append indented lines to open tasks.
|
||||||
|
echo "$REPLY"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
unset state
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
case $REPLY in
|
||||||
|
"[ ] "*|"[@] "*|"[?] "*)
|
||||||
|
state="open_task"
|
||||||
|
echo "$REPLY"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done < "$AGENDA_LAST"
|
||||||
|
fi
|
||||||
56
templates/xit
Executable file
56
templates/xit
Executable file
@@ -0,0 +1,56 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
type agenda >/dev/null
|
||||||
|
|
||||||
|
if [ "${AGENDA_EXTENSION:-}" != "xit" ]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Capitalize the title.
|
||||||
|
echo "$AGENDA_NAME $AGENDA_DATE" | awk '{print toupper(substr($0,0,1))tolower(substr($0,2))}'
|
||||||
|
|
||||||
|
if [ -n "${AGENDA_IS_BACKLOG:-}" ]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Carry over open tasks from the last agenda xit file.
|
||||||
|
if [ -e "$AGENDA_LAST" ] && [ "${AGENDA_LAST#*.}" = "xit" ]; then
|
||||||
|
line=0
|
||||||
|
while IFS= read -r REPLY; do
|
||||||
|
line=$(( line + 1 ))
|
||||||
|
case ${state:-} in
|
||||||
|
"open_task")
|
||||||
|
case $REPLY in
|
||||||
|
"[ ] "*|"[@] "*|"[?] "*|" "*)
|
||||||
|
# Append indented lines to open tasks.
|
||||||
|
echo "$REPLY"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
unset state
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
case $REPLY in
|
||||||
|
"[ ] "*|"[@] "*|"[?] "*)
|
||||||
|
# Carry over group heading with open tasks.
|
||||||
|
if [ -n "${header:-}" ]; then
|
||||||
|
echo
|
||||||
|
echo "$header"
|
||||||
|
unset header
|
||||||
|
fi
|
||||||
|
state="open_task"
|
||||||
|
echo "$REPLY"
|
||||||
|
;;
|
||||||
|
[a-z]*|[A-Z]*)
|
||||||
|
# Skip the first heading (assumed to be the generated
|
||||||
|
# title of the agenda note).
|
||||||
|
if [ $line -gt 1 ]; then
|
||||||
|
header=$REPLY
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done < "$AGENDA_LAST"
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user