(Part3)用 AI IDE 实现 VSCode 插件系列:SlashCommand 让技术写作如丝般顺滑

28 阅读4分钟

Mintlify 是一个现代化的技术写作产品,支持使用 MDX 写文档,界面简洁易用,针对需要写公开文档的技术工作非常友好。作为一名全栈工程师和 Mintlify 的深度用户,我在日常技术写作过程中发现了许多降低写作效率的细节问题。

技术写作者应该把重心放在内容架构和核心价值传达上,而不是把时间花费在细枝末节的检查校对上。受到 Notion、飞书等现代 WYSIWYG 编辑器的启发,我决定将这种流畅的写作体验引入到 VSCode 中,让 Mintlify 文档写作回归本质:专注于思考如何进行内容架构,引导读者了解文档内容的核心价值。

今天要介绍的 SlashCommand 功能,正是这一理念的完美体现。通过 CompletionItemProvider 实现的智能斜杠命令系统,让技术写作变得如丝般顺滑。

演示和下载

功能点详解

用户痛点分析

在传统的 Markdown/MDX 写作过程中,技术写作者经常面临以下痛点:

  1. 组件插入繁琐:需要手动输入完整的 Mintlify 组件标签,容易出错
  2. 语法记忆负担:各种组件的属性和语法需要反复查阅文档
  3. 写作流程中断:频繁切换到文档查看组件用法,打断思路
  4. 代码块配置复杂:不同语言的代码块需要配置各种参数

设计思路

SlashCommand 功能的设计灵感来源于现代 WYSIWYG 编辑器:

  • Notion 的斜杠命令系统:输入 / 即可快速插入各种内容块
  • 飞书文档 的智能提示:根据上下文提供相关的内容建议
  • 现代编辑器 的分类组织:将功能按类别清晰组织,便于查找

核心设计原则:

  1. 零记忆负担:所有组件和语法都通过智能提示提供
  2. 分类清晰:按功能类型组织命令,快速定位
  3. 即插即用:选择即插入,支持 Snippet 占位符
  4. 上下文感知:根据当前编辑环境智能过滤命令

架构图解

整体架构图

graph TB
    A[用户输入 '/'] --> B[SlashCommandCompletionItemProvider]
    B --> C[上下文检查]
    C --> D{是否在有效位置?}
    D -->|否| E[不提供补全]
    D -->|是| F[生成补全项列表]
    F --> G[AI Commands]
    F --> H[Basic Commands]
    F --> I[Mintlify Components]
    F --> J[Code Blocks]
    G --> K[显示分类补全列表]
    H --> K
    I --> K
    J --> K
    K --> L[用户选择]
    L --> M{命令类型?}
    M -->|Snippet| N[插入代码片段]
    M -->|Command| O[执行VSCode命令]

工作流程图

sequenceDiagram
    participant U as 用户
    participant E as VSCode编辑器
    participant P as SlashCommandProvider
    participant C as 补全系统
    
    U->>E: 输入 '/'
    E->>P: 触发 provideCompletionItems
    P->>P: 检查当前行前缀
    P->>P: 验证上下文环境
    alt 在引号或括号内
        P->>C: 返回空列表
    else 有效位置
        P->>P: 创建分类补全项
        P->>P: 设置排序和过滤
        P->>C: 返回补全列表
        C->>E: 显示智能提示
        E->>U: 展示分类命令列表
        U->>E: 选择命令
        alt Snippet类型
            E->>E: 插入代码片段
        else Command类型
            E->>E: 执行VSCode命令
        end
    end

命令分类结构图

graph LR
    A[SlashCommand] --> B[AI Commands]
    A --> C[Basic Commands]
    A --> D[Mintlify Components]
    A --> E[Code Blocks]
    
    B --> B1[✨ Write with AI]
    
    C --> C1[📊 Insert Table]
    C --> C2[📈 Current Date]
    C --> C3[⏰ Current DateTime]
    
    D --> D1[🧩 Note]
    D --> D2[🧩 Tip]
    D --> D3[🧩 Warning]
    D --> D4[🧩 Info]
    D --> D5[📋 Accordion]
    D --> D6[📑 Tabs]
    
    E --> E1[💻 Basic Code Block]
    E --> E2[💻 Code with Title]
    E --> E3[💻 Code with Focus]
    E --> E4[💻 Code with Line Numbers]

代码实现

核心 CompletionItemProvider 实现

class SlashCommandCompletionItemProvider implements vscode.CompletionItemProvider {
    provideCompletionItems(
        document: vscode.TextDocument, 
        position: vscode.Position, 
        token: vscode.CancellationToken,
        context: vscode.CompletionContext
    ): Thenable<vscode.CompletionItem[]> {
        
        const line = document.lineAt(position.line);
        const prefix = line.text.substring(0, position.character);
        
        // 只在行首或空白字符后触发斜杠命令
        if (!prefix.trim().endsWith('/')) {
            return Promise.resolve([]);
        }

        // 上下文环境检查:避免在引号或括号内触发
        const inParentheses = this.isInParentheses(prefix);
        const inQuotes = this.isInQuotes(prefix);
        
        if (inParentheses || inQuotes) {
            return Promise.resolve([]);
        }

        // 生成分类补全项
        const completionItems = this.createCategorizedCompletions();
        return Promise.resolve(completionItems);
    }
}

