返回

CLI-Anything 教程 9:实战案例 - 为开源软件生成 CLI(完整演示)

CLI-Anything 完整实战案例:演示如何为一个实际的开源软件(以 Draw.io 为例)生成完整的 CLI 工具,涵盖所有 7 个阶段。

教程概述

系列目录:CLI-Anything 教程系列索引

本教程是一个完整实战案例,演示如何为 Draw.io 生成 CLI 工具,涵盖 CLI-Anything 的全部 7 个阶段

目标软件:Draw.io

Draw.io 简介

Draw.io(现称 diagrams.net)是一个免费的开源图表绘制工具,支持:

  • 流程图、UML 图、网络图
  • 多种导出格式(PNG、SVG、PDF)
  • 离线桌面应用和在线版本

为什么选择 Draw.io?

  • ✅ 代码开源,易于分析
  • ✅ 有 Electron 桌面版本
  • ✅ API 相对简单
  • ✅ 实用价值高

实战演示:7 阶段完整流程

Phase 1: Analyze(分析)

目标:分析 Draw.io 源码,识别可 CLI 化的功能。

# 1. 克隆 Draw.io 源码
git clone https://github.com/jgraph/drawio.git
cd drawio

# 2. 启动 CLI-Anything 分析
/cli-anything ./drawio

分析输出

# API 映射文档 - Draw.io

## 软件概述
- 名称: Draw.io / diagrams.net
- 版本: 24.x
- 技术栈: Electron, HTML5 Canvas, JavaScript

## 核心功能模块

### 1. 文件操作
- 新建图表
- 打开文件 (.drawio, .xml)
- 保存文件
- 导入 (PNG, SVG, Lucidchart)
- 导出 (PNG, SVG, PDF, HTML)

### 2. 图表操作
- 添加形状
- 连接形状
- 添加文本
- 样式设置
- 图层管理

### 3. 页面管理
- 新建页面
- 删除页面
- 重命名页面
- 页面排序

## CLI 化机会

| 功能 | API/方法 | CLI 命令建议 |
|-----|---------|-------------|
| 新建图表 | app.createFile() | diagram new |
| 打开文件 | app.loadFile() | diagram open |
| 保存文件 | app.saveFile() | diagram save |
| 导出 PNG | app.exportPng() | export png |
| 添加形状 | editor.addShape() | shape add |
| 连接形状 | editor.addConnector() | connector add |

## API 覆盖率评估
- 文件操作: 95%
- 图表操作: 85%
- 页面管理: 90%
- 样式设置: 70%
- **总计: 85%**

Phase 2: Design(设计)

目标:设计 CLI 命令组和状态模型。

# 架构设计文档 - Draw.io CLI

## CLI 概览
- CLI 名称: cli-anything-drawio
- 版本: 1.0.0

## 命令组结构

cli-anything-drawio ├── diagram # 图表管理 │ ├── new │ ├── open │ ├── save │ ├── close │ └── info ├── page # 页面管理 │ ├── new │ ├── delete │ ├── rename │ └── list ├── shape # 形状操作 │ ├── add │ ├── delete │ ├── move │ └── style ├── connector # 连接线 │ ├── add │ ├── delete │ └── style └── export # 导出 ├── png ├── svg ├── pdf └── html


## 状态模型

```python
class DrawioState:
    project_id: str
    diagram_path: Optional[str]
    pages: List[PageState]
    active_page_id: str
    shapes: Dict[str, ShapeState]
    connectors: List[ConnectorState]
    modified: bool

输出格式

  • 人类可读: 表格和 emoji
  • JSON: 结构化数据

### Phase 3: Implement(实现)

**目标**:实现 CLI 代码。

**生成的代码结构**:

drawio/agent-harness/ ├── cli_anything/ │ ├── drawio/ │ │ ├── init.py │ │ ├── cli.py # 主 CLI │ │ ├── repl.py # REPL │ │ ├── state.py # 状态管理 │ │ ├── core/ │ │ │ ├── diagram.py │ │ │ ├── page.py │ │ │ ├── shape.py │ │ │ └── export.py │ │ └── utils/ │ │ └── backend.py # Draw.io 后端封装 │ └── tests/ ├── setup.py ├── README.md └── SKILL.md


**核心代码示例**:

```python
# cli_anything/drawio/core/diagram.py

import click
from ..state import DrawioState
from ..utils.backend import DrawioBackend

@click.group(name='diagram')
def diagram_group():
    """Diagram management commands."""
    pass

@diagram_group.command(name='new')
@click.option('--name', '-n', required=True)
@click.option('--template', '-t', default='blank')
@click.pass_context
def diagram_new(ctx, name, template):
    """Create a new diagram."""
    state = DrawioState(name=name, template=template)

    # 使用后端创建实际文件
    backend = DrawioBackend()
    diagram_file = backend.create_diagram(name, template)

    state.diagram_path = diagram_file
    state.save(f"{name}.json")

    click.echo(f"✓ Created diagram: {name}")
    click.echo(f"  Template: {template}")


@diagram_group.command(name='export')
@click.argument('output')
@click.option('--format', '-f', default='png',
              type=click.Choice(['png', 'svg', 'pdf']))
