抛砖引玉: 介绍命令行AI编程工具aider以及emacs集成aider.el

确实没有加/drop 命令. 它好像可以带文件名, 或者不带文件名. 如果需要经常带文件名. 加个菜单项可以省去粘贴文件名的时间, 今晚我去改一改

我自己一般是完成一个task以后, reset以后加其他文件开始新的工作 reset会清除所有文件和聊天记录

平时没怎么用列出已经加的文件, 因为每次使用ask, code, architect之类, output的最后都已经会列出已经加的文件列表

现在的菜单项有些冗余, 关于add / drop文件, 以及reset / clear这方面, 我再想想如何精简

原来如此,reset 也可以,本身删除的需求确实没那么高。

菜单或许可以做成像 magit 一样的? 按照功能分组,有二级的菜单,不过可能降低了一些便捷性。

1 个赞

是的, 有道理. 最常用的功能比如add保留在顶层, 减少按键次数; 不常用的功能放到二级菜单或者类似的其他办法

顶层菜单太复杂对user experience也不好 我现在更喜欢做减法大于加法 aider提供的各种命令 启动参数已经非常多甚至有些复杂了

除add文件之外,能否有add一个函数,add一段代码这样的功能。 add 弹出类似magit一样的界面,选文件。或者函数 然后添加到会话中 然后ask。。。。

据我所知, aider CLI本身并不直接带有这样的考虑, 得自己拷贝粘贴过去, 像去问chatgpt问题一样.

aider.el的一个基本考虑是希望结合emacs lisp的编程能力把buffer里用户关心的context作为prompt的一部分发给aider, 减轻用户操作的负担. 有好几个命令都是考虑 当前函数, 或者选中代码的, 比如

  1. 询问问题: aider-ask-question: 在当前上下文中向Aider询问有关代码的问题。如果选择了一个区域,使用区域作为上下文。如果没有选定区域, 光标在某个函数里, 那么它会问关于那个函数的问题

  2. 修改代码 aider-function-or-region-refactor:如果选择了一个区域,辅助重构或者修改所选区域。否则,重构或者修改光标下所在函数

  3. 多行注释的in-place新代码生成 aider-implement-todo: 如果有多行注释的选择区域,要求在那个位置实现这些注释中描述需求的代码

  4. 单元测试相关功能

这些功能我自己都在用, 好使的. 它们也都在菜单里

这只是我有限的经验总结的想法 请大家多多提意见 谢谢

为了实现发送多行代码块到aider session的效果, 我的选择是在代码块前后加上{aider … aider} tag. 不然的话aider会把它们当成多行命令, 一行一行逐一执行. 这个实现比较安全, 目前还没翻车. 不过, 可能和有些同学交流的时候, 没太说清楚, 让他误会了.

你描述的很清楚,我没有误会。我理解你的想法,但不理解你的实现具体“安全”在哪里,更不理解我们之前的PR具体“不安全”在哪里。

但没关系,我们想法不同,你继续你的Aider.el,我继续我的Aidermacs。Aidermacs 在昨天和今天两天时间已经加入了非常多的新功能:

  1. vterm和comint双选择
  1. aidermacs--current-output 彻底打通Emacs与aider输入输出通道
  2. M-x aidermacs-list-added-files 添加文件 和 M-x aidermacs-drop-file 移除文件
  1. 重新整理 transient 菜单,引入了二级菜单,强烈提升用户体验

详情可以看:GitHub - MatthewZMD/aidermacs: AI Pair Programming in Emacs

同学, 我好心劝一句, 如果是上班拿工资的人, 白天该上班好好上班. 现在这个经济形势下, 大家好好把饭碗捧牢是正事. 当然这不是我该管的事情. 之前沟通上有些摩擦, 你现在也还生气, 我也有一定责任. 那个时候我这也该睡觉啦. 第二天还要上班呢.

