Emacs有内置的多region支持吗?

elisp

#1

比如函数region-bounds返回的结构是((beg . end))。所以我想是不是可以有多个region?不然为什么最外面是一个list.

但是一直不知道怎么才能激活多个region,网上找了很多几乎都是说multiple cursors的内容,emacs有这方面built-in的支持吗?或者说不依赖multiple cursors的话,多处同时编辑比较好的做法是什么呢?

我不是说multiple cursors不好,但是具有全局状态的功能和multiple cursors整合起来确实有些难度。


#2

C-x SPC (M-x rectangle-mark-mode) 会用到不连续的 Region,2012 年 24.1 加入的新功能,顾名思义,这些 Region 是指一个矩形的各个行,不是任意的 Region。

C-x SPC
M-x (region-bounds)
((95288 . 95312)
 (95334 . 95358)
 (95405 . 95429)
 (95469 . 95493))

#3

原来如此,所以任意的多region还是只能借助overlay来模拟了。


#4

怎么样才算“支持”?

Emacs 并不禁止用户创建多个 region。

实际上高亮 region 的本来就是“模拟”来给用户看的,对机器来说有 mark 就够了。

最常用的单 region,就是创建一个 mark,然后进入 transient-mark-mode 设置高亮:

;; 选中整个 buffer
(goto-char (point-max))
(set-mark (point-min))
;; 展开之后,其核心代码是这样的:
;; (goto-char (point-max))
;; (set-marker (mark-marker) (point-min) (current-buffer))
;; (setq mark-active t)

所以单 region 的范围就是最近创建的那个 mark 的位置(region-begining) ,光标当前的位置 (region-end),即 (cons (region-begining) (region-end))

(defun region-bounds ()
  (funcall region-extract-function 'bounds))

(setq region-extract-function
  (lambda (method)
    (when (region-beginning)
      (cond
       ((eq method 'bounds)
        (list (cons (region-beginning) (region-end))))
       ((eq method 'delete-only)
        (delete-region (region-beginning) (region-end)))
       (t
        (filter-buffer-substring (region-beginning) (region-end) method))))))

而在矩形模式 rectangle-mark-mode 下,region-bounds 函数返回的是 rectangle--extract-region 内容:多个 (beg . end),这时函数名 region-bounds 的意义才体现出来。

在我看来,Emacs 内置了单选区和多选区(矩形选区)这两个最常用的特例(多选区才是常态),任意多选区这种不常用的常态,就留给第三方的包开发者去实现了。

实现任意多选区本质上就就是管理 mark(包括 overlay)。


#5

我想知道怎么可以实现一个比较好的多光标支持,和多region有一些间接的关系。

multiple cursors的逻辑其实有很多局限性,我在想如果Emacs本身有多region的支持,那么所有的对region的功能应该都有内置的支持才对。