duangsuse::Echo
718 subscribers
4.26K photos
130 videos
583 files
6.48K links
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
简而言之,Lkt 的命令行工具就是在支持文章结构的前提下允许自动组织项目结构,利用诸如 package 这样的信息自动组织。
duangsuse::Echo
关于 Literate Kotlin project 结构的设计。 Literate Kotlin 之前基于 literateBegin..literateEnd 且允许单层嵌套的设计,已经在 TypeScript 语言里作为小脚本完成实现,单独的命令行工具也会采用这样的单 markdown 结构。 LiterateKotlin 目前为了实用,先是按向 Gradle project 生成设计的,我们认为,Gradle 的 dependencies 是这样: project(1) : sourceSet(N)…
从序列模式提取的角度看,

-Tgradle 指的 "gradle" 实际上是一种生成插件,我们可以用 interface 来规定一个插件要实现的东西。

interface GenerateIntrinsic {
fun solvePath(src: CompileUnit): Path
fun generateProject(base: File)
}
data class CompileUnit(val scope: String, val sourceSet: String, val name: String)


interface LiterateKtPlugin<CFG> {
val name: String
fun readConfig(entry: Feed<Line>): CFG
fun create(cfg: CFG, properties: Map<String, String>): GenerateIntrinsic
}
从序列模式提取的角度看,

[...](file_reference) 的正则是复用的

```xxx
package ...
``` 的解析器是复用的

-Tgradle 指的 "gradle" 实际上是一种生成插件,我们可以用 interface 来规定一个插件要实现的东西。

interface GeneratePlugin<CFG> {
fun readConfig(entry: Feed<Line>): CFG
fun solvePath(src: CompileUnit): Path
fun generateProject(base: File)
}
data class CompileUnit(val scope: String, val sourceSet: String, val name: String)
有点累……
烦死了,到底该不该有
看起来用这种方式实现 -T, abc-Tabc 一起解析是个错误的决定
强烈建议使用传统方式解析
……简直就是噩梦…… 如果用户输入重了,怎么办?毫无提示? 难道就这样就没有更好的方法了?
This media is not supported in your browser
VIEW IN TELEGRAM
其实这可以更 declarative,可比较麻烦,而且我不知道 -T abc 和 -Tabc 该怎么样用 Parser 库的形式一起支持、处理,那样势必得使用带副作用或 contextual 的 parser,虽然我已经写了一个,但那样真的很 dirty 不如不用。
真是太愚蠢了,我连既能 match 又能 format 的东西都写不出来…… 而且 parser 写得还那么不好看
但它可以工作
但我讨厌只能工作的东西
-Tabc | -T, abc 处理起来真是无聊至极,String 层面不好处理因为有 -Tabc 这种连词的情况、Char 层面也不好处理因为有 -T abc…… 而且实在没必要上 Char解决,会引起处理与 shell 不协调。难道这个流就这么难以施用抽象性高的解析器?
唉,它写起来相当麻烦,Workflow 我现在还没想清楚还在渐进设计,但它相当重要,无法逃避。
duangsuse::Echo
但它可以工作 但我讨厌只能工作的东西 -Tabc | -T, abc 处理起来真是无聊至极,String 层面不好处理因为有 -Tabc 这种连词的情况、Char 层面也不好处理因为有 -T abc…… 而且实在没必要上 Char解决,会引起处理与 shell 不协调。难道这个流就这么难以施用抽象性高的解析器?
准确的说 String 层面也可以处理,可我现在安排的 Parser 基本组合和输入流没有 mark/reset 的支持感觉不自在,而且一旦能够区分 -T 后面有没有配置的话,就得上 contextual 解析器了,实在是没必要。
Kotlin 官方都没有提供 Native 侧的 File API,KN 都这么久了还没官方接口
很多类还是得放 jvmMain 里写

这个项目 DOM TypeScript 侧还好,如果要手动处理 Markdown 部分的话感觉有点越俎代疱,最好还是找找 Markdown 的 DOM 库。
现在的模型是这样,-Tgradle
solvePath 是把 (main, kotlin, org.duangsuse.sample) 给映射到一个包的路径如 /src/main/kotlin/org/duangsuse/sample
generateProject 是映射完项目文件后期再来依据之前提供的 CFG 生成 build.gradle 和 settings.gradle、gradle/wrapper/gradle-wrapper.properties 的

AbstractGenerateIntrinsic
readLinks 属于默认实现,取 README.md 的依赖链接
readCompileUnit 属于默认实现,依据之前的默认 pkg 取 scope, sourceset 什么的和 filter code
晚安世界。
val op = plugin.create(properties)
/**/
val (unit, code) = op.readCompileUnit(src)
val destination = op.solvePath(unit)
File(outBase, destination).writeText(code)
介于这个原因,我要好好放松一下,所以真的不想编程什么的

后来我考虑了一下 Lkt 工具…… 怎么工作呢?其实我基本了解生成过程了,就是把所有 markdown resolvePath 安排好,然后弄 config file generateProject 即可
其中最关键的流程就是

启动 -> 令 Plugin 解析 root README -> 创建 Plugin 的 Intrinsic -> handle root README

-T -t 都是创建 GenerateIntrinsic 用的
-s 是 handle root README 用的,它要确定一个位置
-d 才是整个生命周期里都需要的,所以应该把它做成一个字段,destinationBase

而这个 README/literate 的过程实际上是一个文章依赖广度优先搜索的过程,从 README.md 的链接,到图里最终末的端点,然后就像我上面说的那样:

val (unit, code) = op.readCompileUnit(src)
val destination = op.resolvePath(unit)
File(destinationBase, destination).writeText(code)


这个过程我们用一个 Queue<File> 来解决,也是整个生成过程中都要有的。
广度优先搜索的算法很好写,只需加一个 Set<File> 来记录略过环形依赖关系即可(非必需,为增强健壮性)。

注意 plugin 在解析 root README 的时候是拿不到 properties 的,这是为了保证 Intrinsic 能拿到 README 的解析结果,也不是不能解决,但我觉得…… 其实不支持这个也没什么。