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ソリューションはありますか?
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ソリューションはありますか?
回答:
更新:この問題などを完全に解決するセマンティックリファクタリングパッケージを作成しました。デモを見て、どのように機能するかを確認できます。この文の後のこの回答の残りのテキストは古く、歴史的な理由でそこに置いています。
古い回答:
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-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)
{
.....
}
このアプローチでは、同じ名前のバッファーに直接挿入されませんが、他のケースではより適切です。このユースケースは、同じディレクトリに同じ名前で拡張子が異なる2つのファイルがある場合にのみ機能します。関数宣言と関数定義が異なる名前の異なるファイルに存在しなければならない場合はどうなりますか?
EDIT2:セマンティックタグを使用した関数プロトタイプのスマートな挿入の例を次に示します。現在、トップレベルのセマンティックタグの相対位置(「前」と「後」)に基づいてのみ挿入できます。更新して、ユーザーがセマンティックタグを使用できる任意の場所に挿入できるようにします。つまり、より多くの位置を使用します(つまり、タグがの場合、Class
追加の位置を提供する必要があります:public
、projected
およびprivate
)。START DEMO
下部に表示されると、デモが始まります。
おまけ:.cpp
ヘッダーファイルからファイル内の空の関数定義のリストを生成する場合は、member-functions.elを使用します。しかし、すぐに、セマンティック+発射物に置き換えます。
次のコマンドで実行できます。テストに合格し、外部依存関係はありません。
(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 ";"))))))
私は以下がうまくいくと思います(私にとってはうまくいきます):
(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)
。もちろん、ポイントの近くに新しいラインを作成したり、そこにヤンクしたりするなど、より洗練されたものを追加できますが、それはあなたの好み次第です。