think-tool-kit

TTK: 保持批判,有所取舍,知行合一, 方见真我

see_mountain

用意

在多方面整理自己掌握的内容时,一再感受到思维工具的重要性,而这才是核心本质所在,因而起了这本书。

关于puml->data.json->html的转换

  1. 执行scripts/puml_midmap_json.py获取data.json
  2. 在data.vg.json中使用data.json
  3. 在data.html中使用data.vg.json
  4. 如果相对路径有变化,需要多往上走一级来验证,比如:
../../../../../layer1_visual_tools/map_tools/vega/collections/data_json/rust.json
  • 向上走到src那个目录
  • 然后一步步定位到文件

puml与vega语法映射

  1. * -> #: name
  2. 链接: link
  3. 悬浮弹窗注释: note, 格式为<code>note content</code>
  • 要有:
  • 要以;结尾
**:node name
<code>
note content
</code>;
  1. 节点颜色
  {
  "id": 3,
  "color": "",
  "name": "",
  "link": "",
  "parent": 1,
  "note": ""
}
  1. 考虑到plantuml的’;‘是元素结束符,所以这里将’“;”‘换成’;’
   notes = [note.replace('";"', ';') for note in notes]

关于快速本地实时查看vega网页

  1. 执行./scripts/local_proxy_server.js
  2. 命令行启动静态服务

为了和mdbook的路径一致,在src目录下执行

npm install -g http-server
http-server -c-1

mdbook的定位是从src目录下开始的

  1. 相对路径:需要向上一直走到src目录,然后再一步步定位到文件
  2. 绝对路径:直接从src目录开始定位

关于修改路径后兼容http-server本地和mdbook在线链接的流程图。

目前已知mdbook在github page发布后使用静态资源需要从src目录开始定位,而且要加上项目名称。也就是

/<项目名称>/<从src开始的定位>

为了本地的http-server可以兼容这个路径(因为http-server在本地的src根目录运行,静态资源不带<项目名>)

这里使用http-proxy写了一个代理:

┌─────────────┐                  ┌─────────────┐
│             │   Proxy Request  │             │
│  Client     ├─────────────────►│  Proxy      │
│             │                  │             │
└───────┬─────┘                  └───────┬─────┘
        │                                │
        │                                │
        ▼                                ▼
┌─────────────┐                  ┌─────────────┐
│             │Proxy Request with│             │
│  Proxy      │ modified req.url │  Server     │
│             ├─────────────────►│             │
└───────┬─────┘                  └───────┬─────┘
        │                                │
        │                                │
        ▼                                ▼
┌─────────────┐                  ┌─────────────┐
│             │ Server Response  │             │
│  Proxy      │◄─────────────────┤  Server     │
│             │                  │             │
└─────────────┘                  └─────────────┘
        │                                │
        │                                │
        ▼                                ▼
┌─────────────┐                  ┌─────────────┐
│             │ Proxy Response   │             │
│  Client     │◄─────────────────┤  Proxy      │
│             │                  │             │
└─────────────┘                  └─────────────┘
  • /scripts/local_proxy_server.js

vega强化

悬浮弹窗

          "tooltip": {
"signal": "{'相关笔记': datum.note}"
}

markdown渲染

  1. 按住shift可以一直保持弹窗
  2. 支持kroki系列图表渲染
def get_kroki_preprocessors():
    preprocessors = {
        "puml": "plantuml",
        "seqdiag": "sequediag",
        "svgbob": "svgbob",
        "ditaa": "ditaa",

    }
    return preprocessors


# 将puml/mermaid等内容提交给kroki获取在线图片链接
def get_kroki_link(file_path, preprocessor):
    with open(file_path, 'r') as f:
        content = f.read()
        encoded_cotnent = base64.urlsafe_b64encode(zlib.compress(content.encode('utf8'))).decode('utf8')
        return f"https://kroki.io/{preprocessor}/svg/{encoded_cotnent}"

可以去kroki在线编辑网站测试好后保存文本在本地:Kroki!

网页JS优化

异步核心

executor 还是 reactor?

  1. executor: 在 Rust 中,调度 Future 对象的是一个 Executor 线程,它会不停地轮询 Future 的状态,一旦 Future 对象的状态由 “就绪” 变为 “完成”,Executor 就会把结果返回给调用方。异步计算需要包含可中止、存储当前状态和恢复状态这些特征,这些特征都是由 Future trait 统一实现的,这样在使用时避免了许多重复性的工作。Future trait 的 poll 方法会返回一个 Poll 枚举,它包含两个成员:Ready 和 Pending。
  2. Reactor: 在 Reactor 模型中,主线程通过事件循环来监听异步事件,并在事件发生时调用相应的回调函数。和任务执行不同,整个异步过程是由事件驱动的,主线程会等待事件发生,并且不断轮询异步事件队列。当异步操作完成并返回结果时,主线程会在回调函数中处理结果。Reactror 模型的一个关键点是将事件相关联的回调函数保存在异步队列中,当事件被触发时,会根据事件类型将对应的回调函数压入事件循环队列,然后一次性地调用所有的回调函数。这样做的好处是可以减少线程切换的开销,但也会引入一些问题,比如回调函数的执行时间过长, 会导致其他回调函数的执行被阻塞。为了解决这个问题,可以将回调函数的执行放到线程池中,这样就可以避免阻塞主线程。

rust的future/async/await如何运行

执行 main 函数程序结束执行 main 函数程序结束执行异步函数1执行异步函数2程序执行到等待语句,挂起并将控制权交给 Io 线程异步函数1完成计算并返回结果异步函数2完成计算并返回结果执行异步函数1执行异步函数2将控制权交给 Io 线程异步函数1完成计算并返回结果异步函数2完成计算并返回结果将挂起点打包成 Generator 并存储在 Future 对象中轮询 Future 1,处理中断点的返回值轮询 Future 2,处理中断点的返回值轮询 Future,检查状态是否已转变轮询 Future 1,处理中断点的返回值轮询 Future 2,处理中断点的返回值处理异步函数1的返回结果处理其他 Future 的计算结果处理其他 Future 的计算结果将计算结果返回给 Executor 线程(Future 2 计算完成)继续执行 Future 1 的计算继续执行 Future 2 的计算下一轮切换到 Executor 线程事件1发生,将回调函数1放入事件循环队列事件2发生,将回调函数2放入事件循环队列调用下一个回调函数注册异步事件1,将回调函数1加入异步队列注册异步事件2,将回调函数2加入异步队列开始事件循环执行回调函数1轮询 Future的状态将结果返回给回调函数1并执行之后的操作执行回调函数2轮询 Future的状态将结果返回给回调函数2并执行之后的操作处理异步函数1的返回结果处理其他 Future 的计算结果处理其他 Future 的计算结果Main ThreadAsync ThreadExecutor ThreadIo ThreadReactor Thread

Executor 模式和 Reactor 模式本质上都是为了实现异步编程而设计的模式,它们使用不同的机制来处理异步调用。尽管都涉及多线程,但它们的实现方式有很大的不同,不应简单地认为是多线程的组合。

Executor 模式是采用线程池的方式管理多个子线程来执行异步任务,并在主线程上等待所有的任务完成。在 Rust 的 Executor 模式中,主线程通过轮询 Future 对象的方式等待异步任务完成,并不涉及多线程的处理,I/O 操作使用了操作系统提供的异步调用方式,通过信号通知主线程任务完成。在其他编程语言中,Executor 模式可能需要使用多个线程来处理任务执行。

而 Reactor 模式采用了单线程的方式,在主线程上监听异步事件以及相应的回调函数,并在事件触发后调用回调函数来处理异步任务。Reactror 模式的优势在于不会引入线程切换的开销,当然也存在处理IO密集型任务的性能瓶颈,但异步执行的优势在于任务不需要等待,可以使用事件驱动时间进行并行处理。

