Aidermacs:Emacs 里的 AI 代码助手,真正适配 Emacs 的 Aider 体验

Aidermacs:Emacs 里的 AI 代码助手,真正适配 Emacs 的 Aider 体验

Aidermacs 是什么?

Aidermacs 是一个 Emacs 内的 AI 编程助手,它基于 Aider,可以帮助开发者进行代码编写、重构、修复和优化,类似于 Cursor 编辑器的 AI 体验。

Aidermacs 目前是 aider.el 的一个 fork ,但它不仅仅是一个简单的 aider CLI 封装,而是一个 真正适配 Emacs 工作流的 AI 编程工具

为什么要 Fork aider.el?

1. aider 是一个基于终端的工具,它的多行输入体验很受限制

Aider 本身是一个 命令行工具,它在终端环境下运行,因此 多行输入 存在一些限制:

• 终端无法像 GUI 编辑器一样 自由处理多行文本,所以 aider 需要用户手动使用 {aider … aider} 语法来标记多行输入。

• 这种方式对于 Emacs 用户来说并不直观,因为在 Emacs 里,我们应该像输入普通文本一样和 AI 交互,而不是被终端的局限性所约束。

• aidermacs 通过 完全支持 Emacs 的多行编辑方式,让用户可以像在普通 Emacs 缓冲区中输入代码一样,与 AI 进行交互。

2. aidermacs 提供更好的语法高亮和代码可读性

• aider.el 直接输出 aider 生成的文本,但 没有针对 AI 生成的代码进行格式优化,导致代码可读性较差。

• aidermacs 自动检测代码块,并为其 添加语法高亮,确保 AI 生成的代码更容易阅读和理解。

总而言之,aidermacs 不局限于 CLI 交互方式 ,而是更接近 Emacs 生态中的 智能补全、代码助手、自动修复 体验。欢迎大家一起参与,让Aider和Emacs有机结合!

11 个赞

引用一下我在另一个帖子提到的多行输入的问题的回复。多行输入本身就是终端常用 protocol 的一部分,有标准的解决方案。不需要自己造轮子。

我之前的一些言论确实过重了,我再次向你道歉。

我希望你能好好考虑一下这个功能,这个真的是一个终端 app 的标准,大部分的终端 app 都支持这个 (bash,ipython 等等都支持,不过macOS的bash版本太老了不行),实现这个就可以实现大部分终端 app 的多行输入了。

没问题!感谢你的建议,我会采纳的!

Aidermacs支持vterm啦!

