Skip to content

Latest commit

 

History

History
315 lines (226 loc) · 18.6 KB

README.zh-cn.org

File metadata and controls

315 lines (226 loc) · 18.6 KB

aider.el:在 Emacs 中使用 aider 进行 AI 结对编程

English Version

目录

介绍

  • 你是否喜欢 Cursor AI 代码编辑器 的 AI 功能,同时又偏爱在 Emacs 中工作?
  • Aider 是一个知名且高效的终端 AI 结对编程工具。
  • aider.el 为 Emacs 提供了一个简洁的 aider 用户界面,旨在最大限度地简化用户在 Emacs 环境中操作 aider 的流程。
    • 本仓库中的大部分 Elisp 代码都是由 Aider 或 aider.el 生成的。
    • aider.el 旨在成为我们可以日常使用的稳定生产力工具。我会在代码合并前仔细测试此库中的功能。

优点:友好的用户界面、出色的上下文感知能力以及强大的 AI 结对编程支持

  • 弹出菜单 (aider-transient-menu)

./transient_menu.png

  • 针对 Git 仓库的专属 Aider 会话管理
  • 将代码上下文(例如缓冲区、光标下的内容或选区)与 aider 整合,实现半自动提示构建,并借助 helm 轻松搜索和重用历史提示
  • 为 AI 辅助编程工作流提供专用菜单项,并支持 TDD 循环,从而降低 AI 生成代码可能带来的错误风险

缺点:基于 comint 的 aider 会话功能尚不够丰富

  • 当前实现通过 comint 托管 aider 会话,这种经典的 CLI 交互方式虽然稳定,但最初并未包含代码块颜色渲染、文件跟踪等高级功能。
    • *现已采用 markdown-mode.el 的语法高亮,大大改善了这一局限*。
    • 缺乏文件跟踪功能,导致 aider.el 无法执行 AI 注释。*为解决此问题,我们提供了 aider-implement-todo 命令,该命令默认在光标所在处就地实现注释中的需求*。
  • 实际上,直接通过 comint 终端进行大量交互并非最佳选择。建议采用以下方式生成并发送提示,以减少上下文切换并降低手动输入量:
    • 在代码缓冲区中使用相关的代码更改命令或提问命令;
    • 或者通过 Aider 提示文件(调用命令 aider-open-prompt-file 或 ~C-c a p~)来组织和管理提示。这是 Emacs 中与 comint 缓冲区通信的传统方式(就像 ESS、python-mode、scala-mode 等)。它便于重新访问您使用过的命令,组织和管理需要更多提示的大型代码更改,并将它们分解为子任务(因为它是 org 格式),并且它便于多行提示。最近,为该文件添加了语法高亮、补全和代码片段,现在它是编写和组织提示的好地方。

相比aidermacs, aider.el的特点

  • 更侧重于利用代码(缓冲区/选区)构建提示。
  • 更容易重用提示,并通过 helm 进行模糊搜索。
  • 使用特定于仓库的 Aider 提示文件来组织项目
  • 更侧重于代码质量工具(代码审查、TDD + AI)。
  • 社区提示的代码片段。

安装

  • Emacs 需要 >= 26.1

原生 Emacs 安装

使用 Straight

如果您已安装 Straight

