Jak mogę automatycznie wstawić prototyp do foo.h z foo.c?

11

Załóżmy, że piszę program C w pliku foo.c:

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

Chcę polecenia, które wstawi odpowiedni prototyp funkcji w foo.h:

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

Czy istnieją na to jakieś rozwiązania Emacsa?

Wilfred Hughes
źródło

Odpowiedzi:

9

AKTUALIZACJA : Stworzyłem pakiet Semantic Refactor , który całkowicie rozwiązuje ten problem i jeszcze więcej. Możesz obejrzeć dema, aby zobaczyć, jak to działa. Pozostały tekst tej odpowiedzi, po tym zdaniu, jest stary i umieściłem go tylko ze względów historycznych.

STARA ODPOWIEDŹ :

Możesz użyć senator-copy-tagdo dokładnego skopiowania podpisu funkcji, a następnie wkleić go z powrotem do pliku źródłowego. senator-copy-tagKomendy Senator są dostępne po włączeniu semantic-mode:

(semantic-mode 1)

Semantic to wbudowany pakiet Emacsa.

Możesz połączyć Semantic Senator z Projectile w komendę, aby wstawić prototyp funkcji do innego pliku (pliku o tej samej nazwie, ale z innym rozszerzeniem) z dowolnego miejsca w projekcie. Jeśli istnieje tylko jeden inny plik, polecenie wstawia natychmiast do tego pliku; jeśli więcej niż jeden, pojawi się monit o wybranie pliku; jeśli nie ma, zostanie wyświetlony monit o podanie wszystkich plików w projekcie. Po wybraniu pliku, monit wyświetla listę znaczników semantycznych w bieżącym buforze, po których można wstawić.

Przesłałem PR do Emacs Refactor . Pełny kod, jeśli chcesz spróbować bez oczekiwania na PR: kliknij tutaj .

Oto demo (zaczyna się, gdy zobaczysz START DEMOna dole):

prototyp-semantyczna-wstaw-funkcja-prototyp

Możesz także użyć tylko Senatora do kopiowania i działania prototypu. Tak długo, jak punkt znajduje się gdziekolwiek w podpisie funkcji lub treści funkcji, uruchom senator-copy-tag, który jest C-c , M-wdomyślnie związany, kopiuje całą funkcję: zarówno podpis, jak i treść. Możesz jednak wkleić tylko podpis, jeśli chcesz, uruchamiając polecenie senator-yank-tag, które jest C-c , C-ydomyślnie powiązane . Naciśnięcie C-ywklei całą sygnaturę funkcji wraz z jej ciałem. senator-copy-tagdziała nawet z sygnaturą funkcji rozwiniętą w wielu liniach, takich jak to:

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

Chociaż to podejście nie wstawia bezpośrednio do bufora o tej samej nazwie, jest bardziej odpowiednie w innych przypadkach. Twój przypadek użycia działa tylko wtedy, gdy masz dwa pliki w tym samym katalogu i o tej samej nazwie, ale z różnymi rozszerzeniami. Co jeśli deklaracja funkcji i definicja funkcji muszą pozostać w różnych plikach o różnych nazwach?

EDYCJA 2 : Oto przykład inteligentnego wstawienia prototypu funkcji za pomocą znaczników semantycznych. Obecnie można wstawiać tylko na podstawie względnych pozycji („przed” i „po”) znaczników semantycznych najwyższego poziomu. Będę aktualizować, aby użytkownik mógł wstawić w dowolnym miejscu, w którym są dostępne znaczniki semantyczne, z większą liczbą stanowisk (tj gdy znacznik jest Class, to powinien oferować dodatkowe pozycje: public, projecteda private). Demo rozpocznie się, gdy zobaczysz START DEMOna dole:

protile-semantic-insert-function-prototype2

Premia : Jeśli chcesz wygenerować listę pustych definicji funkcji w .cpppliku z pliku nagłówka, użyj member-functions.el . Ale wkrótce zastąpię go pociskiem Semantic +.

Do zrobienia
źródło
3

Następujące polecenie powinno to zrobić. Przeszedł moje testy i nie ma zewnętrznych zależności.

(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 ";"))))))
Malabarba
źródło
2

Myślę, że następujące powinny działać (to działa dla mnie):

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

Wymaga to smartparens, choć możesz zhakować własną kopię, sp-backward-up-sexpjeśli jest to niedopuszczalne.

Pamiętaj również, że spowoduje to umieszczenie nagłówka w dowolnym miejscu, w którym pozostawiłeś (point)ostatni. Ponieważ nie określiłeś, gdzie chcesz, pomyślałem, że to prawdopodobnie najlepsze. Oczywiście, jeśli chcesz, aby dopisał się na końcu, możesz wstawić (end-of-buffer)przed (yank). Oczywiście możesz dodawać bardziej wyszukane rzeczy, takie jak tworzenie nowej linii w pobliżu punktu i szarpanie tam, ale to zależy od twojego gustu.

PythonNut
źródło