你只需要:

  1. git pull 获取最新代码
  2. init.el里把aider 重命名为 aidermacs
  3. 然后设置(setq aidermacs-backend 'vterm)

欢迎大家尝试并提供反馈

1 个赞

研究了一会儿,没找到comint-mode加control sequence的方式,貌似不可以?结果把vterm解决了,如果你知道欢迎提供PR!

写了一个用 ipython 的 comint 的 demo 来实现 bracketed paste


(setq bracketed-paste-start-pattern (format "%s[200~" (kbd "ESC")))
(setq bracketed-paste-end-pattern (format "%s[201~\r" (kbd "ESC")))

(defun --comint-send-string (buffer text)
  (with-current-buffer buffer
    (let ((process (get-buffer-process buffer))
          (inhibit-read-only t))
      (goto-char (process-mark process))
      ;; Insert text with proper face properties
      (insert text)
      ;; Update process mark and send text
      (set-marker (process-mark process) (point))
      (message (format "%s%s%s" bracketed-paste-start-pattern text bracketed-paste-end-pattern))
      (comint-send-string process (format "%s%s%s" bracketed-paste-start-pattern text bracketed-paste-end-pattern)))))

(comint-run "ipython")
(--comint-send-string-syntax-highlight "*ipython*" "def hello():\n\n\n\n    print('hello')\n")
(--comint-send-string-syntax-highlight "*ipython*" "hello()")


你可以看到 def hello():\n\n\n\n print('hello')\n 这一整坨是作为一个整体发送给终端的,在 ipython 里也显示为一个单独的 cell

但是我对 comint 实在不熟,所以一些 buffer 显示上的效果实在是不会控制。但是从 send-string 实现上来说就是 append 两个 string 的一件事情。

Screenshot 2025-02-12 at 02.20.05

我懂了,这解决的还是整段multiline发送给aider的问题,但没有解决在comint-mode内换行的功能。其实你和我们的想法是一致的:都希望通过Emacs的方式让整段multiline可以一次性发给aider,你通过标准的control sequence,我们通过5行代码

我们的方法还同时解决了在comint-mode回车的问题,绑定comint-accumulateS-RET直接换行,最后回车统一发给aider。但是Aider.el作者多次强调要保持和Aider上游的一致性(这里这里这里),Aider上游用极其麻烦 counterintuitive 的workaround解决CLI没办法像comint-accumulate那般轻易换行的问题: {aider ... aider} 那Aider.el也必须这么用,同时拒绝合并我们这种简易的方法,拒绝用comint-accumulate在comint-mode换行,逼着大家跟着他适应aider上游奇葩的{aider ... aider} workaround,明明Emacs可以用更简单的方式做的更好,这才是我最不能理解的地方。

不理解,尊重,我还是fork吧……

2 个赞

明白了。

aider 其实还内置了一个很简便的换行方式,就是换行的时候不要输入 Enter,而是输入 M-enter。因此其实就是只需要 call comint-send-string 的时候把除了最后一个 \n 之外的 \n 全部换成 \e\r 就行了。但是我不用 comint 所以不知道 comint-mode 里能 type 输入 \e\r 吗?我猜需要 workaround 没有简单直接的办法?

comint-mode真的很简单,绑定comint-accumulate就已经完事了,不需要做什么骚操作哈哈

你说的这个,可能可以运用到 vterm 里面,我有空看看

1 个赞

我觉得aider最大的问题在于不经过你确认就把代码改了,代码有问题很可能还得回退。

而如果把aider每次修改后commit这个功能关闭,回退都不一定方便(没试过,不很确定aider有没有支持)。而每次aider修改后就commit,在有些公司不一定被允许。

就像reddit里有个人评论的一样,我个人更希望看到一个更好的aider。

加载和保存 session 可以用 /save /load

第一种情况就是不 auto commit (aider —no-auto-commits) 自己 manage commit 的状态。

第二种情况就是 auto commit,然后自己去 ammend drop,squash,revert,rebase。相当于把 git 的 commit history 当作编辑器的 undo-redo tree 来使用。

不管怎样就是要更频繁的使用 git。感觉最好的方式是每次用 aider 就开一个新分支。分支里 commit 随便怎么搞,改完了合并到主分支的时候使用 squash merge。

感觉 agent 自动改代码应该也是为了 agentic 的 workflow 连贯完整实现起来方便,要不然 ai 代码改到一半了被你拒绝了,那后续的 workflow 没走完流程该怎么走? cursor composer 也采用了自动改代码的思路。

我在考虑把这个做成一个defcustom来提升visibility

我刚刚推送了一个更新, aidermacs--current-output 让Emacs可以实时记录aider最后的输出。

目前的实现有点hack,如果大家知道如何调整,欢迎提PR。

彻底打通Emacs与aider输入输出的通道后,可以玩太多有趣的东西了,欢迎一起玩!

1 个赞

Aidermacs 两日更新:

  1. vterm和comint双选择
  1. aidermacs--current-output 彻底打通Emacs与aider输入输出通道
  2. M-x aidermacs-list-added-files 添加文件 和 M-x aidermacs-drop-file 移除文件
  1. 重新整理 transient 菜单(暂时没加入二级菜单)
  1. (setq aidermacs-auto-commits nil) 可以关闭 自动 commit

  2. M-x aidermacs-run-in-current-dir 可以将 Aidermacs 从你当前dir启动,自带--subtree-only

感谢 @milanglacier@zsxh 两位大佬的PR!!

最新版已经重新refactor transient菜单,加入了二级菜单了。

1 个赞

aidermacs可以通过emacs的方式 (setq aidermacs-auto-commits nil) 关闭Autocommit,省得你自己加arg


由于Aider 的auto-commit实在过于烦人,Aidermacs已经默认关闭auto-commit,如果有人喜欢,可以手动打开 (setq aidermacs-auto-commits t)

Aidermacs预想: In the long run I want to eliminate the need for a terminal at all, interaction should be streamlined from Emacs to Aider directly, having any terminal, whether comint or vterm or EAT, is a compromise because aider is CLI.

有精力的同学可以一起来实现一下。

发现你把fork之后昨晚我merge的PR Refactor: remove aider--infix-add-file-read-only, add aider-drop-current-file, and fix dup short key in menu by tninja · Pull Request #88 · tninja/aider.el · GitHub 相关的change 加你的code里了。这是我第一次做开源工作,经验有限;不知道在不通知别人, 也不注明从哪里来的的情况下就这么做是否礼貌。我以前在学校的时候,写论文,引用别人的工作,也要加参考文献的。

是的,这是你第一次做开源工作,欢迎了解一下开源是什么:开源协议是什么?都有什么区别?_哔哩哔哩_bilibili

这是你的Aider.el开源协议的原文,如果看不懂,可以问问ChatGPT:GitHub - tninja/aider.el: aider emacs plugin for https://github.com/paul-gauthier/aider

最后回应一下你的accusation:

我已经在所有场合所有文件都有注明并再三强调Aidermacs来源自Aider.el,,每一页.el文件都有注明你的名字,我想我应该不需要把

Aidermacs fork 自 Aider.el

这几个大字写在脸上吧?应该吧?

虽然我理解你的注意力,理解能力和阅读能力都有问题,但你信口开河的能力也太让人叹为观止了。