如何从foo.c自动在foo.h中插入原型?


11

假设我正在文件foo.c中编写一个C程序:

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

我想要一个将在foo.h中插入相应函数原型的命令:

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

是否有任何现有的Emacs解决方案?

Answers:


9

更新:我创建了语义重构包,可以完全解决此问题以及更多问题。您可以查看演示以了解其工作原理。在此句子之后,该答案的其余文本很旧,仅出于历史原因将其放在此处。

老答案

您可以使用它senator-copy-tag来精确复制功能签名,然后粘贴回源文件中。senator-copy-tag启用时,可以使用和Senator命令semantic-mode

(semantic-mode 1)

语义是Emacs内置软件包。

您可以将Semantic Senator和Projectile组合成一个命令,以将函数原型从项目中的任何位置插入其他文件(名称相同但扩展名不同的文件)中。如果只有另一个文件,该命令将立即插入该文件;否则,该命令将立即插入该文件。如果不止一个,则提示您选择一个文件;如果没有,则系统会提示您输入项目中的整个文件。选择文件后,提示会提供当前缓冲区中的语义标签列表,您可以选择在其后插入。

我提交了一个公关Emacs的重构。如果您想不等待PR就尝试完整代码,请单击此处

这是一个演示(当您START DEMO在底部看到它时开始):

弹丸语义插入功能原型

您也可以仅使用Senator复制和运行原型。只要point在函数签名或函数主体内部的任何位置,run (默认情况下senator-copy-tag绑定)C-c , M-w,它将复制整个函数:签名和主体。但是,如果需要,可以通过运行默认senator-yank-tag绑定的命令仅粘贴签名C-c , C-y。按C-y粘贴整个功能签名及其主体。senator-copy-tag甚至可以将函数签名扩展到多行,如下所示:

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

尽管此方法不会直接插入具有相同名称的缓冲区,但在其他情况下更适用。仅当您在同一目录中有两个文件且名称相同但扩展名不同时,您的用例才有效。如果函数声明和函数定义必须保留在具有不同名称的不同文件中怎么办?

EDIT2:这是一个使用语义标记智能插入功能原型的示例。当前,您只能基于顶级语义标签的相对位置(“之前”和“之后”)进行插入。我会更新,使用户能够在语义标签齐备,拥有多个位置的任何地方插入(即当一个标签是Class,它应该提供额外的位置:publicprojectedprivate)。当您START DEMO在底部看到时,演示开始:

弹丸语义插入功能原型2

奖励:如果要.cpp从头文件在文件中生成空函数定义的列表,请使用member-functions.el。但是很快,我将用语义+射弹替换它。


3

以下命令应执行此操作。它通过了我的测试,并且没有外部依赖性。

(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

认为以下应该起作用(对我有用):

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

这需要smartparens,尽管您可以破解自己的副本,sp-backward-up-sexp如果这是不可接受的。

还要注意,这会将标头放置在标题的(point)最后位置。由于您没有指定想要的位置,因此我认为这可能是最好的。当然,如果要在末尾附加,可以在(end-of-buffer)之前放置一个(yank)。当然,您可以添加一些奇妙的东西,例如在该点附近创建新线并在此处拉线,但这取决于您的口味。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.