1 个不稳定版本
0.2.0 | 2024年2月27日 |
---|
#636 in 开发工具
87KB
2.5K SLoC
文献编程工具集
这是一个用于文献编程的程序集。它们试图使这个过程尽可能顺畅。
基本设计决策
该软件是用 Rust 编写的。它使用自己的工具生成 Rust 源代码。
每个逻辑部分都单独在子 crate 中。大多数这些子 crate 在此 crate 中定义了同名的命令行工具。在每一个子 crate 文件夹中,我们都有一个 <name>.adoc
文件,这是该子 crate 的主要源文件。
子 crate 包括:
asciidoctrine:: 一个可扩展的 asciidoctrine/asciidoctrine.adoc#, asciidoc 解释器。目前还不是非常成熟。lisi:: 一个灵活的 lisi/lisi.adoc#,文献编程工具,适用于 tangle 和 weave。目前有一些基本功能。ansicht:: 一个 ansicht/ansicht.adoc#,可视化编程工具,主要用于与文献编程工具一起使用。目前仅是一个草案。dolmetscher:: 一个 dolmetscher/dolmetscher.adoc#,翻译辅助工具。目前仅是一个草案。
我认为 asciidoc 比 markdown 更优秀,所以我们使用它作为基本输入格式。
安装
安装和使用此软件有一些不同的选项
从您的发行版软件包管理器安装::下载预编译的二进制文件::对于Windows,您可以下载通过github actions构建的https://nightly.link/kober-systems/literate_programming_toolsuite/actions/runs/8063422942/lisi-Windows.zip[最新 Windows二进制文件] 使用Docker镜像::您可以使用Dockerhub上的预编译镜像lammermann/lisi。如果您想修改Dockerfile本身的代码,您可以在dockerfile,单独部分中找到代码。使用cargo安装::运行[[install_with_cargo]]cargo install --force --path lisi
从源码构建::如果您想为项目做出贡献或修改代码以供个人使用,这最有意义。您可以在文档中的build_instructions,文档后面的部分中找到说明。NixOS/nix::安装::[[install_with_nix]]nix-env -i -f lisi.nix
本地构建::[[build_locally]]nix-build lisi.nix
[[build_instructions]]
从源码构建
如果您想修改程序以适应您的使用案例,您需要构建和编译代码。
构建工具集需要几个步骤。
[source, sh, save] .build.sh
set -e # <4>
[check_generated_sources_are_vcs_clean](#check_generated_sources_are_vcs_clean) # <1>
[generate_sources](#generate_sources)
[build_and_test](#build_and_test)
[update_docs](#update_docs)
[ask_for_vcs_check_in](#ask_for_vcs_check_in) # <2>
[publish_on_crates_io](#publish_on_crates_io)
[ask_for_local_install](#ask_for_local_install) # <3>
<1> 如果我们手动编辑了一些生成的源代码,我们可能不希望它们在我们将它们合并回asciidoc源之前被我们的构建过程覆盖。<2> 一旦我们的构建成功,我们很可能会想要将更改保存到我们的vcs中。<3> 如果一切顺利,我们可能想在本地安装我们的新版本的工具集。<4> 当某个步骤失败时,我们希望脚本结束
先决条件
您的计算机上必须安装一些程序才能发布一个版本的literate programming toolsuite
。
git:: 它目前在github上发布,因此我们需要git。rust,cargo等:: 这些程序是用rust编写的,因此我们需要rust工具链。asciidoc:: 目前我们需要asciidcotor
来构建文档。在未来的版本中,计划使用我们自己的asciidoctrine
程序。我们的文档生成过程还有一些额外的依赖项。asciidcotor-diagram::: 对于我们的图表。ditaa::: 对于我们的图表。pygments::: 对于源代码高亮。
检查生成的文件在VCS中是否未更改
也许我们手动编辑了一些我们的生成的源文件。在这种情况下,我们希望在生成文件之前警告我们。这样我们就可以检查是否想将我们的更改放入我们的asciidoc源中,或者是否不关心它们是否被覆盖。
我们假设所有更改的文件(非asciidoc文件)都可能被覆盖。
[[check_generated_sources_are_vcs_clean]] [source, sh]
changed_files=`git diff --name-only | grep --invert-match '\.adoc$'`
if [[ ! -z "$changed_files" ]]; then
while true; do
echo "some files are modified"
echo "$changed_files"
read -p "Do you wish continue anyway? [yes|no] " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
fi
生成源文件
[[generate_sources]] [source, sh]
echo "Start generating source files ..."
cd asciidoctrine/
lisi -o ../docs/asciidoctrine/asciidoctrine.lisi.html asciidoctrine.adoc \
|| echo "lisi is currenty not installed"
cd ..
cd lisi
lisi -o /dev/null lisi.adoc || echo "lisi is currenty not installed" # <1>
# The new generated source must be able to
# generate itself
cargo run --manifest-path ../Cargo.toml --bin lisi -- -o lisi.html lisi.adoc
cd ..
cargo run --bin lisi -- -o /dev/null README.adoc # <2>
echo "Generating source files done!"
<1> 我们使用预安装的lisi
版本来构建源文件。这有助于我们在生成的源文件中存在错误时。如果我们还没有安装lisi
版本,则没有问题,脚本将只会给我们一个警告,并在下一步生成源文件。<2> 由于lisi
目前无法评估带有用户命令行输入的脚本,我们需要定期刷新构建脚本。
构建和测试
[[build_and_test]] [source, sh]
cargo test
为github页面构建网站
TODO 我们希望在将来使用asciidoctrine
单独完成此操作。
[[update_docs]] [source, sh]
echo "Start generating html files ..."
asciidoctor \
[asciidoctor-styles](#asciidoctor-styles)
-D docs \
README.adoc -o index.html
asciidoctor \
[asciidoctor-styles](#asciidoctor-styles)
-D docs/lisi \
lisi/lisi.adoc
asciidoctor \
[asciidoctor-styles](#asciidoctor-styles)
-D docs/asciidoctrine \
asciidoctrine/asciidoctrine.adoc
asciidoctor \
[asciidoctor-styles](#asciidoctor-styles)
-D docs/ansicht \
ansicht/ansicht.adoc
asciidoctor \
[asciidoctor-styles](#asciidoctor-styles)
-D docs/dolmetscher \
dolmetscher/dolmetscher.adoc
echo "Generating html files done!"
我们有一些通用的样式,应该在所有文件中保持一致
[[asciidoctor-styles]] [source, sh]
-r asciidoctor-diagram \
-a source-highlighter=pygments \
-a toc=left \
-a icons=font \
-a toclevels=4 \
-a data-uri \
-a reproducible \
黑客指南
如果您想修改代码以适应您的需求,可以遵循以下步骤,这是我在此描述的过程
更改源代码:这是一个文献程序,所以这里的真相是asciidoc文档。然而,我通常认为文献文档和生成的源代码是同一程序的两种不同视角。为了保持它们同步,我确保在从文献源重新生成源代码之前,将我对生成的源代码所做的任何更改提交到版本控制系统(VCS)。然后我可以查看生成的源代码和我的修改版本之间的差异,并相应地更改文献源,直到生成的代码与VCS中的代码不再有差异。当两个源同步时,我就可以随意修改文献源,并直接重新生成源代码。编译:在整个修改过程中,我循环编译和测试。为此,我使用watchexec作为我的简陋的CI。提交:当错误被修复或功能被实现等时,我将我的修改提交到VCS。检查:经过一段时间后,我想发布。在这种情况下,我会做以下事情:检查文献和生成的源代码是否同步。重新渲染文档。推送到GitHub。让CI完成其工作。
穷人的CI
每当Rust文件更改时,我们希望重建和测试程序。
[source, sh, save] .auto_build_loop.sh
watchexec -w . -c -e rs,toml --no-vcs-ignore -- "[build_and_test](#build_and_test)"
每当asciidoc文件更改时,我们希望重新生成源文件。但在我们能够这样做之前,我们必须确保当前源文件和生成的源文件是同步的。
TODO 这并不容易,因为当asciidoc文件被修改时,它们会生成“脏”的源文件(从VCS的角度来看)。因此,我们必须以某种方式存储这些更改,以便它们看起来与源文件同步。
请求将更改提交到VCS
[[ask_for_vcs_check_in]] [source, sh]
while true; do
git diff; # <1>
read -p "Do you wish to commit your changes to git? [yes|no] " yn
case $yn in
[Yy]* )
git add .; # <2>
git commit; # <2>
break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
<1> 在提交一切之前,我们应该进行最后的审查。<2> 通常我们知道我们在做什么,可以直接添加所有内容并继续,但如果我们在提交中看到了我们不希望包含的内容,我们应该在提交之前停止(通过让提交消息为空或通过在其他shell中更改包含的块)。
在我们的计算机上安装工具
[[ask_for_local_install]] [source, sh]
while true; do
read -p "Do you wish to install this program? [yes|no] " yn
case $yn in
[Yy]* )
[install_with_nix](#install_with_nix);
break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
审查流程
每当主分支上的代码或通过pull request更新时,它将被审查。审查的主要部分遵循本节中记录的指南。
TODO github actions
发布
当一切顺利时,是时候考虑发布了。
[[publish_on_crates_io]] [source, sh]
cargo publish --dry-run -p asciidoctrine
while true; do
read -p "Do you wish to publish asciidoctrine? [yes|no] " yn
case $yn in
[Yy]* )
cargo login;
cargo publish --dry-run -p asciidoctrine;
break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
cargo publish --dry-run -p lisi
while true; do
read -p "Do you wish to publish lisi? [yes|no] " yn
case $yn in
[Yy]* )
cargo login;
cargo publish --dry-run -p lisi;
break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
[[dockerfile]]
Dockerfile
要在ci-scripts中使用 lisi
(至少这是我的用例),有一个现成的Docker镜像非常方便。然而,当涉及到Docker镜像大小时,大小是关键。因此,我们在Dockerfile中使用了多个不同的阶段
- 一个用于构建我们的软件并包含所有构建依赖项
- 一个仅包含我们的最终二进制文件和最小运行时依赖项,以实现小型镜像
[source, Dockerfile, save] .Dockerfile
[docker_build_step](#docker_build_step)
[docker_final_image_step](#docker_final_image_step)
为了构建具有最小运行时依赖项的二进制文件,我们使用musl目标,它允许我们构建静态编译的二进制文件。为此,我们使用基于alpine的rust Docker镜像
[[docker_build_step]] [source, Dockerfile]
FROM rust:alpine AS builder
RUN apk --no-cache add g++ # <1>
WORKDIR /home/rust/
COPY . .
RUN cargo test
RUN cargo build --release
RUN strip target/release/lisi # <2>
<1> 由于某种奇怪的原因,我无法理解,我们只能在安装了 g++
的系统上编译(参见相关错误这里)。<2> 编译完二进制文件后,我们可以通过剥离它们来显著减小它们的大小。
我们构建程序后,基于alpine(因为它很小)创建一个新镜像,并将我们的二进制文件复制过来。
[[docker_final_image_step]] [source, Dockerfile]
FROM alpine:latest
WORKDIR /home/lisi
COPY --from=builder /home/rust/target/release/lisi .
ENV PATH="${PATH}:/home/lisi"
TODO 为docker镜像添加github actions
依赖项
~17–27MB
~376K SLoC