感谢提醒,最近在休假,不用担心我的工作,况且这几个功能虽然花些时间,又没有什么难的,写写还挺有意思。

我就是不想直接拒绝而已 公开吵架 太难看 有些code我不想merge 同意了以后 不管我自己熟悉不熟悉 将来就要维护它 我只是量力而行

当然 只是我个人的判断 对于这样古老的编辑器 如果有 品行好 有才华的年轻人 愿意贡献自己的时间帮助做emacs 相关的事情 对于这个community 而言 也是好事情 因为之前很多人都担心现在年轻人不再使用emacs

1 个赞

这又回到这一整个月包括昨天和今天都重复不下几十遍的事了,你觉得不够stable却又拿不出合理理由,什么都是你觉得,都是你的判断……这当然可以,毕竟是你的项目。但开源软件的协作和你公司里的传统工作模式可能会有些区别,你可能不够了解社区模式,也不够了解elisp。

总之我们的分歧在我Fork之后就没有任何意义了,这个话题到此为止,之后我不会再回复关于之前PR/我们分歧方面的任何内容。一切交给用户自己去判断吧。

当然,关于Aider和Aider.el或Aidermacs的功能,欢迎一起聊,毕竟Emacs社区没几个人集成Aider了。


另外,如果你的Aider.el要是实现了什么新功能,欢迎来我的帖子宣传,好的功能大家一起用才是好事。

3 个赞

那基本就是我想的功能。

比如我针对一个函数问了一个问题或让aider重构修改。它会不会自己去找函数相关的函数?这个需要aider.el来告诉它,还是它自己作?

希望这些功能对你有用。就是因为有和你类似的需求,意外的发现aider可以识别代码文件里的语法单元比如函数,正好elisp可以识别光标下的语法单元,才这么做的。

如果是想解释代码,并且依赖的函数也在这个文件里,或者在已经加的其他文件里,我几个月前试过,可以用ask让它recursive的解释函数,比如,please recursively explain xx function。甚至还可以让它画dependency ascii chart. 具体效果好坏好像也看用哪个模型。现在想来模型已经更聪明了吧。

aider.el没有针对递归解释代码的要求做一个函数。虽然尝试这件事的时候很兴奋,实际上我并没有用很多次,因此也不值得占一个宝贵的菜单项。不过,如果你愿意用helm的话,可以尝试也加载aider-helm.el。它的作用是把以前用过的prompt存下来,按照使用频率排序。所以如果第一次你输入这样的要求prompt, 下次helm的模糊匹配就会起作用,敲很少的字就能找到以前用过的这个prompt。这也有点接近菜单项了

复杂的重构修改,我觉得要小心, 不要高估AI的智商。prompt越具体越好。尽量多提供有用的信息给aider,和非常具体要做什么事情的指示。即便如此,也要小心检查产生的结果,所以这个功能我用的/architect. 它会提供change供用户审核,同意了再make change,代价是多花一点token也就是钱。recursive修改的话,最好说清楚目的,和具体要改哪些函数,怎么改。当然,更安全一点的是,逐步让它做小的修改,并且经常运行单元测试。

好的。非常感谢。

# Aider Prompt File - Command Reference:
# C-c C-n: Send current line or selected region line by line
# C-c C-r: Send current block or selected region as a whole
# C-c C-z: Switch to aider buffer

可以分享一些用例,解释怎么用 Aider Prompt File 吗?

C-c C-n 是发送当前行,或者把 region 的内容发送过去。

C-c C-r 是发送 block,在 org mode 里,一个 block 对应的似乎就是一个段落。

它也可以发送 region,和 line by line 不同的是它会把内容包裹在 {aider} 中。

感觉两个功能很相近,想知道,一般什么时候会用 line-by-line 什么时候会用 block ?

如果都差不多是不是可以合并?感觉绑定在 C-c C-c 更好理解,因为 org mode 中执行 src block ,magit 中提交 commit 都是这个绑定键,比较容易按也容易记忆。

