#版本控制 #控制系统 #Mathematica #解析器 #命令行解析器

应用程序 mathematica-notebook-filter

mathematica-notebook-filter 解析 Mathematica 笔记本文件,并移除冗余信息,以便更容易地将它们提交到版本控制系统

9 个版本

0.2.2 2019 年 2 月 20 日
0.2.0 2018 年 6 月 13 日
0.1.6 2018 年 4 月 4 日
0.1.5 2018 年 2 月 23 日
0.1.2 2017 年 9 月 14 日

文本处理 中排名第 825

每月下载量 29

GPL-3.0 许可证

115KB
2K SLoC

Rust 1K SLoC // 0.1% comments Wolfram 634 SLoC // 0.2% comments Shell 110 SLoC // 0.1% comments

mathematica-notebook-filter

mathematica-notebook-filter 是一个用 Rust 编写的程序,用于解析 Mathematica 笔记本文件,并移除冗余信息,以便更容易地将它们提交到版本控制系统中。有关将此程序集成到版本控制系统的说明,请参阅以下内容,并且可以设置透明地完成所有操作,而无需修改磁盘上的文件。

Crates.io Travis Codecov

GPLv3 许可下授权。

此程序尚未经过严格测试。它在我的笔记本上运行正常,但可能仍有一些情况尚未考虑。如果您使用此程序,请告知我(无论是正面还是负面的反馈)。

简介

版本控制系统(如 gitmercurial 等)提供了一种跟踪文件更改的绝佳方式,允许多个人协作工作而不会意外覆盖他人的更改。版本控制系统主要跟踪源代码,如果两个人修改了相同的文件,则可以并排比较这两个文件,以便合并更改。

尽管二进制文件(如编译输出、图像、PDF等)也可以包含在版本控制系统中,但通常无法或没有意义去比较一个二进制文件的两个版本的更改。因此,二进制文件对版本控制系统来说非常不透明,如果它们将经常更改,不建议将二进制文件存储在版本控制系统中。

这对于Mathematica笔记本来说尤其是一个问题,因为它们将输入和输出都存储在同一个文件中。一个相当典型的例子是简单的输入

Plot[Sin[x] / x, {x, -4 Pi, 4 Pi}]

当绘制时,它以以下方式存储在笔记本文件中

