momo-ai 1.0.20 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/.claude/skills/algorithmic-art/LICENSE.txt +202 -0
  2. package/.claude/skills/algorithmic-art/SKILL.md +405 -0
  3. package/.claude/skills/algorithmic-art/templates/generator_template.js +223 -0
  4. package/.claude/skills/algorithmic-art/templates/viewer.html +599 -0
  5. package/.claude/skills/r2mo-rad-lain/PROMPT.md +281 -0
  6. package/.claude/skills/r2mo-rad-lain/README.md +192 -0
  7. package/.claude/skills/r2mo-rad-lain/SKILL.md +412 -0
  8. package/.claude/skills/r2mo-rad-lain/examples/argument-parsing.js +154 -0
  9. package/.claude/skills/r2mo-rad-lain/examples/file-operations.js +182 -0
  10. package/.claude/skills/r2mo-rad-lain/file-utils-api.md +281 -0
  11. package/.claude/skills/r2mo-rad-lain/menu-api.md +187 -0
  12. package/.claude/skills/r2mo-rad-lain/scripts/file-utils.js +223 -0
  13. package/.claude/skills/r2mo-rad-lain/scripts/menu.js +289 -0
  14. package/.claude/skills/r2mo-rad-lain/scripts/yaml-parser.js +209 -0
  15. package/.claude/skills/r2mo-rad-lain/templates/command.json.template +13 -0
  16. package/.claude/skills/r2mo-rad-lain/templates/executor.js.template +32 -0
  17. package/.claude/skills/r2mo-rad-lain/templates/interactive-menu.js.template +221 -0
  18. package/.cursor/mcp.json +17 -0
  19. package/.obsidian/app.json +1 -0
  20. package/.obsidian/appearance.json +4 -0
  21. package/.obsidian/community-plugins.json +4 -0
  22. package/.obsidian/core-plugins.json +33 -0
  23. package/.obsidian/plugins/ai-agent/main.js +98495 -0
  24. package/.obsidian/plugins/ai-agent/manifest.json +11 -0
  25. package/.obsidian/plugins/ai-agent/styles.css +806 -0
  26. package/.obsidian/plugins/dataview/main.js +20876 -0
  27. package/.obsidian/plugins/dataview/manifest.json +11 -0
  28. package/.obsidian/plugins/dataview/styles.css +141 -0
  29. package/.obsidian/plugins/obsidian-excalidraw-plugin/main.js +10 -0
  30. package/.obsidian/plugins/obsidian-excalidraw-plugin/manifest.json +12 -0
  31. package/.obsidian/plugins/obsidian-excalidraw-plugin/styles.css +1 -0
  32. package/.obsidian/plugins/templater-obsidian/main.js +45 -0
  33. package/.obsidian/plugins/templater-obsidian/manifest.json +11 -0
  34. package/.obsidian/plugins/templater-obsidian/styles.css +226 -0
  35. package/.obsidian/plugins/terminal/main.js +200 -0
  36. package/.obsidian/plugins/terminal/manifest.json +14 -0
  37. package/.obsidian/plugins/terminal/styles.css +32 -0
  38. package/.obsidian/themes/AnuPpuccin/manifest.json +7 -0
  39. package/.obsidian/themes/AnuPpuccin/theme.css +9080 -0
  40. package/.obsidian/themes/Things/manifest.json +7 -0
  41. package/.obsidian/themes/Things/theme.css +1628 -0
  42. package/.obsidian/workspace.json +196 -0
  43. package/README.md +10 -123
  44. package/docs/images/logo.jpeg +0 -0
  45. package/install.sh +1 -0
  46. package/package.json +6 -2
  47. package/skills/r2mo-rad-lain/SKILL.md +101 -0
  48. package/src/_mcp/skills-server.mjs +70 -0
  49. package/src/_skill/repositories.json +16 -0
  50. package/src/commander/help.json +5 -0
  51. package/src/commander/mcp.json +13 -0
  52. package/src/commander/open.json +8 -2
  53. package/src/commander/skills.json +20 -0
  54. package/src/executor/executeEnv.js +48 -38
  55. package/src/executor/executeHelp.js +77 -16
  56. package/src/executor/executeInit.js +203 -149
  57. package/src/executor/executeMcp.js +290 -0
  58. package/src/executor/executeOpen.js +144 -125
  59. package/src/executor/executeSkills.js +747 -0
  60. package/src/executor/index.js +5 -39
  61. package/src/momo.js +2 -1
  62. package/src/utils/momo-args.js +39 -0
  63. package/src/utils/momo-file-utils.js +75 -0
  64. package/src/utils/momo-menu.js +54 -0
  65. package/src/commander/actor.json +0 -12
  66. package/src/commander/actors.json +0 -6
  67. package/src/commander/add.json +0 -12
  68. package/src/commander/agent.json +0 -12
  69. package/src/commander/agentcfg.json +0 -5
  70. package/src/commander/archive.json +0 -12
  71. package/src/commander/commit.json +0 -12
  72. package/src/commander/console.json +0 -7
  73. package/src/commander/lain.json +0 -7
  74. package/src/commander/list.json +0 -7
  75. package/src/commander/plan.json +0 -12
  76. package/src/commander/project.json +0 -12
  77. package/src/commander/pull.json +0 -6
  78. package/src/commander/push.json +0 -6
  79. package/src/commander/repo.json +0 -18
  80. package/src/commander/run.json +0 -18
  81. package/src/commander/show.json +0 -12
  82. package/src/commander/tasks.json +0 -18
  83. package/src/commander/unlock.json +0 -6
  84. package/src/commander/validate.json +0 -12
  85. package/src/executor/executeActor.js +0 -133
  86. package/src/executor/executeActors.js +0 -58
  87. package/src/executor/executeAdd.js +0 -307
  88. package/src/executor/executeAgent.js +0 -299
  89. package/src/executor/executeAgentCfg.js +0 -210
  90. package/src/executor/executeArchive.js +0 -124
  91. package/src/executor/executeCommit.js +0 -202
  92. package/src/executor/executeConsole.js +0 -142
  93. package/src/executor/executeList.js +0 -133
  94. package/src/executor/executePlan.js +0 -164
  95. package/src/executor/executeProject.js +0 -313
  96. package/src/executor/executePull.js +0 -127
  97. package/src/executor/executePush.js +0 -243
  98. package/src/executor/executeRepo.js +0 -238
  99. package/src/executor/executeRun.js +0 -644
  100. package/src/executor/executeShow.js +0 -164
  101. package/src/executor/executeTasks.js +0 -384
  102. package/src/executor/executeUnlock.js +0 -110
  103. package/src/executor/executeValidate.js +0 -210
