2013-08-20 31 views
1

我试图编写一个elisp函数,它取得当前区域中的所有(非空)行并重复这些行in-place。我给你举个例子:区域“in-place”中的重复行

此输入:

1号线
线路2
3号线

变为

一号线
1号线
二号线
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. 被插入总是与错误的压痕(在零列)插入的第一行中,所有其他线被插入到右缩进。

我有点坚持了推进功能,更可使用状态。另外,我高度怀疑,我的做法是特别有效/写得好......也许一些elisp的导师知道,可用于在单独一个区域中的各行的工作更简单的方法...

回答

3

这可能是欺骗,但你可以只使用一个正则表达式替换匹配非空行,并与捕捉到的线路和重复替换它们。使用的Mx替代,正则表达式与区域突出显示,以下参数:

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

注意,在上面,^J代表一个换行符/引述回车键,CQ CJ

转化为elisp的这个,你只需要确保逃脱反斜线和括号:

(defun duplicate-lines-in-region (beg end) 
    (interactive "*r") 
    (replace-regexp "\\(.+\\)$" "\\&\n\\&" nil beg end))