GraphicsBox[{{{{}, {},
  TagBox[
       {RGBColor[0.368417, 0.506779, 0.709798], AbsoluteThickness[1.6],
        Opacity[1.], LineBox[CompressedData["<omitted>"]],
        LineBox[CompressedData["<omitted>"]]},
       Annotation[#,
        "Charting`Private`Tag$5185#1"]& ], {}}, {{}, {}, {}}}, {}, {}},
   AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
   Axes->{True, True},
   AxesLabel->{None, None},
   AxesOrigin->{0, 0},
   DisplayFunction->Identity,
   Frame->{{False, False}, {False, False}},
   FrameLabel->{{None, None}, {None, None}},
   FrameTicks->{{Automatic,
      Charting`ScaledFrameTicks[{Identity, Identity}]}, {Automatic,
      Charting`ScaledFrameTicks[{Identity, Identity}]}},
   GridLines->{None, None},
   GridLinesStyle->Directive[
     GrayLevel[0.5, 0.4]],
   ImagePadding->All,
   Method->{
    "DefaultBoundaryStyle" -> Automatic, "DefaultMeshStyle" ->
     AbsolutePointSize[6], "ScalingFunctions" -> None,
     "CoordinatesToolOptions" -> {"DisplayFunction" -> ({
         (Identity[#]& )[
          Part[#, 1]],
         (Identity[#]& )[
          Part[#, 2]]}& ), "CopiedValueFunction" -> ({
         (Identity[#]& )[
          Part[#, 1]],
         (Identity[#]& )[
          Part[#, 2]]}& )}},
   PlotRange->
    NCache[{{(-4) Pi, 4 Pi}, {-0.21723358083481298`,
      0.9999892952885239}}, {{-12.566370614359172`,
     12.566370614359172`}, {-0.21723358083481298`, 0.9999892952885239}}],
   PlotRangeClipping->True,
   PlotRangePadding->{{
      Scaled[0.02],
      Scaled[0.02]}, {
      Scaled[0.05],
      Scaled[0.05]}},
   Ticks->{Automatic, Automatic}]

请注意,上面的代码片段被显著缩减,因为压缩后的base-64编码数据有大约300行左右。

对于版本控制系统来说,如此大的输出极为繁琐,因为输入中微小的更改(例如将Sin[x]替换为Sin[2 x])将产生300+行的差异。mathematica-notebook-filter的目的就是特别避免这样大的差异,并试图使它们更有意义。它通过解析Mathematica笔记本文件格式并删除所有输出单元和元数据来实现这一点。该程序是用Rust编写的,并在crates.io上分发。

然而,应该指出的是,不幸的是,Mathematica没有以非常简单的方式存储输入,因为它不仅存储了纯Mathematica表达式,还存储了格式化信息。具体来说,带有上述绘图函数的输入单元将存储在笔记本文件中,如下所示

Cell[BoxData[
 RowBox[{"Plot", "[",
  RowBox[{
   FractionBox[
    RowBox[{"Sin", "[", "x", "]"}], "x"], ",",
   RowBox[{"{",
    RowBox[{"x", ",",
     RowBox[{
      RowBox[{"-", "4"}], "Pi"}], ",",
     RowBox[{"4", "Pi"}]}], "}"}]}], "]"}]], "Input"]

Sin[x]更改为Sin[2 x]会导致单元现在存储为

Cell[BoxData[
 RowBox[{"Plot", "[",
  RowBox[{
   FractionBox[
    RowBox[{"Sin", "[",
     RowBox[{"2", "x"}], "]"}], "x"], ",",
   RowBox[{"{",
    RowBox[{"x", ",",
     RowBox[{
      RowBox[{"-", "4"}], "Pi"}], ",",
     RowBox[{"4", "Pi"}]}], "}"}]}], "]"}]], "Input"]

至少在这个阶段,该程序不会删除额外的格式化信息。如果您想避免这种情况,则应将笔记本保存为脚本文件(扩展名为.wl.m)。

使用说明

mathematica-notebook-filter解析Mathematica笔记本文件(通常以.nb扩展名存储)并删除所有生成的输出和其他元数据。默认情况下,程序从标准输入读取并输出到标准输出。更多使用信息可以从

mathematica-notebook-filter --help

尽管可以使用mathematica-notebook-filter手动,但它被设计为与版本控制系统集成(有关说明,请参阅下面),以便在生成差异之前,笔记本首先通过过滤器。这样设计是为了确保原始文件保持不变,保留所有输出和元数据,过滤器使版本控制系统对额外内容视而不见。

如果您想手动运行它,一个简单的调用将是

mathematica-notebook-filter -i my_notebook.nb -o my_notebook_cleaned.nb

如果输入和输出文件相同,程序将首先输出到临时文件,只有成功解析整个输入后,才会替换原始文件。

该程序通常不解析 Wolfram 语言,并且仅针对 完整 Mathematica 笔记本,因此它对将要找到的函数及其顺序做出了一些相当强烈的假设。它一次只解析一个笔记本,并在解析完第一个笔记本后停止。如果在解析过程中遇到错误,mathematica-notebook-filter 将以非零代码退出,并且输出将是不完整的。

还应重申,将 Mathematica 代码提交给版本控制系统最好的方式是将代码保存为脚本文件(.wl.m)。这样做时,Mathematica 会以一个非常简单的格式(本质上是一个纯文本文件)保存文件,没有多余的格式化信息,也没有输出。不幸的是,这有一个缺点,即笔记本界面不可用。

另外,请注意,Mathematica 笔记本允许您复制粘贴图形(例如生成的图表)并将它们用作输入。如果您这样做,版本控制系统将不得不将整个图表包含在 diff 中,从而违背了 mathematica-notebook-filter 的目的。复制粘贴输出的替代方法是存储输出到一个变量中,或使用 %(以及 %%%%% 等)来引用上一个输出(但请确保仅在单个单元格内使用 %,而不是跨单元格,因为 % 指的是最后一个生成的输出,而不是笔记本顺序中的上一个输出)。

安装

该程序是用 Rust 编写的。最简单安装 Rust 的方法可能是使用 rustup.rs 脚本。一旦设置好,只需运行

cargo install mathematica-notebook-filter

这将下载、编译并安装 mathematica-notebook-filter 到您的 Cargo 家目录(默认情况下,Linux 上的 ~/.cargo)。假设您已正确设置您的 PATH 变量(rustup.rs 应该会自动完成),那么您可以通过键入 mathematica-notebook-filter 来执行程序。

集成

Git

可以根据模式 glob 设置 属性。在这个例子中,我们想确保在提交之前,所有 *.nb 文件都经过此过滤器处理。要全局设置属性,请向 ~/.gitattributes 添加以下内容

*.nb    filter=dropoutput_nb

以及到您的 ~/.gitconfig

[filter "dropoutput_nb"]
    clean = mathematica-notebook-filter
    smudge = cat

其他

欢迎提交添加其他版本控制系统说明的拉取请求。

免责声明

遗憾的是,Wolfram Research 组织似乎没有提供其语言或其文件格式的任何规范。因此,此过滤器完全是在检查 Mathematica 生成的输出后开发的。具体来说,这是使用 Mathematica 11.1 开发的,因此无法保证此过滤器与过去或未来的 Notebook 文件格式版本兼容。

如果您发现任何错误,请随时打开一个问题,但请提供足够的信息来重现错误或一个 Notebook 文件的最小示例,该文件导致问题。

贡献

欢迎提交改进与其他版本兼容性(或修复错误)的拉取请求。如果您发现任何错误,请随时打开一个问题,并确保提供足够的信息来重现错误或一个 Notebook 文件的最小示例,该文件导致问题。

依赖关系

~3–13MB
~140K SLoC