分享一个Emacs酷炫操作:交换两个s-expression子表达式

在编辑 Lisp 代码的时候,有时需要对两个子表达式进行交换。

注:尽管这样的场景不多见,一旦出现还挺烦人的(因为剪切会导致一个空白,完了之后还要手动调整)。

我在网上查了下,发现 Emacs 已经内置了这个功能 transpose-sexps

然而,这个功能的描述挺费解的,使用起来也不方便。

今天经过多次实验后,终于明白了它的用法,重新封装了两个更加直观的接口:

;;----------------------------------------------------------------------------
;; Drag S-Expression
;;----------------------------------------------------------------------------
(defun drag-prev-sexp-forward ()
  (interactive)
  (call-interactively 'transpose-sexps))

(defun drag-prev-sexp-backward ()
  (interactive)
  (let ((current-prefix-arg '(-1)))
    (call-interactively 'transpose-sexps)))

drag-prev-sexp-forward 的意思是:把当前光标之前的 sexp 和它后面的 sexp 交换

drag-prev-sexp-backward 的意思是:把当前光标之前 sexp 和它再前面 的 sexp 交换

注意:这两个命令要求光标必须出现在两个 sexp 表达式的中间。但在实际用的时候,我们只要光标出现在待 drag 的表达式的末尾即可。

下面是演示,很酷炫把:

drag-sexp

学会这个操作,在给人做演示或演讲的时候会加分哦~

:stuck_out_tongue: 赶快绑上你最喜欢的快捷键吧 :stuck_out_tongue:

3 个赞

以前写的一个扩展:

说到这个 emacs 有内置的 secondary selection. 可以用鼠标按着 alt 选,不过没有内置的交换两个 selection 的功能。

关于transpose有这么多的用法,而且默认已经有快捷键了。感觉没有必要再封装。而且默认的快捷键也非常容易理解,符合C, M, C-M越来越大的规则。

3 个赞

经常编辑LISP代码建议尝试下lispy。刚开始会有些别扭,但是习惯以后操作sexp确实比用组合键快捷得多。例如移动光标下的sexp就是W/S键,跟打游戏的键位差不多。

请问有没有交换 C/C++ 函数中参数位置的函数?

PS: 找到了一个解决方案,可以用于 C++ 交换参数位置

https://github.com/elbeno/dotemacs/blob/0d4a51bf383cb1064c351ad9d5b841bcb568a8e7/.emacs.d/cpp-modes.el#L296

Lispy(如果不喜欢vim-like按键的可以看下paredit)确实不错,但是他们都默认占用了太多的按键。导致很多时候,你按下某些键的时候,与你想的根本不一样。

交换方便不方便要看选择,如果选起来很方便的话。。。

当然临近的两个还是 transpose 好用。

transpose-确实有很多变体,但transpose-sexp的用法和其他变体不完全一致。

这个封装只是让它更符合直觉(此外,prefix args 也是一个记忆负担)。

当然,以上的判断完全是主观的。

1 个赞

确实不完全一样,但非常容易理解。基本上就是交换光标左右的单位。sexp要求光标必须在两个exp中间而已。

我倒是觉得-lines才是比较怪的那个,竟然必须与上一行换,即便是在行尾。

1 个赞