所以,Executor 模式和 Reactor 模式是两种不同的异步编程模型,它们在实现方面有明显的不同。虽然它们都涉及多线程,但其中 Executor 模式使用线程池管理多个异步任务,而 Reactor 模式使用事件循环监听异步事件并调用相应的回调函数,具体实现上不尽相同。

你只管调用,与系统交互交给异步运行时

在 Rust 中,异步运行时是一个独立的运行时环境,它负责管理异步任务的执行,包括任务的调度、线程池的管理、任务的执行等。

Rust 的异步运行时并没有直接暴露出创建底层线程的接口,而是提供了一些抽象接口和默认实现,以方便用户创建和管理异步任务。如果需要深入了解 Rust 异步运行时的具体实现方式,可以参考 tokio 等库的源码。

以tokio异步运行时为例

创建 Runtime 对象获取 handle向待执行队列中提交任务执行异步操作并处理任务结果关闭 Runtime 对象并释放资源创建线程池等待待执行任务队列中的任务将任务加入待执行队列从待执行队列中取出任务处理异步委托任务的返回结果检查待执行队列是否为空,并处理挂起事件等待文件IO事件执行 IO 事件处理器等待运行时发送的异步事件执行异步事件异步任务执行完成Main ThreadRuntime ThreadIO ThreadAsync Thread

在 tokio 的运行时中,线程的创建和销毁、任务的调度和执行都是在 runtime 自己的线程池中完成的。具体流程如下:

  1. 创建 runtime:在 Builder::new() 方法中调用一系列方法,比如 num_threads()、threaded_scheduler(),以设置线程池大小和线程调度器类型等属性。最终通过 build() 方法创建 runtime 对象。
  2. 获取 handle:通过 handle() 方法获取 runtime handle,用于在运行时中 spawn 新的 future 和执行异步操作。
  3. Spawn future:通过 spawn() 方法异步地启动一个 future,并返回一个 JoinHandle,用于跟踪 future 的执行状态。此时 future 并不会被直接执行,而是进入到待执行队列中。
  4. Run tasks:在 block_on() 方法中,runtime 会持续地从待执行队列中取出 future 并执行,直到所有任务都完成为止。
  5. Shutdown runtime:通过 drop(rt) 方法关闭 runtime,释放所有资源,包括线程池、任务队列、调度器等。

异步运行时与系统交互

下面是一个概括性的异步运行时如何与系统底层交互的流程:

  1. 创建运行时对象:在运行时初始化过程中,需要创建并初始化一些系统资源,比如文件描述符、线程池、事件循环等。在这个过程中,需要调用系统底层接口来申请和释放这些资源,并设置相应的事件处理器(比如 epoll 或 kqueue)。

  2. 注册/注销事件:在执行异步任务的过程中,需要对文件 IO 或网络 IO 等事件进行处理。为了实现高效地异步 IO,可以使用系统底层提供的事件处理器来监听文件描述符和网络端口等事件,并在事件发生时及时通知异步运行时。这个过程需要调用系统底层标准库方法,比如 epoll_ctl 等。

  3. 调用异步模块:当程序使用异步模块来发起异步操作请求时,通常是将请求的状态信息(比如回调函数、数据缓冲区等)传递给异步运行时。异步运行时会将这些状态信息保存到一个任务队列中,以便在事件就绪后及时调用相应的回调函数进行异步操作。

  4. 处理异步事件:当异步请求的 IO 事件发生时,事件处理器会向异步运行时发送通知,并触发异步事件处理函数的执行。在这个过程中,异步运行时需要调用系统底层提供的标准库方法,比如 poll 等,来获取异步 IO 事件的状态和数据,并将其传递给相应的回调函数。如果异步请求执行完毕,异步运行时也需要从任务队列中移除对应的状态信息,以释放底层资源并回收内存。

一个更加简化的异步运行时泳道图

创建运行时对象调用异步模块处理异步事件移除对应状态信息注册事件触发异步事件运行时对象异步模块事件处理器

对比python和golang

future对比

语言
Future/Async/Await执行方式
优点
缺点
Python
通过事件循环实现Future/Async/Await的执行
异步编程模型简单易学,基于asyncio库提供了一整套异步 I/O 操作的API,更容易上手和维护;Python具有丰富的第三方库支持,生态丰富,可以支持异步编程和同步编程混合使用。
Python的异步运行时是单线程的,需要经常切换协程,限制了并发能力。同时,对于一些I/O 密集型操作,异步编程模型和同步编程相比,复杂度稍高,难以处理边界和异常情况。
Golang
基于Goroutine和Channel实现Future/Async/Await
执行快、代价小,一个新的Goroutine的栈大约只需要 4-5KB 的内存;Goroutine之间通信方式简单直观,更容易编写程序,代码可读性好;Golang天然支持并发控制,开发分布式系统有很大优势。
Golang缺少异步I/O模型的直接支持,需要自己手工实现异步I/O,开发人员需要了解文件描述符、Socket等内容;Golang的调度器可能会因为竞争条件而导致性能问题,开发人员需要注意保证调度器正确性。
Rust
通过执行器(executor)实现Future/Async/Await
Rust的异步编程模型具有很好的可伸缩性和并发性,Future对象的执行是由执行器自动调度的,可以更好地利用多核CPU;Rust天然地支持异步 I/O 操作,性能更高,更适合高并发场景。
Rust的异步编程模型对于初学者来说较为复杂,需要了解Future、Executor的概念,学习曲线较陡峭。Rust在处理一些复杂场景时,也需要进行代码重构,使得逻辑更加清晰。

异步运行时特点

语言
异步运行时特点
Executor/Reactor
注意
Python
基于协程的异步编程模型,通过asyncio库实现异步运行时
使用事件循环实现Reactor(基于select/epoll实现)
Python的异步运行时是单线程的,限制了其并发能力
Golang
基于Goroutine和Channel实现非阻塞式异步编程
使用调度器实现Executor(基于Go runtime实现)
需要注意Golang的调度器可能会因为竞争条件而导致性能问题
Rust
基于Future和Async/Await实现异步编程模型
使用块级任务调度器实现Executor(基于Tokio实现)
Rust需要对内存安全做出很多保证,导致其在编程复杂度上较高一些

Python、Golang和Rust在异步运行时的实现上有以下不同:

  1. Python使用协程实现异步编程,其异步运行时基于asyncio库。

asyncio库通过事件循环和协程实现异步编程,该库在事件循环中注册了协程,当有IO时,事件循环会自动执行协程。Python的异步运行时是单线程的,通过在事件循环中切换协程实现异步操作。

  1. Golang的异步编程模型是基于并发的原语 Goroutine 和 Channel。 Goroutine是一种轻量级线程,Channel是一种线程间的通信机制,通过Goroutine和Channel可以实现非阻塞的异步编程。Golang的异步运行时是通过调度器(Scheduler)在多个Goroutine之间进行调度。

  2. Rust的异步编程模型是通过Future和Async/Await实现的。 Future是异步计算的结果,而Async函数返回一个Future类型的值,表示异步计算的进程。Rust的异步运行时通过块级任务调度器实现,可以在同一线程上执行,也可以在多个线程上执行。

rust代码编译过程与宏展开过程

rust代码编译过程

编译过程泳道图

将源代码传递给预处理器将 \$crate 转换成实际 crate 名称展开所有宏定义,包括通过 include 指令添加的文件将预处理过的代码发送给下一个步骤将预处理过的代码分解成 token 串将代码中的注释删除将 token 组装成 AST(抽象语法树)检查代码是否符合 Rust 的语法规范检查 AST 是否符合 Rust 的语义规范进行 borrow checker 检查,确保没有内存安全问题将 AST 传递给代码优化器构建中间代码 IR(intermediate representation)利用 LLVM 进行高效优化将 IR 翻译成汇编代码在宏展开中对于涉及项的类型推断将汇编代码转成具体的机器代码生成可执行二进制文件或动态链接库预处理词法分析语法分析语义分析代码优化和翻译中间代码生成目标代码生成

