Compare commits
1 Commits
feat/built
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
fa8154fc21
|
@@ -12,11 +12,4 @@ 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/
|
||||||
|
|||||||
49
Makefile
49
Makefile
@@ -1,24 +1,45 @@
|
|||||||
PREFIX := /usr/local
|
SHELL = /bin/sh
|
||||||
|
|
||||||
./agenda.1.gz: ./agenda.1
|
# See the following link regarding GNU Makefile conventions.
|
||||||
gzip -fk ./agenda.1
|
# https://www.gnu.org/software/make/manual/html_node/Makefile-Conventions.html
|
||||||
|
|
||||||
|
# This seems stupid. Isn't install a coreutil anyways?
|
||||||
|
# INSTALL := install
|
||||||
|
# INSTALL_PROGRAM := $(INSTALL)
|
||||||
|
# INSTALL_DATA := ${INSTALL} -m 644
|
||||||
|
|
||||||
|
# Variables for installation directories.
|
||||||
|
# https://www.gnu.org/software/make/manual/html_node/Directory-Variables.html
|
||||||
|
|
||||||
|
DESTDIR :=
|
||||||
|
|
||||||
|
prefix := /usr/local
|
||||||
|
exec_prefix := $(prefix)
|
||||||
|
bindir := $(exec_prefix)/bin
|
||||||
|
datarootdir := $(prefix)/share
|
||||||
|
datadir := $(datarootdir)
|
||||||
|
# libdir := $(prefix)/lib
|
||||||
|
mandir := $(datarootdir)/man
|
||||||
|
man1dir := $(mandir)/man1
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: ./agenda.1.gz
|
||||||
|
|
||||||
.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 $(DESTDIR)$(bindir)/agenda
|
||||||
mkdir -p $(PREFIX)/share/agenda/templates
|
install -m 644 -D ./agenda.1.gz $(DESTDIR)$(man1dir)/agenda.1.gz
|
||||||
install -m 755 ./templates/* $(PREFIX)/share/agenda/templates
|
install -m 644 -D ./completion.bash $(DESTDIR)$(datarootdir)/bash-completion/completions/agenda
|
||||||
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
|
|
||||||
|
|
||||||
.PHONY: uninstall
|
.PHONY: uninstall
|
||||||
uninstall:
|
uninstall:
|
||||||
$(RM) $(PREFIX)/bin/agenda
|
rm -f $(DESTDIR)$(bindir)/agenda
|
||||||
$(RM) $(PREFIX)/share/agenda/templates/*
|
rm -f $(DESTDIR)$(man1dir)/agenda.1.gz
|
||||||
$(RM) $(PREFIX)/share/man/man1/agenda.1.gz
|
rm -f $(DESTDIR)$(datarootdir)/bash-completion/completions/agenda
|
||||||
$(RM) $(PREFIX)/share/bash-completion/completions/agenda
|
|
||||||
rmdir $(PREFIX)/share/agenda/templates $(PREFIX)/share/agenda
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
$(RM) ./agenda.1.gz
|
rm -f ./agenda.1.gz
|
||||||
|
|
||||||
|
./agenda.1.gz: ./agenda.1
|
||||||
|
gzip -fk ./agenda.1
|
||||||
|
|||||||
59
agenda
59
agenda
@@ -17,9 +17,6 @@ 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"}
|
||||||
|
|
||||||
@@ -27,10 +24,7 @@ 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
|
||||||
@@ -62,15 +56,7 @@ __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
|
||||||
|
|
||||||
@@ -305,7 +291,6 @@ __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 \
|
||||||
@@ -327,18 +312,7 @@ __agenda_create() {
|
|||||||
tmp_err=$(mktemp)
|
tmp_err=$(mktemp)
|
||||||
|
|
||||||
if [ "$backlog" = "no" ]; then
|
if [ "$backlog" = "no" ]; then
|
||||||
# Search for a template program if the AGENDA_TEMPLATE variable is empty.
|
# Capture exit code of the template command.
|
||||||
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"
|
||||||
@@ -360,15 +334,25 @@ __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
|
||||||
|
|
||||||
@@ -391,19 +375,6 @@ __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.2.0"
|
.TH AGENDA 1 "2024-06-07" "agenda 0.1.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,26 +107,7 @@ 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
|
||||||
\fBXDG_DATA_HOME\fP\fI/agenda\fP will be used.
|
`${XDG_DATA_HOME:-"$HOME/.local/share"}/agenda` 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
|
||||||
\#
|
\#
|
||||||
@@ -146,14 +127,10 @@ 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 variable is not empty the value is interpreted as a command and
|
If this is not empty the value is interpreted as a command and executed when
|
||||||
executed when creating a new agenda note with the \fI-c\fP flag. Any std output
|
creating a new agenda note with the \fI-c\fP flag. Any std output of the
|
||||||
of the command is written to the new file. The template process has access to
|
command is written to the new file. The template process has access to certain
|
||||||
certain environment variables.
|
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.
|
||||||
@@ -176,10 +153,6 @@ 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
|
||||||
@@ -215,21 +188,6 @@ 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
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#!/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
42
templates/md
@@ -1,42 +0,0 @@
|
|||||||
#!/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
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
#!/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