1 个不稳定版本

0.2.0 2024年2月27日

#636 in 开发工具

MIT 许可证

87KB
2.5K SLoC

文献编程工具集

这是一个用于文献编程的程序集。它们试图使这个过程尽可能顺畅。

link link link link

基本设计决策

该软件是用 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