声明宏展开

声明宏展开过程

输入 Rust 代码将代码解析成 token将 token 存储为输入语法树读取输入语法树将语法树转换成 Rust 代码结构用语法树分析器确定宏的实现方法生成宏的实现代码用实现代码扩展语法树将宏形式参数输入宏展开将语法树转换成 Rust 代码结构重新处理代码生成最终的代码TokenizationParsingExpansion

Rust 的声明宏在编译时对代码进行转换,因此其展开过程是在编译期间完成的。展开过程可以分为三个阶段:

  1. Tokenization:解析输入的 Rust 代码,将其转换成一个个 token(如标识符、关键字、符号等)。
  2. Parsing:将 token 转化成语法树,用于对代码进行进一步处理。
  3. Expansion:对语法树进行处理,生成最终的代码。

在第三个阶段,宏会根据语法树中的特定模式对代码进行重构。这些模式可以是任何 Rust 代码片段,包括类型、结构体、函数、表达式等。宏甚至可以递归地展开自己。

展开过程中,宏的实现代码可以使用标准的 Rust 代码编写,包括控制结构和函数调用等。

展开后的代码与宏的实现代码完全一样,因此对于用户而言,使用宏和使用函数没有什么区别。

过程宏展开

属性、类型、函数三种过程宏展开过程对比

遇到属性宏yes未遇到属性宏执行属性宏遇到类型宏yes未遇到类型宏执行类型宏遇到函数宏yes未遇到函数宏执行函数宏获取宏参数解析宏参数属性是单个值yes属性是多个值获取属性值修改属性获取属性值列表修改属性获取宏参数解析宏参数参数是单个类型yes参数是多个类型获取类型参数生成新类型修改类型获取类型参数列表生成新类型修改类型获取宏参数解析宏参数执行预处理逻辑获取函数体解析函数体需要额外处理yes无需额外处理执行额外处理生成新代码生成新代码返回属性继续解析代码返回类型继续解析代码返回代码继续解析代码解析代码准备解析宏参数返回属性返回类型返回代码

属性宏和类型宏展开过程的流程较为相似,都需要解析宏参数、生成新的属性或类型、修改原有属性或类型,并返回属性或类型等步骤。但是由于其作用的范围不同,展开过程中需要解析的内容也不尽相同。例如,类型宏需要解析的是类型参数,用于生成新的类型;而属性宏需要解析的是属性参数,用于生成新的属性。

  1. 函数宏和其他两种宏不同的是,函数宏需要对整个函数体进行处理,并生成新的代码。在执行完预处理逻辑和解析函数体后,需要判断是否需要进行额外处理,然后才能最终生成新代码并返回。

对比

声明宏
属性宏/类型宏
函数宏
异同点
不能修改源代码
- 作用于某个规模较小的表达式或语句
- 可以在声明中使用
可以修改源代码
- 作用于属性/类型
- 可以在声明中使用
生成新的代码
- 不能修改原有代码
- 作用于整个函数体
- 不能在声明中使用
使用场景
封装底层功能
- 生成器语法扩展
- DRY原则
重载运算符
- 自定义标记
- 序列化/反序列化
实现特殊流程控制
- 实现嵌套参数模板
关键字
macro
- derive
- repr
- allow
- compiler_builtins
- link
macro_rules
JavaScriptFetchParseCompile and OptimizeRe-optimize and DeoptimizeExecuteGC

idea自带插件:

Excalidraw Integration - IntelliJ IDEs Plugin | Marketplace

更正:目前新版的Excalidraw Integration已经修复,修改后会直接更新源文件!

idea插件不适合kroki-excalidraw

  1. Excalidraw Integration只是一个画图工具:
  • 没有保存文件按钮,只能导出为图片
  • 哪怕打开画好的文件,也只能预览,修改之后不能保存更新源文件

那还不如用在线app

  1. 在线excalidraw的文件才是kroki-excalidraw可用的
  • 可以载入第三方组件库

在线绘制工具

excalidraw/excalidraw: Virtual whiteboard for sketching hand-drawn like diagrams

将绘制步骤动态化

dai-shi/excalidraw-animate: A tool to animate Excalidraw drawings

好用的库

excalidraw/excalidraw-libraries: Collection of publicly available libraries

创建幻灯片

dai-shi/excalidraw-claymate: A tool based on Excalidraw to create stop motion animations and slides.

vega

kroki-vega/vegalite

相关资源

Vega Examples

word cloud

DECLARATIVEVISUALIZATIONGRAMMARSACCELERATEDEVELOPMENTFACILITATERETARGETINGACROSSPLATFORMSALLOWLANGUAGELEVELOPTIMIZATIONSHOWEVEREXISTINGLANGUAGESPRIMARILYCONCERNEDVISUALENCODINGRELYIMPERATIVEEVENTHANDLERSINTERACTIVEBEHAVIORSRESPONSEINTRODUCEMODELINTERACTIONDESIGNDATAVISUALIZATIONSADOPTINGMETHODSREACTIVEPROGRAMMINGLOWEVENTSCOMPOSABLESTREAMSFORMHIGHERSEMANTICSIGNALSFEEDPREDICATESSCALEINVERSIONSGENERALIZESELECTIONSITEMGEOMETRYPIXELSQUERIESDOMAINPRODUCTIONRULESUSEMANIPULATEAPPEARANCEREUSESHARINGCONSTRUCTSENCAPSULATEDNAMEDINTERACTORSSTANDALONEPURELYSPECIFICATIONSTECHNIQUESASSESSFEASIBILITYEXPRESSIVITYINSTANTIATINGEXTENSIONSVEGAGRAMMARDIVERSERANGEEXAMPLESDEMONSTRATECOVERAGEESTABLISHEDTAXONOMYPRESENTSYSTEMARCHITECTUREPROVIDESFIRSTROBUSTCOMPREHENSIVETREATMENTSTARTINGSINGLESPECIFICATIONDATAFLOWGRAPHINPUTSCENEELEMENTSTREATEDCLASSSTREAMINGSOURCESSUPPORTEXPRESSIVEMAYINVOLVETIMEVARYINGSCALARRELATIONALHIERARCHICALDYNAMICALLYWRITERUNTIMEEXTENDINGPRUNINGBRANCHESDRIVENFASHIONDISCUSSCOMPILERUNAPPLIEDWITHINSHARERESULTSBENCHMARKSTUDIESINDICATESUPERIORPERFORMANCEORIGINALNONLITEHIGHENABLESRAPIDCOMBINESTRADITIONALGRAPHICSPROVIDINGCOMPOSITIONALGEBRALAYEREDMULTIVIEWDISPLAYSNOVELUSERSSPECIFYSEMANTICSCOMPOSINGSELECTIONABSTRACTIONDEFINESPROCESSINGPOINTSINTERESTPREDICATEFUNCTIONINCLUSIONTESTINGPARAMETERIZEENCODINGSSERVINGDEFININGEXTENTSDRIVINGCONDITIONALLOGICCOMPILERAUTOMATICALLYSYNTHESIZESREQUISITEFLOWHANDLINGOVERRIDECUSTOMIZATIONCONTRASTDECOMPOSECONCISEENUMERABLEUNITSEVALUATEDEMONSTRATINGSUCCINCTCUSTOMIZEDCOMMONPANNINGZOOMINGLINKED

Diverging Stacked Bar Chart

−40−20020406080100PercentageQuestion 1Question 2Question 3Question 4Question 5Question 6Question 7Question 8QuestionStrongly disagreeDisagreeNeither agree nor disagreeAgreeStrongly agreeResponse

