1

我正在尝试编写一个 elisp 函数,该函数采用当前区域中的所有(非空)行并就地复制这些行。我给你举个例子:

这个输入:

线路1
线路2 线路
3

变成

线路1 线路1 线路2 线路
2
线路3
线路
3

如果有空行,它们将保留在原处,不应重复。如果编写了以下函数:

(defun duplicate-lines-in-region (beg end)
  "Duplicates the lines in the current region \"in-place\"."
  (interactive "r")
  (if (use-region-p)
      (let* ((text (buffer-substring-no-properties (region-beginning) (region-end)))
             (lines (split-string text "\n" t))
             (num-lines (length lines))
             (current-line 0)
             (end-pos 0))
        (save-excursion
          (goto-char (region-beginning))
          (while (< current-line num-lines)
            (end-of-line)
            (insert "\n")
            (insert (nth current-line lines))
            (next-line)
            (setq current-line (+ current-line 1))
            (setq end-pos (point))))
        (goto-char end-pos))
    (error "No active region!")))

然而,这个函数有一些(至少两个)错误:

  1. 空行不会被忽略,而是完全破坏输出(行插入错误的位置)。
  2. 插入的第一行总是以错误的缩进插入(在第 0 列),所有其他行都插入正确的缩进。

我有点坚持将功能提升到更有用的状态。另外,我高度怀疑我的方法是否特别有效/写得好......也许一些elisp-guru知道一种更直接的方法,可以用于单独处理区域中的每一行......

4

1 回答 1

3

这可能是作弊,但您可以使用正则表达式替换来匹配非空行并将它们替换为捕获的行和副本。M-x replace-regexp与突出显示的区域和以下参数一起使用:

  • 替换正则表达式:\(.+\)$
  • 和:\&^J\&

注意,在上面,^J代表一个换行符/引用的回车键,C-q C-j.

要将其转换为 elisp,您只需要确保转义反斜杠和括号:

(defun duplicate-lines-in-region (beg end)
  (interactive "*r")
  (replace-regexp "\\(.+\\)$" "\\&\n\\&" nil beg end))
于 2013-08-20T10:12:49.253 回答