From b13e54b9e32c01afd58676cc7f5eec340caeb890 Mon Sep 17 00:00:00 2001 From: ARCJ137442 <61109168+ARCJ137442@users.noreply.github.com> Date: Sun, 4 Feb 2024 13:40:21 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20:bug:=20=E7=BB=A7=E7=BB=AD=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=85=BC=E5=AE=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 删除残余的`const`类型注释 --- README.md | 2 +- src/IpynbCompile.ipynb | 25 +++++++++---------------- src/IpynbCompile.jl | 2 +- test/runtests.jl | 2 +- 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index a84a18f..eb4ef0b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - + # IpynbCompile.jl: 一个实用的Jupyter笔记本构建工具 ## 主要功能 diff --git a/src/IpynbCompile.ipynb b/src/IpynbCompile.ipynb index 6e762a5..84b7097 100644 --- a/src/IpynbCompile.ipynb +++ b/src/IpynbCompile.ipynb @@ -739,7 +739,7 @@ "output_type": "stream", "text": [ "\u001b[36m\u001b[1m┌ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mJSON转译结构化成功!\n", - "\u001b[36m\u001b[1m│ \u001b[22m\u001b[39m notebook_raw_cell = IpynbNotebook{Any}(Any[Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"# IpynbCompile.jl: 一个实用的Jupyter笔记本构建工具\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"(✨执行其中所有单元格,可自动构建、测试并生成相应`.jl`源码、测试文件与README!)\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"## 主要功能\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"### 简介\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"📍主要功能:为 [***Jupyter***](https://jupyter.org/) 笔记本(`.ipynb`文件)提供一套特定的注释语法,以支持 **编译转换**&**解释执行** 功能,扩展其应用的可能性\\n\", \"\\n\", \"- 📌可【打开】并【解析】Jupyter笔记本:提供基本的「Jupyter笔记本」「Jupyter笔记本元数据」「Jupyter笔记本单元格」数据结构定义\\n\", \" - 笔记本 `IpynbNotebook{单元格类型}`\\n\", \" - 元数据 `IpynbNotebookMetadata`\\n\", \" - 单元格 `IpynbCell`\\n\", \"- 📌可将Jupyter笔记本(`.ipynb`文件)【转换】成可直接执行的 [***Julia***](https://julialang.org/) 代码\\n\", \" - 编译单元格 `compile_cell`\\n\", \" - 编译笔记本 `compile_notebook`\\n\", \" - 方法1:`compile_notebook(笔记本::IpynbNotebook)`\\n\" … \" - `nothing`(若为其它类型)\\n\", \" - 解析笔记本 `parse_notebook`\\n\", \" - 等效于「编译笔记本的**所有单元格**」\\n\", \" - 执行单元格 `eval_cell`\\n\", \" - 等效于「【解析】并【执行】单元格」\\n\", \" - 执行笔记本 `eval_notebook`\\n\", \" - 等效于「【解析】并【执行】笔记本」\\n\", \" - 逐单元格版本:`eval_notebook_by_cell`\\n\", \" - 引入笔记本 `include_notebook`\\n\", \" - 逐单元格版本:`include_notebook_by_cell`\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"✨创新点:**使用多样的「特殊注释」机制,让使用者能更灵活、更便捷地编译Jupyter笔记本,并能将其【交互式】优势用于库的编写之中**\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"### 重要机制:单元格「特殊注释」\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"简介:单元格的主要「特殊注释」及其作用(以`# 单行注释` `#= 块注释 =#`为例)\\n\", \"\\n\", \"- `# %ignore-line` 忽略下一行\\n\", \"- `# %ignore-below` 忽略下面所有行\\n\", \"- `# %ignore-cell` 忽略整个单元格\\n\", \"- `# %ignore-begin` 块忽略开始\\n\", \"- `# %ignore-end` 块忽略结束\\n\", \"- `#= %only-compiled` 仅编译后可用(头)\\n\", \"- `%only-compiled =#` 仅编译后可用(尾)\\n\", \"- `# %include <路径>` 引入指定路径的文件内容,替代一整行注释\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"✨**该笔记本自身**,就是一个好的用法参考来源\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"#### 各个「特殊注释」的用法\"], \"metadata\" => Dict{String, Any}()) … Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"## 自动构建\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"构建过程主要包括:\\n\", \"\\n\", \"- **自举**构建主模块,生成库文件\\n\", \"- 扫描`src`目录下基本所有Jupyter笔记本(`.ipynb`),编译生成`.jl`源码\\n\", \"- 提取该文件开头Markdown笔记,在**项目根目录**下**生成自述文件**(`README.md`)\\n\", \" - 因此`README.md`暂且只有一种语言(常更新的语言)\\n\", \"\\n\", \"⚠️不应该在编译后的库文件中看到任何代码\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"### 自举生成源码\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"outputs\" => Any[Dict{String, Any}(\"name\" => \"stdout\", \"output_type\" => \"stream\", \"text\" => Any[\"\\e[93m\\e[1m✅Jupyter笔记本「主模块」自编译成功!\\e[22m\\e[39m\\n\", \"\\e[93m\\e[1m(共写入 nothing 个字节)\\e[22m\\e[39m\\n\"])], \"cell_type\" => \"code\", \"source\" => Any[\"# %ignore-cell # * 自举构建主模块\\n\", \"# * 自编译生成`.jl`源码\\n\", \"let OUT_LIB_FILE = \\\"IpynbCompile.jl\\\" # 直接作为库的主文件\\n\", \" # !不能在`runtests.jl`中运行\\n\", \" contains(@__DIR__, \\\"test\\\") && return\\n\", \"\\n\", \" # * 测试Pair编译\\n\", \" write_bytes = compile_notebook(SELF_PATH => joinpath(ROOT_PATH, \\\"src\\\", OUT_LIB_FILE))\\n\", \" printstyled(\\n\", \" \\\"✅Jupyter笔记本「主模块」自编译成功!\\\\n(共写入 \\$write_bytes 个字节)\\\\n\\\";\\n\", \" color=:light_yellow, bold=true\\n\", \" )\\n\", \"end\"], \"metadata\" => Dict{String, Any}(), \"execution_count\" => 30), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"### 文件夹下其它笔记本的编译\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"outputs\" => Any[Dict{String, Any}(\"name\" => \"stdout\", \"output_type\" => \"stream\", \"text\" => Any[\"\\e[92m\\e[1mCompiled: .\\\\compiler.ipynb => .\\\\compiler.jl\\e[22m\\e[39m\\n\"])], \"cell_type\" => \"code\", \"source\" => Any[\"# %ignore-cell\\n\", \"# * 扫描`src`目录,自动构建主模块\\n\", \"# * - 📝Julia 文件夹遍历:`walkdir`迭代器\\n\", \"# * - 🔗参考:参考:https://stackoverflow.com/questions/58258101/how-to-loop-through-a-folder-of-sub-folders-in-julia\\n\", \"PATH_SRC = \\\".\\\"\\n\", \"let root_folder = PATH_SRC\\n\", \"\\n\", \" # !不能在`runtests.jl`中运行\\n\", \" contains(@__DIR__, \\\"test\\\") && return\\n\", \"\\n\" … \" path => new_path # * 测试Pair\\n\", \" # ! 根目录后续会由`path`自行指定\\n\", \" )\\n\", \" # 输出编译结果\\n\", \" printstyled(\\n\", \" \\\"Compiled: \\$path => \\$new_path\\\\n\\\";\\n\", \" color=:light_green, bold=true\\n\", \" )\\n\", \" end\\n\", \"end\"], \"metadata\" => Dict{String, Any}(), \"execution_count\" => 31), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"### 编译生成测试文件`runtests.jl`\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"outputs\" => Any[Dict{String, Any}(\"name\" => \"stdout\", \"output_type\" => \"stream\", \"text\" => Any[\"\\e[92m\\e[1m✅测试文件编译成功!\\e[22m\\e[39m\\n\", \"\\e[92m\\e[1m(共写入 40900 个字节)\\e[22m\\e[39m\\n\"])], \"cell_type\" => \"code\", \"source\" => Any[\"# %ignore-cell # * 自举构建主模块\\n\", \"if !contains(@__DIR__, \\\"test\\\") # 不能在测试代码中被重复调用\\n\", \" OUT_TEST_JL = joinpath(ROOT_PATH, \\\"test\\\", \\\"runtests.jl\\\") # 直接作为库的主文件\\n\", \" # 直接拼接所有代码单元格\\n\", \" code_tests = join((\\n\", \" join(cell.source)\\n\", \" for cell in notebook.cells\\n\", \" if cell.cell_type == \\\"code\\\"\\n\", \" ), \\\"\\\\n\\\\n\\\")\\n\", \" # 开头使用Test库,并添加测试上下文\\n\" … \" code_tests *= \\\"\\\"\\\"\\n\", \" end\\n\", \" \\\"\\\"\\\" =#\\n\", \" # 最终写入\\n\", \" write_bytes = write(OUT_TEST_JL, code_tests)\\n\", \" printstyled(\\n\", \" \\\"✅测试文件编译成功!\\\\n(共写入 \\$write_bytes 个字节)\\\\n\\\";\\n\", \" color=:light_green, bold=true\\n\", \" )\\n\", \"end\"], \"metadata\" => Dict{String, Any}(), \"execution_count\" => 32), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"### 编译生成自述文件`README.md`(非库功能)\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"outputs\" => Any[Dict{String, Any}(\"name\" => \"stdout\", \"output_type\" => \"stream\", \"text\" => Any[\"\\n\", \"# IpynbCompile.jl: 一个实用的Jupyter笔记本构建工具\\n\", \"\\n\", \"## 主要功能\\n\", \"\\n\", \"### 简介\\n\", \"\\n\", \"📍主要功能:为 [***Jupyter***](https://jupyter.org/) 笔记本(`.ipynb`文件)提供一套特定的注释语法,以支持 **编译转换**&**解释执行** 功能,扩展其应用的可能性\\n\", \"\\n\", \"- 📌可【打开】并【解析】Jupyter笔记本:提供基本的「Jupyter笔记本」「Jupyter笔记本元数据」「Jupyter笔记本单元格」数据结构定义\\n\" … \"# ↑ 上面一行会被替换成数据\\n\", \"```\\n\", \"\\n\", \"📝Julia的「空白符无关性」允许在等号后边大范围附带注释的空白\\n\", \"\\n\", \"## 参考\\n\", \"\\n\", \"- 本Julia库的灵感来源:[Promises.jl/src/notebook.jl](https://github.com/fonsp/Promises.jl/blob/main/src/notebook.jl)\\n\", \" - 源库使用了 [**Pluto.jl**](https://github.com/fonsp/Pluto.jl) 的「笔记本导出」功能\\n\", \"- **Jupyter Notebook** 文件格式(JSON):[🔗nbformat.readthedocs.io](https://nbformat.readthedocs.io/en/latest/format_description.html#notebook-file-format)\\n\"]), Dict{String, Any}(\"output_type\" => \"execute_result\", \"data\" => Dict{String, Any}(\"text/plain\" => Any[\"7338\"]), \"metadata\" => Dict{String, Any}(), \"execution_count\" => 33)], \"cell_type\" => \"code\", \"source\" => Any[\"# %ignore-cell # * 扫描自身Markdown单元格,自动生成`README.md`\\n\", \"\\\"决定「单元格采集结束」的标识\\\" # ! 不包括结束处单元格\\n\", \"FLAG_END = \\\"\\n\", \"\\$README_markdown_TEXT\\\\\\n\", \"\\\"\\\"\\\"\\n\", \"print(README_markdown_TEXT)\\n\", \"\\n\", \"README_FILE = \\\"README.md\\\"\\n\", \"write(joinpath(ROOT_PATH, README_FILE), README_markdown_TEXT)\"], \"metadata\" => Dict{String, Any}(), \"execution_count\" => 33)], IpynbNotebookMetadata(Dict{String, Any}(\"file_extension\" => \".jl\", \"mimetype\" => \"application/julia\", \"name\" => \"julia\", \"version\" => \"1.10.0\"), Dict{String, Any}(\"name\" => \"julia-1.10\", \"display_name\" => \"Julia 1.10.0\", \"language\" => \"julia\")), 4, 2)\n", + "\u001b[36m\u001b[1m│ \u001b[22m\u001b[39m notebook_raw_cell = IpynbNotebook{Any}(Any[Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"# IpynbCompile.jl: 一个实用的Jupyter笔记本构建工具\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"(✨执行其中所有单元格,可自动构建、测试并生成相应`.jl`源码、测试文件与README!)\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"## 主要功能\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"### 简介\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"📍主要功能:为 [***Jupyter***](https://jupyter.org/) 笔记本(`.ipynb`文件)提供一套特定的注释语法,以支持 **编译转换**&**解释执行** 功能,扩展其应用的可能性\\n\", \"\\n\", \"- 📌可【打开】并【解析】Jupyter笔记本:提供基本的「Jupyter笔记本」「Jupyter笔记本元数据」「Jupyter笔记本单元格」数据结构定义\\n\", \" - 笔记本 `IpynbNotebook{单元格类型}`\\n\", \" - 元数据 `IpynbNotebookMetadata`\\n\", \" - 单元格 `IpynbCell`\\n\", \"- 📌可将Jupyter笔记本(`.ipynb`文件)【转换】成可直接执行的 [***Julia***](https://julialang.org/) 代码\\n\", \" - 编译单元格 `compile_cell`\\n\", \" - 编译笔记本 `compile_notebook`\\n\", \" - 方法1:`compile_notebook(笔记本::IpynbNotebook)`\\n\" … \" - `nothing`(若为其它类型)\\n\", \" - 解析笔记本 `parse_notebook`\\n\", \" - 等效于「编译笔记本的**所有单元格**」\\n\", \" - 执行单元格 `eval_cell`\\n\", \" - 等效于「【解析】并【执行】单元格」\\n\", \" - 执行笔记本 `eval_notebook`\\n\", \" - 等效于「【解析】并【执行】笔记本」\\n\", \" - 逐单元格版本:`eval_notebook_by_cell`\\n\", \" - 引入笔记本 `include_notebook`\\n\", \" - 逐单元格版本:`include_notebook_by_cell`\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"✨创新点:**使用多样的「特殊注释」机制,让使用者能更灵活、更便捷地编译Jupyter笔记本,并能将其【交互式】优势用于库的编写之中**\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"### 重要机制:单元格「特殊注释」\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"简介:单元格的主要「特殊注释」及其作用(以`# 单行注释` `#= 块注释 =#`为例)\\n\", \"\\n\", \"- `# %ignore-line` 忽略下一行\\n\", \"- `# %ignore-below` 忽略下面所有行\\n\", \"- `# %ignore-cell` 忽略整个单元格\\n\", \"- `# %ignore-begin` 块忽略开始\\n\", \"- `# %ignore-end` 块忽略结束\\n\", \"- `#= %only-compiled` 仅编译后可用(头)\\n\", \"- `%only-compiled =#` 仅编译后可用(尾)\\n\", \"- `# %include <路径>` 引入指定路径的文件内容,替代一整行注释\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"✨**该笔记本自身**,就是一个好的用法参考来源\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"#### 各个「特殊注释」的用法\"], \"metadata\" => Dict{String, Any}()) … Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"## 自动构建\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"构建过程主要包括:\\n\", \"\\n\", \"- **自举**构建主模块,生成库文件\\n\", \"- 扫描`src`目录下基本所有Jupyter笔记本(`.ipynb`),编译生成`.jl`源码\\n\", \"- 提取该文件开头Markdown笔记,在**项目根目录**下**生成自述文件**(`README.md`)\\n\", \" - 因此`README.md`暂且只有一种语言(常更新的语言)\\n\", \"\\n\", \"⚠️不应该在编译后的库文件中看到任何代码\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"### 自举生成源码\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"outputs\" => Any[Dict{String, Any}(\"name\" => \"stdout\", \"output_type\" => \"stream\", \"text\" => Any[\"\\e[93m\\e[1m✅Jupyter笔记本「主模块」自编译成功!\\e[22m\\e[39m\\n\", \"\\e[93m\\e[1m(共写入 nothing 个字节)\\e[22m\\e[39m\\n\"])], \"cell_type\" => \"code\", \"source\" => Any[\"# %ignore-cell # * 自举构建主模块\\n\", \"# * 自编译生成`.jl`源码\\n\", \"let OUT_LIB_FILE = \\\"IpynbCompile.jl\\\" # 直接作为库的主文件\\n\", \" # !不能在`runtests.jl`中运行\\n\", \" contains(@__DIR__, \\\"test\\\") && return\\n\", \"\\n\", \" # * 测试Pair编译\\n\", \" write_bytes = compile_notebook(SELF_PATH => joinpath(ROOT_PATH, \\\"src\\\", OUT_LIB_FILE))\\n\", \" printstyled(\\n\", \" \\\"✅Jupyter笔记本「主模块」自编译成功!\\\\n(共写入 \\$write_bytes 个字节)\\\\n\\\";\\n\", \" color=:light_yellow, bold=true\\n\", \" )\\n\", \"end\"], \"metadata\" => Dict{String, Any}(), \"execution_count\" => 63), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"### 文件夹下其它笔记本的编译\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"outputs\" => Any[Dict{String, Any}(\"name\" => \"stdout\", \"output_type\" => \"stream\", \"text\" => Any[\"\\e[92m\\e[1mCompiled: .\\\\compiler.ipynb => .\\\\compiler.jl\\e[22m\\e[39m\\n\"])], \"cell_type\" => \"code\", \"source\" => Any[\"# %ignore-cell\\n\", \"# * 扫描`src`目录,自动构建主模块\\n\", \"# * - 📝Julia 文件夹遍历:`walkdir`迭代器\\n\", \"# * - 🔗参考:参考:https://stackoverflow.com/questions/58258101/how-to-loop-through-a-folder-of-sub-folders-in-julia\\n\", \"PATH_SRC = \\\".\\\"\\n\", \"let root_folder = PATH_SRC\\n\", \"\\n\", \" # !不能在`runtests.jl`中运行\\n\", \" contains(@__DIR__, \\\"test\\\") && return\\n\", \"\\n\" … \" path => new_path # * 测试Pair\\n\", \" # ! 根目录后续会由`path`自行指定\\n\", \" )\\n\", \" # 输出编译结果\\n\", \" printstyled(\\n\", \" \\\"Compiled: \\$path => \\$new_path\\\\n\\\";\\n\", \" color=:light_green, bold=true\\n\", \" )\\n\", \" end\\n\", \"end\"], \"metadata\" => Dict{String, Any}(), \"execution_count\" => 64), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"### 编译生成测试文件`runtests.jl`\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"outputs\" => Any[Dict{String, Any}(\"name\" => \"stdout\", \"output_type\" => \"stream\", \"text\" => Any[\"\\e[92m\\e[1m✅测试文件编译成功!\\e[22m\\e[39m\\n\", \"\\e[92m\\e[1m(共写入 40869 个字节)\\e[22m\\e[39m\\n\"])], \"cell_type\" => \"code\", \"source\" => Any[\"# %ignore-cell # * 自举构建主模块\\n\", \"if !contains(@__DIR__, \\\"test\\\") # 不能在测试代码中被重复调用\\n\", \" OUT_TEST_JL = joinpath(ROOT_PATH, \\\"test\\\", \\\"runtests.jl\\\") # 直接作为库的主文件\\n\", \" # 直接拼接所有代码单元格\\n\", \" code_tests = join((\\n\", \" join(cell.source)\\n\", \" for cell in notebook.cells\\n\", \" if cell.cell_type == \\\"code\\\"\\n\", \" ), \\\"\\\\n\\\\n\\\")\\n\", \" # 开头使用Test库,并添加测试上下文\\n\" … \" code_tests *= \\\"\\\"\\\"\\n\", \" end\\n\", \" \\\"\\\"\\\" =#\\n\", \" # 最终写入\\n\", \" write_bytes = write(OUT_TEST_JL, code_tests)\\n\", \" printstyled(\\n\", \" \\\"✅测试文件编译成功!\\\\n(共写入 \\$write_bytes 个字节)\\\\n\\\";\\n\", \" color=:light_green, bold=true\\n\", \" )\\n\", \"end\"], \"metadata\" => Dict{String, Any}(), \"execution_count\" => 65), Dict{String, Any}(\"cell_type\" => \"markdown\", \"source\" => Any[\"\\n\", \"### 编译生成自述文件`README.md`(非库功能)\"], \"metadata\" => Dict{String, Any}()), Dict{String, Any}(\"outputs\" => Any[Dict{String, Any}(\"name\" => \"stdout\", \"output_type\" => \"stream\", \"text\" => Any[\"\\n\", \"# IpynbCompile.jl: 一个实用的Jupyter笔记本构建工具\\n\", \"\\n\", \"## 主要功能\\n\", \"\\n\", \"### 简介\\n\", \"\\n\", \"📍主要功能:为 [***Jupyter***](https://jupyter.org/) 笔记本(`.ipynb`文件)提供一套特定的注释语法,以支持 **编译转换**&**解释执行** 功能,扩展其应用的可能性\\n\", \"\\n\", \"- 📌可【打开】并【解析】Jupyter笔记本:提供基本的「Jupyter笔记本」「Jupyter笔记本元数据」「Jupyter笔记本单元格」数据结构定义\\n\" … \"# ↑ 上面一行会被替换成数据\\n\", \"```\\n\", \"\\n\", \"📝Julia的「空白符无关性」允许在等号后边大范围附带注释的空白\\n\", \"\\n\", \"## 参考\\n\", \"\\n\", \"- 本Julia库的灵感来源:[Promises.jl/src/notebook.jl](https://github.com/fonsp/Promises.jl/blob/main/src/notebook.jl)\\n\", \" - 源库使用了 [**Pluto.jl**](https://github.com/fonsp/Pluto.jl) 的「笔记本导出」功能\\n\", \"- **Jupyter Notebook** 文件格式(JSON):[🔗nbformat.readthedocs.io](https://nbformat.readthedocs.io/en/latest/format_description.html#notebook-file-format)\\n\"]), Dict{String, Any}(\"output_type\" => \"execute_result\", \"data\" => Dict{String, Any}(\"text/plain\" => Any[\"7338\"]), \"metadata\" => Dict{String, Any}(), \"execution_count\" => 66)], \"cell_type\" => \"code\", \"source\" => Any[\"# %ignore-cell # * 扫描自身Markdown单元格,自动生成`README.md`\\n\", \"\\\"决定「单元格采集结束」的标识\\\" # ! 不包括结束处单元格\\n\", \"FLAG_END = \\\"\\n\", \"\\$README_markdown_TEXT\\\\\\n\", \"\\\"\\\"\\\"\\n\", \"print(README_markdown_TEXT)\\n\", \"\\n\", \"README_FILE = \\\"README.md\\\"\\n\", \"write(joinpath(ROOT_PATH, README_FILE), README_markdown_TEXT)\"], \"metadata\" => Dict{String, Any}(), \"execution_count\" => 66)], IpynbNotebookMetadata(Dict{String, Any}(\"file_extension\" => \".jl\", \"mimetype\" => \"application/julia\", \"name\" => \"julia\", \"version\" => \"1.10.0\"), Dict{String, Any}(\"name\" => \"julia-1.10\", \"display_name\" => \"Julia 1.10.0\", \"language\" => \"julia\")), 4, 2)\n", "\u001b[36m\u001b[1m└ \u001b[22m\u001b[39m notebook_metadata = IpynbNotebookMetadata(Dict{String, Any}(\"file_extension\" => \".jl\", \"mimetype\" => \"application/julia\", \"name\" => \"julia\", \"version\" => \"1.10.0\"), Dict{String, Any}(\"name\" => \"julia-1.10\", \"display_name\" => \"Julia 1.10.0\", \"language\" => \"julia\"))\n" ] } @@ -1072,7 +1072,7 @@ ], "source": [ "\"【内部】编程语言⇒常用扩展名(不带`.`)\"\n", - "const LANG_EXTENSION_DICT::Dict{Symbol,String} = Dict{Symbol,String}(\n", + "const LANG_EXTENSION_DICT = Dict{Symbol,String}(\n", " # ! 以下「特殊注释」需要在行首\n", "#= %inline-compiled =# include(\"./../src/language_extension_dict.data.jl\")\n", " # !【2024-01-27 00:48:32】为了兼容自动生成的测试文件`runtests.jl`,需要使用「相对绝对路径」`./../src/`\n", @@ -1589,7 +1589,7 @@ " IpynbCell(\"code\", [\"#= %only-compiled # ! 模块上下文:导出元素\\n\", \"export @notebook_str\\n\", \"%only-compiled =#\\n\", \"\\n\", \"macro notebook_str(path::AbstractString)\\n\", \" :(read_notebook(\\$path)) |> esc\\n\", \"end\\n\", \"# %ignore-below\\n\", \"@macroexpand notebook\\\"IpynbCompile.ipynb\\\"\"], Dict{String, Any}(), nothing)\n", " IpynbCell(\"code\", [\"\\\"【内部】编程语言⇒正则表达式 识别字典\\\"\\n\", \"const LANG_IDENTIFY_DICT = Dict{Symbol,Regex}(\\n\", \" lang => Regex(\\\"^(?:\\$regex_str)\\\\\\$\\\") # ! ←必须头尾精确匹配(不然就会把`JavaScript`认成`r`)\\n\", \" for (lang::Symbol, regex_str::String) in\\n\", \" # ! 以下「特殊注释」需要在行首\\n\", \" # * 下方内容是「执行时动态引入,编译时静态内联」\\n\", \"#= %inline-compiled =# include(\\\"./../src/language_identify_dict.data.jl\\\")\\n\", \" # !【2024-01-27 00:48:32】为了兼容自动生成的测试文件`runtests.jl`,需要使用「相对绝对路径」`./../src/`\\n\", \")\\n\", \"\\n\" … \" # ! 默认返回空字串\\n\", \" \\\"\\\"\\n\", \" )\\n\", \" )\\n\", \")\\n\", \"identify_lang(language_text::AbstractString) =\\n\", \" findfirst(LANG_IDENTIFY_DICT) do regex\\n\", \" contains(language_text, regex)\\n\", \" end # ! 默认返回`nothing`\\n\", \"# %ignore-below # ! 测试代码在最下边\"], Dict{String, Any}(), nothing)\n", " IpynbCell(\"code\", [\"\\\"【内部】编程语言⇒单行注释\\\"\\n\", \"const LANG_COMMENT_DICT_INLINE = Dict{Symbol,String}()\\n\", \"\\n\", \"\\\"【内部】编程语言⇒多行注释开头\\\"\\n\", \"const LANG_COMMENT_DICT_MULTILINE_HEAD = Dict{Symbol,String}()\\n\", \"\\n\", \"\\\"【内部】编程语言⇒多行注释结尾\\\"\\n\", \"const LANG_COMMENT_DICT_MULTILINE_TAIL = Dict{Symbol,String}()\\n\", \"\\n\", \"# * 遍历表格,生成列表\\n\" … \"generate_comment_inline(lang::Symbol) = LANG_COMMENT_DICT_INLINE[lang]\\n\", \"\\n\", \"\\\"【内部】生成块注释开头 | ⚠️找不到⇒报错\\\"\\n\", \"generate_comment_multiline_head(lang::Symbol) = LANG_COMMENT_DICT_MULTILINE_HEAD[lang]\\n\", \"\\n\", \"\\\"【内部】生成块注释结尾 | ⚠️找不到⇒报错\\\"\\n\", \"generate_comment_multiline_tail(lang::Symbol) = LANG_COMMENT_DICT_MULTILINE_TAIL[lang]\\n\", \"\\n\", \"# %ignore-below # ! 测试代码在最下边\\n\", \"@info \\\"\\\" LANG_COMMENT_DICT_INLINE LANG_COMMENT_DICT_MULTILINE_HEAD LANG_COMMENT_DICT_MULTILINE_TAIL\"], Dict{String, Any}(), nothing)\n", - " IpynbCell(\"code\", [\"\\\"【内部】编程语言⇒常用扩展名(不带`.`)\\\"\\n\", \"const LANG_EXTENSION_DICT::Dict{Symbol,String} = Dict{Symbol,String}(\\n\", \" # ! 以下「特殊注释」需要在行首\\n\", \"#= %inline-compiled =# include(\\\"./../src/language_extension_dict.data.jl\\\")\\n\", \" # !【2024-01-27 00:48:32】为了兼容自动生成的测试文件`runtests.jl`,需要使用「相对绝对路径」`./../src/`\\n\", \")\\n\", \"\\n\", \"\\\"\\\"\\\"\\n\", \"【内部】根据编程语言猜测扩展名\\n\", \"- @returns 特定语言的`Symbol` | 语言本身的字符串形式\\n\", \" - @default 如`:aaa => \\\"aaa\\\"`\\n\", \"\\\"\\\"\\\"\\n\", \"get_extension(lang::Symbol) = get(\\n\", \" LANG_EXTENSION_DICT, lang,\\n\", \" string(lang)\\n\", \")\\n\", \"\\n\", \"# %ignore-below # ! 测试代码在最下边\\n\", \"@info \\\"\\\" LANG_EXTENSION_DICT\"], Dict{String, Any}(), nothing)\n", + " IpynbCell(\"code\", [\"\\\"【内部】编程语言⇒常用扩展名(不带`.`)\\\"\\n\", \"const LANG_EXTENSION_DICT = Dict{Symbol,String}(\\n\", \" # ! 以下「特殊注释」需要在行首\\n\", \"#= %inline-compiled =# include(\\\"./../src/language_extension_dict.data.jl\\\")\\n\", \" # !【2024-01-27 00:48:32】为了兼容自动生成的测试文件`runtests.jl`,需要使用「相对绝对路径」`./../src/`\\n\", \")\\n\", \"\\n\", \"\\\"\\\"\\\"\\n\", \"【内部】根据编程语言猜测扩展名\\n\", \"- @returns 特定语言的`Symbol` | 语言本身的字符串形式\\n\", \" - @default 如`:aaa => \\\"aaa\\\"`\\n\", \"\\\"\\\"\\\"\\n\", \"get_extension(lang::Symbol) = get(\\n\", \" LANG_EXTENSION_DICT, lang,\\n\", \" string(lang)\\n\", \")\\n\", \"\\n\", \"# %ignore-below # ! 测试代码在最下边\\n\", \"@info \\\"\\\" LANG_EXTENSION_DICT\"], Dict{String, Any}(), nothing)\n", " IpynbCell(\"code\", [\"# %ignore-cell\\n\", \"let path_examples(path) = joinpath(ROOT_PATH, \\\"examples\\\", path),\\n\", \" notebooks = [\\n\", \" path_examples(\\\"c.ipynb\\\") # C\\n\", \" path_examples(\\\"java.ipynb\\\") # Java\\n\", \" SELF_PATH # Julia # * 直接使用自身\\n\", \" path_examples(\\\"python.ipynb\\\") # Python\\n\", \" path_examples(\\\"typescript.ipynb\\\") # TypeScript\\n\", \" ] .|> read_ipynb_json .|> IpynbNotebook\\n\", \"\\n\" … \" ])\\n\", \"\\n\", \" langs = identify_lang.(notebooks)\\n\", \" @info \\\"识别到的所有语言\\\" langs\\n\", \"\\n\", \" table_comments = [langs generate_comment_inline.(langs) generate_comment_multiline_head.(langs) generate_comment_multiline_tail.(langs)]\\n\", \" @info \\\"生成的所有注释 [语言 单行 多行开头 多行结尾]\\\" table_comments\\n\", \"\\n\", \" @info \\\"生成的常见扩展名 [语言 扩展名]\\\" [langs get_extension.(langs)]\\n\", \"end\"], Dict{String, Any}(), nothing)\n", " ⋮\n", " IpynbCell(\"code\", [\"\\\"\\\"\\\"\\n\", \"对Markdown的编译\\n\", \"- 📌主要方法:转换成多个单行注释\\n\", \"- ✨不对Markdown单元格作过于特殊的处理\\n\", \" - 仅将其视作语言为 `markdown` 的源码\\n\", \" - 仅在编译后作为程序语言注释\\n\", \"\\n\", \"@example IpynbCell(\\\"markdown\\\", [\\\"# IpynbCompile.jl: 一个通用的Jupyter笔记本集成编译工具\\\"], Dict{String, Any}(), nothing)\\n\", \"(行号为1)将被转换为\\n\", \"```julia\\n\" … \" 全部被忽略!\\n\", \" \\\"\\\"\\\"markdown\\n\", \" local compiled::String = compile_cell(cell; lang=:julia, line_num=1)\\n\", \" @assert compiled == \\\"\\\"\\\"\\\\\\n\", \" # %% [1] markdown\\n\", \" # 这些内容不会被忽略\\n\", \" # \\n\", \" \\\"\\\"\\\"\\n\", \" compiled |> println\\n\", \"end\"], Dict{String, Any}(), nothing)\n", @@ -1635,14 +1635,7 @@ "output_type": "stream", "text": [ "# 这是一段会被`# %include`引入编译后笔记本的内容\n", - "println(\"Hello World\")" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", + "println(\"Hello World\")\n", "\u001b[92m\u001b[1m↓现在预览下其中所有代码的部分\u001b[22m\u001b[39m\n", "# %% [1] code\n", "# ! ↓这后边注释的代码只有在编译后才会被执行\n", @@ -1947,7 +1940,7 @@ "\n", "# %% [12] code\n", "\"【内部】编程语言⇒常用扩展名(不带`.`)\"\n", - "const LANG_EXTENSION_DICT::Dict{Symbol,String} = Dict{Symbol,String}(\n", + "const LANG_EXTENSION_DICT = Dict{Symbol,String}(\n", " # ! 以下「特殊注释」需要在行首\n", "# ! be included in: IpynbCompile.jl @ module IpynbCompile\n", "# * 记录【未指定路径时】从语言到扩展名的映射 | 一般是常见扩展名 | 不带「.」 | 注释为【不确定】项\n", @@ -2980,7 +2973,7 @@ " \u001b[90m#= none:86 =#\u001b[39m\n", " LANG_COMMENT_DICT_MULTILINE_TAIL[lang]\n", " end))))\n", - " :($(Expr(:toplevel, :(\u001b[90m#= none:2 =#\u001b[39m), :(\u001b[90m#= none:2 =#\u001b[39m Core.@doc \"【内部】编程语言⇒常用扩展名(不带`.`)\" const LANG_EXTENSION_DICT::Dict{Symbol, String} = Dict{Symbol, String}([:c => \"c\"; :cpp => \"cpp\"; :java => \"java\"; :javascript => \"js\"; :julia => \"jl\"; :markdown => \"md\"; :php => \"php\"; :python => \"py\"; :r => \"r\"; :typescript => \"ts\"])), :(\u001b[90m#= none:65 =#\u001b[39m), :(\u001b[90m#= none:65 =#\u001b[39m Core.@doc \"【内部】根据编程语言猜测扩展名\\n- @returns 特定语言的`Symbol` | 语言本身的字符串形式\\n - @default 如`:aaa => \\\"aaa\\\"`\\n\" get_extension(lang::Symbol) = begin\n", + " :($(Expr(:toplevel, :(\u001b[90m#= none:2 =#\u001b[39m), :(\u001b[90m#= none:2 =#\u001b[39m Core.@doc \"【内部】编程语言⇒常用扩展名(不带`.`)\" const LANG_EXTENSION_DICT = Dict{Symbol, String}([:c => \"c\"; :cpp => \"cpp\"; :java => \"java\"; :javascript => \"js\"; :julia => \"jl\"; :markdown => \"md\"; :php => \"php\"; :python => \"py\"; :r => \"r\"; :typescript => \"ts\"])), :(\u001b[90m#= none:65 =#\u001b[39m), :(\u001b[90m#= none:65 =#\u001b[39m Core.@doc \"【内部】根据编程语言猜测扩展名\\n- @returns 特定语言的`Symbol` | 语言本身的字符串形式\\n - @default 如`:aaa => \\\"aaa\\\"`\\n\" get_extension(lang::Symbol) = begin\n", " \u001b[90m#= none:70 =#\u001b[39m\n", " get(LANG_EXTENSION_DICT, lang, string(lang))\n", " end))))\n", @@ -4005,7 +3998,7 @@ "\n", "# %% [64] code\n", "\"【内部】编程语言⇒常用扩展名(不带`.`)\"\n", - "const LANG_EXTENSION_DICT::Dict{Symbol,String} = Dict{Symbol,String}(\n", + "const LANG_EXTENSION_DICT = Dict{Symbol,String}(\n", " # ! 以下「特殊注释」需要在行首\n", "# ! be included in: IpynbCompile.jl @ module IpynbCompile\n", "# * 记录【未指定路径时】从语言到扩展名的映射 | 一般是常见扩展名 | 不带「.」 | 注释为【不确定】项\n", @@ -5215,7 +5208,7 @@ "output_type": "stream", "text": [ "\u001b[92m\u001b[1m✅测试文件编译成功!\u001b[22m\u001b[39m\n", - "\u001b[92m\u001b[1m(共写入 40890 个字节)\u001b[22m\u001b[39m\n" + "\u001b[92m\u001b[1m(共写入 40869 个字节)\u001b[22m\u001b[39m\n" ] } ], @@ -5274,7 +5267,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "\n", + "\n", "# IpynbCompile.jl: 一个实用的Jupyter笔记本构建工具\n", "\n", "## 主要功能\n", diff --git a/src/IpynbCompile.jl b/src/IpynbCompile.jl index ebabe84..928411a 100644 --- a/src/IpynbCompile.jl +++ b/src/IpynbCompile.jl @@ -724,7 +724,7 @@ generate_comment_multiline_tail(lang::Symbol) = LANG_COMMENT_DICT_MULTILINE_TAIL # %% [64] code "【内部】编程语言⇒常用扩展名(不带`.`)" -const LANG_EXTENSION_DICT::Dict{Symbol,String} = Dict{Symbol,String}( +const LANG_EXTENSION_DICT = Dict{Symbol,String}( # ! 以下「特殊注释」需要在行首 # ! be included in: IpynbCompile.jl @ module IpynbCompile # * 记录【未指定路径时】从语言到扩展名的映射 | 一般是常见扩展名 | 不带「.」 | 注释为【不确定】项 diff --git a/test/runtests.jl b/test/runtests.jl index bbaa4c0..13ec35a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -222,7 +222,7 @@ generate_comment_multiline_tail(lang::Symbol) = LANG_COMMENT_DICT_MULTILINE_TAIL @info "" LANG_COMMENT_DICT_INLINE LANG_COMMENT_DICT_MULTILINE_HEAD LANG_COMMENT_DICT_MULTILINE_TAIL "【内部】编程语言⇒常用扩展名(不带`.`)" -const LANG_EXTENSION_DICT::Dict{Symbol,String} = Dict{Symbol,String}( +const LANG_EXTENSION_DICT = Dict{Symbol,String}( # ! 以下「特殊注释」需要在行首 #= %inline-compiled =# include("./../src/language_extension_dict.data.jl") # !【2024-01-27 00:48:32】为了兼容自动生成的测试文件`runtests.jl`,需要使用「相对绝对路径」`./../src/`