Ditaa: Conjugate prior relationships

ditaa的含义

ditaa 是 DIagrams Through Ascii Art,作者是 Stathis Sideris。

支持ascii图像渲染 kroki-ditaa

ExponentiallambdataulambdaLognormalGammaPoissonbetatautauNormalmu

相关资源

Mermaid

kroki-mermaid

Sequence diagram

AliceBobJohnloop[Healthcheck]Rational thoughts prevail...Hello John, how are you?Fight against hypochondriaGreat!How about you?Jolly good!AliceBobJohn

Gantt

A Gantt Diagram2014-01-052014-01-122014-01-192014-01-262014-02-022014-02-092014-02-16A task           Task in sec      another task     Another task     SectionAnotherA Gantt Diagram

Nomnoml: UML diagram

kroki-nomnoml


	[Pirate|eyeCount: Int|raid();pillage()|
	  [beard]--[parrot]
	  [beard]-:>[foul mouth]
	]
	
	[<abstract>Marauder]<:--[Pirate]
	[Pirate]- 0..7[mischief]
	[jollyness]->[Pirate]
	[jollyness]->[rum]
	[jollyness]->[singing]
	[Pirate]-> *[rum|tastiness: Int|swig()]
	[Pirate]->[singing]
	[singing]<->[rum]
	
	[<start>st]->[<state>plunder]
	[plunder]->[<choice>more loot]
	[more loot]->[st]
	[more loot] no ->[<end>e]
	
	[<actor>Sailor] - [<usecase>shiver me;timbers]
	
		
			
				
			
			
				
					
						
					
					
					0..7
					
					
					
					
					
					
					
					*
					
					
					
					
					
					
					
					
					
					
					
					
					
					no
					
					
					
					
						
							
							
							
							
						
						
							
								Pirate
								
							
						
						
							
								eyeCount: Int
								
							
						
						
							
								raid()
								pillage()
								
							
						
						
							
								
									
										
									
									
									
									
										
											
										
										
											
												beard
												
											
										
									
									
										
											
										
										
											
												parrot
												
											
										
									
									
										
											
										
										
											
												foul mouth
												
											
										
									
								
							
						
					
					
						
							
							
							
						
						
							
								rum
								
							
						
						
							
								tastiness: Int
								
							
						
						
							
								swig()
								
							
						
					
					
						
							
						
						
							
								Marauder
								
							
						
					
					
						
							
						
						
							
								mischief
								
							
						
					
					
						
							
						
						
							
								jollyness
								
							
						
					
					
						
							
						
						
							
								singing
								
							
						
					
					
						
							
						
					
					
						
							
						
						
							
								plunder
								
							
						
					
					
						
							
						
						
							
								more loot
								
							
						
					
					
						
							
							
						
					
					
						
							
							
							
							
						
						
							
								Sailor
								
							
						
					
					
						
							
						
						
							
								shiver me
								timbers
								
							
						
					
				
			
		
	

相关资源

BPMN

bpmn-js

来历

  • 业务流程模型和标记法是一套图形化表示法,用于以业务流程模型详细说明各种业务流程。

  • 它最初由业务流程管理倡议组织开发,名称为“Business Process Modeling Notation“,

即“业务流程建模标记法”。

kroki-bpmn

Pizza CustomerHungry for pizzaSelect a pizzaOrder a pizzapizza received60 minutesAsk for the pizzaPay the pizzaEat the pizzaHunger satisfiedPizza vendordelivery boypizza chefclerkOrder received„where is my pizza?“Calm customerBake the pizzaDeliver the pizzaReceive paymentpizza orderreceiptmoneypizza

相关资源

Bytefield

kroki-bytefield, 不支持引入

WaveDrom: Digital Timing diagram

kroki-wavedrom

clkDataheadbodytaildataRequestAcknowledge

Svgbob

kroki-svgbob

connected Servers


  
  
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
  
  
  
  
  
  
  
  
  ,
  
  
  
  .
  
  
  ,
  )
  
  .
  
  '
  
  [
  ]
  ::
  
  
  
  [
  
  ...
  
  
  .
  
  '
  
  ::::
  
  O
  
  ]
  ]
  |
  |
  
  
  
    
    
    
    
  
  
    
    
    
    
    
    
    
  
  
    
    
    
    
  
  
    
    
    
    
  
  
    
    
    
  
  
    
    
    
  
  
    ...°
    ]
  
  
    
    
    
  
  
    
    
    
    
    
  
  
    
    
    
  
  
    
    
  
  
    
    
    
  
  
    
    
    
  

UMlet

what is

UMLet is a free, open-source UML tool with a simple user interface: draw UML diagrams fast, build sequence and activity diagrams from plain text, export diagrams to eps, pdf, jpg, svg, and clipboard, share diagrams using Eclipse, and create new, custom UML elements. UMLet runs stand-alone or as Eclipse plug-in on Windows, OS X and Linux.

kroki-umlet

State machine

This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!This Element has an Error!

VEGA深度使用

缘起

一直以来,mindmap、UML(plantuml)、excalidraw这些工具只能表达少量概念之间的联系,缺少可以看到更加全面知识点联系的工具。

在尝试scapple之后,它的局限性太明显,无法和在线文档结合起来。这时候我在学习kroki的使用时,发现vege这个工具。

img

A visualization grammar

vega在github上面的口号就深得我心,直接定位可视化语法。

基础使用方法(基于kroki-vega)

⚠️kroki不支持文件内再导入其他文件

![\tree map])\kroki-vega:../../../materials/vega/radial-tree.json)

本地转化本地查看plantuml思维导图plantuml思维导图文本解析器python脚本将plantuml文本转为json文本解析器python脚本将plantuml文本转为jsonvega配置文件vega配置文件本地html包含vega嵌入式所需js本地html包含vega嵌入式所需js本地mdbook server本地mdbook server在线mdbook托管于github在线mdbook托管于github确认节点关系、属性1. 方便看出节点层次感,包含关系2. 添加节点的相关属性:链接、注释、颜色等传入转为vega要求的json格式将json文件存放mdbook项目src内,这样才能被放在book文件目录内相对路径导入方便本地查看效果在src目录执行anywherenpm install -g anywhereanywhere可以在指定路径启动网站服务本地打开html本地mdbook serve查看git上传,自动编译

编写好的py脚本

puml_mindmap_json

"""
主要将plantuml的mindmap写法转为vega可用的json文件
"""
import sys
import re
import json
import os
import base64
import zlib


def converter(puml_path: str):
    """
    传入puml文件路径进行解析转化
    1. 标题都是以*开头, 且一个*的都是根节点
    2. 父级节点只会比子级节点少一个*,如果当前节点比下一个节点少于超过一个*,puml就无法通过
    3. 如果下一个节点比上一个节点少*,就去对应列表里面找最后一个
    :param puml_path:
    :return:
    """
    print(f"开始处理{puml_path}...")
    levels = {}
    json_results = []
    # 找到同级的md文档目录
    md_dir_path = f"{puml_path.replace(puml_path.split('/')[-1], '')}md"
    data_json_path = f"{puml_path.replace(puml_path.split('/')[-1], '')}data.json"
    with open(puml_path, 'r') as f:
        notes = extract_notes(md_dir_path, f.read())

    with open(puml_path, 'r') as f:
        lines = [line for line in f.readlines()]
        title_index = 1
        for index, line in enumerate(lines):
            # 标题的*后面只会出现三种情况:空格、:、[
            if line.startswith('*'):
                stars, name, color, links = extract_stars_name_links_color(line)
                levels[stars] = (line, title_index)
                parent = levels.get(stars[:-1])
                node = {
                    "id": title_index,
                    "name": name,
                    # "size": len(name)
                    # "link": 'https://www.google.com'
                }
                if parent:
                    node["parent"] = parent[1]
                if links:
                    # 如果是有链接,就变成子节点
                    link_count = 1
                    for link_name, link in links.items():
                        title_index += 1
                        wrap_link_name = get_wrap_name(f"链接{link_count}: {link_name}")
                        child_node = {
                            "id": title_index,
                            "name": wrap_link_name,
                            "link": link,
                            "parent": node['id'],
                            "note": f'[来自{node["name"]}的链接]({link})'
                        }
                        json_results.append(child_node)
                        link_count += 1
                if color:
                    node["color"] = '#' + color
                if index < len(lines) and lines[index + 1].startswith('<code>'):
                    note = notes.pop(0)
                    # print(f"弹出的注释:{note}")
                    node['note'] = note
                json_results.append(node)
                title_index += 1
    result_path = puml_path.replace('.puml', '.json')
    with open(data_json_path, 'w') as f:
        f.write(json.dumps(json_results))


