Wie kann ich automatisch einen Prototyp von foo.c in foo.h einfügen?


11

Angenommen, ich schreibe ein C-Programm in eine Datei foo.c:

int add_numbers(int x, int y, int z) {
    // Very complex implementation here.
    return x + y + z;
}

Ich möchte einen Befehl, der einen entsprechenden Funktionsprototyp in foo.h einfügt:

int add_numbers(int x, int y, int z);

Gibt es dafür bereits Emacs-Lösungen?

Antworten:


9

UPDATE : Ich habe ein Semantic Refactor- Paket erstellt, das dieses Problem und mehr vollständig löst. Sie können sich die Demos ansehen, um zu sehen, wie es funktioniert. Der verbleibende Text dieser Antwort nach diesem Satz ist alt und wird nur aus historischen Gründen dort abgelegt.

ALTE ANTWORT :

Sie können die senator-copy-tagFunktionssignatur genau kopieren und dann wieder in Ihre Quelldatei einfügen. senator-copy-tagund Senator-Befehle sind verfügbar, wenn Sie Folgendes aktivieren semantic-mode:

(semantic-mode 1)

Semantic ist ein in Emacs integriertes Paket.

Sie können Semantic Senator mit Projectile in einem Befehl kombinieren, um Funktionsprototypen von überall in Ihrem Projekt in eine andere Datei (Datei mit demselben Namen, aber unterschiedlicher Erweiterung) einzufügen. Wenn nur eine andere Datei vorhanden ist, wird der Befehl sofort in diese Datei eingefügt. Wenn mehr als eine Datei vorhanden ist, werden Sie aufgefordert, eine Datei auszuwählen. Wenn keine vorhanden sind, werden Sie aufgefordert, die gesamten Dateien in Ihrem Projekt einzugeben. Nachdem Sie eine Datei ausgewählt haben, bietet eine Eingabeaufforderung eine Liste der semantischen Tags im aktuellen Puffer an, die Sie nach dem Einfügen auswählen können.

Ich habe eine PR bei Emacs Refactor eingereicht . Vollständiger Code, wenn Sie es versuchen möchten, ohne auf die PR zu warten: Klicken Sie hier .

Hier ist eine Demo (sie beginnt, wenn Sie START DEMOunten sehen):

Projektil-Semantik-Insert-Funktions-Prototyp

Sie können auch nur Senator verwenden, um Prototypen zu kopieren und zu funktionieren. Solange sich der Punkt irgendwo innerhalb der Funktionssignatur oder des Funktionskörpers senator-copy-tagbefindet C-c , M-w, kopiert run , an den standardmäßig gebunden ist , die gesamte Funktion: sowohl die Signatur als auch den Textkörper. Sie können jedoch nur die Signatur einfügen, wenn Sie möchten, indem Sie den Befehl senator-yank-tagausführen, C-c , C-yan den standardmäßig gebunden ist . Durch Drücken von C-ywird die gesamte Funktionssignatur zusammen mit ihrem Körper eingefügt. senator-copy-tagfunktioniert sogar mit Funktionssignatur, die in mehreren Zeilen wie folgt erweitert wurde:

void 
func(int a,
     int b, 
     int c)
{
    .....
}

Obwohl dieser Ansatz nicht direkt in einen gleichnamigen Puffer eingefügt wird, ist er in anderen Fällen besser anwendbar. Ihr Anwendungsfall funktioniert nur, wenn Sie zwei Dateien im selben Verzeichnis und mit demselben Namen, aber unterschiedlichen Erweiterungen haben. Was ist, wenn die Funktionsdeklaration und die Funktionsdefinition in verschiedenen Dateien mit unterschiedlichen Namen verbleiben müssen?

EDIT2 : Hier ist ein Beispiel für das intelligente Einfügen eines Funktionsprototyps mithilfe semantischer Tags. Derzeit können Sie nur basierend auf den relativen Positionen ("vor" und "nach") von semantischen Tags der obersten Ebene einfügen. Ich werde aktualisieren, damit der Benutzer an jeder Stelle, an der semantische Tags verfügbar sind, mehr Positionen einfügen kann (dh wenn ein Tag ein ist Class, sollte es zusätzliche Positionen bieten : public, projectedund private). Die Demo beginnt, wenn Sie START DEMOunten sehen:

Projektil-Semantik-Insert-Funktions-Prototyp2

Bonus : Wenn Sie .cppaus einer Header-Datei eine Liste leerer Funktionsdefinitionen in einer Datei erstellen möchten , verwenden Sie member-functions.el . Aber bald werde ich es durch Semantic + Projectile ersetzen.


3

Der folgende Befehl sollte es tun. Es hat meine Tests bestanden und hat keine externen Abhängigkeiten.

(defun endless/copy-proto-to-header-file ()
  (interactive)
  (save-excursion
    ;; c-mode's `beginning-of-defun' should be robust enough.
    (beginning-of-defun)
    (let ((l (point)))
      (search-forward-regexp " *{")
      (let ((proto (buffer-substring l (match-beginning 0))))
        (ff-find-other-file)
        ;; If other file is already open, we don't want to move point.
        (save-excursion
          (goto-char (point-max))
          ;; Do some more movement here if you want.
          (insert "\n" proto ";"))))))

2

Ich denke, das sollte funktionieren (es funktioniert für mich):

(defun c-copy-function-signature-to-header ()
  (interactive)
  (save-excursion
    (let ((last-point -1))
      (while (/= (point) last-point)
        (setq last-point (point))
        (sp-backward-up-sexp))
      (kill-ring-save (point) (line-beginning-position))
      (ff-find-other-file)
      (yank)
      ;; clean whitespace between closing paren and opening curly 
      (delete-trailing-whitespace
        (line-beginning-position)
        (line-end-position))
      (insert ";")))

Dies erfordert smartparens, obwohl Sie möglicherweise Ihre eigene Kopie von hacken können, sp-backward-up-sexpwenn dies nicht akzeptabel ist.

Beachten Sie auch, dass dadurch die Kopfzeile dort platziert wird, wo Sie die (point)letzte in der Kopfzeile belassen haben . Da Sie nicht angegeben haben, wo Sie es wollten, dachte ich, dass dies wahrscheinlich das Beste ist. Wenn Sie möchten, dass es am Ende angehängt wird, können Sie natürlich ein (end-of-buffer)vor das setzen (yank). Natürlich können Sie auch schickere Dinge hinzufügen, z. B. eine neue Linie in der Nähe des Punkts erstellen und dort ziehen, aber das liegt ganz nach Ihrem Geschmack.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.