Làm cách nào tôi có thể tự động chèn một nguyên mẫu trong foo.h từ foo.c?


11

Giả sử tôi đang viết chương trình C trong tệp foo.c:

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

Tôi muốn một lệnh sẽ chèn một nguyên mẫu hàm tương ứng trong foo.h:

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

Có bất kỳ giải pháp Emacs hiện có cho việc này?

Câu trả lời:


9

CẬP NHẬT : Tôi đã tạo gói Semantic Refactor giải quyết hoàn toàn vấn đề này và hơn thế nữa. Bạn có thể nhìn vào các bản demo để xem nó hoạt động như thế nào. Các văn bản còn lại của câu trả lời này, sau câu này, đã cũ và đặt nó ở đó chỉ vì lý do lịch sử.

TRẢ LỜI :

Bạn có thể sử dụng senator-copy-tagđể sao chép chính xác chữ ký hàm, sau đó dán lại vào tệp nguồn của bạn. senator-copy-tagvà các lệnh Thượng nghị sĩ khả dụng khi bạn bật semantic-mode:

(semantic-mode 1)

Semantic là một gói tích hợp Emacs.

Bạn có thể kết hợp Semantic Senator với Projectile vào một lệnh để chèn nguyên mẫu hàm vào tệp khác (tệp có cùng tên nhưng phần mở rộng khác nhau) từ bất kỳ đâu trong dự án của bạn. Nếu chỉ có một tệp khác, lệnh sẽ chèn ngay vào tệp đó; nếu có nhiều hơn một, bạn được nhắc chọn một tệp; nếu không có, bạn được nhắc cho toàn bộ tệp trong dự án của bạn. Sau khi bạn chọn tệp, lời nhắc sẽ cung cấp danh sách các thẻ Semantic trong bộ đệm hiện tại mà bạn có thể chọn để chèn sau.

Tôi đã gửi một PR cho Emacs Refactor . Mã đầy đủ nếu bạn muốn thử mà không cần chờ PR: bấm vào đây .

Đây là một bản demo (nó bắt đầu khi bạn nhìn thấy START DEMOở phía dưới):

dự án-ngữ nghĩa-chèn-chức năng-nguyên mẫu

Bạn cũng có thể chỉ sử dụng Thượng nghị sĩ để sao chép và thực hiện chức năng nguyên mẫu. Miễn là điểm là bất cứ nơi nào bên trong chữ ký hàm hoặc thân hàm, chạy senator-copy-tag, được ràng buộc C-c , M-wtheo mặc định, nó sao chép toàn bộ hàm: cả chữ ký và thân. Tuy nhiên, bạn chỉ có thể dán chữ ký nếu bạn muốn bằng cách chạy lệnh senator-yank-tag, được ràng buộc C-c , C-ytheo mặc định. Nhấn C-ydán toàn bộ chữ ký chức năng cùng với cơ thể của nó. senator-copy-tagthậm chí hoạt động với chữ ký hàm được mở rộng trên nhiều dòng như thế này:

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

Mặc dù cách tiếp cận này không chèn trực tiếp vào bộ đệm có cùng tên, nhưng nó được áp dụng nhiều hơn trong các trường hợp khác. Ca sử dụng của bạn chỉ hoạt động nếu bạn có hai tệp trong cùng một thư mục và có cùng tên nhưng các phần mở rộng khác nhau. Điều gì xảy ra nếu khai báo hàm và định nghĩa hàm phải ở trong các tệp khác nhau với các tên khác nhau?

EDIT2 : Đây là một ví dụ để chèn thông minh nguyên mẫu hàm bằng cách sử dụng các thẻ Semantic. Hiện tại, bạn chỉ có thể chèn dựa trên các vị trí tương đối ("trước" và "sau") của các thẻ Semantic cấp cao nhất. Tôi sẽ cập nhật để làm cho người sử dụng để có thể chèn vào bất kỳ nơi thẻ Semantic có sẵn, với vị trí hơn (tức là khi một thẻ là một Class, cần cung cấp vị trí bổ sung: public, projectedprivate). Bản demo bắt đầu khi bạn nhìn thấy START DEMOở phía dưới:

Projectile-semantic-insert-function -otype2

Phần thưởng : Nếu bạn muốn tạo một danh sách các định nghĩa hàm trống trong một .cpptệp từ tệp tiêu đề, hãy sử dụng thành viên-tests.el . Nhưng sẽ sớm thôi, tôi sẽ thay thế nó bằng Semantic + Projectile.


3

Các lệnh sau nên làm điều đó. Nó đã vượt qua các bài kiểm tra của tôi, và không có sự phụ thuộc bên ngoài.

(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

Tôi nghĩ rằng những điều sau đây nên hoạt động (nó hoạt động với tôi):

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

Điều này đòi hỏi smartparens, mặc dù bạn có thể hack bản sao của chính mình sp-backward-up-sexpnếu điều đó không được chấp nhận.

Cũng lưu ý rằng điều này sẽ đặt tiêu đề bất cứ nơi nào bạn để lại (point)cuối cùng trong tiêu đề. Vì bạn không xác định nơi bạn muốn, tôi nghĩ rằng đây có lẽ là điều tốt nhất. Tất nhiên, nếu bạn muốn nó xuất hiện ở cuối, bạn có thể đặt (end-of-buffer)trước (yank). Tất nhiên bạn có thể thêm các công cụ fancier như tạo một dòng mới gần điểm và kéo dài ở đó, nhưng đó là tùy theo sở thích của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.