def extract_stars_name_links_color(line=''):
    color = None
    links = re.findall('\[\[(.*?)\]\]', line)
    link_dict = {}
    for link in links:
        href, title = link.split(' ', 1)
        line = line.replace(f"[[{href} {title}]]", f" {title}")
        link_dict[title] = href
    try:
        stars = re.split('[ :\[]', line)[0]
        name = line[len(stars):]
        if name.startswith('[#'):  # 如果有颜色
            color = re.findall('\[#(.*?)\]', name)[0]
            name = name.split(']')[1]
        if name.startswith(':'):  # 如果有注释
            name = name[1:]
    except:
        print(line)
    wrap_name = get_wrap_name(name)
    return stars, wrap_name, color, link_dict


def get_wrap_name(name):
    # 统一添加换行符
    wrap_name = []
    space_count = 0
    for char in name:
        if char == ' ':
            space_count += 1
        if space_count == 3:
            char = '\n'
            space_count = 0
        wrap_name.append(char)
    return ''.join(wrap_name)


# [Kroki!](https://kroki.io/)
def get_kroki_preprocessors():
    preprocessors = {
        "puml": "plantuml",
        "seqdiag": "sequediag",
        "svgbob": "svgbob",
        "ditaa": "ditaa",

    }
    return preprocessors


# 将puml/mermaid等内容提交给kroki获取在线图片链接
def get_kroki_link(file_path, preprocessor):
    with open(file_path, 'r') as f:
        content = f.read()
        encoded_cotnent = base64.urlsafe_b64encode(zlib.compress(content.encode('utf8'))).decode('utf8')
        return f"https://kroki.io/{preprocessor}/svg/{encoded_cotnent}"


# 1. 提取内容
# 2. 如果是md文档地址,就取文档地址内容为note
# 3. 对note的内容进行处理
def extract_notes(md_dir_path, text=''):
    #     text = '''
    #         ****:tail -n 80 customSpec.json
    # <code>
    #
    # 此命令显示 Wasm 二进制字段后面的最后部分,
    # 包括运行时使用的几个托盘的详细信息,
    # 例如 sudo 和 balances 托盘。
    # </code>;
    # ****:Modify the name field to identify this chain specification as a custom chain specification.
    # <code>
    #
    # "name": "My Custom Testnet",
    # </code>
    # ****:Modify aura field to specify the nodes
    # <code>
    #     '''
    # 同时匹配换行符
    # (?:pattern) 来解决方括号不适用的场景
    # [正则匹配所有字符(包括换行)_尐东东的博客-CSDN博客_正则匹配所有字符](https://blog.csdn.net/u011158908/article/details/105666329)
    notes = re.findall('\<code\>((?:.|\n)*?)\</code\>', text)
    # 考虑到html默认只支持br换行,所以这里统一替换成br
    # notes = [note.replace('\n', '<br>') for note in notes]
    preprocessors = get_kroki_preprocessors()

    def inner_note_replace(note):
        # 如果是md文件地址,就替换
        if note.startswith("md_file:"):
            md_file = note.replace("md_file:", "")
            with open(f"{md_dir_path}/{md_file}", 'r') as f:
                note = f.read()
        # 考虑到plantuml的';'是元素结束符,所以这里将'";"'换成';'
        note = note.replace('";"', ';')
        # 提取其中的markdown图片链接,如果是puml后缀,就单独处理
        # ![](xxx.puml) -> ![xxx.puml](new_path)
        img_links = re.findall('!\[(.*?)\]\((.*?)\)', note)
        for img_link in img_links:
            img_name, img_path = img_link
            suffix = img_path.split('.')[-1]
            if suffix in preprocessors.keys():
                kroki_link = get_kroki_link(img_path, preprocessors[suffix])
                file_name = img_path.split('/')[-1]
                note = note.replace(f"![]({img_path})",
                                    f"- [{file_name}点开大图]({kroki_link})\n![{file_name}]({kroki_link})")
        return note

    notes = [inner_note_replace(note.strip()) for note in notes]
    return notes


def extract_links(text=''):
    links = re.findall('\[\[(.*?)\]\]', text)
    link_dict = {}
    for link in links:
        href, title = link.split(' ', 1)
        link_dict[title] = href
    return link_dict


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("请传入puml文件路径...")
    else:
        puml_path = sys.argv[1]
        puml_paths = []
        if os.path.isdir(puml_path):
            puml_paths = [f"{puml_path}/{item}" for item in os.listdir(puml_path) if item.endswith('.puml')]
        elif not puml_path.endswith('.puml'):
            print("请传入puml文件...")
        else:
            puml_paths.append(puml_path)
        for puml_path in puml_paths:
            converter(puml_path)

两种格式:svg和canvas

  • svg本质上是xml数据,它渲染的可视化图片会分成很多节点DOM。好处在于节点操作更顺畅,坏处在于更加占资源
  • canvas只有一个DOM,正好与svg相反。
  • 二者互补,节点多优先选canvas

两种渲染方式

embed

<head>
    <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
    <script src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
    <script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
</head>
<body>
<div id="vis"/>
</code>
<script>
    vegaEmbed(
        '#vis',
        'vega/tree.vg.json'
    );
</script>
</body>

embed

<head>
    <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
</head>
<body>
<div id="view"></div>
<script type="text/javascript">
    var view;

    fetch('vega/circle_packing.vg.json')
        .then(res => res.json())
        .then(spec => render(spec))
        .catch(err => console.error(err));

    function render(spec) {
        view = new vega.View(vega.parse(spec), {
            renderer:  'svg',  // renderer (canvas or svg)
            container: '#view',   // parent DOM container
            hover:     true       // enable hover processing
        });
        return view.runAsync();
    }
</script>
</body>

优先选embed

view组件方式不支持hover等特性,放弃

参考资源

yarn 
yarn start

这本书最大的特点是根据数据特点提供对应的图表类型

  • Four Views of the Same Data: Scatterplot, Clustered Barchart, Clustered Barchart, Stacked Barchart
  • Question: How Is a Value Distributed?: Categorical Histogram , Quantitative Histogram , Smoothed Histogram , Box Plot, Categorical Density Plot, Continuous Density Plot
  • Question: How Do Groups Differ from Each Other?: Bar Chart, Paired (or Multiple) Series Bar Chart, Pie (or Doughnut ) Chart, Heatmap
  • Question: Do Invidual Items Fall Into Groups? Is There a Relationship Between Attributes of Items?: Scatterplot, Line Chart, Stacked Area Chart
  • Question: How Are Objects Related To Each Other in a Network or Hierarchy?: Node-Link View (Force-Directed Layout), Circular Network Layout, Adjacency Matrix, Tree View, Treemap, Sunburst plot
  • Question: Where Are Objects Located?: Choropleth, Dotplot map
  • Question: What Is In This Text?: Word Cloud
  • Chapter 6: Multiviews: Small Multiples, Split by Dimension, Small Multiples, Showing Different Measures, SPLOM, Cross-Selection