另外,选择 region 再发送感觉有点麻烦,如果可以直接把 heading 下的内容直接发送感觉更方便,这样我就可以用 heading 来描述我的动作,在它下面写相关指令和上下文。

感觉会更容易组织 prompt 记录。

不过自己选择 region 就相对更灵活和精确一些吧,需要什么自己选就是了。

完全同意 能完成工作 需要记忆的命令函数越少越好

C-c C-n是发送单行 在没有选中区域的时候 按这个按键有点像单步调试 这样也比较小心

这个功能可以选择区域执行 有时候某个具体task里涉及到多个文件需要add或者readonly 在prompt文件里就形成了好几行 对应好几个prompt 第二天过来继续工作的时候 选中这几条prompt C-c C-n 会一条条line by line发过去 这个不是multi-line prompt 发过去的时候 也不会在头尾加tag

C-c C-r是发送multi-line single prompt 没有选区域的时候 它会根据光标位置寻找周围的连续code block发过去 block就是连续的行 之间没有空行 用这个命令是认为光标下的多行只是一个prompt 因此前后会加tag 这个功能我在用rss写R的时候 或者scala-mode写spark的时候很省事 不需要选择区域的

在选择了区域以后 它就发选择区域过去 前后也会加tag

我本来希望第二个功能bind to C-c C-c 和ess一样 但是or mode已经占用了 所以就改用了C-c C-r 如果有办法改 我也想改成C-c C-c

如果不需要line by line 多prompt发送 这两个确实可以合成一个的

这个讨论也说明上面截图里面注释里的描述没有讲清楚

你说的有道理 我再想想怎么样再简单一点

是不是可以借鉴一下 embark 的思路,它会识别当前指针下面是什么,执行对应的操作。

获许可以在 aider-minor-mode 下稍微调整一下 C-c C-c 的逻辑,基于 pointer 的位置:

  1. 如果是单行或者段落,执行 block 的逻辑,发送一个 block 过去,只有一行的 block 就和 line by line 没区别。

  2. 如果是在 heading 上,则可以发送 heading 里的内容,整体发送过去

  3. 如果是 region,则发送 region

他们都可以用 {aider} 包裹,反正包了也不影响。

这样一个按键就能实现很多事情了,容易操作,也容易记忆。

确实有这样的场景需求。

考虑光标下是不是个aider prompt block再决定是否call 这个函数 还是org mode 已经有的功能 可能可行 这样就还能继续用C-c C-c了 我可以去看看怎么弄

多行prompt 包在aider tag里好像不按多个prompt处理 回头我可以再核实一下

现在单行的用第二个函数 和第一个 效果应该一样的 就是多了个tag block

我没明白你说的heading是什么意思 是org的标题么? 能麻烦举个例子吗

对,就是 heading 就是说的标题。

例如你的多行场景,可以放在 heading 下,直接执行 heading 完成,类似 line-by-line,省去了选择 region 的动作。

我觉得也不用强求都在一个命令里,对于 line by line 多行这种场景,可以保留一个快捷键去完成?

然后剩下的大部分都能用 C-c C-c 完成,这样就挺方便的。

确实不是两个都经常用 不过 我自己用的感觉是 大部分情况下单行prompt 够用了 很少需要用到复杂的多行prompt

不过有时候copy paste例子什么的进prompt 作为context帮助大模型理解 需要multiline prompt

Aider prompt org file现在仅仅是加了上面两个eval函数 具体怎么用好 可能还得再想想 虽然是prompt文件 但是里面也可能有prompt以外的内容 比如说描述如何解决某个task或者子task的思考 或者描述prompt做得怎么样 下一步怎么改进 这样回头看的时候 有具体的文字描述 这些内容不属于prompt 也不需要发给aider

另外单独给add文件开个标题 觉得标题有点太细了 我现在还是更习惯用标题描述具体任务