分类补全项创建

private createCategorizedCompletions(): vscode.CompletionItem[] {
    const completionItems: vscode.CompletionItem[] = [];
    
    // 定义各类命令
    const aiCommands = [{
        label: '✨ Write with AI',
        detail: 'AI-powered writing assistant',
        description: 'Generate content with artificial intelligence',
        command: 'flashMintlify.writeWithAI',
        insertText: ''
    }];
    
    const componentCommands = [{
        label: '🧩 Note',
        detail: 'Insert note callout',
        description: 'Note callout component',
        insertText: '<Note>\n${1:This adds a note in the content}\n</Note>',
        kind: vscode.CompletionItemKind.Snippet
    }];
    
    // 创建分类函数
    const createCategoryItems = (commands: any[], categoryPrefix: string, categoryName: string) => {
        const items: vscode.CompletionItem[] = [];
        
        // 添加分类标题(分隔符效果)
        const separator = new vscode.CompletionItem(
            `────────── ${categoryName} ──────────`,
            vscode.CompletionItemKind.Text
        );
        separator.sortText = `${categoryPrefix}000`;
        items.push(separator);
        
        // 添加命令项
        commands.forEach((cmd, index) => {
            const item = new vscode.CompletionItem(
                cmd.label, 
                cmd.kind || vscode.CompletionItemKind.Function
            );
            
            // 设置详细信息
            item.detail = cmd.detail;
            item.documentation = new vscode.MarkdownString(cmd.description);
            
            // 处理不同类型的命令
            if (cmd.command) {
                // 执行命令类型
                item.insertText = '';
                item.command = {
                    command: cmd.command,
                    title: cmd.label
                };
            } else {
                // 插入文本类型
                if (cmd.insertText.includes('$')) {
                    item.insertText = new vscode.SnippetString(cmd.insertText);
                } else {
                    item.insertText = cmd.insertText;
                }
            }
            
            // 设置排序和删除触发字符
            item.sortText = `${categoryPrefix}${String(index + 1).padStart(3, '0')}`;
            item.additionalTextEdits = [
                vscode.TextEdit.delete(new vscode.Range(
                    position.line, position.character - 1,
                    position.line, position.character
                ))
            ];
            
            items.push(item);
        });
        
        return items;
    };
    
    // 创建各分类的补全项
    const aiItems = createCategoryItems(aiCommands, '1', 'AI');
    const componentItems = createCategoryItems(componentCommands, '3', 'Mintlify Components');
    
    completionItems.push(...aiItems, ...componentItems);
    return completionItems;
}

注册 CompletionItemProvider

function createCompletionProviders() {
    // 注册斜杠命令提供器
    const slashCommandProvider = vscode.languages.registerCompletionItemProvider(
        [{ language: 'mdx', scheme: 'file' }, { language: 'markdown', scheme: 'file' }],
        new SlashCommandCompletionItemProvider(),
        '/'  // 触发字符
    );
    
    return [slashCommandProvider];
}

export function activate(context: vscode.ExtensionContext) {
    context.subscriptions.push(
        ...createCompletionProviders()
    );
}

关键实现要点

  1. 触发字符设置:使用 '/' 作为触发字符,当用户输入斜杠时自动触发补全
  2. 上下文检查:通过检查前缀内容,避免在不合适的位置(如引号内)触发补全
  3. 分类组织:使用分隔符和排序前缀实现清晰的分类显示
  4. 双重模式:支持 Snippet 插入和 Command 执行两种模式
  5. 用户体验:自动删除触发的斜杠字符,提供无缝的插入体验

简单总结

SlashCommand 功能成功将现代 WYSIWYG 编辑器的流畅体验引入到 VSCode 的技术写作环境中。通过 CompletionItemProvider 的巧妙实现,我们实现了:

  1. 零学习成本:熟悉 Notion 的用户可以无缝上手
  2. 高效写作:大幅减少组件插入的时间和出错率
  3. 分类清晰:智能分类让功能查找更加便捷
  4. 扩展性强:可以轻松添加新的命令类型和功能

这个功能对技术写作效率的提升是显著的,让写作者能够专注于内容本身,而不是被技术细节所困扰。在 AI IDE 如 Cursor 的加持下,整个开发过程变得更加高效,从需求分析到代码实现,AI 助手提供了强有力的支持。

后续可以改进的方向包括:

  • 增加更多 Mintlify 组件的支持
  • 实现基于上下文的智能推荐
  • 添加自定义命令配置功能
  • 集成 AI 写作助手的实际功能

通过这样的功能创新,FlashMintlify 插件正在成为技术写作者的得力助手,让 Mintlify 文档写作变得更加高效和愉悦。

我的个人网站:www.fastcar.fun/