Wie kann ich erkennen, ob das aktuelle Zeichen ein Kommentarzeichen für diesen Hauptmodus ist?

12

Ich arbeite an dieser kleinen Funktion, die die nächste Zeile zur aktuellen Zeile hochzieht. Ich möchte eine Funktionalität hinzufügen, damit, wenn die aktuelle Zeile ein Zeilenkommentar ist und die nächste Zeile auch ein Zeilenkommentar ist, die Kommentarzeichen nach der Aktion "Hochziehen" entfernt werden.

Beispiel:

Vor

;; comment 1▮
;; comment 2

Berufung M-x modi/pull-up-line

Nach

;; comment 1▮comment 2

Beachten Sie, dass die ;;Zeichen entfernt werden, die zuvor waren comment 2.

(defun modi/pull-up-line ()
  "Join the following line onto the current one (analogous to `C-e', `C-d') or
`C-u M-^' or `C-u M-x join-line'.

If the current line is a comment and the pulled-up line is also a comment,
remove the comment characters from that line."
  (interactive)
  (join-line -1)
  ;; If the current line is a comment
  (when (nth 4 (syntax-ppss))
    ;; Remove the comment prefix chars from the pulled-up line if present
    (save-excursion
      (forward-char)
      (while (looking-at "/\\|;\\|#")
        (delete-forward-char 1))
      (when (looking-at "\\s-")
        (delete-forward-char 1)))))

Die obige Funktion funktioniert , aber für jetzt, unabhängig von dem Haupt-Modus, wird es betrachten /oder ;oder #als Kommentarzeichen: (looking-at "/\\|;\\|#").

Ich möchte diese Zeile intelligenter gestalten. Hauptmodus spezifisch.

Lösung

Dank der Lösung von @ericstokes glaube ich, dass das Folgende jetzt alle meine Anwendungsfälle abdeckt :)

(defun modi/pull-up-line ()
  "Join the following line onto the current one (analogous to `C-e', `C-d') or
`C-u M-^' or `C-u M-x join-line'.

If the current line is a comment and the pulled-up line is also a comment,
remove the comment characters from that line."
  (interactive)
  (join-line -1)
  ;; If the current line is a comment
  (when (nth 4 (syntax-ppss))
    ;; Remove the comment prefix chars from the pulled-up line if present
    (save-excursion
      (forward-char)
      ;; Delete all comment-start or space characters
      (while (looking-at (concat "\\s<" ; comment-start char as per syntax table
                                 "\\|" (substring comment-start 0 1) ; first char of `comment-start'
                                 "\\|" "\\s-")) ; extra spaces
        (delete-forward-char 1)))))
Kaushal Modi
quelle
Möchten Sie, dass dies intelligent genug ist, um verschiedene Start- und Endzeichen von Kommentaren und Kommentare mit mehreren Zeichen (z. B. Cs /* ... */) zu verarbeiten?
Erikstokes
Nein, das war alles was ich brauchte. Vielen Dank!
Kaushal Modi
@erikstokes Wie würden Sie aus Neugier mit Kommentaren im C-Stil umgehen?
Pradhan
Diese Lösung funktioniert auch bei mehrzeiligen Kommentaren. Es sind keine besonderen Maßnahmen erforderlich, da beim Zusammenfügen mehrzeiliger Kommentare keine Zeichen gelöscht werden müssen.
Kaushal Modi
2
@Pradhan Es gibt die Zeichenfolgen comment-startund comment-end, die in c-mode(aber nicht c++-mode) auf "/ *" und "* /" gesetzt sind . Und c-comment-start-regexpdas passt zu beiden Stilen. Sie löschen die Endzeichen dann am Anfang nach dem Beitritt. Aber ich denke meine Lösung wäre es uncomment-region, join-lineden comment-regionEmacs zu überlassen, welcher Kommentarcharakter was ist.
Erikstokes

Antworten:

12

Sie können überprüfen , ob das aktuelle Zeichen ein Kommentarzeichen unter Verwendung der Syntax - Tabelle ist: (looking-at "\\s<"). Der reguläre Ausdruck entspricht einem \\s<beliebigen Zeichen mit der Syntax "Kommentaranfang". \\s>Entspricht der Syntax "Kommentarende".

Eine weitere Option ist die Variable comment-start, bei der es sich um die von comment-dwimund friends eingefügte Zeichenfolge handelt . Es wird normalerweise auf das Kommentar-Startzeichen plus ein Leerzeichen gesetzt.

erikstokes
quelle
2

Es gibt eine viel einfachere Lösung . Bitte lesen Sie meinen Code unter https://github.com/redguardtoo/evil-nerd-commenter/blob/master/evil-nerd-commenter.el

Ich werde hier nicht den gesamten Code kopieren / einfügen. Aber hier sind die wichtigsten Punkte:

  • Kommentar hat seine eigene Schriftart, Suche Schriftart-Sperre-Kommentar-Gesicht und Schriftart-Sperre-Kommentar-Trennzeichen-Gesicht in meinem Code

  • Verwenden Sie die Emacs-eigene API, um das Kommentarzeichen für die zweite Zeile zu entfernen, und verbinden Sie sie dann mit der ersten Zeile

Es sollte auf allen vernünftigen Hauptmodi funktionieren.

Dieser Trick ist nicht von mir erfunden. Es ist eigentlich aus Emacs eigenem Code (genauer gesagt Flyspell). Die Lösung sollte daher alle von Flyspell unterstützten Hauptmodi unterstützen

chen bin
quelle
3
Um etwas als Kommentar hervorzuheben, muss die Syntaxtabelle entsprechend eingerichtet sein. Daher bezweifle ich, dass dies intelligenter ist als die Alternative, die Syntax zu betrachten.
Wasamasa
Ich habe diesen Trick gelernt, indem ich Emacs eigenen Code gelesen habe (eigentlich ist es Flyspell), wie ich in meinem Code dokumentiert habe.
Chen Bin
0

Wenn Sie mit dieser Funktion nach Lisp-Code suchen (Elisp, Clojure, Scheme und Common Lisp), sollten Sie lispy ausprobieren . Eine Funktion namens lispy-fillerledigt dies.

Wenn Sie diese Funktion für eine andere Sprache suchen, sollten Sie rebox2 (überprüft für Cund Python), eine aufgerufene Funktion rebox-filloder eine andere aufgerufene Funktion so rebox-dwimetwas tun.

Sie sind beide großartige Pakete, und sie stehen nicht in Konflikt miteinander, da sie für verschiedene Hauptmodi verwendet werden, und sie sind beide ( lispy-fillund rebox-dwim) daran gebunden M-q, ziemlich ordentlich.

CodyChan
quelle