mermaid使用示例

介绍

mermaid

mermaid本身是一种mindmap+UML的语法, 其灵感来源于markdown语法的渲染机制。

示例

思维导图

默认不支持,虽然Mermaid本身暂未支持思维导图的绘制,但是考虑到Mermaid对流程图的支持,可以用Mermaid绘制极简单的思维导图

graph TD
A(工业用地效率)-->B1(土地利用强度)
A-->B2(土地经济效益)
B1-->C1(容积率)
B1-->C2(建筑系数)
B1-->C3(亩均固定资本投入)
B2-->D1(亩均工业产值)
B2-->D2(亩均税收)
`

流程图

flowchart LR

A[Hard] -->|Text| B(Round)
B --> C{Decision}
C -->|One| D[Result 1]
C -->|Two| E[Result 2]
`

时序图

sequenceDiagram
Alice->>John: Hello John, how are you?
loop Healthcheck
    John->>John: Fight against hypochondria
end
Note right of John: Rational thoughts!
John-->>Alice: Great!
John->>Bob: How about you?
Bob-->>John: Jolly good!
`

甘特图

gantt
    section Section
    Completed :done,    des1, 2014-01-06,2014-01-08
    Active        :active,  des2, 2014-01-07, 3d
    Parallel 1   :         des3, after des1, 1d
    Parallel 2   :         des4, after des1, 1d
    Parallel 3   :         des5, after des3, 1d
    Parallel 4   :         des6, after des4, 1d
`

类图

classDiagram
Class01 <|-- AveryLongClass : Cool
<<Interface>> Class01
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
class Class10 {
  <<service>>
  int id
  size()
}
`

状态图

stateDiagram-v2
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
`

饼图

pie
"Dogs" : 386
"Cats" : 85.9
"Rats" : 15
`

gitgraph(experimental in v9)

  gitGraph
    commit
    commit
    branch develop
    checkout develop
    commit
    commit
    checkout main
    merge develop
    commit
    commit
`

日记图

  journey
    title My working day
    section Go to work
      Make tea: 5: Me
      Go upstairs: 3: Me
      Do work: 1: Me, Cat
    section Go home
      Go downstairs: 5: Me
      Sit down: 3: Me
`

C4架构图(experimental in v9)

C4Context
title System Context diagram for Internet Banking System

Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")
Person(customerB, "Banking Customer B")
Person_Ext(customerC, "Banking Customer C")
System(SystemAA, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")

Person(customerD, "Banking Customer D", "A customer of the bank, <br/> with personal bank accounts.")

Enterprise_Boundary(b1, "BankBoundary") {

  SystemDb_Ext(SystemE, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")

  System_Boundary(b2, "BankBoundary2") {
    System(SystemA, "Banking System A")
    System(SystemB, "Banking System B", "A system of the bank, with personal bank accounts.")
  }

  System_Ext(SystemC, "E-mail system", "The internal Microsoft Exchange e-mail system.")
  SystemDb(SystemD, "Banking System D Database", "A system of the bank, with personal bank accounts.")

  Boundary(b3, "BankBoundary3", "boundary") {
    SystemQueue(SystemF, "Banking System F Queue", "A system of the bank, with personal bank accounts.")
    SystemQueue_Ext(SystemG, "Banking System G Queue", "A system of the bank, with personal bank accounts.")
  }
}

BiRel(customerA, SystemAA, "Uses")
BiRel(SystemAA, SystemE, "Uses")
Rel(SystemAA, SystemC, "Sends e-mails", "SMTP")
Rel(SystemC, customerA, "Sends e-mails to")
`

参考资源

mdbook 更新mermaid版本

  1. 下载好对应版本的mermaid.min.js文件
  2. 替换book.toml中对应的additional-js中的mermaid.min.js文件
  3. 注意要多刷新两次才能更新缓存

PlantUML

plantuml & Graphviz

Graphviz 已安装?yesno处理所有绘制任务仅处理时序图活动

示例

添加超链接、提示、标签

plantuml-hyperlink

注意mindmap只能在节点标题使用链接

```kroki-plantuml
@startmindmap
* Build a local blockchain [[#build-a-local-blockchain jump]]
@endmindmap
```

超链接

