foo.cからfoo.hにプロトタイプを自動的に挿入するにはどうすればよいですか?


11

Cプログラムをファイルfoo.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ソリューションはありますか?

回答:


9

更新:この問題などを完全に解決するセマンティックリファクタリングパッケージを作成しました。デモを見て、どのように機能するかを確認できます。この文の後のこの回答の残りのテキストは古く、歴史的な理由でそこに置いています。

古い回答

senator-copy-tag関数シグネチャを正確にコピーしてから、ソースファイルに貼り付けることができます。senator-copy-tagを有効にすると、上院議員のコマンドが使用可能になりますsemantic-mode

(semantic-mode 1)

セマンティックは、Emacsの組み込みパッケージです。

Semantic SenatorとProjectileをコマンドに組み合わせて、関数プロトタイプをプロジェクト内のどこからでも他のファイル(同じ名前で拡張子が異なるファイル)に挿入できます。他にファイルが1つしかない場合、コマンドはそのファイルにすぐに挿入します。複数の場合は、ファイルを選択するように求められます。ない場合は、プロジェクト内のファイル全体の入力を求められます。ファイルを選択すると、プロンプトが表示され、現在のバッファーにあるセマンティックタグのリストが表示されます。このタグを後で挿入することを選択できます。

私が提出したPRをするEmacsのリファクタリング。PRを待たずに試してみたい場合の完全なコード:ここをクリックしてください

これがデモです(START DEMO下部に表示されたときに開始します)。

発射体-セマンティック-挿入-関数-プロトタイプ

プロトタイプをコピーして機能させるには、セネターのみを使用することもできます。ポイントが関数のシグネチャまたは関数の本体runのどこかにある限り、run senator-copy-tagC-c , M-wデフォルトでバインドされ、関数全体(シグネチャと本体の両方)をコピーします。ただし、デフォルトでsenator-yank-tagバインドされているコマンドを実行して、必要な場合にのみ署名を貼り付けることができC-c , C-yます。C-y関数シグネチャ全体をその本体と一緒に押して貼り付けます。senator-copy-tagこのように複数行に展開された関数シグネチャでも機能します:

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

このアプローチでは、同じ名前のバッファーに直接挿入されませんが、他のケースではより適切です。このユースケースは、同じディレクトリに同じ名前で拡張子が異なる2つのファイルがある場合にのみ機能します。関数宣言と関数定義が異なる名前の異なるファイルに存在しなければならない場合はどうなりますか?

EDIT2:セマンティックタグを使用した関数プロトタイプのスマートな挿入の例を次に示します。現在、トップレベルのセマンティックタグの相対位置(「前」と「後」)に基づいてのみ挿入できます。更新して、ユーザーがセマンティックタグを使用できる任意の場所に挿入できるようにします。つまり、より多くの位置を使用します(つまり、タグがの場合、Class追加の位置を提供する必要があります:publicprojectedおよびprivate)。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)。もちろん、ポイントの近くに新しいラインを作成したり、そこにヤンクしたりするなど、より洗練されたものを追加できますが、それはあなたの好み次第です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.