Ändern Sie die Reihenfolge der Symbole für «Sortierzeilen»

7

Ich verwende «Sortierzeilen», um Includes in C / C ++ - Dateien vor dem Speichern zu sortieren . Das Problem, das auftritt, ist, dass Überschriften mit "Symbolen höher sortiert sind als solche mit <Symbolen. Aber ich will das Gegenteil.

Wie ändere ich die Reihenfolge so, dass das <Zeichen eine höhere Priorität als das "Symbol hat?

Hallo Engel
quelle
2
Möglicherweise müssen Sie Ihre eigene Prädikatfunktion schreiben und sort-subrdirekt aufrufen . Oder ... als Hack könnten Sie raten sort-lines, dass Sie vor dem Sortieren "und den <Zeichen und dann nach dem Sortieren die Zeichen zurücktauschen. :-)
Glucas

Antworten:

2

Sie können verwenden sort-regexp-fields. Markieren Sie die Region und machen Sie:

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

Die Gruppe mit regulären Ausdrücken erfasst alles nach #include "oder #include <und sortiert danach anstelle der gesamten Zeile.

Zu Ihrer Information, ich glaube, der Grund für die Sortierung, die Sie sehen, ist, dass sie "höher ist als <in ASCII.

Kindermädchen
quelle
1
Vielen Dank, ich dachte schon über den Namen eines Header Sortier- und ignoriert die Öffnung <, "Symbole. Aber ich bin zu dem Schluss gekommen, dass auf diese Weise sortierte Überschriften etwas chaotisch aussehen. Deshalb möchte ich nur die Reihenfolge der Zeichen ändern.
Hi-Angel
2

In der Zwischenzeit habe ich einen Code geschrieben, um den von @glucas erwähnten Hack zu implementieren. Es passt vielleicht nur zum Sortieren von Headern in C, aber ich hoffe, jemand findet es nützlich.

(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)))))))))

Die Funktion swap-<-and-quote-includesverwandelt jeden Text wie <foo>zu "foo", und jedes "foo"zu <foo>innerhalb des gegebenen Bereichs beg , Ende .

Und hier ist der Code zum Suchen und Sortieren von Headern:

(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))
      )))

Die Funktion c-sort-includessucht nach dem ersten Absatz von «#include» und sortiert ihn. Ich habe es before-save-hookmit einem Code hinzugefügt, um es nur für C- und C ++ - Modi auszuführen. Bekannte Nachteile: α) Nur der erste Absatz mit Includes wird sortiert. Das liegt daran, dass die Suche bis zum Ende einer Datei teuer sein kann - z. B. bei meinem Job habe ich kürzlich eine .cDatei mit gefunden - können Sie sich das überhaupt vorstellen?! - 16000 Zeilen! Die richtige Lösung wäre eher ein kleinerer Modus, der nachverfolgt, wo sich Headerblöcke in der Datei befinden. β) Bei älteren Emacs ab dem Jahr 2015 konnte die Funktion hängen bleiben - es war ein Fehler, der später behoben wurde.

Hallo Engel
quelle