- 你是否喜欢 Cursor AI 代码编辑器 的 AI 功能,同时又偏爱在 Emacs 中工作?
- Aider 是一个知名且高效的终端 AI 结对编程工具。
- aider.el 为 Emacs 提供了一个简洁的 aider 用户界面,旨在最大限度地简化用户在 Emacs 环境中操作 aider 的流程。
- 本仓库中的大部分 Elisp 代码都是由 Aider 或 aider.el 生成的。
- aider.el 旨在成为我们可以日常使用的稳定生产力工具。我会在代码合并前仔细测试此库中的功能。
- 弹出菜单 (
aider-transient-menu
)
- 针对 Git 仓库的专属 Aider 会话管理
- 将代码上下文(例如缓冲区、光标下的内容或选区)与 aider 整合,实现半自动提示构建,并借助 helm 轻松搜索和重用历史提示
- 为 AI 辅助编程工作流提供专用菜单项,并支持 TDD 循环,从而降低 AI 生成代码可能带来的错误风险
- 当前实现通过 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 格式),并且它便于多行提示。最近,为该文件添加了语法高亮、补全和代码片段,现在它是编写和组织提示的好地方。
- 更侧重于利用代码(缓冲区/选区)构建提示。
- 更容易重用提示,并通过 helm 进行模糊搜索。
- 使用特定于仓库的 Aider 提示文件来组织项目
- 更侧重于代码质量工具(代码审查、TDD + AI)。
- 社区提示的代码片段。
- Emacs 需要 >= 26.1
- 安装 aider
- 使用您的包管理器安装 Emacs 依赖库 Transient、Magit 和 Markdown-mode。
- 使用以下代码安装 aider.el:
使用 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+ 内置)
(package-vc-install '(aider :url "https://github.com/tninja/aider.el"))
配置部分与上面的 straight 相同
在 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/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 菜单*,因为我经常使用临时菜单,所以它得到了更好的维护。
- 任何想为 doom 菜单做贡献的人,欢迎帮助改进。谢谢。
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-run-aider
- 创建基于 comint 的、*特定于 git 仓库的 Aider 会话*,用于交互式对话。
- Git 仓库识别基于当前文件的路径
- 可以同时为不同的 Git 仓库运行多个 Aider 会话
- 当使用通用参数(~C-u~)调用时,将提示用户更改此会话的
aider-args
内容。
- aider-switch-to-buffer
- 切换到 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 命令补全、文件路径补全支持
- 使用
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 的提示可能共享类似的结构。可以使用 Yasnippet 来帮助重用这些提示。
- Aider 提示文件现在支持 yasnippet。当前片段来自 这个 reddit 帖子、另一个 reddit 帖子 和一个 git 仓库。
- 您可以使用
M-x yas-describe-tables
查看可用的片段M-x yas-insert-snippet
插入片段。M-x yas-expand
展开光标下的片段。
- 欢迎在 片段文件夹 中添加更多片段/改进现有片段!
- / 键触发 aider 命令补全
- 文件路径补全会在某些命令后自动触发
- 使用 TAB 键从迷你缓冲区输入提示,或使用带补全的 helm
- 感谢 LLM 的贡献。虽然利用 AI 生成大量代码非常便捷,但仅仅依赖生成代码不足以确保项目的正确性。
- 这些代码中可能潜藏错误,因此必须验证其功能是否符合预期,以及代码改动是否会破坏现有功能。
- 同时,开发人员可能对 AI 生成代码理解不足,过多难懂的代码可能增加维护风险。
- *单元测试在解决上述问题时十分关键*,而 aider 也能辅助生成测试代码。
- 尽管 AI 生成的测试代码可能需要人工检查或修正,但相对来说,这些测试代码往往更容易理解。
- 执行单元测试不仅有助于验证代码正确性和发现问题,还能帮助开发人员更好地理解 AI 生成代码的运行原理,从而增强对新代码的信心。
TDD 风格的 AI 编程工作流
- **实施或修改代码**:
- 针对已有代码:将光标置于函数内部,或选中代码区域后使用
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
确认更改。 - 针对已有代码:将光标置于函数内部,或选中代码区域后使用
- **生成测试**:通过
aider-write-unit-test
验证您的实现。运行测试以验证代码行为。aider-write-unit-test
可以在代码实现之前用于编写单元测试,只需在单元测试类中调用该函数。我用它测试过力扣问题,效果很好。
- **完善代码和测试**:根据需要使用其他提示或手动调整进一步重构。~aider-refactor-book-method~ 提供了 Martin Flower 的重构书籍 中的几种重构技术。
- 返回步骤 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 编码约定。在我的情况下,我在 CONVENTIONS.md 文件中添加了 “- reply in Chinese”,并通过 .aider.conf.yml 加载工作。或者,将类似以下内容放入 aider-args 变量中。
- 如何在 aider 会话缓冲区中输入多行提示?
- aider 本身支持这一点,文档。
- 使用 aider 提示文件(~aider-open-prompt-file~,~C-c a p~)编写多行提示(我们不希望它们消失,对吧?特别是如果它不完美需要修改,而且我们可能想在以后的某个时候重用它)。
- aider.el 能与 tramp 一起工作吗?(aider 在远程机器上运行)
- 更多上下文敏感的代码更改/代码阅读命令 [1/1]
- [X] 当前的 aider-ask-question 需要改进,因为可能有很多不同的问题要问
- [ ] 思考如何改进函数的候选列表
- [ ] 如何将候选列表功能移植到 aider-plain-read-string
- 更多关于如何简化菜单/命令的思考
- 更多关于改进代码质量工具(如单元测试)的思考
- 标记发布版本,使其在 melpa stable 上可用
- 更好的单元测试/集成测试。希望是自动化的。
- 受启发与致谢:
- 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 客户端