@@ -0,0 +1,412 @@
1
+ ---
2
+ name: r2mo-rad-lain
3
+ description: "R2MO RAD 快速应用开发技能 - 专注于 Momo/LAIN 项目的 CLI 命令开发。支持交互式菜单、参数解析、文件操作等功能。用于快速开发终端工具、交互式界面和命令行应用。"
4
+ version: 2.0.0
5
+ category: 🟢 R2MO RAD (快速应用开发)
6
+ tags:
7
+ - r2mo
8
+ - rad
9
+ - lain
10
+ - nodejs
11
+ - cli
12
+ - momo
13
+ ---
14
+
15
+ # R2MO RAD LAIN 技能
16
+
17
+ ## 概述
18
+
19
+ 本技能用于开发 Momo/LAIN 项目的 CLI 命令。项目采用 CommonJS 规范,使用轻量级原生风格,不依赖 Commander/Yargs 等重型框架。
20
+
21
+ ## 技术栈限制与规范
22
+
23
+ ### 必须遵守
24
+
25
+ | 项目 | 要求 | 说明 |
26
+ |------|------|------|
27
+ | **模块规范** | CommonJS | 使用 `require`/`module.exports`,禁止使用 ES Module |
28
+ | **Node 版本** | >= 22.x | 项目要求的最低版本 |
29
+ | **参数解析** | 原生/Epic | 使用 `Ec.parseArgument` 或 `process.argv` |
30
+ | **日志输出** | Epic 工具 | 使用 `Ec.info`/`Ec.warn`/`Ec.error`/`Ec.waiting` |
31
+ | **颜色库** | colors | 已全局配置,使用 `.green`/`.blue` 等 |
32
+ | **用户输入** | Ec.ask | 使用项目统一的 readline 封装 |
33
+
34
+ ### 禁止使用
35
+
36
+ | 项目 | 原因 |
37
+ |------|------|
38
+ | Commander.js | 过重,与项目风格不符 |
39
+ | Yargs | 过重,与项目风格不符 |
40
+ | Inquirer.js | 与项目 readline 冲突 |
41
+ | ES Module (import/export) | 项目使用 CommonJS |
42
+ | TypeScript | 项目使用纯 JavaScript |
43
+
44
+ ### 推荐使用
45
+
46
+ | 项目 | 场景 |
47
+ |------|------|
48
+ | fs/fs.promises | 文件操作 |
49
+ | path | 路径处理 |
50
+ | os | 系统信息(如 homedir、tmpdir) |
51
+ | child_process | 外部命令执行 |
52
+ | readline | 交互式菜单(仅限本技能脚本) |
53
+
54
+ ## 工作流决策树
55
+
56
+ ### 开发新命令
57
+ 1. 阅读本文档 SKILL.md
58
+ 2. 创建命令配置 `src/commander/{command}.json`
59
+ 3. 创建执行器 `src/executor/execute{Command}.js`
60
+ 4. 在 `src/executor/index.js` 中注册
61
+
62
+ ### 需要交互式菜单
63
+ 1. **必须阅读**: [`menu-api.md`](menu-api.md) - 完整菜单 API 文档
64
+ 2. 使用 `scripts/menu.js` 模块
65
+ 3. 菜单完成后再使用 `Ec.ask` 进行确认
66
+
67
+ ### 需要文件操作
68
+ 1. **必须阅读**: [`file-utils-api.md`](file-utils-api.md) - 文件工具 API 文档
69
+ 2. 使用 `scripts/file-utils.js` 模块
70
+ 3. 使用 `scripts/yaml-parser.js` 解析 YAML
71
+
72
+ ## 项目架构
73
+
74
+ ### 目录结构
75
+ ```
76
+ src/
77
+ ├── commander/ # 命令配置文件 (JSON)
78
+ │ └── {command}.json
79
+ ├── executor/ # 命令执行器
80
+ │ ├── index.js # 执行器导出索引
81
+ │ └── execute{Command}.js
82
+ ├── epic/ # 核心工具库
83
+ │ ├── index.js # 统一导出
84
+ │ ├── momo.fn.log.js # 日志输出
85
+ │ ├── lain.fn.parse.js # 参数解析
86
+ │ └── ...
87
+ ├── _skill/ # 技能配置
88
+ │ └── repositories.json
89
+ └── momo.js # 主入口
90
+ ```
91
+
92
+ ## 命令配置格式
93
+
94
+ 在 `src/commander/` 目录下创建 JSON 配置文件:
95
+
96
+ ```json
97
+ {
98
+ "executor": "executeMyCommand",
99
+ "description": "命令描述(CV前缀表示会复制到剪切板)",
100
+ "command": "mycommand",
101
+ "options": [
102
+ {
103
+ "name": "param",
104
+ "alias": "p",
105
+ "description": "参数描述",
106
+ "type": "string",
107
+ "default": "默认值"
108
+ }
109
+ ]
110
+ }
111
+ ```
112
+
113
+ **字段说明:**
114
+ - `executor`: 对应 `src/executor/` 中的执行器函数名
115
+ - `description`: 命令描述,`(CV)` 前缀表示会复制内容到剪切板
116
+ - `command`: 命令名称
117
+ - `options`: 参数列表
118
+ - `name`: 参数全名 (--name)
119
+ - `alias`: 参数别名 (-n)
120
+ - `type`: 类型 string/number/boolean
121
+ - `default`: 默认值
122
+ - `required`: 是否必需
123
+
124
+ ## 执行器开发
125
+
126
+ ### 基础模板
127
+
128
+ 参考 `templates/executor.js.template`:
129
+
130
+ ```javascript
131
+ const fs = require('fs');
132
+ const path = require('path');
133
+ const Ec = require('../epic');
134
+ const fsAsync = require('fs').promises;
135
+
136
+ module.exports = async (options) => {
137
+ try {
138
+ // 参数解析
139
+ const parsed = Ec.parseArgument(options);
140
+ const paramValue = parsed.param || parsed.p;
141
+
142
+ // 业务逻辑
143
+ Ec.waiting('正在执行...');
144
+
145
+ // 成功退出
146
+ Ec.info('✅ 执行成功!');
147
+ process.exit(0);
148
+ } catch (error) {
149
+ Ec.error(`❌ 执行失败: ${error.message}`);
150
+ process.exit(1);
151
+ }
152
+ };
153
+ ```
154
+
155
+ ### 带交互菜单的执行器
156
+
157
+ 参考 `templates/interactive-menu.js.template`。
158
+
159
+ **关键:使用本技能提供的菜单脚本**
160
+
161
+ ```javascript
162
+ const Ec = require('../epic');
163
+ // 引用技能脚本(需要调整路径或复制到项目中)
164
+ const { selectMultiple } = require('../../skills/r2mo-rad-lain/scripts/menu');
165
+
166
+ module.exports = async (options) => {
167
+ const items = [
168
+ { name: 'item-1', description: '选项一' },
169
+ { name: 'item-2', description: '选项二' }
170
+ ];
171
+
172
+ // 1. 菜单选择(raw mode)
173
+ const result = await selectMultiple(items, '选择菜单');
174
+
175
+ if (result.items.length === 0) {
176
+ Ec.waiting('未选择任何项');
177
+ process.exit(0);
178
+ }
179
+
180
+ // 2. 确认(普通输入模式,菜单完成后才能使用)
181
+ const answer = await Ec.ask('确认?(y/N): ');
182
+ if (answer.toLowerCase() !== 'y') {
183
+ Ec.waiting('已取消');
184
+ process.exit(0);
185
+ }
186
+
187
+ // 3. 执行操作
188
+ // ...
189
+ };
190
+ ```
191
+
192
+ ## Epic 工具库 API
193
+
194
+ ### 日志输出
195
+
196
+ ```javascript
197
+ Ec.info('绿色信息'); // [Momo AI] 绿色信息
198
+ Ec.waiting('蓝色执行'); // [Momo AI] 蓝色执行
199
+ Ec.warn('黄色警告'); // [Momo AI] 黄色警告
200
+ Ec.error('红色错误'); // [Momo ER] 红色错误
201
+ ```
202
+
203
+ ### 参数解析
204
+
205
+ ```javascript
206
+ const parsed = Ec.parseArgument(options);
207
+ // 支持 --name 和 -n 两种形式
208
+ const value = parsed.name || parsed.n;
209
+ ```
210
+
211
+ **注意:** `Ec.parseArgument` 要求参数成对出现。对于可选值参数(如 `-r` 可带可不带值),需要自行解析 `process.argv`。
212
+
213
+ ### 用户输入
214
+
215
+ ```javascript
216
+ const answer = await Ec.ask('请输入: ');
217
+ // 程序退出前关闭
218
+ Ec.askClose();
219
+ ```
220
+
221
+ ### 颜色扩展
222
+
223
+ ```javascript
224
+ '文本'.green // 绿色
225
+ '文本'.blue // 蓝色
226
+ '文本'.yellow // 黄色
227
+ '文本'.red // 红色
228
+ '文本'.cyan // 青色
229
+ '文本'.gray // 灰色
230
+ '文本'.bold // 加粗
231
+ ```
232
+
233
+ ## UI 排版规范
234
+
235
+ ### 动态对齐
236
+
237
+ ```javascript
238
+ // 计算最大长度
239
+ const maxLen = Math.max(...items.map(i => i.name.length), 4);
240
+
241
+ // 使用 padEnd 对齐
242
+ items.forEach(item => {
243
+ const name = item.name.padEnd(maxLen);
244
+ console.log(` ${name} ${item.description}`);
245
+ });
246
+ ```
247
+
248
+ ### 分隔线
249
+
250
+ ```javascript
251
+ console.log('─'.repeat(50).gray);
252
+ ```
253
+
254
+ ### 视觉层级
255
+
256
+ ```javascript
257
+ console.log(''); // 空行分隔区块
258
+ Ec.info('=== 标题 ==='); // 区块标题
259
+ console.log('');
260
+ // 内容...
261
+ console.log('');
262
+ ```
263
+
264
+ ## 开发心得与避坑指南
265
+
266
+ ### readline 回显问题
267
+
268
+ **问题:** 输入显示两次
269
+
270
+ **原因:** 同时使用多个 readline 实例,或 raw mode 与普通 readline 混用
271
+
272
+ **解决:**
273
+ 1. 使用本技能提供的 `scripts/menu.js`,它正确处理了 raw mode
274
+ 2. 菜单选择和确认输入分离:菜单完成后才使用 `Ec.ask`
275
+ 3. 不要在 raw mode 中调用 `Ec.ask`
276
+
277
+ ### raw mode 管理
278
+
279
+ **问题:** 程序退出后终端异常
280
+
281
+ **原因:** 未正确退出 raw mode
282
+
283
+ **解决:**
284
+ ```javascript
285
+ // 所有退出路径都要恢复
286
+ process.stdin.setRawMode(false);
287
+ process.stdin.removeListener('keypress', onKeypress);
288
+ ```
289
+
290
+ ### 异步流程问题
291
+
292
+ **问题:** setTimeout 中的 async 函数未被等待
293
+
294
+ **原因:** Promise 未正确链接
295
+
296
+ **解决:** 使用独立的 async 函数,而不是在 Promise 回调中嵌套 async
297
+
298
+ ```javascript
299
+ // 错误
300
+ setTimeout(async () => {
301
+ const answer = await Ec.ask('?');
302
+ resolve(answer); // resolve 可能在 await 之前执行
303
+ }, 100);
304
+
305
+ // 正确:分离成两个函数
306
+ const menuResult = await selectMenu(items); // 菜单
307
+ const answer = await Ec.ask('确认?'); // 确认
308
+ ```
309
+
310
+ ### 参数解析限制
311
+
312
+ **问题:** `Ec.parseArgument` 不支持可选值参数
313
+
314
+ **解决:** 自行解析 `process.argv`
315
+
316
+ ```javascript
317
+ const parseOptionalArg = (flagName, aliasName) => {
318
+ const args = process.argv.slice(3);
319
+ let hasFlag = false;
320
+ let value = null;
321
+
322
+ for (let i = 0; i < args.length; i++) {
323
+ if (args[i] === `-${aliasName}` || args[i] === `--${flagName}`) {
324
+ hasFlag = true;
325
+ const next = args[i + 1];
326
+ if (next && !next.startsWith('-')) {
327
+ value = next;
328
+ }
329
+ break;
330
+ }
331
+ }
332
+
333
+ return { hasFlag, value };
334
+ };
335
+ ```
336
+
337
+ ### 资源清理
338
+
339
+ **问题:** 临时文件未清理
340
+
341
+ **解决:** 使用 try/finally
342
+
343
+ ```javascript
344
+ let tempDir = null;
345
+ try {
346
+ tempDir = createTempDir('task');
347
+ // 操作...
348
+ } finally {
349
+ if (tempDir) {
350
+ await cleanup(tempDir);
351
+ }
352
+ }
353
+ ```
354
+
355
+ ## 脚本引用
356
+
357
+ 本技能提供以下可复用的脚本模块:
358
+
359
+ | 脚本 | 说明 | 文档 |
360
+ |------|------|------|
361
+ | `scripts/menu.js` | 交互式菜单 | [menu-api.md](menu-api.md) |
362
+ | `scripts/file-utils.js` | 文件操作工具 | [file-utils-api.md](file-utils-api.md) |
363
+ | `scripts/yaml-parser.js` | YAML 解析器 | [file-utils-api.md](file-utils-api.md) |
364
+
365
+ **使用方式:**
366
+
367
+ 1. **复制到项目中使用**(推荐)
368
+ ```bash
369
+ cp -r skills/r2mo-rad-lain/scripts src/_scripts
370
+ ```
371
+
372
+ 2. **直接引用**(开发阶段)
373
+ ```javascript
374
+ const { selectMultiple } = require('../../skills/r2mo-rad-lain/scripts/menu');
375
+ ```
376
+
377
+ ## 注册执行器
378
+
379
+ 在 `src/executor/index.js` 中添加:
380
+
381
+ ```javascript
382
+ const executeMyCommand = require('./executeMyCommand');
383
+
384
+ const exported = {
385
+ // ... 其他执行器
386
+ executeMyCommand
387
+ };
388
+ module.exports = exported;
389
+ ```
390
+
391
+ ## 测试命令
392
+
393
+ ```bash
394
+ # 运行命令
395
+ node src/momo.js mycommand
396
+
397
+ # 带参数
398
+ node src/momo.js mycommand -p value
399
+
400
+ # 查看帮助
401
+ node src/momo.js help -c mycommand
402
+ ```
403
+
404
+ ## 依赖说明
405
+
406
+ 本技能使用的依赖(项目已包含):
407
+
408
+ - **colors**: 终端颜色支持
409
+ - **co**: 生成器函数执行
410
+ - **commander**: 命令行框架(仅用于底层,执行器不直接使用)
411
+ - **underscore**: 工具函数
412
+ - **immutable**: 不可变数据结构
@@ -0,0 +1,154 @@
1
+ /**
2
+ * 参数解析示例
3
+ * 演示如何处理复杂的命令行参数
4
+ */
5
+
6
+ // ============================================================
7
+ // 使用 Ec.parseArgument(标准方式)
8
+ // ============================================================
9
+
10
+ /**
11
+ * 标准参数解析
12
+ * 适用于 key-value 成对参数
13
+ *
14
+ * 命令示例:momo cmd -n value --name value
15
+ */
16
+ const standardParsing = (options) => {
17
+ const Ec = require('../epic');
18
+ const parsed = Ec.parseArgument(options);
19
+
20
+ // 支持 --name 和 -n 两种形式
21
+ const name = parsed.name || parsed.n;
22
+ const type = parsed.type || parsed.t;
23
+
24
+ return { name, type };
25
+ };
26
+
27
+ // ============================================================
28
+ // 自定义参数解析(支持可选值)
29
+ // ============================================================
30
+
31
+ /**
32
+ * 解析可选值参数
33
+ * 适用于参数值可以省略的情况
34
+ *
35
+ * 命令示例:
36
+ * momo cmd -r -> hasFlag: true, value: null
37
+ * momo cmd -r value -> hasFlag: true, value: 'value'
38
+ * momo cmd -> hasFlag: false, value: null
39
+ */
40
+ const parseOptionalArg = (flagName, aliasName) => {
41
+ const args = process.argv.slice(3);
42
+ let hasFlag = false;
43
+ let value = null;
44
+
45
+ for (let i = 0; i < args.length; i++) {
46
+ const arg = args[i];
47
+ if (arg === `-${aliasName}` || arg === `--${flagName}`) {
48
+ hasFlag = true;
49
+ // 检查下一个参数是否是值(不以 - 开头)
50
+ const nextArg = args[i + 1];
51
+ if (nextArg && !nextArg.startsWith('-')) {
52
+ value = nextArg;
53
+ }
54
+ break;
55
+ }
56
+ }
57
+
58
+ return { hasFlag, value };
59
+ };
60
+
61
+ // ============================================================
62
+ // 布尔标志解析
63
+ // ============================================================
64
+
65
+ /**
66
+ * 解析布尔标志
67
+ *
68
+ * 命令示例:
69
+ * momo cmd --verbose -> true
70
+ * momo cmd -v -> true
71
+ * momo cmd -> false
72
+ */
73
+ const parseBooleanFlag = (flagName, aliasName) => {
74
+ const args = process.argv.slice(3);
75
+ return args.includes(`--${flagName}`) || args.includes(`-${aliasName}`);
76
+ };
77
+
78
+ // ============================================================
79
+ // 位置参数解析
80
+ // ============================================================
81
+
82
+ /**
83
+ * 解析位置参数
84
+ *
85
+ * 命令示例:
86
+ * momo cmd arg1 arg2 -> ['arg1', 'arg2']
87
+ */
88
+ const parsePositionalArgs = () => {
89
+ const args = process.argv.slice(3);
90
+ const positional = [];
91
+
92
+ let i = 0;
93
+ while (i < args.length) {
94
+ const arg = args[i];
95
+ if (arg.startsWith('-')) {
96
+ // 跳过 flag 和它的值
97
+ i += 2;
98
+ } else {
99
+ positional.push(arg);
100
+ i++;
101
+ }
102
+ }
103
+
104
+ return positional;
105
+ };
106
+
107
+ // ============================================================
108
+ // 完整示例
109
+ // ============================================================
110
+
111
+ /**
112
+ * 综合参数解析示例
113
+ *
114
+ * 命令格式:momo mycommand [target] -n name -r [repo] --verbose
115
+ */
116
+ const parseAllArgs = (options) => {
117
+ // 1. 标准参数
118
+ const Ec = require('../epic');
119
+ let parsed = {};
120
+ try {
121
+ parsed = Ec.parseArgument(options);
122
+ } catch (e) {
123
+ // 忽略缺少值的错误,手动处理
124
+ }
125
+
126
+ // 2. 可选值参数
127
+ const remote = parseOptionalArg('remote', 'r');
128
+
129
+ // 3. 布尔标志
130
+ const verbose = parseBooleanFlag('verbose', 'v');
131
+
132
+ // 4. 位置参数
133
+ const positional = parsePositionalArgs();
134
+ const target = positional[0] || '.';
135
+
136
+ return {
137
+ name: parsed.name || parsed.n,
138
+ remote: remote,
139
+ verbose: verbose,
140
+ target: target
141
+ };
142
+ };
143
+
144
+ // ============================================================
145
+ // 导出
146
+ // ============================================================
147
+
148
+ module.exports = {
149
+ standardParsing,
150
+ parseOptionalArg,
151
+ parseBooleanFlag,
152
+ parsePositionalArgs,
153
+ parseAllArgs
154
+ };