«sort-lines»の記号の順序を変更する


7

保存する前に、«sort-lines»を使用してC / C ++ファイルのincludeをソートしています。発生する問題は、"記号の付いたヘッダーが記号の付いたヘッダーよりも上位にソートされることです<。しかし、私は逆が欲しいです。

<文字を"シンボルよりも優先するために、順序を変更するにはどうすればよいですか?


2
独自の述語関数を作成してsort-subr直接呼び出す必要がある場合があります。それとも...ハックとして、あなたは助言することができsort-lines、ソート前に入れ替えるように"し、<文字と、その後の並べ替え後にあなたが戻ってそれらを交換します。:-)
グルカ、2015

回答:


2

使用できますsort-regexp-fields。リージョンをマークして、次の操作を行います。

M-x sort-regexp-fields RET #include .\(.*\) RET \1 RET

正規表現のグループは、すべてのものをキャプチャします後#include "または#include <ソート代わりに、行全体のそれに。

ちなみに、あなたが見ているソートの理由はASCII "よりも高いためです<


1
ありがとう、私はすでにヘッダの名前でソートし、開口部を無視して考えた<"シンボル。しかし、私は結論に達しました。このように並べ替えられたヘッダーは少し乱雑に見えます。そのため、文字の順序を変更したいのです。
Hi-Angel

2

一方、@ glucasが言及したハックを実装するためのコードを書きました。それはおそらくCでヘッダーをソートする目的にのみ適していますが、誰かがそれを役にたてることを願っています。

(defun replace-char-after (character-number replacement)
  "Replaces char in the buffer after the `character-number' with `replacement'"
  (save-excursion
    (goto-char character-number)
    (delete-char 1)
    (insert-char replacement)))

(defun replace-delimiters (old-closing-char new-opening-char new-closing-char opening-point end-point)
  "Replaces delimiters between `opening-point' and the
`end-point'. Note, that the `opening-point' should point to the
opening symbol, thus the function seeks only the closing"
  (block replace-delimiters
    (let ((closing-point opening-point))
      (setq closing-point (+ 1 opening-point))
      (while (< closing-point end-point)
        (if (eq (char-after closing-point) ?\n) ;;no closing delimiter
            (progn
              (print "Err: no closing delimiter")
              (return-from replace-delimiters nil))
          (when (eq (char-after closing-point) old-closing-char)
            (progn
              (replace-char-after opening-point new-opening-char);;opening delimiter
              (replace-char-after closing-point new-closing-char);;closing delimiter
              (return-from replace-delimiters (+ 1 closing-point)))))
        (setq closing-point (+ closing-point 1))))))

(defun swap-<-and-quote-includes (beg end)
    "Swaps in the text between `beg' and `end' the matching «<» and
  «>» character to the \" quote, and vice versa. Mainly used
  before sorting to swap the order of these characters, next
  after the sort to restore the text."
  (block swap-<-and-quote-includes
    (let ((curr-point beg))
      (while (< curr-point end)
        (setq curr-point (+ curr-point 1))
        ;;first check «"»
        (if (eq (char-after curr-point) ?\")
            (progn
              (setq curr-point (replace-delimiters ?\" ?< ?> curr-point end))
              (if (eq curr-point nil)
                  (return-from swap-<-and-quote-includes t)))
          ;;else if «<»
          (if (eq (char-after curr-point) ?<)
              (progn
                (setq curr-point (replace-delimiters ?\> ?\" ?\" curr-point end))
                (if (eq curr-point nil)
                    (return-from swap-<-and-quote-includes t)))))))))

この関数は、toのswap-<-and-quote-includesようなすべてのテキスト、および指定された範囲begend内のすべてのto <foo>を変換します。"foo""foo"<foo>

そして、これがヘッダーを見つけてソートするためのコードです:

(defun sort-lines-nocase (reverse beg end)
  (let ((sort-fold-case t))
    (sort-lines reverse beg end)))

(defun c-sort-includes ()
  "Sorts #include statements"
  (interactive)
  (save-excursion
    (let (beg end orig-content sorted-content)
      (goto-char (point-min))
      (while (and (not (looking-at "#include "));;look for includes, if no then
                  (eq (forward-line 1) 0) ;;go one line down (if not EOF).
                  ))
      (setq beg (point))
      (while (and (looking-at "#include ")
                  (eq (forward-line 1) 0)));;to not hang cuz of EOF
      (setq end (point))
      (setq orig-content (buffer-substring-no-properties beg end))
      (setq sorted-content (with-temp-buffer
                             (insert orig-content)
                             (swap-<-and-quote-includes (point-min) (point-max)) ;;swap characters < and > in includes
                             (sort-lines-nocase (point-min) (point-max)) ;;sort
                             (swap-<-and-quote-includes (point-min) (point-max)) ;;swap the characters  back
                             (buffer-string)))
      (when (not (string= orig-content sorted-content))
        (kill-region beg end)
        (insert sorted-content))
      )))

この関数c-sort-includesは、«#include»の最初の段落を探して並べ替えます。before-save-hookCおよびC ++モードでのみ実行するコードを追加しました。既知の短所:α)インクルードのある最初の段落のみがソートされます。それは、ファイルの最後までの検索は高額になる可能性があるためです(たとえば、私の仕事では、最近.cファイルを見つけたのですが)想像できますか?!—≈16000行!正しい解決策は、ファイル内のヘッダーブロックが存在する場所を追跡するマイナーモードではなく、β)古いEmacsでは、≈2015年以降、機能がハングする可能性がありました-後で修正されたバグです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.