aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore8
-rw-r--r--CHANGELOG.md2
-rw-r--r--Makefile113
-rw-r--r--README.md36
-rw-r--r--aux/guix/manifest.scm15
-rwxr-xr-xaux/workflow/assert-manpages.sh220
-rwxr-xr-xaux/workflow/installcheck.sh61
-rwxr-xr-xaux/workflow/l10n.sh70
-rwxr-xr-xaux/workflow/manpages.sh68
-rw-r--r--doc/gistatic.119
-rw-r--r--doc/gistatic.en.1.in0
-rw-r--r--doc/gistatic.eo.1.in0
-rw-r--r--doc/gistatic.fr.1.in0
-rw-r--r--doc/gistatic.pt.1.in0
-rw-r--r--po/LC_MESSAGES/CHANGELOG.en.md/eo.po6
-rw-r--r--po/LC_MESSAGES/CHANGELOG.en.md/fr.po6
-rw-r--r--po/LC_MESSAGES/CHANGELOG.en.md/pt.po6
-rw-r--r--po/LC_MESSAGES/README.en.md/eo.po176
-rw-r--r--po/LC_MESSAGES/README.en.md/fr.po176
-rw-r--r--po/LC_MESSAGES/README.en.md/pt.po176
-rw-r--r--po/LC_MESSAGES/doc/gistatic.en.1.in/eo.po18
-rw-r--r--po/LC_MESSAGES/doc/gistatic.en.1.in/fr.po18
-rw-r--r--po/LC_MESSAGES/doc/gistatic.en.1.in/pt.po18
-rw-r--r--src/gistatic.c3
-rw-r--r--src/lib.rs19
-rw-r--r--src/main.rs4
26 files changed, 1154 insertions, 84 deletions
diff --git a/.gitignore b/.gitignore
index 81df051..badfe37 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,8 @@
/public/
-/target/
+/src/gistatic
+*.t
+*.mo
+*.po~
+/doc/*.1
+/README.*.md
+/CHANGELOG.*.md
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 65f247b..61a61a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,3 +8,5 @@
## Fixed
## Security
-->
+
+Changelog for [gistatic](https://euandreh.xyz/gistatic/en/).
diff --git a/Makefile b/Makefile
index 4edd7b6..ffbdf40 100644
--- a/Makefile
+++ b/Makefile
@@ -1,51 +1,94 @@
.POSIX:
-PREFIX = /usr/local
-MANPREFIX = $(PREFIX)/share/man
-DATE = 1970-01-01
-VERSION = 0.1.0
-NAME = gistatic
+PREFIX = /usr/local
+MANPREFIX = $(PREFIX)/usr/local
+DATE = 1970-01-01
+VERSION = 0.1.0
+NAME = gistatic
+MAILING_LIST = public-inbox
+TRANSLATIONS = pt fr eo
+CONTRIBLANGS =
+DEFS = \
+ -D_POSIX_C_SOURCE=200809L \
+ -DVERSION='"$(VERSION)"' \
+ -DDATE='"$(DATE)"'
-manpages = \
- doc/$(NAME).1 \
+.SUFFIXES: .in .t
-all: target/release/$(NAME)
+.in:
+ sed -e 's:@VERSION@:$(VERSION):g' -e 's:@DATE@:$(DATE):g' < $< > $@
-target/release/$(NAME):
- cargo build --release
+.c:
+ $(CC) $(CFLAGS) $(DEFS) -o $@ $<
-check: all
- cargo test --release
+.c.t:
+ $(CC) $(CFLAGS) $(DEFS) -DTEST -o $@ $<
-dev-check: check
- sh aux/assert-shellcheck.sh
- sh aux/workflow/assert-todos.sh
- sh aux/workflow/assert-changelog.sh $(NAME)
-do_subst = sed \
- -e 's:[@]VERSION[@]:$(VERSION):g' \
- -e 's:[@]DATE[@]:$(DATE):g'
+manpages.en.in = \
+ doc/gistatic.en.1.in
+manpages.in = $(manpages.en.in) \
+ doc/gistatic.pt.1.in \
+ doc/gistatic.fr.1.in \
+ doc/gistatic.eo.1.in
+manpages = $(manpages.in:.in=)
+
+
+all: $(manpages) src/gistatic
+
+check: all src/gistatic.t
+ ./src/gistatic.t
+
+clean:
+ rm -rf public/ $(manpages) README.*.md CHANGELOG.*.md messages.mo \
+ src/gistatic src/gistatic.t
install: all
- install -m 755 -D target/release/$(NAME) $(DESTDIR)$(PREFIX)/bin/$(NAME)
- for m in $(manpages); do \
- n=$${m##*.}; \
- mkdir -p $(DESTDIR)$(MANPREFIX)/man$$n; \
- $(do_subst) < $$m > $(DESTDIR)$(MANPREFIX)/man$$n/`basename $${m%%.*}.$$n`.gz; \
- done
+ mkdir -p $(DESTDIR)$(PREFIX)/bin
+ cp src/gistatic $(DESTDIR)$(PREFIX)/bin
+ sh aux/workflow/manpages.sh -ip $(DESTDIR)$(MANPREFIX) $(manpages)
uninstall:
- rm -f $(DESTDIR)$(PREFIX)/bin/$(NAME)
- for m in $(manpages); do rm -f $(DESTDIR)$(MANPREFIX)/man$${m##*.}/`basename $${m%%.*}`.$${m##*.}.gz; done
+ sh aux/workflow/manpages.sh -up $(DESTDIR)$(MANPREFIX) $(manpages)
-clean:
- rm -rf public/
- cargo clean
+
+#
+# Personal workflow targets
+#
+
+dev-check: check public
+ sh aux/assert-shellcheck.sh
+ sh aux/workflow/assert-todos.sh
+ sh aux/workflow/assert-changelog.sh -n $(NAME)
+ sh aux/workflow/assert-readme.sh -n $(NAME) -m $(MAILING_LIST)
+ sh aux/workflow/assert-manpages.sh -n $(NAME) -m $(MAILING_LIST) \
+ -l '$(TRANSLATIONS) en' $(manpages.en.in)
+ . aux/lib.sh && $(MAKE) PREFIX=`mkdtemp` \
+ install installcheck uninstall uninstallcheck
+
+installcheck:
+ sh aux/workflow/installcheck.sh -x1 -l1 -f5 -p $(PREFIX)
+
+uninstallcheck:
+ sh aux/workflow/installcheck.sh -up $(PREFIX)
dist:
- sh aux/workflow/dist.sh $(DATE) $(VERSION) $(NAME)
+ sh aux/workflow/dist.sh -d $(DATE) -V $(VERSION) \
+ -n $(NAME) -m $(MAILING_LIST)
+
+README.en.md: README.md
+ ln -fs $? $@
+
+CHANGELOG.en.md: CHANGELOG.md
+ ln -fs $? $@
+
+l10n-gen: README.en.md CHANGELOG.en.md $(manpages.en.in)
+ sh aux/workflow/l10n.sh -l '$(TRANSLATIONS)' -L '$(CONTRIBLANGS)' $?
-public: README.md TODOs.md CHANGELOG.md
- sh aux/workflow/public.sh $(NAME) $(NAME) public-inbox
- for m in $(manpages); do groff -m man -Thtml $$m > public/`basename $$m`.html; done
+public: l10n-gen TODOs.md $(manpages)
+ sh aux/workflow/public.sh -l '$(TRANSLATIONS) $(CONTRIBLANGS) en' \
+ -n $(NAME) -m $(MAILING_LIST) -o public
+ sh aux/workflow/manpages.sh -Ho public $(manpages)
-.PHONY: all clean check dev-check dist install uninstall
+spellcheck: public
+ sh aux/workflow/assert-spelling.sh -l '$(TRANSLATIONS) en' \
+ $$(find public -type f -name '*.html')
diff --git a/README.md b/README.md
index b3692ad..952c1ea 100644
--- a/README.md
+++ b/README.md
@@ -66,3 +66,39 @@ and for generating the documentation HTML and website, run:
```shell
$ make public
```
+
+For running the extra development-only checks, run:
+
+```shell
+$ make dev-check
+```
+
+and for generating the documentation HTML and website, run:
+
+```shell
+$ make public
+```
+
+Send contributions to the [mailing list] via
+[`git send-email`](https://git-send-email.io/).
+
+
+## Links
+
+- [homepage](https://euandreh.xyz/gistatic/en/)
+- [source code](https://git.euandreh.xyz/gistatic/)
+- [bug tracking](https://euandreh.xyz/gistatic/TODOs.html)
+- [mailing list]
+- [CI logs](https://euandreh.xyz/gistatic/ci.html)
+- [CHANGELOG](https://euandreh.xyz/gistatic/en/CHANGELOG.html)
+
+[mailing list]: https://lists.sr.ht/~euandreh/public-inbox?search=%5Bgistatic%5D
+
+
+## License
+
+The code is licensed under
+[GNU Affero General Public License v3.0 or later][AGPL-3.0-or-later]
+(AGPL-3.0-or-later).
+
+[AGPL-3.0-or-later]: https://git.euandreh.xyz/gistatic/tree/COPYING
diff --git a/aux/guix/manifest.scm b/aux/guix/manifest.scm
index 5b21f76..3698645 100644
--- a/aux/guix/manifest.scm
+++ b/aux/guix/manifest.scm
@@ -6,14 +6,17 @@
diffutils
grep
sed
+ m4
git
- tar
gawk
make
- perl
shellcheck
- groff
pandoc
-
- rust
- rust:cargo)))
+ gettext
+ po4a-text
+ mdpo-patched
+ hunspell
+ hunspell-dict-en-utf8
+ hunspell-dict-pt-utf8
+ hunspell-dict-fr-utf8
+ hunspell-dict-eo-utf8)))
diff --git a/aux/workflow/assert-manpages.sh b/aux/workflow/assert-manpages.sh
new file mode 100755
index 0000000..f9a6807
--- /dev/null
+++ b/aux/workflow/assert-manpages.sh
@@ -0,0 +1,220 @@
+#!/bin/sh
+set -eu
+
+TLD="$(cat aux/tld.txt)"
+. aux/lib.sh
+
+IN_PLACE=false
+while getopts 'l:n:m:i' flag; do
+ case "$flag" in
+ n)
+ PROJECT="$OPTARG"
+ ;;
+ m)
+ MAILING_LIST="$OPTARG"
+ ;;
+ i)
+ IN_PLACE=true
+ ;;
+ l)
+ LANGS="$OPTARG"
+ ;;
+ *)
+ exit 2
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+assert_arg() {
+ if [ -z "$1" ]; then
+ echo "Missing $2" >&2
+ exit 2
+ fi
+}
+
+assert_arg "${PROJECT:-}" '-n PROJECT'
+assert_arg "${MAILING_LIST:-}" '-m MAILING_LIST'
+assert_arg "${LANGS:-}" '-l LANGS'
+
+
+EXPECTED_EN="$(mkstemp)"
+cat <<EOF | sed 's|-|\\-|g' >> "$EXPECTED_EN"
+
+
+.SH AUTHORS
+
+.MT eu@euandre.org
+EuAndreh
+.ME
+and contributors.
+
+
+.SH BUGS
+
+.IP \(bu
+Report bugs to the
+.MT ~euandreh/$MAILING_LIST@lists.sr.ht
+mailing list
+.ME .
+Use the subject "\f(CR[$PROJECT] BUG or TASK:
+<description>\fR".
+.IP \(bu
+Browse bugs
+.UR https://$TLD/$PROJECT/TODOs.html
+online
+.UE .
+.IP \(bu
+.UR https://$TLD/$PROJECT/en/
+Homepage
+.UE .
+.IP \(bu
+.UR https://lists.sr.ht/~euandreh/$MAILING_LIST?search=%5B$PROJECT%5D
+Comments and discussions
+.UE .
+EOF
+
+EXPECTED_PT="$(mkstemp)"
+cat <<EOF | sed 's|-|\\-|g' >> "$EXPECTED_PT"
+
+
+.SH AUTORES
+
+.MT eu@euandre.org
+EuAndreh
+.ME
+e colaboradores.
+
+
+.SH BUGS
+
+.IP \(bu
+Relate bugs na
+.MT ~euandreh/$MAILING_LIST@lists.sr.ht
+lista de discussão
+.ME .
+Use o assunto "\f(CR[$PROJECT] BUG ou TASK:
+<descrição>\fR".
+.IP \(bu
+Veja os bugs
+.UR https://$TLD/$PROJECT/TODOs.html
+online
+.UE .
+.IP \(bu
+.UR https://$TLD/$PROJECT/pt/
+Página inicial
+.UE .
+.IP \(bu
+.UR https://lists.sr.ht/~euandreh/$MAILING_LIST?search=%5B$PROJECT%5D
+Comentários e discussões
+.UE .
+EOF
+
+EXPECTED_FR="$(mkstemp)"
+cat <<EOF | sed 's|-|\\-|g' >> "$EXPECTED_FR"
+
+
+.SH AUTEURS
+
+.MT eu@euandre.org
+EuAndreh
+.ME
+et les contributeurs.
+
+
+.SH BUGS
+
+.IP \(bu
+Soumettre un bogue dans la
+.MT ~euandreh/$MAILING_LIST@lists.sr.ht
+liste
+de diffusion
+.ME .
+Utilise le sujet "\f(CR[$PROJECT] BUG ou TASK:
+<description>\fR".
+.IP \(bu
+Parcourir les bogues
+.UR https://$TLD/$PROJECT/TODOs.html
+en
+ligne
+.UE .
+.IP \(bu
+.UR https://$TLD/$PROJECT/fr/
+Page d'accueil
+.UE .
+.IP \(bu
+.UR https://lists.sr.ht/~euandreh/$MAILING_LIST?search=%5B$PROJECT%5D
+Commentaires et discussions
+.UE .
+EOF
+
+EXPECTED_EO="$(mkstemp)"
+cat <<EOF | sed 's|-|\\-|g' >> "$EXPECTED_EO"
+
+
+.SH AŬTOROJ
+
+.MT eu@euandre.org
+EuAndreh
+.ME
+kaj la kontribuuloj.
+
+
+.SH MISFUNKCIOJ
+
+.IP \(bu
+Raportu misfunkcioj al la
+.MT ~euandreh/$MAILING_LIST@lists.sr.ht
+dissendolisto
+.ME .
+Uzu la subjekton "\f(CR[$PROJECT] BUG aŭ TASK:
+<priskribo>\fR".
+.IP \(bu
+Foliumu misfunkcioj
+.UR https://$TLD/$PROJECT/TODOs.html
+rete
+.UE .
+.IP \(bu
+.UR https://$TLD/$PROJECT/eo/
+Ĉefpaĝo
+.UE .
+.IP \(bu
+.UR https://lists.sr.ht/~euandreh/$MAILING_LIST?search=%5B$PROJECT%5D
+Komentoj kaj diskutoj
+.UE .
+EOF
+
+
+for from_f in "$@"; do
+ for lang in $LANGS; do
+ case "$lang" in
+ en)
+ EXPECTED="$EXPECTED_EN"
+ ;;
+ pt)
+ EXPECTED="$EXPECTED_PT"
+ ;;
+ fr)
+ EXPECTED="$EXPECTED_FR"
+ ;;
+ eo)
+ EXPECTED="$EXPECTED_EO"
+ ;;
+ *)
+ printf 'Unsupported lang: %s\n' "$lang" >&2
+ exit 2
+ ;;
+ esac
+
+ f="$(echo "$from_f" | sed "s/\.en\./.$lang./")"
+ if ! tail -n "$(wc -l < "$EXPECTED")" "$f" |
+ diff - "$EXPECTED"; then
+ echo "Missing metadata at the end of \"$f\" file"
+ if [ "$IN_PLACE" = true ]; then
+ cat "$EXPECTED" >> "$f"
+ else
+ exit 1
+ fi
+ fi
+ done
+done
diff --git a/aux/workflow/installcheck.sh b/aux/workflow/installcheck.sh
new file mode 100755
index 0000000..0aae391
--- /dev/null
+++ b/aux/workflow/installcheck.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+set -eu
+
+while getopts 'p:x:l:f:u' flag; do
+ case "$flag" in
+ p)
+ PREFIX="$OPTARG"
+ ;;
+ x)
+ EXECUTABLES_EXPECTED="$OPTARG"
+ ;;
+ l)
+ SYMLINKS_EXPECTED="$OPTARG"
+ ;;
+ f)
+ FILES_EXPECTED="$OPTARG"
+ ;;
+ u)
+ UNINSTALL=1
+ ;;
+ *)
+ exit 2
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+
+if [ -n "${UNINSTALL:-}" ]; then
+ if [ "$(find "$PREFIX" -type f | wc -l)" != 0 ]; then
+ printf 'When uninstalling, left over files in the'
+ printf 'PREFIX directory:\n'
+ find "$PREFIX" -type f
+ exit 1
+ fi
+ exit
+fi
+
+EXECUTABLES_ACTUAL="$(find "$PREFIX" -type f -perm -a=x | wc -l)"
+if [ "${EXECUTABLES_EXPECTED:-0}" != "$EXECUTABLES_ACTUAL" ]; then
+ printf 'Expected %s executables, found %s:\n' \
+ "$EXECUTABLES_EXPECTED" "$EXECUTABLES_ACTUAL" >&2
+ find "$PREFIX" -type f -perm -a=x
+ exit 1
+fi
+
+SYMLINKS_ACTUAL="$(find "$PREFIX" -type l | wc -l)"
+if [ "${SYMLINKS_EXPECTED:-0}" != "$SYMLINKS_ACTUAL" ]; then
+ printf 'Expected %s symlinks, found %s:\n' \
+ "$SYMLINKS_EXPECTED" "$SYMLINKS_ACTUAL" >&2
+ find "$PREFIX" -type l
+ exit 1
+fi
+
+FILES_ACTUAL="$(find "$PREFIX" -type f | wc -l)"
+if [ "${FILES_EXPECTED:-0}" != "$FILES_ACTUAL" ]; then
+ printf 'Expected %s files, found %s:\n' \
+ "$FILES_EXPECTED" "$FILES_ACTUAL" >&2
+ find "$PREFIX" -type f
+ exit 1
+fi
diff --git a/aux/workflow/l10n.sh b/aux/workflow/l10n.sh
new file mode 100755
index 0000000..683758f
--- /dev/null
+++ b/aux/workflow/l10n.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+set -eu
+
+LANGS=
+while getopts 'l:L:' flag; do
+ case "$flag" in
+ l)
+ LANGS="$OPTARG"
+ ;;
+ L)
+ CONTRIBLANGS="$OPTARG"
+ ;;
+ *)
+ exit 2
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+assert_arg() {
+ if [ -z "$1" ]; then
+ echo "Missing $2" >&2
+ exit 2
+ fi
+}
+
+assert_arg "${LANGS:-}" '-l LANGS'
+
+for from_f in "$@"; do
+ for lang in $LANGS ${CONTRIBLANGS:-}; do
+ to_f="$(echo "$from_f" | sed "s/\.en\./.$lang./")"
+ printf 'Generating %s...\n' "$to_f"
+ pofile="po/LC_MESSAGES/$from_f/$lang.po"
+ mkdir -p "$(dirname "$pofile")"
+
+ case "$from_f" in
+ *.en.[1-9].in)
+ po4a-updatepo -f man -m "$from_f" -p "$pofile"
+ po4a-translate -f man -m "$from_f" \
+ -p "$pofile" -l "$to_f" -k 0 -v >&2
+ ;;
+ *.en.md)
+ touch "$pofile"
+ md2po --include-codeblocks --quiet --save \
+ --po-filepath "$pofile" < "$from_f"
+ po2md --pofiles "$pofile" --save "$to_f" \
+ --quiet --wrapwidth 999 < "$from_f"
+ ;;
+ *)
+ echo "Unsupported file format: $from_f" >&2
+ exit 2
+ ;;
+ esac
+ done
+done
+
+end="\033[0m"
+yellowb="\033[1;33m"
+for lang in $LANGS; do
+ # shellcheck disable=2044
+ for pofile in $(find po/ -type f -name "$lang.po"); do
+ if ! LANG=POSIX msgfmt --statistics "$pofile" 2>&1 |
+ grep untranslated; then
+ continue
+ fi
+ # shellcheck disable=2059
+ printf "\n ${yellowb}WARNING${end}!" >&2
+ printf "\n Missing translations for %s\n\n" "$pofile" >&2
+ done
+done
diff --git a/aux/workflow/manpages.sh b/aux/workflow/manpages.sh
new file mode 100755
index 0000000..5c83a37
--- /dev/null
+++ b/aux/workflow/manpages.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+set -eu
+
+while getopts 'iuHo:p:' flag; do
+ case "$flag" in
+ i)
+ ACTION=install
+ ;;
+ u)
+ ACTION=uninstall
+ ;;
+ H)
+ ACTION=html
+ ;;
+ o)
+ OUTDIR="$OPTARG"
+ ;;
+ p)
+ MANPREFIX="$OPTARG"
+ ;;
+ *)
+ exit 2
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+assert_arg() {
+ if [ -z "$1" ]; then
+ echo "Missing $2" >&2
+ exit 2
+ fi
+}
+
+assert_arg "${ACTION:-}" '-[iuH] for choosing action'
+
+for f in "$@"; do
+ l="$(echo "$f" | awk -F. '{print $(NF-1)}')"
+ n="$(echo "$f" | awk -F. '{print $NF}')"
+ case "$ACTION" in
+ html)
+ assert_arg "${OUTDIR:-}" '-o OUTDIR'
+ to_name="$(basename "${f%.$l.$n}.$n.html")"
+ mkdir -p "$OUTDIR/$l"
+ pandoc -s -r man -w html --metadata "lang=$l" \
+ < "$f" > "$OUTDIR/$l/$to_name"
+ ;;
+ install)
+ assert_arg "${MANPREFIX:-}" '-p MANPREFIX'
+ to_name="$(basename "${f%.$l.$n}.$n")"
+ mkdir -p "$MANPREFIX/$l/man$n" "$MANPREFIX/man$n"
+ cp "$f" "$MANPREFIX/$l/man$n/$to_name"
+ ln -fs "../en/man$n/$to_name" \
+ "$MANPREFIX/man$n/$to_name"
+ ;;
+ uninstall)
+ assert_arg "${MANPREFIX:-}" '-p MANPREFIX'
+ to_name="$(basename "${f%.$l.$n}.$n")"
+ rm -f \
+ "$MANPREFIX/$l/man$n/$to_name" \
+ "$MANPREFIX/man$n/$to_name"
+ ;;
+ *)
+ echo "Bad ACTION: $ACTION"
+ exit 1
+ ;;
+ esac
+done
diff --git a/doc/gistatic.1 b/doc/gistatic.1
deleted file mode 100644
index db90e5d..0000000
--- a/doc/gistatic.1
+++ /dev/null
@@ -1,19 +0,0 @@
-=pod
-
-=head1 Heading Text
-
-=head2 Heading Text
-
-=head3 Heading Text
-
-=head4 Heading Text
-
-=begin format
-
-=end format
-
-=for format text...
-
-=encoding utf8
-
-=cut
diff --git a/doc/gistatic.en.1.in b/doc/gistatic.en.1.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/doc/gistatic.en.1.in
diff --git a/doc/gistatic.eo.1.in b/doc/gistatic.eo.1.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/doc/gistatic.eo.1.in
diff --git a/doc/gistatic.fr.1.in b/doc/gistatic.fr.1.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/doc/gistatic.fr.1.in
diff --git a/doc/gistatic.pt.1.in b/doc/gistatic.pt.1.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/doc/gistatic.pt.1.in
diff --git a/po/LC_MESSAGES/CHANGELOG.en.md/eo.po b/po/LC_MESSAGES/CHANGELOG.en.md/eo.po
new file mode 100644
index 0000000..92c03c1
--- /dev/null
+++ b/po/LC_MESSAGES/CHANGELOG.en.md/eo.po
@@ -0,0 +1,6 @@
+#
+msgid ""
+msgstr ""
+
+msgid "Changelog for [gistatic](https://euandreh.xyz/gistatic/en/)."
+msgstr ""
diff --git a/po/LC_MESSAGES/CHANGELOG.en.md/fr.po b/po/LC_MESSAGES/CHANGELOG.en.md/fr.po
new file mode 100644
index 0000000..92c03c1
--- /dev/null
+++ b/po/LC_MESSAGES/CHANGELOG.en.md/fr.po
@@ -0,0 +1,6 @@
+#
+msgid ""
+msgstr ""
+
+msgid "Changelog for [gistatic](https://euandreh.xyz/gistatic/en/)."
+msgstr ""
diff --git a/po/LC_MESSAGES/CHANGELOG.en.md/pt.po b/po/LC_MESSAGES/CHANGELOG.en.md/pt.po
new file mode 100644
index 0000000..92c03c1
--- /dev/null
+++ b/po/LC_MESSAGES/CHANGELOG.en.md/pt.po
@@ -0,0 +1,6 @@
+#
+msgid ""
+msgstr ""
+
+msgid "Changelog for [gistatic](https://euandreh.xyz/gistatic/en/)."
+msgstr ""
diff --git a/po/LC_MESSAGES/README.en.md/eo.po b/po/LC_MESSAGES/README.en.md/eo.po
new file mode 100644
index 0000000..ace966d
--- /dev/null
+++ b/po/LC_MESSAGES/README.en.md/eo.po
@@ -0,0 +1,176 @@
+#
+msgid ""
+msgstr ""
+
+msgid "gistatic"
+msgstr ""
+
+msgid "Static Git repository generator"
+msgstr ""
+
+msgid ""
+"Generate HTML pages for a Git repository. The generated pages are static and"
+" offline-first, and can be made available online as static assets."
+msgstr ""
+
+msgid "Usage"
+msgstr ""
+
+msgid "Generate static HTML website for Git repository:"
+msgstr ""
+
+msgid "$ gistatic path/to/git/ -o public/\n"
+msgstr ""
+
+msgid "Installation"
+msgstr ""
+
+msgid "Get the latest tarball and install it:"
+msgstr ""
+
+msgid ""
+"wget https://euandreh.xyz/gistatic/tarballs/gistatic-main.tar.gz\n"
+"tar xvf gistatic-main.tar.gz\n"
+"cd gistatic-main/\n"
+"make\n"
+"[sudo] make install\n"
+msgstr ""
+
+msgid "The requirements are Perl with dependencies:"
+msgstr ""
+
+msgid "[Git::Raw][Git::Raw]: Perl bindings to [libgit2][libgit2];"
+msgstr ""
+
+msgid ""
+"[Mustache::Simple][Mustache::Simple]: template library for generating output"
+" files;"
+msgstr ""
+
+msgid "[CommonMark][cm-p]: [CommonMark][cm-spec] renderer."
+msgstr ""
+
+msgid "Documentation"
+msgstr ""
+
+msgid ""
+"Documentation available via installed manpages, also available online: "
+"[`gistatic.1`](gistatic.1.html) and [`gistatic-template.5`](gistatic-"
+"template.5.html)."
+msgstr ""
+
+msgid "Contributing"
+msgstr ""
+
+msgid "Extra tools used for development are:"
+msgstr ""
+
+msgid "[Perl::Critic][Perl::Critic] and [B::Lint][B::Lint] for linting;"
+msgstr ""
+
+msgid "[perltidy][perltidy] for code formatting;"
+msgstr ""
+
+msgid "[ShellCheck][ShellCheck] for validating scripts;"
+msgstr ""
+
+msgid "[pandoc][pandoc] for generating the documentation HTML and website."
+msgstr ""
+
+msgid "For running the extra development-only checks, run:"
+msgstr ""
+
+msgid "$ make dev-check\n"
+msgstr ""
+
+msgid "and for generating the documentation HTML and website, run:"
+msgstr ""
+
+msgid "$ make public\n"
+msgstr ""
+
+msgid ""
+"Send contributions to the [mailing list][mailing list] via [`git send-"
+"email`](https://git-send-email.io/)."
+msgstr ""
+
+msgid "Links"
+msgstr ""
+
+msgid "[homepage](https://euandreh.xyz/gistatic/en/)"
+msgstr ""
+
+msgid "[source code](https://git.euandreh.xyz/gistatic/)"
+msgstr ""
+
+msgid "[bug tracking](https://euandreh.xyz/gistatic/TODOs.html)"
+msgstr ""
+
+msgid "[mailing list][mailing list]"
+msgstr ""
+
+msgid "[CI logs](https://euandreh.xyz/gistatic/ci.html)"
+msgstr ""
+
+msgid "[CHANGELOG](https://euandreh.xyz/gistatic/en/CHANGELOG.html)"
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid ""
+"The code is licensed under [GNU Affero General Public License v3.0 or "
+"later][AGPL-3.0-or-later] (AGPL-3.0-or-later)."
+msgstr ""
+
+#, fuzzy
+msgid "[Git::Raw]: https://metacpan.org/pod/Git::Raw"
+msgstr "[Git::Raw]: https://metacpan.org/pod/Git::Raw"
+
+#, fuzzy
+msgid "[libgit2]: https://libgit2.org/"
+msgstr "[libgit2]: https://libgit2.org/"
+
+#, fuzzy
+msgid "[Mustache::Simple]: https://metacpan.org/pod/Mustache::Simple"
+msgstr "[Mustache::Simple]: https://metacpan.org/pod/Mustache::Simple"
+
+#, fuzzy
+msgid "[cm-p]: https://metacpan.org/pod/CommonMark"
+msgstr "[cm-p]: https://metacpan.org/pod/CommonMark"
+
+#, fuzzy
+msgid "[cm-spec]: https://commonmark.org/"
+msgstr "[cm-spec]: https://commonmark.org/"
+
+#, fuzzy
+msgid "[Perl::Critic]: https://metacpan.org/pod/Perl::Critic"
+msgstr "[Perl::Critic]: https://metacpan.org/pod/Perl::Critic"
+
+#, fuzzy
+msgid "[B::Lint]: https://metacpan.org/pod/B::Lint"
+msgstr "[B::Lint]: https://metacpan.org/pod/B::Lint"
+
+#, fuzzy
+msgid "[perltidy]: https://metacpan.org/pod/perltidy"
+msgstr "[perltidy]: https://metacpan.org/pod/perltidy"
+
+#, fuzzy
+msgid "[ShellCheck]: https://www.shellcheck.net/"
+msgstr "[ShellCheck]: https://www.shellcheck.net/"
+
+#, fuzzy
+msgid "[pandoc]: https://pandoc.org/"
+msgstr "[pandoc]: https://pandoc.org/"
+
+#, fuzzy
+msgid ""
+"[mailing list]: https://lists.sr.ht/~euandreh/public-"
+"inbox?search=%5Bgistatic%5D"
+msgstr ""
+"[mailing list]: https://lists.sr.ht/~euandreh/public-"
+"inbox?search=%5Bgistatic%5D"
+
+#, fuzzy
+msgid "[AGPL-3.0-or-later]: https://git.euandreh.xyz/gistatic/tree/COPYING"
+msgstr "[AGPL-3.0-or-later]: https://git.euandreh.xyz/gistatic/tree/COPYING"
diff --git a/po/LC_MESSAGES/README.en.md/fr.po b/po/LC_MESSAGES/README.en.md/fr.po
new file mode 100644
index 0000000..ace966d
--- /dev/null
+++ b/po/LC_MESSAGES/README.en.md/fr.po
@@ -0,0 +1,176 @@
+#
+msgid ""
+msgstr ""
+
+msgid "gistatic"
+msgstr ""
+
+msgid "Static Git repository generator"
+msgstr ""
+
+msgid ""
+"Generate HTML pages for a Git repository. The generated pages are static and"
+" offline-first, and can be made available online as static assets."
+msgstr ""
+
+msgid "Usage"
+msgstr ""
+
+msgid "Generate static HTML website for Git repository:"
+msgstr ""
+
+msgid "$ gistatic path/to/git/ -o public/\n"
+msgstr ""
+
+msgid "Installation"
+msgstr ""
+
+msgid "Get the latest tarball and install it:"
+msgstr ""
+
+msgid ""
+"wget https://euandreh.xyz/gistatic/tarballs/gistatic-main.tar.gz\n"
+"tar xvf gistatic-main.tar.gz\n"
+"cd gistatic-main/\n"
+"make\n"
+"[sudo] make install\n"
+msgstr ""
+
+msgid "The requirements are Perl with dependencies:"
+msgstr ""
+
+msgid "[Git::Raw][Git::Raw]: Perl bindings to [libgit2][libgit2];"
+msgstr ""
+
+msgid ""
+"[Mustache::Simple][Mustache::Simple]: template library for generating output"
+" files;"
+msgstr ""
+
+msgid "[CommonMark][cm-p]: [CommonMark][cm-spec] renderer."
+msgstr ""
+
+msgid "Documentation"
+msgstr ""
+
+msgid ""
+"Documentation available via installed manpages, also available online: "
+"[`gistatic.1`](gistatic.1.html) and [`gistatic-template.5`](gistatic-"
+"template.5.html)."
+msgstr ""
+
+msgid "Contributing"
+msgstr ""
+
+msgid "Extra tools used for development are:"
+msgstr ""
+
+msgid "[Perl::Critic][Perl::Critic] and [B::Lint][B::Lint] for linting;"
+msgstr ""
+
+msgid "[perltidy][perltidy] for code formatting;"
+msgstr ""
+
+msgid "[ShellCheck][ShellCheck] for validating scripts;"
+msgstr ""
+
+msgid "[pandoc][pandoc] for generating the documentation HTML and website."
+msgstr ""
+
+msgid "For running the extra development-only checks, run:"
+msgstr ""
+
+msgid "$ make dev-check\n"
+msgstr ""
+
+msgid "and for generating the documentation HTML and website, run:"
+msgstr ""
+
+msgid "$ make public\n"
+msgstr ""
+
+msgid ""
+"Send contributions to the [mailing list][mailing list] via [`git send-"
+"email`](https://git-send-email.io/)."
+msgstr ""
+
+msgid "Links"
+msgstr ""
+
+msgid "[homepage](https://euandreh.xyz/gistatic/en/)"
+msgstr ""
+
+msgid "[source code](https://git.euandreh.xyz/gistatic/)"
+msgstr ""
+
+msgid "[bug tracking](https://euandreh.xyz/gistatic/TODOs.html)"
+msgstr ""
+
+msgid "[mailing list][mailing list]"
+msgstr ""
+
+msgid "[CI logs](https://euandreh.xyz/gistatic/ci.html)"
+msgstr ""
+
+msgid "[CHANGELOG](https://euandreh.xyz/gistatic/en/CHANGELOG.html)"
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid ""
+"The code is licensed under [GNU Affero General Public License v3.0 or "
+"later][AGPL-3.0-or-later] (AGPL-3.0-or-later)."
+msgstr ""
+
+#, fuzzy
+msgid "[Git::Raw]: https://metacpan.org/pod/Git::Raw"
+msgstr "[Git::Raw]: https://metacpan.org/pod/Git::Raw"
+
+#, fuzzy
+msgid "[libgit2]: https://libgit2.org/"
+msgstr "[libgit2]: https://libgit2.org/"
+
+#, fuzzy
+msgid "[Mustache::Simple]: https://metacpan.org/pod/Mustache::Simple"
+msgstr "[Mustache::Simple]: https://metacpan.org/pod/Mustache::Simple"
+
+#, fuzzy
+msgid "[cm-p]: https://metacpan.org/pod/CommonMark"
+msgstr "[cm-p]: https://metacpan.org/pod/CommonMark"
+
+#, fuzzy
+msgid "[cm-spec]: https://commonmark.org/"
+msgstr "[cm-spec]: https://commonmark.org/"
+
+#, fuzzy
+msgid "[Perl::Critic]: https://metacpan.org/pod/Perl::Critic"
+msgstr "[Perl::Critic]: https://metacpan.org/pod/Perl::Critic"
+
+#, fuzzy
+msgid "[B::Lint]: https://metacpan.org/pod/B::Lint"
+msgstr "[B::Lint]: https://metacpan.org/pod/B::Lint"
+
+#, fuzzy
+msgid "[perltidy]: https://metacpan.org/pod/perltidy"
+msgstr "[perltidy]: https://metacpan.org/pod/perltidy"
+
+#, fuzzy
+msgid "[ShellCheck]: https://www.shellcheck.net/"
+msgstr "[ShellCheck]: https://www.shellcheck.net/"
+
+#, fuzzy
+msgid "[pandoc]: https://pandoc.org/"
+msgstr "[pandoc]: https://pandoc.org/"
+
+#, fuzzy
+msgid ""
+"[mailing list]: https://lists.sr.ht/~euandreh/public-"
+"inbox?search=%5Bgistatic%5D"
+msgstr ""
+"[mailing list]: https://lists.sr.ht/~euandreh/public-"
+"inbox?search=%5Bgistatic%5D"
+
+#, fuzzy
+msgid "[AGPL-3.0-or-later]: https://git.euandreh.xyz/gistatic/tree/COPYING"
+msgstr "[AGPL-3.0-or-later]: https://git.euandreh.xyz/gistatic/tree/COPYING"
diff --git a/po/LC_MESSAGES/README.en.md/pt.po b/po/LC_MESSAGES/README.en.md/pt.po
new file mode 100644
index 0000000..ace966d
--- /dev/null
+++ b/po/LC_MESSAGES/README.en.md/pt.po
@@ -0,0 +1,176 @@
+#
+msgid ""
+msgstr ""
+
+msgid "gistatic"
+msgstr ""
+
+msgid "Static Git repository generator"
+msgstr ""
+
+msgid ""
+"Generate HTML pages for a Git repository. The generated pages are static and"
+" offline-first, and can be made available online as static assets."
+msgstr ""
+
+msgid "Usage"
+msgstr ""
+
+msgid "Generate static HTML website for Git repository:"
+msgstr ""
+
+msgid "$ gistatic path/to/git/ -o public/\n"
+msgstr ""
+
+msgid "Installation"
+msgstr ""
+
+msgid "Get the latest tarball and install it:"
+msgstr ""
+
+msgid ""
+"wget https://euandreh.xyz/gistatic/tarballs/gistatic-main.tar.gz\n"
+"tar xvf gistatic-main.tar.gz\n"
+"cd gistatic-main/\n"
+"make\n"
+"[sudo] make install\n"
+msgstr ""
+
+msgid "The requirements are Perl with dependencies:"
+msgstr ""
+
+msgid "[Git::Raw][Git::Raw]: Perl bindings to [libgit2][libgit2];"
+msgstr ""
+
+msgid ""
+"[Mustache::Simple][Mustache::Simple]: template library for generating output"
+" files;"
+msgstr ""
+
+msgid "[CommonMark][cm-p]: [CommonMark][cm-spec] renderer."
+msgstr ""
+
+msgid "Documentation"
+msgstr ""
+
+msgid ""
+"Documentation available via installed manpages, also available online: "
+"[`gistatic.1`](gistatic.1.html) and [`gistatic-template.5`](gistatic-"
+"template.5.html)."
+msgstr ""
+
+msgid "Contributing"
+msgstr ""
+
+msgid "Extra tools used for development are:"
+msgstr ""
+
+msgid "[Perl::Critic][Perl::Critic] and [B::Lint][B::Lint] for linting;"
+msgstr ""
+
+msgid "[perltidy][perltidy] for code formatting;"
+msgstr ""
+
+msgid "[ShellCheck][ShellCheck] for validating scripts;"
+msgstr ""
+
+msgid "[pandoc][pandoc] for generating the documentation HTML and website."
+msgstr ""
+
+msgid "For running the extra development-only checks, run:"
+msgstr ""
+
+msgid "$ make dev-check\n"
+msgstr ""
+
+msgid "and for generating the documentation HTML and website, run:"
+msgstr ""
+
+msgid "$ make public\n"
+msgstr ""
+
+msgid ""
+"Send contributions to the [mailing list][mailing list] via [`git send-"
+"email`](https://git-send-email.io/)."
+msgstr ""
+
+msgid "Links"
+msgstr ""
+
+msgid "[homepage](https://euandreh.xyz/gistatic/en/)"
+msgstr ""
+
+msgid "[source code](https://git.euandreh.xyz/gistatic/)"
+msgstr ""
+
+msgid "[bug tracking](https://euandreh.xyz/gistatic/TODOs.html)"
+msgstr ""
+
+msgid "[mailing list][mailing list]"
+msgstr ""
+
+msgid "[CI logs](https://euandreh.xyz/gistatic/ci.html)"
+msgstr ""
+
+msgid "[CHANGELOG](https://euandreh.xyz/gistatic/en/CHANGELOG.html)"
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid ""
+"The code is licensed under [GNU Affero General Public License v3.0 or "
+"later][AGPL-3.0-or-later] (AGPL-3.0-or-later)."
+msgstr ""
+
+#, fuzzy
+msgid "[Git::Raw]: https://metacpan.org/pod/Git::Raw"
+msgstr "[Git::Raw]: https://metacpan.org/pod/Git::Raw"
+
+#, fuzzy
+msgid "[libgit2]: https://libgit2.org/"
+msgstr "[libgit2]: https://libgit2.org/"
+
+#, fuzzy
+msgid "[Mustache::Simple]: https://metacpan.org/pod/Mustache::Simple"
+msgstr "[Mustache::Simple]: https://metacpan.org/pod/Mustache::Simple"
+
+#, fuzzy
+msgid "[cm-p]: https://metacpan.org/pod/CommonMark"
+msgstr "[cm-p]: https://metacpan.org/pod/CommonMark"
+
+#, fuzzy
+msgid "[cm-spec]: https://commonmark.org/"
+msgstr "[cm-spec]: https://commonmark.org/"
+
+#, fuzzy
+msgid "[Perl::Critic]: https://metacpan.org/pod/Perl::Critic"
+msgstr "[Perl::Critic]: https://metacpan.org/pod/Perl::Critic"
+
+#, fuzzy
+msgid "[B::Lint]: https://metacpan.org/pod/B::Lint"
+msgstr "[B::Lint]: https://metacpan.org/pod/B::Lint"
+
+#, fuzzy
+msgid "[perltidy]: https://metacpan.org/pod/perltidy"
+msgstr "[perltidy]: https://metacpan.org/pod/perltidy"
+
+#, fuzzy
+msgid "[ShellCheck]: https://www.shellcheck.net/"
+msgstr "[ShellCheck]: https://www.shellcheck.net/"
+
+#, fuzzy
+msgid "[pandoc]: https://pandoc.org/"
+msgstr "[pandoc]: https://pandoc.org/"
+
+#, fuzzy
+msgid ""
+"[mailing list]: https://lists.sr.ht/~euandreh/public-"
+"inbox?search=%5Bgistatic%5D"
+msgstr ""
+"[mailing list]: https://lists.sr.ht/~euandreh/public-"
+"inbox?search=%5Bgistatic%5D"
+
+#, fuzzy
+msgid "[AGPL-3.0-or-later]: https://git.euandreh.xyz/gistatic/tree/COPYING"
+msgstr "[AGPL-3.0-or-later]: https://git.euandreh.xyz/gistatic/tree/COPYING"
diff --git a/po/LC_MESSAGES/doc/gistatic.en.1.in/eo.po b/po/LC_MESSAGES/doc/gistatic.en.1.in/eo.po
new file mode 100644
index 0000000..a2c9416
--- /dev/null
+++ b/po/LC_MESSAGES/doc/gistatic.en.1.in/eo.po
@@ -0,0 +1,18 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2021-07-27 14:28-0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
diff --git a/po/LC_MESSAGES/doc/gistatic.en.1.in/fr.po b/po/LC_MESSAGES/doc/gistatic.en.1.in/fr.po
new file mode 100644
index 0000000..a2c9416
--- /dev/null
+++ b/po/LC_MESSAGES/doc/gistatic.en.1.in/fr.po
@@ -0,0 +1,18 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2021-07-27 14:28-0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
diff --git a/po/LC_MESSAGES/doc/gistatic.en.1.in/pt.po b/po/LC_MESSAGES/doc/gistatic.en.1.in/pt.po
new file mode 100644
index 0000000..a2c9416
--- /dev/null
+++ b/po/LC_MESSAGES/doc/gistatic.en.1.in/pt.po
@@ -0,0 +1,18 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2021-07-27 14:28-0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
diff --git a/src/gistatic.c b/src/gistatic.c
new file mode 100644
index 0000000..061ed7e
--- /dev/null
+++ b/src/gistatic.c
@@ -0,0 +1,3 @@
+int main(void) {
+ return 0;
+}
diff --git a/src/lib.rs b/src/lib.rs
deleted file mode 100644
index 2bd4a2e..0000000
--- a/src/lib.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-const LOG: &'static str = include_str!("templates/log.html");
-
-pub fn a_fn() -> i32 {
- // println!("log.html.tmpl: {}", t);
- let template = mustache::compile_str(LOG).unwrap();
- let _data = mustache::MapBuilder::new()
- .insert_str("name", "Venus")
- .build();
-
- let mut d2 = std::collections::HashMap::new();
- d2.insert("a", "b");
- template.render(&mut std::io::stdout(), &d2). unwrap();
-
- 0
-}
-
-#[test]
-fn a_test() {
-}
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index cdb964d..0000000
--- a/src/main.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-pub fn main() {
- println!("Hello, World!");
- println!("a_fn(): {}", gistatic::a_fn());
-}