(use-package aider
  :straight (:host github :repo "tninja/aider.el" :files ("aider.el" "aider-core.el" "aider-file.el" "aider-code-change.el" "aider-discussion.el" "aider-prompt-mode.el"))
  :config
  ;; 对于最新的 claude sonnet 模型
  (setq aider-args '("--model" "sonnet"))
  (setenv "ANTHROPIC_API_KEY" anthropic-api-key)
  ;; 或 chatgpt 模型
  ;; (setq aider-args '("--model" "o3-mini"))
  ;; (setenv "OPENAI_API_KEY" <your-openai-api-key>)
  ;; 或使用您的个人配置文件
  ;; (setq aider-args `("--config" ,(expand-file-name "~/.aider.conf.yml")))
  ;; ;;
  ;; 可选:为临时菜单设置键绑定
  (global-set-key (kbd "C-c a") 'aider-transient-menu))
  • *aider-args 直接传递给 aider CLI*,aider 选项参考
  • 如果 aider-args 为空(默认),它将使用 ~/.aider.conf.yml 文件。这样,aider CLI 和 aider.el 共享相同的配置

使用 package-vc-install(Emacs 30+ 内置)

  • 通过在 Emacs 中运行以下代码安装 aider.el
    • 您需要手动安装所需的包,如 TransientMagit 和 helm。
(package-vc-install '(aider :url "https://github.com/tninja/aider.el"))

配置部分与上面的 straight 相同

With Melpa + package-install

在 init.el 或 .emacs 文件中的 (require ‘package) 之后和 package-initialize 调用之前,通过向 package-archives 添加条目来启用从 MELPA 安装包:

(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
;; 如果需要,可以注释/取消注释此行以启用 MELPA Stable。请参阅 `package-archive-priorities`
;; 和 `package-pinned-packages`。大多数用户不需要或不想这样做。
;;(add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t)
(package-initialize)
  • 使用 M-x package-refresh-contents 或 M-x package-list-packages 确保 Emacs 已获取 MELPA 包列表
  • 使用 M-x package-install 安装 aider 包

Doom 安装和配置

  • 将以下代码添加到您的 doom/packages.el
(package! aider :recipe (:host github :repo "tninja/aider.el" :files ("aider.el" "aider-core.el" "aider-file.el" "aider-code-change.el" "aider-discussion.el" "aider-prompt-mode.el" "aider-doom.el")))
  • 调整并将以下代码添加到您的 doom/config.el
(use-package aider
  :config
  (setq aider-args '("--model" "sonnet")))

aider 前缀是 ~A~。

  • 启动并打开 aider 缓冲区:=[SPC] A o=
  • 使用 [SPC] A a c 添加当前文件
  • 使用 [SPC] A r 重置 aider 会话

./doom_menus.png

  • *然而,更推荐使用临时菜单而不是 doom 菜单*,因为我经常使用临时菜单,所以它得到了更好的维护。
    • 任何想为 doom 菜单做贡献的人,欢迎帮助改进。谢谢。

可选功能

Helm 支持

Helm 为命令历史提示启用模糊搜索功能。由于我们很可能会使用之前写过的提示,这可能会节省大量输入时间。*如果您可以接受 helm,强烈推荐这个插件*。

如果您通过 melpa 和 package-install 安装了 aider.el,只需要 (require 'aider-helm)

否则,安装 helm 库后,您可以通过运行以下代码获得基于 helm 的补全:

(use-package aider
  :straight (:host github :repo "tninja/aider.el" :files ("aider.el" "aider-core.el" "aider-file.el" "aider-code-change.el" "aider-discussion.el" "aider-prompt-mode.el" "aider-doom.el" "aider-helm.el")))

最常用功能(已集成到aider菜单中)

Aider 会话管理

aider-run-aider
创建基于 comint 的、*特定于 git 仓库的 Aider 会话*,用于交互式对话。
  • Git 仓库识别基于当前文件的路径
  • 可以同时为不同的 Git 仓库运行多个 Aider 会话
  • 当使用通用参数(~C-u~)调用时,将提示用户更改此会话的 aider-args 内容。
aider-switch-to-buffer
切换到 Aider 缓冲区。
  • 在菜单中使用 ^ 可以在当前框架内的其他窗口中切换打开 aider 会话,或为 aider 会话打开专用框架。当有多个显示器时,这很有用,一个框架/显示器用于保存代码的多个缓冲区,另一个框架/显示器保存 aider 会话。

更多向 Aider 缓冲区添加文件的方法

aider-add-current-file-or-dired-marked-files
添加当前缓冲区文件。如果在 dired 缓冲区中使用,添加所有 dired 标记的文件。
  • C-u 前缀以只读方式添加文件。
aider-add-files-in-current-window
添加当前窗口中的所有缓冲区。

编写代码

aider-function-or-region-refactor
如果选择了区域,要求 Aider 重构所选区域。否则,要求 Aider 更改/重构光标下的函数。
aider-implement-todo
在当前上下文中实现注释中的需求。
  • 如果光标在注释行上,就地实现该特定注释。
  • 如果有多行注释的选择区域,就地为这些注释实现代码。
  • 如果光标在函数内,为该函数实现 TODO。
  • 否则为整个当前文件实现 TODO。

支持敏捷开发

aider-write-unit-test
如果当前缓冲区是主源代码文件,为当前函数或文件生成全面的单元测试。如果光标在测试源代码文件中,当光标在测试函数上时,实现该测试函数。否则,提供描述来实现测试函数(或规范)。
  • 如果主源代码出现问题且测试函数失败,可以在失败的测试函数上使用 aider-function-or-region-refactor 要求 Aider 修复代码以使测试通过。
aider-refactor-book-method
使用 Martin Flower 的重构书籍 中的技术进行代码重构

代码问题

aider-ask-question
向 Aider 询问当前上下文中的代码问题。如果选择了区域,使用该区域作为上下文。
  • 您可以询问关于代码的任何问题。例如,解释函数、审查代码并找出错误等
  • 使用 aider-helm.el 时提供了几个常用的提示
aider-go-ahead
当您使用上述命令要求 aider 建议更改时,甚至在几轮讨论之后,当您对解决方案满意时,可以使用此命令要求 Aider 继续实施更改。

Aider 提示文件

  • 语法高亮、aider 命令补全、文件路径补全支持
  • 使用 C-c a p 打开当前仓库专用的提示文件。您可以使用此文件组织任务,并撰写提示并将其发送到 Aider 会话。支持多行提示。
  • 喜欢从编辑器缓冲区向 comint 缓冲区发送代码的人(例如 ESS、python-mode、scala-mode)可能会喜欢这个。这是一种交互式且可重现的方式。
  • C-c C-n 快捷键可用于将当前提示行发送至 comint 缓冲区。或者批量逐行发送所选区域。根据我的经验,这是 aider 提示文件中最常用的方法。
  • C-c C-c 快捷键用于多行提示。以下示例显示了当光标在提示上时按下 C-c C-c 键的情况。

./aider_prompt_file.png

  • aider 的提示可能共享类似的结构。可以使用 Yasnippet 来帮助重用这些提示。
  • Aider 提示文件现在支持 yasnippet。当前片段来自 这个 reddit 帖子另一个 reddit 帖子 和一个 git 仓库
  • 您可以使用
    • M-x yas-describe-tables 查看可用的片段
    • M-x yas-insert-snippet 插入片段。
    • M-x yas-expand 展开光标下的片段。
  • 欢迎在 片段文件夹 中添加更多片段/改进现有片段!

在 comint 缓冲区内

  • / 键触发 aider 命令补全
  • 文件路径补全会在某些命令后自动触发
  • 使用 TAB 键从迷你缓冲区输入提示,或使用带补全的 helm

注意AI生成的代码

  • 感谢 LLM 的贡献。虽然利用 AI 生成大量代码非常便捷,但仅仅依赖生成代码不足以确保项目的正确性。
    • 这些代码中可能潜藏错误,因此必须验证其功能是否符合预期,以及代码改动是否会破坏现有功能。
    • 同时,开发人员可能对 AI 生成代码理解不足,过多难懂的代码可能增加维护风险。
  • *单元测试在解决上述问题时十分关键*,而 aider 也能辅助生成测试代码。
    • 尽管 AI 生成的测试代码可能需要人工检查或修正,但相对来说,这些测试代码往往更容易理解。
    • 执行单元测试不仅有助于验证代码正确性和发现问题,还能帮助开发人员更好地理解 AI 生成代码的运行原理,从而增强对新代码的信心。

TDD 风格的 AI 编程工作流

  1. **实施或修改代码**:
    • 针对已有代码:将光标置于函数内部,或选中代码区域后使用 aider-function-or-region-refactor 命令;
    • 针对新代码:请在 TODO 注释行上直接使用 aider-implement-todo 命令。

    *添加新代码的示例*:

    光标在此注释上:

    # TODO: Implement a function that checks if a number is prime
        

    运行 aider-implement-todo 可能会生成:

    def is_prime(n):
        if n <= 1:
            return False
        for i in range(2, int(n ** 0.5) + 1):
            if n % i == 0:
                return False
        return True
        

    如果建议不令人满意,使用 Ask Question 进行改进,并使用 Go Ahead 确认更改。

  2. **生成测试**:通过 aider-write-unit-test 验证您的实现。运行测试以验证代码行为。
    • aider-write-unit-test 可以在代码实现之前用于编写单元测试,只需在单元测试类中调用该函数。我用它测试过力扣问题,效果很好。
  3. **完善代码和测试**:根据需要使用其他提示或手动调整进一步重构。~aider-refactor-book-method~ 提供了 Martin Flower 的重构书籍 中的几种重构技术。
  4. 返回步骤 1

常见问题

  • 如何审查/接受代码更改?
    • 与 cursor 相比,aider 有不同的方式来处理代码更改。讨论
    • 注意:*Aider v0.77.0 自动接受 /architect 命令的更改。如果您想像以前那样在接受更改之前审查代码更改(适用于 aider.el 中的许多命令),可以在 aider-args 或 .aider.conf.yml 中使用 “–no-auto-accept-architect” 禁用该标志*。
  • 如何禁用 aider 的自动提交功能?
    • 在 aider-args 中添加 –no-auto-commits。aider-args 直接传递给 aider CLI。aider 选项参考
  • aider 支持哪些类型的模型?是否支持本地部署的模型?
  • 如何让 aider 用中文回复?
    • 使用 aider 编码约定。在我的情况下,我在 CONVENTIONS.md 文件中添加了 “- reply in Chinese”,并通过 .aider.conf.yml 加载工作。或者,将类似以下内容放入 aider-args 变量中。
      • “–read” (expand-file-name “~/.emacs.d/.emacs/aider/CONVENTIONS.md”)
  • 如何在 aider 会话缓冲区中输入多行提示?
    • aider 本身支持这一点,文档
    • 使用 aider 提示文件(~aider-open-prompt-file~,~C-c a p~)编写多行提示(我们不希望它们消失,对吧?特别是如果它不完美需要修改,而且我们可能想在以后的某个时候重用它)。
  • aider.el 能与 tramp 一起工作吗?(aider 在远程机器上运行)
    • artyom-smushkov 使 aider-add-current-file 支持 tramp 文件:#36
    • mgcyung 说它可以这样工作:#85

未来工作

功能

  • 更多上下文敏感的代码更改/代码阅读命令 [1/1]
    • [X] 当前的 aider-ask-question 需要改进,因为可能有很多不同的问题要问
    • [ ] 思考如何改进函数的候选列表
    • [ ] 如何将候选列表功能移植到 aider-plain-read-string
  • 更多关于如何简化菜单/命令的思考
  • 更多关于改进代码质量工具(如单元测试)的思考
  • 标记发布版本,使其在 melpa stable 上可用

代码质量

  • 更好的单元测试/集成测试。希望是自动化的。

其他 Emacs AI 编码工具

  • 受启发与致谢:
    • ancilla.el:AI 编码助手支持代码生成/代码重写/讨论
    • chatgpt-shell:ChatGPT 和 DALL-E Emacs shells + Org Babel,基于 comint 会话的想法
    • copilot.el:GitHub Copilot 的 Emacs 插件
    • copilot-chat.el:在 Emacs 中与 GitHub Copilot 聊天
    • gptel:Emacs 中最受欢迎/广泛使用的 LLM 客户端