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-includes
verwandelt 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-includes
sucht nach dem ersten Absatz von «#include» und sortiert ihn. Ich habe es before-save-hook
mit 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 .c
Datei 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.
sort-subr
direkt aufrufen . Oder ... als Hack könnten Sie ratensort-lines
, dass Sie vor dem Sortieren"
und den<
Zeichen und dann nach dem Sortieren die Zeichen zurücktauschen. :-)