用Cursor自动生成完整函数教程

27 阅读4分钟

在日常开发中,我们经常遇到需要快速实现某个功能但又不愿重复造轮子的情况。最近我发现了一个高效的方法:使用Cursor编辑器配合其强大的AI功能,可以自动生成完整的、可直接使用的函数代码。下面我将通过一个实际案例,分享整个操作流程。

从实际问题出发

假设我们需要开发一个Markdown文档解析工具,其中有一个需求:提取文档中所有图片链接,并返回包含文件名和URL的对象数组

传统做法是:打开搜索引擎,查找正则表达式,调试边界情况……但今天我们用不同的方式。

在Cursor中的实际操作

步骤1:明确描述需求

我在Cursor中新建了一个JavaScript文件,然后直接以注释的形式描述需求:

// 需求:编写一个函数,从markdown文本中提取所有图片链接
// 输入:markdown字符串
// 输出:数组,每个元素包含 filename 和 url
// 图片格式为 ![](url) 或 ![alt](url)
// 需要处理相对路径和绝对路径

步骤2:生成初始代码

将光标放在注释下方,按下 Cmd+K(Mac)或 Ctrl+K(Windows),Cursor会弹出AI对话框。我直接输入:

“请实现这个函数,要求处理标准markdown图片语法,并考虑各种边界情况。”

生成的第一个版本如下:

function extractImageLinks(markdown) {
const regex = /![(.*?)]((.*?))/g;
const matches = [];
let match;

while ((match = regex.exec(markdown)) !== null) {
    const altText = match[1];
    const url = match[2];
    // 从URL中提取文件名
    const filename = url.substring(url.lastIndexOf('/') + 1) || `image_${matches.length + 1}`;
    
    matches.push({
      filename: filename,
      url: url,
      alt: altText || ''
    });
  }

return matches;
}

步骤3:迭代优化

第一版代码基本可用,但我发现几个问题:

  1. 文件名提取太简单,可能包含查询参数
  2. 没有处理baseURL
  3. 没有去重

我继续与Cursor对话:

“优化这个函数:1. 清理文件名中的查询参数和哈希 2. 添加baseURL参数处理相对路径 3. 对结果去重”

Cursor给出了改进版本:

function extractImageLinks(markdown, baseURL = '') {
const regex = /![(.*?)]((.*?))/g;
const linkMap = newMap();
let match;

while ((match = regex.exec(markdown)) !== null) {
    let url = match[2].trim();
    
    // 处理相对路径
    if (baseURL && !url.startsWith('http') && !url.startsWith('//')) {
      const base = baseURL.endsWith('/') ? baseURL : baseURL + '/';
      const relative = url.startsWith('/') ? url.slice(1) : url;
      url = base + relative;
    }
    
    // 提取干净的文件名
    const cleanUrl = url.split('?')[0].split('#')[0];
    let filename = cleanUrl.substring(cleanUrl.lastIndexOf('/') + 1);
    
    // 如果没有文件名,生成一个
    if (!filename || filename.includes('.')) {
      filename = filename || `image_${linkMap.size + 1}`;
    } else {
      filename += '.jpg'; // 默认扩展名
    }
    
    const key = cleanUrl.toLowerCase();
    if (!linkMap.has(key)) {
      linkMap.set(key, {
        filename: filename,
        url: url,
        cleanUrl: cleanUrl,
        alt: match[1].trim() || ''
      });
    }
  }

returnArray.from(linkMap.values());
}

步骤4:添加测试用例

为了确保函数可靠性,我让Cursor生成测试用例:

“为这个函数编写测试用例,覆盖:正常图片、带alt文本、相对路径、重复图片、空输入等情况”

// 测试用例
const testMarkdown = `
# 测试文档

![图片1](https://example.com/image1.jpg)
![图片2](/relative/path/image2.png)
![图片1](https://example.com/image1.jpg) <!-- 重复 -->
![带alt文本](https://example.com/image3.jpg?width=800#section)
`;

const results = extractImageLinks(testMarkdown, 'https://example.com');
console.assert(results.length === 3, '应该去重');
console.assert(results[0].filename === 'image1.jpg', '文件名提取正确');
console.assert(results[1].url === 'https://example.com/relative/path/image2.png', '相对路径转换正确');

处理复杂需求

当我需要更复杂的功能时,比如支持嵌套在代码块中的图片、处理HTML格式的img标签,我可以更具体地描述:

“扩展函数功能:1. 忽略代码块内的图片 2. 支持HTML img标签 3. 添加文件类型过滤”

Cursor生成了包含完整错误处理和配置选项的生产级代码:

function extractImageLinksAdvanced(markdown, options = {}) {
const {
    baseURL = '',
    ignoreCodeBlocks = true,
    includeHTML = true,
    allowedTypes = ['.jpg', '.jpeg', '.png', '.gif', '.webp']
  } = options;

// 移除代码块(如果启用)
let processedText = markdown;
if (ignoreCodeBlocks) {
    processedText = processedText.replace(/```[\s\S]*?```/g, '');
    processedText = processedText.replace(/`[^`]*`/g, '');
  }

const results = [];
const urlSet = newSet();

// 处理markdown图片
const mdRegex = /![(.*?)]((.*?))/g;
let mdMatch;

while ((mdMatch = mdRegex.exec(processedText)) !== null) {
    processImage(mdMatch[2], mdMatch[1]);
  }

// 处理HTML图片(如果启用)
if (includeHTML) {
    const htmlRegex = /<img[^>]+src="([^"]+)"[^>]*alt="([^"]*)"[^>]*>/gi;
    let htmlMatch;
    
    while ((htmlMatch = htmlRegex.exec(processedText)) !== null) {
      processImage(htmlMatch[1], htmlMatch[2]);
    }
  }

function processImage(rawUrl, altText) {
    // ... 详细的处理逻辑
    // (此处省略具体实现,Cursor生成了约50行代码)
  }

// 类型过滤
return results.filter(img => {
    const ext = img.filename.toLowerCase().substring(img.filename.lastIndexOf('.'));
    return allowedTypes.includes(ext);
  });
}

总结

经过多次实践,我总结出以下使用Cursor生成函数的经验:

  1. 分步描述需求:先描述核心功能,再逐步添加细节要求
  2. 指定输入输出:明确说明参数类型和返回值格式
  3. 要求错误处理:主动要求添加边界情况处理和错误捕获
  4. 生成测试用例:让AI编写测试,确保代码可靠性
  5. 代码风格一致:指定与你项目一致的编码风格(如ES6+、TypeScript等)

推荐阅读

软件测试/测试开发丨常见面试题与流程篇(附答案)

软件测试/测试开发丨学习笔记之Allure2测试报告

软件测试/测试开发丨Pytest测试用例生命周期管理-Fixture

软件测试/测试开发丨Python学习笔记之基本数据类型与操作

软件测试/测试开发丨学习笔记之列表、元组、集合

软件测试/测试开发丨Python常用数据结构-学习笔记

软件测试/测试开发丨Python控制流-判断&循环

软件测试/测试开发丨Python学习笔记之内置库科学计算、日期与时间处理

软件测试/测试开发丨面试题之软素质与反问面试官篇(附答案)

软件测试/测试开发丨iOS 自动化测试踩坑(一): 技术方案、环境配置与落地实践