@startuml
[[link{with_bracket}&id=10]]:Some activity\n(with link with brackets)\n""link{with_bracket}&id=10"";
[["link{with_bracket}"{}]]:Some activity\n(with link with brackets and empy tooltip)\n"""link{with_bracket}"{}"";
[["link{with_bracket}"{with tooltip}]]:Some activity\n(with link finished by brackets and tooltip)\n"""link{with_bracket}"{with tooltip}"";
[["link{with_bracket}&id=10"{with tooltip}]]:Some activity\n(with link with brackets and tooltip)\n"""link{with_bracket}&id=10"{with tooltip}"";
@enduml

Some activity(with link with brackets)link{with_bracket}&id=10Some activity(with link with brackets and empy tooltip)"link{with_bracket}"{}Some activity(with link finished by brackets and tooltip)"link{with_bracket}"{with tooltip}Some activity(with link with brackets and tooltip)"link{with_bracket}&id=10"{with tooltip}

思维导图

OrgMode 语法

@startmindmap
'orgmode
* Debian
** Ubuntu
*** Linux Mint
*** Kubuntu
*** Lubuntu
*** KDE Neon
** LMDE
** SolydXK
** SteamOS
** Raspbian with a very long name
*** <s>Raspmbc</s> => OSMC
*** <s>Raspyfi</s> => Volumio
@endmindmap
DebianUbuntuLinux MintKubuntuLubuntuKDE NeonLMDESolydXKSteamOSRaspbian with a very long nameRaspmbc=> OSMCRaspyfi=> Volumio

Markdown语法

@startmindmap
* root node
	* some first level node
		* second level node
		* another second level node
	* another first level node
@endmindmap
root nodesome first level nodesecond level nodeanother second level nodeanother first level node

运算符决定方向

@startmindmap
+ OS
++ Ubuntu
+++ Linux Mint
+++ Kubuntu
+++ Lubuntu
+++ KDE Neon
++ LMDE
++ SolydXK
++ SteamOS
++ Raspbian
-- Windows 95
-- Windows 98
-- Windows NT
--- Windows 8
--- Windows 10
@endmindmap
OSUbuntuLinux MintKubuntuLubuntuKDE NeonLMDESolydXKSteamOSRaspbianWindows 95Windows 98Windows NTWindows 8Windows 10

多行表示

@startmindmap
* Class Templates
**:Example 1
<code>
template <typename T>
class cname{
void f1()<U+003B>
...
}
</code>
;
**:Example 2
<code>
other template <typename T>
class cname{
...
</code>
;
@endmindmap
Class TemplatesExample 1template <typename T>class cname{void f1()<U+003B>...} Example 2other template <typename T>class cname{... 

多根节点

@startmindmap
* Root 1
** Foo
** Bar
* Root 2
** Lorem
** Ipsum
@endmindmap
Root 1FooBarRoot 2LoremIpsum

改变节点颜色

@startmindmap
*[#Orange] Colors
**[#lightgreen] Green
**[#FFBBCC] Rose
**[#lightblue] Blue
@endmindmap
ColorsGreenRoseBlue

移除方框

@startmindmap
* root node
** some first level node
***_ second level node
***_ another second level node
***_ foo
***_ bar
***_ foobar
** another first level node
@endmindmap
root nodesome first level nodesecond level nodeanother second level nodefoobarfoobaranother first level node

指定左右方向

@startmindmap
* count
** 100
*** 101
*** 102
** 200

left side

** A
*** AA
*** AB
** B
@endmindmap
count100101102200AAAABB

带标签的完整示例

@startmindmap
caption figure 1
title My super title

* <&flag>Debian
** <&globe>Ubuntu
*** Linux Mint
*** Kubuntu
*** Lubuntu
*** KDE Neon
** <&graph>LMDE
** <&pulse>SolydXK
** <&people>SteamOS
** <&star>Raspbian with a very long name
*** <s>Raspmbc</s> => OSMC
*** <s>Raspyfi</s> => Volumio

header
My super header
endheader

center footer My super footer

legend right
  Short
  legend
endlegend
@endmindmap
My super headerMy super titleDebianUbuntuLinux MintKubuntuLubuntuKDE NeonLMDESolydXKSteamOSRaspbian with a very long nameRaspmbc=> OSMCRaspyfi=> VolumioShortlegendfigure 1My super footer

应用:rust的模块系统整理

@startmindmap
scale 900 width
skinparam monochrome reverse
skinparam classFontName ttf-wqy-zenhei
*[#lightblue] Rust模块系统
**[#FFBBCC] 两种视角
*** 程序猿
**** 文件结构
*** rustc:module tree
****:可执行root
<code>
src/main.rs
-> binary crate(默认与cargo.toml->[package].name同名)
</code>;
****:库root
<code>
src/lib.rs
-> lib crate(默认与cargo.toml->[package].name同名)
</code>;
****:crate
<code>编译的最小基本单位</code>;
**[#FFBBCC] project的五个层级
*** workspace
*** package
*** crates
*** modules
*** paths
**[#FFBBCC] bin文件夹:可以直接使用src/lib.rs
**[#lightgreen] crates.io保存的什么?
*** 发布流程
**** cargo login
****[#lightgreen]:cargo package
<code>
$ cargo help package
从帮助信息结合substrate源码实验🧪可知:
1. 从当前目录开始执行路径开始,首先去父文件夹找Cargo.toml,
然后找当前目录的Cargo.toml,找不到就报错
2. 找到的Cargo.toml如果有workspace配置,
就按照workspace里面的subpackage顺序来依次打包
3. 每次打包的标志为src/main.rs或者src/lib.rs,
且src同级存在Cargo.toml,Cargo.toml里面有[package]
4. 开始打包为上传到crate.io的格式
5. 依次打包
6. 所有依赖必须是在crate.io可以找到的,找不到就报错
7. 以包含Cargo.toml父文件夹为项目根目录,
放在target/package里面
</code>;
**** cargo publish
**** cargo yank
**** cargo owner
***[#lightgreen]:crate.io包含代码总结
<code>
1. 只包含最小crate内容,也就是src/main.rs或者src/lib.rs + Cargo.toml
2. rust只能允许一级嵌套,使用workspace分出subpackage
</code>;
@endmindmap
Rust模块系统两种视角程序猿文件结构rustc:module tree可执行rootsrc/main.rs-> binary crate(默认与cargo.toml->[package].name同名)库rootsrc/lib.rs-> lib crate(默认与cargo.toml->[package].name同名)crate<code>编译的最小基本单位</code>project的五个层级workspacepackagecratesmodulespathsbin文件夹:可以直接使用src/lib.rscrates.io保存的什么?发布流程cargo logincargo package$ cargo help package从帮助信息结合substrate源码实验🧪可知:1. 从当前目录开始执行路径开始,首先去父文件夹找Cargo.toml,然后找当前目录的Cargo.toml,找不到就报错2. 找到的Cargo.toml如果有workspace配置,就按照workspace里面的subpackage顺序来依次打包3. 每次打包的标志为src/main.rs或者src/lib.rs,且src同级存在Cargo.toml,Cargo.toml里面有[package]4. 开始打包为上传到crate.io的格式5. 依次打包6. 所有依赖必须是在crate.io可以找到的,找不到就报错7. 以包含Cargo.toml父文件夹为项目根目录,放在target/package里面cargo publishcargo yankcargo ownercrate.io包含代码总结1. 只包含最小crate内容,也就是src/main.rs或者src/lib.rs + Cargo.toml2. rust只能允许一级嵌套,使用workspace分出subpackage

使用skinparam进行样式设置

颜色

@startuml
colors
@enduml
APPLICATIONAliceBlueAntiqueWhiteAquaAquamarineAzureBUSINESSBeigeBisqueBlackBlanchedAlmondBlueBlueVioletBrownBurlyWoodCadetBlueChartreuseChocolateCoralCornflowerBlueCornsilkCrimsonCyanDarkBlueDarkCyanDarkGoldenRodDarkGrayDarkGreenDarkGreyDarkKhakiDarkMagentaDarkOliveGreenDarkOrchidDarkRedDarkSalmonDarkSeaGreenDarkSlateBlueDarkSlateGrayDarkSlateGreyDarkTurquoiseDarkVioletDarkorangeDeepPinkDeepSkyBlueDimGrayDimGreyDodgerBlueFireBrickFloralWhiteForestGreenFuchsiaGainsboroGhostWhiteGoldGoldenRodGrayGreenGreenYellowGreyHoneyDewHotPinkIMPLEMENTATIONIndianRedIndigoIvoryKhakiLavenderLavenderBlushLawnGreenLemonChiffonLightBlueLightCoralLightCyanLightGoldenRodYellowLightGrayLightGreenLightGreyLightPinkLightSalmonLightSeaGreenLightSkyBlueLightSlateGrayLightSlateGreyLightSteelBlueLightYellowLimeLimeGreenLinenMOTIVATIONMagentaMaroonMediumAquaMarineMediumBlueMediumOrchidMediumPurpleMediumSeaGreenMediumSlateBlueMediumSpringGreenMediumTurquoiseMediumVioletRedMidnightBlueMintCreamMistyRoseMoccasinNavajoWhiteNavyOldLaceOliveOliveDrabOrangeOrangeRedOrchidPHYSICALPaleGoldenRodPaleGreenPaleTurquoisePaleVioletRedPapayaWhipPeachPuffPeruPinkPlumPowderBluePurpleRedRosyBrownRoyalBlueSTRATEGYSaddleBrownSalmonSandyBrownSeaGreenSeaShellSiennaSilverSkyBlueSlateBlueSlateGraySlateGreySnowSpringGreenSteelBlueTECHNOLOGYTanTealThistleTomatoTurquoiseVioletWheatWhiteWhiteSmokeYellowYellowGreen

字体与大小

查看系统支持的字体

plantuml -language

  • skinparam classFontColor red
  • skinparam classFontSize 10
  • skinparam classFontName Aapex

考虑可移植性

请注意:字体名称高度依赖于操作系统,因此不要过度使用它, 当你考虑到可移植性时。 Helvetica and Courier 应该是全平台可用。

文本对齐

  • skinparam sequenceMessageAlign center/right/left
@startuml
skinparam sequenceMessageAlign center
Alice -> Bob : Hi
Alice -> Bob : This is very long
@enduml
AliceAliceBobBobHiThis is very long

手写体

UserUserFirst ClassFirst ClassSecond ClassSecond ClassLast ClassLast ClassDoWorkCreate RequestDoWorkWorkDoneRequest CreatedDone

下面罗列当前版本plantuml可用样式

调整生成图片大小

scale 900 width/height

语法概览

语法全览

高级使用

标题、页脚与分页

BobBobAliceAliceMarkMarkhelloSayHelloPage 1 of 2

高级语法:Preprocessing

Use the preprocessor

参考资源

why create mdbook-puml

I created this preprocessor because mdbook-plantuml wasn’t working for me—specifically, mdbook-plantuml is currently incompatible with mdbook watch and mbbook serve because it triggers a rebuild loop.

This crate is quite simple and non-customizable at this point as it does all that I need it to for my own purposes. Feel free to fork and/or PR away though, and I’ll be happy to include changes.

小插曲一:给mdbook-puml安装合适的plantuml

  1. plantuml是基于graphviz的一个工具, Graphviz 是一个开源的图可视化工具,非常适合绘制结构化的图标和网络。它使用一种叫 DOT 的语言来表示图形。

官网可以看到,官方不再提供编译好的各个平台版本,现在都是第三方编译好保存的。这也难怪ubuntu的版本那么低。

  1. plantuml的uml图生成需要的graphviz版本较低

  2. plantuml新出的非uml图,比如思维导图,需要较新的plantuml才能支持

  3. osx的brew可以安装3.0版本graphviz,plantuml的版本也比较新,支持思维导图渲染

  • plantuml版本:1.2022.4, graphviz版本:3.0.0
brew install plantuml                                                                                                                            ─╯
Warning: plantuml 1.2022.4 is already installed and up-to-date.
To reinstall 1.2022.4, run:
  brew reinstall plantuml

brew install graphviz                                                                                                                            ─╯
Warning: graphviz 3.0.0 is already installed and up-to-date.
To reinstall 3.0.0, run:
  brew reinstall graphviz

  1. ubuntu的apt只能安装2.x版本graphviz,这个没关系,但是plantuml是2017年的,不支持思维导图渲染
成功:plantuml test_uml 
失败: plantuml test_mindmap

plantuml版本过老:1.2017.15-1

sudo apt-get install plantuml
[work] 0:vim- 1:bash*Z                                                                                                 "ip-172-26-8-185" 13:22 09-Jul-22
Reading package lists... Done
Building dependency tree
Reading state information... Done
plantuml is already the newest version (1:1.2017.15-1).
The following package was automatically installed and is no longer required:
  linux-aws-5.4-headers-5.4.0-1075
Use 'sudo apt autoremove' to remove it.
0 upgraded, 0 newly installed, 0 to remove and 123 not upgraded

目前apt-get安装的graphviz为2.40.1-2

sudo apt-get install graphviz
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following package was automatically installed and is no longer required:
  linux-aws-5.4-headers-5.4.0-1075
Use 'sudo apt autoremove' to remove it.
Suggested packages:
  gsfonts graphviz-doc
The following NEW packages will be installed:
  graphviz
0 upgraded, 1 newly installed, 0 to remove and 123 not upgraded.
Need to get 0 B/601 kB of archives.
After this operation, 3076 kB of additional disk space will be used.
Selecting previously unselected package graphviz.
(Reading database ... 142532 files and directories currently installed.)
Preparing to unpack .../graphviz_2.40.1-2_amd64.deb ...
Unpacking graphviz (2.40.1-2) ...
Setting up graphviz (2.40.1-2) ...
Processing triggers for man-db (2.8.3-2) ...
  1. 最后找到一个专门下载安装最新版本plantuml的脚本,才成功安装

我把这个脚本放在.github/workflows里面。

IDEA自带plantuml语法插件:PlantUML Integration

支持新建plantuml文件

image-20220711170958629

除了默认的指定文件名后缀,还可以新建文件名指定用plantuml studio打开

比如还没有mindmap类型,但是新版plantuml已经支持这个语法

image-20220711172727971

注意到,这里可以选择指定文件或者文件名后缀的打开方式

进入方式:file -> Associate With File Type File type associations | IntelliJ IDEA

为plantuml指定默认文件类型

其实plantuml可以直接识别puml后缀

还可以用mdbook的include语法嵌入:

可以用include语法嵌入

@startmindmap scale 900 width skinparam monochrome reverse skinparam classFontName ttf-wqy-zenhei *[#lightblue] Rust模块系统 **[#FFBBCC] 两种视角 *** 程序猿 **** 文件结构 *** rustc:module tree ****:可执行root

src/main.rs -> binary crate(默认与cargo.toml->[package].name同名) ; ****:库root

src/lib.rs -> lib crate(默认与cargo.toml->[package].name同名) ; ****:crate 编译的最小基本单位; **[#FFBBCC] project的五个层级 *** workspace *** package *** crates *** modules *** paths **[#FFBBCC] bin文件夹:可以直接使用src/lib.rs **[#lightgreen] crates.io保存的什么? *** 发布流程 **** cargo login ****[#lightgreen]:cargo package

$ cargo help package 从帮助信息结合substrate源码实验🧪可知:

  1. 从当前目录开始执行路径开始,首先去父文件夹找Cargo.toml, 然后找当前目录的Cargo.toml,找不到就报错

  2. 找到的Cargo.toml如果有workspace配置, 就按照workspace里面的subpackage顺序来依次打包

  3. 每次打包的标志为src/main.rs或者src/lib.rs, 且src同级存在Cargo.toml,Cargo.toml里面有[package]

  4. 开始打包为上传到crate.io的格式

  5. 依次打包

  6. 所有依赖必须是在crate.io可以找到的,找不到就报错

  7. 以包含Cargo.toml父文件夹为项目根目录, 放在target/package里面 ; **** cargo publish **** cargo yank **** cargo owner ***[#lightgreen]:crate.io包含代码总结

  8. 只包含最小crate内容,也就是src/main.rs或者src/lib.rs + Cargo.toml

  9. rust只能允许一级嵌套,使用workspace分出subpackage ; @endmindmap

关于设置plantuml_limit_size

方法一:修改vmoption

  1. Open the option ‘Help->Edit custom VM option’
  2. add ‘-DPLANTUML_LIMIT_SIZE=8192’ on the last line
  3. It can be work after restart idea. how to set PLANTUML_LIMIT_SIZE when running intellij idea plugin - PlantUML Q&A

Error rendering admonishment

Failed with: TOML parsing error: expected an equals, found a newline at line 1 column 6

Original markdown input:

```admonish info title='方法二:preference
1. Open Preferences/Languages & Frameworks/PlantUML
2. Change the target option
[Where to define plantuml limit size environment variable when using PlantUML integration plugin with IntelliJ? - PlantUML Q&A](https://forum.plantuml.net/11078/plantuml-environment-variable-plantuml-integration-intellij)
```

关于scale缩放语法失效

CleanShot 2022-07-23 at 11.53.28@2x

关于高级语法:导入文件、定义变量

这里还有许多plantuml的高级语法

语法说明

  1. !define, !undef

  2. including files

  • can .zip a file and include it
  • You can use system environment variable or constant definition when using include

!include %windir%/test1.txt !define PLANTUML_HOME /home/foo !include PLANTUML_HOME/test1.txt

  1. include URL

  2. constants

  3. date and time

Draw.io可以用插入plantuml/mermaid

注意版本

  1. 在线版是v20,支持plantUML
  2. 桌面版是v19,还不支持plantUML: Releases · jgraph/drawio-desktop
Currently under reviewOnboarding and offboarding tasksOnboardingPrior to first dayContract signedEmployee handbookIT equipment reservedFirst dayOffice tourTeam introsAccount setupFirst weekShadow team membersSoftware trainingFirst monthAssign projects/tasksSet goalsGet team feedbackOffboardingFeedback and reviewExit interviewTasks/projects reassignedHandoverAccount deactivation/deletionIT hardware returnprioritymeetingsTasksLast updated: May

草图方法

笔记方法

思维理念

思维模型

参考书籍

  • <结构化思维>
  • <PDCA工作法>

WH模型

参考书籍

  • 《结构化思维》

使用2W1H模型阅读源码

时序图

What: 有什么语法关键字代码元素What: 有什么语法关键字代码元素What is: 是什么语法知识从何引入What is: 是什么语法知识从何引入如何运行代码逻辑业务逻辑如何运行代码逻辑业务逻辑loop识别语法关键字/引入元素是什么(属于单纯理解知识点)搜索语法点搜索文档,Rust还有完善的rustdoc这些语法元素如何组织

思维体系

巅峰刻意练习

相关资源

Checklist