PHP標準関数のsnippetを作る
寝れないのでご無沙汰エントリ。
http://hg.apgwoz.com/yasnippet-php-mode/
ここのを使ってたりしたんですが、どうもカスタマイズしたくなってきて
こんな感じで、自分用オレオレPHP標準関数snippetを生成しました。(作ったのは結構前なんですが)
オレオレなところは、
- yasnippetはanything-c-yasnippetからしか使ってないので、それに特化した感じで。
- anythingの候補選択時に、関数の簡単な説明も表示したい。(関数名だけじゃわかんない)
- 引数毎に、TABで移動するのは面倒なのでまとめて一つのフィールドに。(アドバイス程度に表示するくらいに)
get_defined_functions()を使って、実行環境に定義されている関数を取得し、
PHPのドキュメントにぶつけてsnippetを生成します。
anything-c-yasnippet等の導入方法などは、作者のid:IMAKADOさんのエントリを参照。
http://d.hatena.ne.jp/IMAKADO/20080401/1206715770
1. PHPのドキュメントを落としてくる
http://jp.php.net/download-docs.php
から php_manual_ja.tar.gz(英語のでもたぶん大丈夫です)をwgetしてきます。解凍したらhtmlというディレクトリ以下にファイルが展開されます。
2. snippet生成
下記の、やっつけ生成スクリプトをコピペして実行します。
snippet_gen.php
#!/usr/bin/env php <?php define('DOC_DIR' , './html'); // PHPドキュメントディレクトリ define('SNIPPET_DIR', './snippets'); // snippet作成先ディレクトリ // snippetファイルフォーマット #name : 関数名 : 説明文 $SNIPPET_FORMAT = <<<EOF #name : %-30s : %s # -- %s EOF; if (!is_dir(SNIPPET_DIR)) { mkdir(SNIPPET_DIR) or exit("can't make snippet directory: " . SNIPPET_DIR . PHP_EOL); } // aliases.htmlを無理やり解析してから、エイリアス関数名 => エイリアス先関数名のハッシュを作る $alias_file = sprintf('%s/aliases.html', DOC_DIR); if (!is_file($alias_file)) { exit("alias doc file does not exist" . PHP_EOL); } $body = file_get_contents($alias_file); $alias_pattern = <<<EOF <tr[ ]valign="middle"> \s+ <td[ ]align="left">(.+?)</td> \s+ <td[ ]align="left"><[^>]+>(.+?)\(\)</[^>]+></td> .+? </tr> EOF; preg_match_all("|$alias_pattern|xms", $body, $matches, PREG_SET_ORDER); // エイリアス名 => エイリアス先関数名 $alias_map = array(); foreach ($matches as $matche) { $alias_map[$matche[1]] = $matche[2]; } // 定義済み関数を1件ずつ処理 foreach (array_shift(get_defined_functions()) as $function) { $name = isset($alias_map[$function]) ? $alias_map[$function] : $function; list($description, $arguments) = get_func_information($name); // エイリアスの場合は、説明文にエイリアスと追記 if ($name !== $function) { $description = "[Alias $name] $description"; } // snippetファイル作成 $snippet_file = sprintf('%s/%s', SNIPPET_DIR, $function); $snippet = $arguments ? sprintf('%s(${1:%s})', $function, $arguments) : sprintf('%s($1)' , $function); if (!file_put_contents( $snippet_file, sprintf($SNIPPET_FORMAT, $function, $description, $snippet))) { echo "can't wirte snippet file: $function" . PHP_EOL; } } function get_func_information($function) { $name = strtr(strtolower($function), array('_' => '-')); $doc_file = sprintf('%s/function.%s.html', DOC_DIR, $name); $description = ''; $arguments = ''; if (is_file($doc_file)) { $body = file_get_contents($doc_file); // 説明文 $r = preg_match('|<title>(.+?)</title>|ms', $body, $matches); $description = $r ? filter($matches[1]) : ''; // 引数を無理やり解析 $r = preg_match('|<div class="methodsynopsis dc-description">.+?\((.+?)\).+?</div>|ms', $body, $matches); $arguments = $r ? filter($matches[1]) : ''; if ($arguments === 'void') { $arguments = ''; } } else { echo "doc file does not exist: $function" . PHP_EOL; } return array($description, $arguments); } // 不要な文字列を除去する function filter($str) { $str = strip_tags($str); $str = html_entity_decode($str); $str = preg_replace(array("|\n|", '|\s{2,}|'), array('' , '' ), $str); return trim($str); }
実行したらsnippets以下にファイルが作成されるはずなので、後はこんな感じで自分のsnippet配下に登録して..
$ ./snippet_gen.php $ cp snippets/* ~/.emacs.d/snippets/text-mode/php-mode/
M-x yas/reload-all でyasnippet再読み込み。
動かなかったらゴメンナサイ。
php-completionの関数名補完と連携してみたいなあ。