1

現在のリージョンのすべての (空でない) 行を取得し、これらの行を in-place で複製する 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!")))

ただし、この関数にはいくつかの (少なくとも 2 つの) バグがあります。

  1. 空行は無視されませんが、出力が完全に破棄されます (行が間違った場所に挿入されます)。
  2. 挿入される最初の行は常に間違ったインデント (列 0) で挿入され、他のすべての行は正しいインデントに挿入されます。

私は、機能をより便利な状態に進めることにちょっとこだわっています。また、私のアプローチが特に効率的/よく書かれているとは思えません...おそらく、一部のelispの達人は、リージョン内の各行を個別に処理するために使用できる、より簡単なアプローチを知っています...

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 に答える