@click.option('--page', '-p', help='Page to export')
@click.pass_context
def diagram_export(ctx, output, format, page):
    """Export diagram to various formats."""
    state = ctx.obj['project_state']

    backend = DrawioBackend()
    result = backend.export(
        state.diagram_path,
        output,
        format=format,
        page=page
    )

    if result.success:
        click.echo(f"✓ Exported to {output}")
        click.echo(f"  Format: {format}")
        click.echo(f"  Size: {result.file_size} bytes")
    else:
        click.echo(f"✗ Export failed: {result.error}", err=True)

Phase 4: Plan Tests(测试计划)

TEST.md 内容

# 测试计划 - Draw.io CLI

## 单元测试

### diagram 模块
- [ ] diagram new - 正常创建
- [ ] diagram new - 参数验证
- [ ] diagram open - 打开现有文件
- [ ] diagram save - 保存修改
- [ ] diagram export - PNG 导出
- [ ] diagram export - 格式选择

### page 模块
- [ ] page new - 新建页面
- [ ] page delete - 删除页面
- [ ] page rename - 重命名

### shape 模块
- [ ] shape add - 添加形状
- [ ] shape delete - 删除形状
- [ ] shape move - 移动位置

## E2E 测试

### 场景 1: 创建-编辑-导出流程
1. 创建图表
2. 添加形状
3. 连接形状
4. 导出 PNG
5. 验证输出文件

### 场景 2: 多页面处理
1. 创建图表
2. 添加多个页面
3. 在每个页面添加内容
4. 批量导出所有页面

Phase 5: Write Tests(编写测试)

测试代码

# tests/unit/test_diagram.py

import pytest
from click.testing import CliRunner
from cli_anything.drawio.cli import cli

class TestDiagramCommands:
    def test_diagram_new(self, runner, temp_dir):
        result = runner.invoke(cli, [
            '--json',
            'diagram', 'new',
            '--name', 'TestDiagram'
        ])

        assert result.exit_code == 0
        output = json.loads(result.output)
        assert output['success'] is True

    def test_diagram_export_png(self, runner, temp_dir):
        # 创建测试图表
        diagram_path = temp_dir / 'test.drawio'
        create_test_diagram(diagram_path)

        output_path = temp_dir / 'output.png'

        result = runner.invoke(cli, [
            '--json',
            'diagram', 'export', str(output_path),
            '--format', 'png'
        ])

        assert result.exit_code == 0
        assert output_path.exists()

Phase 6: Document(文档)

SKILL.md 示例

# Skill Definition: cli-anything-drawio

## Overview
**CLI Name**: cli-anything-drawio
**Target Software**: Draw.io / diagrams.net
**Purpose**: Create and edit diagrams programmatically

## Capabilities

### diagram - Diagram Management
- `diagram new` - Create new diagram
- `diagram open` - Open existing diagram
- `diagram export` - Export to PNG/SVG/PDF

### shape - Shape Operations
- `shape add` - Add shape to diagram
- `shape connect` - Connect shapes

## Usage Examples

### Create Flowchart
```bash
cli-anything-drawio diagram new --name Flowchart
cli-anything-drawio shape add --type process --text "Start"
cli-anything-drawio shape add --type decision --text "Check?"
cli-anything-drawio connector add --from 1 --to 2
cli-anything-drawio export png flowchart.png

### Phase 7: Publish(发布)

```bash
# 本地测试
pip install -e .

# 运行测试
pytest

# 构建发布
python -m build

# 上传到 PyPI
twine upload dist/*

使用生成的 CLI

命令行模式

# 创建新图表
cli-anything-drawio diagram new --name "MyFlowchart" --template flowchart

# 添加形状
cli-anything-drawio shape add --type "process" --text "Initialize" --x 100 --y 100
cli-anything-drawio shape add --type "decision" --text "Valid?" --x 100 --y 200

# 连接形状
cli-anything-drawio connector add --from-shape "shape_001" --to-shape "shape_002"

# 导出
cli-anything-drawio export png flowchart.png --border 10

REPL 模式

$ cli-anything-drawio
╔══════════════════════════════════════════╗
║       cli-anything-drawio v1.0.0        ║
║     Draw.io CLI for AI Agents           ║
╚══════════════════════════════════════════╝

drawio> diagram new --name ProjectFlow
✓ Created diagram: ProjectFlow

drawio[ProjectFlow]> page new --name "Phase 1"
✓ Created page: Phase 1

drawio[ProjectFlow/Phase 1]> shape add --type rect --text "Requirements"
✓ Added shape: rect at (100, 100)

drawio[ProjectFlow/Phase 1]> export svg diagram.svg
✓ Exported: diagram.svg (15 KB)

drawio[ProjectFlow/Phase 1]> exit

迭代优化

# 发现缺少图层功能
/cli-anything:refine ./drawio "add layer management commands"

# 优化导出功能
/cli-anything:refine ./drawio "support batch export of all pages"

小结

本实战案例演示了完整的 CLI 生成流程:

  1. Analyze - 分析 Draw.io 源码,识别功能点
  2. Design - 设计命令组和状态模型
  3. Implement - 实现 Click CLI 和 REPL
  4. Plan Tests - 制定测试计划
  5. Write Tests - 编写 pytest 测试
  6. Document - 生成 SKILL.md 文档
  7. Publish - 发布到 PyPI

系列导航