在编辑 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 的表达式的末尾即可。
下面是演示,很酷炫把:
学会这个操作,在给人做演示或演讲的时候会加分哦~
赶快绑上你最喜欢的快捷键吧
7 个赞
说到这个 emacs 有内置的 secondary selection. 可以用鼠标按着 alt 选,不过没有内置的交换两个 selection 的功能。
1 个赞
关于transpose有这么多的用法,而且默认已经有快捷键了。感觉没有必要再封装。而且默认的快捷键也非常容易理解,符合C, M, C-M越来越大的规则。
4 个赞
经常编辑LISP代码建议尝试下lispy。刚开始会有些别扭,但是习惯以后操作sexp确实比用组合键快捷得多。例如移动光标下的sexp就是W/S键,跟打游戏的键位差不多。
1 个赞
请问有没有交换 C/C++ 函数中参数位置的函数?
PS: 找到了一个解决方案,可以用于 C++ 交换参数位置
cabins
7
Lispy(如果不喜欢vim-like按键的可以看下paredit)确实不错,但是他们都默认占用了太多的按键。导致很多时候,你按下某些键的时候,与你想的根本不一样。
交换方便不方便要看选择,如果选起来很方便的话。。。
当然临近的两个还是 transpose 好用。
transpose-
确实有很多变体,但transpose-sexp
的用法和其他变体不完全一致。
这个封装只是让它更符合直觉(此外,prefix args 也是一个记忆负担)。
当然,以上的判断完全是主观的。
2 个赞
cabins
10
确实不完全一样,但非常容易理解。基本上就是交换光标左右的单位。sexp要求光标必须在两个exp中间而已。
我倒是觉得-lines才是比较怪的那个,竟然必须与上一行换,即便是在行尾。
2 个赞
(dotimes (n 10)
(insert (format "%02d -- %02d\n" n n)))
(defun create-marker-at-point (&optional point)
(if point
(save-excursion
(goto-char point)
(point-marker))
(point-marker)))
(defun transpose-region-selection ()
(interactive)
(when (and (secondary-selection-exist-p) (use-region-p))
(let* ((selection (car (secondary-selection-exist-p)))
(s-beg (create-marker-at-point (overlay-start selection)))
(s-end (create-marker-at-point (overlay-end selection)))
(r-beg (create-marker-at-point (region-beginning)))
(r-end (create-marker-at-point (region-end))))
(transpose-regions r-beg r-end
s-beg s-end)
;; move secondary-selection to original region (swap)
(delete-overlay selection)
(move-overlay selection (marker-position s-beg) (marker-position r-end))
;; move region to original secondary-selection (swap)
(push-mark (marker-position r-beg) t t)
(goto-char (marker-position s-end))
(activate-mark)
;; Make region mark activate
(setq deactivate-mark nil)
(set-marker s-beg nil)
(set-marker s-end nil)
(set-marker r-beg nil)
(set-marker r-end nil)
)))
1 个赞