選択範囲をポップアップウインドウで表示するgoogle chrome拡張を作った
写経とかでwebページ内のサンプルプログラムときに使うgoogle chrome拡張を作った。コピーしたい範囲を含む部分を選択してツールバーのボタンを押すと、選択範囲を含む範囲を切り取って小さなポップアップウインドウで表示するというもの。自分がmac book使ってる時に画面が狭くて苦労したので役に立つかもと思って作ってみた。スタイルは参照されているスタイルシートしか取ってこなくスクリプトとかも無視してしまうので、表示は少し変わってしまう。全くたいした物ではないですが以下で公開してます。
https://chrome.google.com/extensions/detail/defdgohhfapbjdbmaepdammfhfkdihlk
Javascript: The Good Parts読んだ
オライリーのJavascript: The Good Partsを読んだ。
第二章あたりで面白くない感じがして放り出してしまっていたんだけど、続きもちゃんと読んだらやはりかなり面白かった。特に第四章、第五章はかなり良かった。この本ではJavascriptがプロトタイプベースの継承を用いることを強調している。自分もクラスベースのオブジェクト指向に慣れていたためか、プロトタイプベースの継承がどうも理解出来ていなかったが、この本を読むことによって実は結構簡単なことじゃないかと思えてきた。プロトタイプ継承の自分の理解をまとめる。
- 同じコンストラクタから作られたオブジェクトは同じprototypeオブジェクトを共有する
- prototypeオブジェクトは親(継承元)のprototypeオブジェクトの参照を持っている(prototypeチェーン)
- 自分のオブジェクトが所有してないプロパティへのアクセスはprototypeチェーンをさかのぼり探す
こうして書くとやはりとてもシンプルに感じる。この他にもこの本では、自分の理解が曖昧だったとこを整理できたとこが沢山あって良かった。多くの人が勧めてる本ではありますがおすすめです。
XULからGoogle Maps APIは使えない
仕事関連でGoogle Maps APIを使うFirefox拡張をつくっていたのだけど、XULで読み込んだjavascriptでGoogle Maps APIが使えなくて困っていた。で、解決方法は、XULからGoogle Maps APIを直接使うのはあきらめ、
Ubuntu10.10 Netbook Editionでemacsclientの終了時にemacsが固まる
という問題があって困っていた。で、調べていたら、原因がemacsclient自体ではなく、emacsclientの終了時に最小化させる設定を入れていて、その最小化が原因で固まってしまっていたらしいということに気付いた。
ちなみに、emacsclient終了時に最小化させる設定は以下のようにしている。
(server-start) (defun iconify-emacs-when-server-is-done () (unless server-clients (iconify-frame))) ;; 編集が終了したらemacsをアイコン化する (add-hook 'server-done-hook 'iconify-emacs-when-server-is-done)
この設定は「Emacs テクニックバイブル」という本のマネ。このserver-done-hookを外すようにしたら、終了時に固まる問題は出なくなった。よかったよかった。
Text::Templateを使ってみた
Text::Templateというのを使ってみたのでメモ。
これの特徴は、「テンプレートの記述にPerlをそのまま書ける」ということにあるらしい。
- 独自のテンプレート言語を覚えなくてよい
- 記述力が高い
というのがメリット。そのかわり、デメリットとしては
- 何でも書けるからテンプレートに書きすぎてしまう可能性がある
というのがあるかと思われる。使い方次第だと思うけど。
使い方
基本的な使い方は以下のような感じ。
use strict; use warnings; use utf8; use Encode; use Text::Template; use IO::File; # 日本語を扱うときなどは自分でファイルを開く必要があるっぽい my $fh_in = new IO::File("template.txt", "r") or die "$!"; $fh_in->binmode(":utf8"); my $template = Text::Template->new(TYPE => 'FILEHANDLE', SOURCE => $fh_in) or die "$Text::Template::ERROR"; # 入力はここでcloseして問題ない $fh_in->close; # テンプレートで展開される変数 my $name = "名無し"; # テンプレート展開 my $result = $template->fill_in(HASH => {name => $name}); # 出力 if (defined $result) { print encode("utf8", $result); } else { die "couldn't fill in template : $Text::Template::ERROR"; }
fill_inという関数に与えるnameでテンプレートで展開する用の変数を渡す。テンプレートのファイルはtemplate.txtとした。例えば内容は以下のようになっているとする。
ハロー {$name} さん!
{}で囲まれている部分にPerlプログラムを記述できる(ただしデリミタの変更は可能らしい)。この例の場合は、$nameが展開されて以下のような出力が得られる。
ハロー 名無し さん!
一応だけど、ここでそれぞれのファイルの文字コードはutf8。
関数を使う
テンプレートから関数を使うことも出来る。最初の例のfill_in関数の引数のHASHで関数を渡せばよい。
# 関数を渡す my $result = $template->fill_in(HASH => {name => $name, hello => \&hello}); sub hello { my $name = shift; return "ハロー $name さん。"; }
テンプレートファイル(template.txt)には以下のように書く。
{hello($name)}
クラスを使う
テンプレートにクラスのオブジェクトを渡すことも出来る。普通に変数を渡すのとは違い、参照渡しをするのがポイント。
# サンプルのクラス package Sample; use strict; use warnings; use utf8; sub new { my ($class) = @_; my $self = { NAME => "" }; bless $self, $class; return $self; } sub set_name { my ($self, $name) = @_; $self->{NAME} = $name; } sub hello { my $self = shift; return "ハロー $self->{NAME} さん。"; } package main; use strict; use warnings; use utf8; use Encode; use Text::Template; use IO::File; # 日本語を扱うときなどは自分でファイルを開く必要があるっぽい my $fh_in = new IO::File("template.txt", "r") or die "$!"; $fh_in->binmode(":utf8"); my $template = Text::Template->new(TYPE => 'FILEHANDLE', SOURCE => $fh_in) or die "$Text::Template::ERROR"; # 入力はここでcloseして問題ない $fh_in->close; # テンプレートで展開される変数 my $name = "名無し"; my $sample = new Sample; # テンプレート展開。オブジェクトを渡す my $result = $template->fill_in(HASH => {name => $name, sample => \$sample}); # 出力 if (defined $result) { print encode("utf8", $result); } else { die "couldn't fill in template : $Text::Template::ERROR"; }
テンプレートファイルには以下のように書く。
{$sample->set_name($name); $sample->hello}
クラスを使う2
fill_inするところで、クラスが使えるようになっていれば、テンプレートの中でクラスをnew出来る。つまり、テンプレートファイルに以下のように書けるということ。
{$obj = new Sample; $obj->set_name($name); $obj->hello}
どうもここまでくると、テンプレートでやり過ぎてしまっているような感は拭えないが、使いどころはあるかもしれない。
だいたいこんな感じ。あと以下のようなところが分かってないが気になっている。気が向いたら調べる。
- テンプレート側とプログラム側の名前空間の扱い方
- 後ろの改行を消すやり方はあるか?(M4のdnl的なもの)
WindowsプログラムのウインドウプロシージャからC++のウインドウクラスにアクセスする方法
WIN32でWindowsプログラム作ろうと思って検討した内容のメモ。
WIN32のプログラムって、ウインドウプロシージャ(WndProcなど)の関数をコールバック関数にして、普通はここに巨大なswitch文があってメッセージを振り分ける構造になっています。
また、C++ではWindowsのウインドウにクラス(C++のクラス)を対応させて、普通は作ります。
この時に、ウインドウプロシージャから、どうやってウインドウクラスのオブジェクトを見れるようにするか、というのでちょっと悩んでしまったので、オープンソースプラグラムでその辺の設計をどうしてるか調べてみました。
見てみたのは、Notepad++(http://sourceforge.net/projects/notepad-plus/)とFLTK(http://www.fltk.org/)。WindowsのC++であまり規模が大きすぎないオープンソースということで参考にさせていただいきました。
GWL_USERDATAにオブジェクトポインタを関連付ける(Notepad++)
以下のようにする。Windowsプログラムではそこそこ一般的な方法みたい。
- メインのCreateWindow関数のlpParamにthisを渡す
- WM_NCCREATEメッセージで以下のようにポインタを取得し、GWLP_USERDATAに設定する
Notepad_plus_Window *pM30ide = (Notepad_plus_Window *)(((LPCREATESTRUCT)lParam)->lpCreateParams); ::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pM30ide);
- その後のメッセージ処理は、以下のようにメインウインドウのポインタを取得して行う
Notepad_plus_Window *pM30ide = (Notepad_plus_Window *)::GetWindowLongPtr(hwnd, GWL_USERDATA))->runProc(hwnd, Message, wParam, lParam);
もしかしたらWM_NCCREATEじゃなくWM_CREATEでもポインタは取れるかも(未確認)。
グローバルにデータを置かないですむという利点があると思う。
複数ウインドウオブジェクトをハンドルに関連付けて管理 (FLTK)
ちゃんと読めてないから、間違っているかもしれないけど、複数のウインドウをリストで管理しているデータ構造があり、ウインドウハンドルを引数にしてウインドウプロシージャの頭でウインドウクラスを取得してるっぽい。データ自体はグローバルにおいてるように見える。
複数のウインドウを考慮された設計かな?
また、2つの方法を合わせたやり方もある気がする。。。
elispでディレクトリ名を操作する関数
メモ。
- ディレクトリ名として扱う
(setq my-shared-directory "~/Dropbox") (file-name-as-directory my-shared-directory)
上と下の結果がどちらも"~/Dropbox/"になる
(setq my-shared-directory "~/Dropbox") (file-name-as-directory my-shared-directory)
- ディレクトリ名をつなげる
(concat (file-name-as-directory directory-name) file-name)
[出典]
http://www.gnu.org/software/emacs/elisp/html_node/Directory-Names.html