4

コンマを項目区切り記号として使用して、マークされた領域内の項目を逆にする小さな関数を作成しました。関数コードは次のとおりです。

(defun reverse-list (beg end)
  "Reverses a list in-place, where comma ',' is the list item separator."
  (interactive "r")
  (if (region-active-p)
    (let ((region-list (reverse (split-string (region-as-string) ","))))
      (kill-region beg end)
      (loop for s in region-list do (progn
                                      (insert (chomp s))
                                      (insert ", ")))
      (delete-char -2))
    (message "Error: No region selected!")))  

wherechompは、文字列から先頭/末尾の空白をregion-as-string取り除き、領域を文字列として生成します。

この機能は非常に便利ですが、その場でセパレーターを選択できると便利です。私が探している動作は次のとおりです。

  • ユニバーサル引数なしで呼び出された場合は、コンマをアイテム区切りとして使用します
  • ユニバーサル引数 ( C-u) で呼び出された場合、ユーザーに (複数文字の可能性がある) 区切り文字列を入力するように求めます。

私はこれを達成しようとしましたが、成功していません。お手伝いいただけると助かります!

前もってありがとう、
エレマキル

4

2 に答える 2

7

対話型コード を使用して、 「生の」前置引数Pを読み取ることができます。これは、前置引数がない場合であり、前置引数があった場合ではないため、これをテストして、セパレーターを に設定するか、ユーザーに入力を促すために使用するかを決定できます。nilnil","read-string

また、あなたのコードに次のコメントを付けます。

  1. 関数はインタラクティブに呼び出された場合にのみ機能するため、begendは実際には領域の始まりと終わりです。非対話的に呼び出された場合、これらは一致しない可能性があり (またはリージョンが存在しない可能性もあります)、その場合、関数は正しく動作しません (これは、begとの間のバッファを削除しendますが、リージョンの反転を挿入するためです)。(buffer-substring beg end)したがって、 ではなくを呼び出す必要があります(region-as-string)

  2. [編集済み、コメントを参照] 領域が非アクティブな場合にエラーを発生させるのは得策ではありません。Emacs では、非アクティブ(つまり、強調表示されていない)の場合でも、リージョンは存在し続けます。または、ユーザーが電源をオフにして、アクティブな領域がまったくない可能性があります。どちらの場合でも、ユーザーはコマンドを実行したいと思うかもしれません。transient-mark-mode

    せいぜい、領域がアクティブなときにコマンドの動作を変更するだけです (たとえば、 を参照comment-dwim)。

  3. を呼び出して領域を削除すると、削除kill-regionされたテキストがキルリングにコピーされます。これは本当にやりたいことですか?ユーザーを驚かせるかもしれません。delete-region削除したテキストを実際に保存するつもりがない場合は、呼び出した方がよいでしょう。

  4. 呼び出しを開始する前に、ポイントが正しい場所にあることを確認していませんinsert。インタラクティブな使用ではそれで問題ありませんが、非インタラクティブな使用ではポイントがどこにでもある可能性があるため、明示的に移動する必要があります。もちろん、も使用save-excursionします。

  5. ", "エクストラを挿入して後で削除しなければならないというのは、非常に洗練されていないように思えます。そもそも入れないほうがいい。

上記のすべてを修正する改訂されたコードを次に示します。

(defun reverse-list (beg end read-separator)
  "Reverse the region in-place, treating it as a list of items
separated by commas. With a prefix argument, prompt for the
separator."
  (interactive "r\nP")
  (save-excursion
    (let* ((separator (if read-separator (read-string "Separator: ") ","))
           (region-list (nreverse (split-string (buffer-substring beg end) separator)))
           (separator (concat separator " ")))
      (goto-char beg)
      (delete-region beg end)
      (loop for s in region-list
            for sep = "" then separator
            do (insert sep) (insert (chomp s))))))
于 2012-12-03T13:54:47.610 に答える
-1
r -- Region: point and mark as 2 numeric args, smallest first.  Does no I/O.

rは常に最初の2つの引数だからです。C-u引数を渡すために使用する場合。次に、引数を区切り文字として3番目の引数に渡す必要がある場合があります。ただし、1番目と2番目の引数なしで3番目の引数を渡すことはできません。(ここではわかりません。私も初心者です)

私はあなたがそれを達成するためにとオプションを使用することを目的としてrsます。ただし、常に区切り引数を指定する必要があります。

例:

(defun reverse-list (beg end &optional sepeartor )
  (interactive "r
ssepeartor:")
  (princ beg)
  (princ "*")
  (princ end)
  (princ sepeartor))
于 2012-12-03T13:47:11.107 に答える