OS X Mavericksとdocdiff 0.5.0

単語単位での2つのファイルの相違点をカラー表示してくれるdocdiffは非常に重宝します。wdiffだと日本語がうまくいかないということで、rubyで作られているdocdiffを使っていますが、Mavericksにアップデートしたら動かなくなるとか、インストーラが以前はあったけど現在のシステムで動かないといろいろあり、困ってしまいました。ソースから動かす方法を、ほとんど自分の備忘録として書いておきます。

まず、githubにあるdocdiffのサイトから、ソース一式を「Download ZIP」ボタンでダウンロードします。Makeとかあるのだけど、Ver.1.8 onlyとあります。MavericksはVer.2.0がデフォルトです。それで、最低限の作業を考えた結果このような流れでできることが分かりました。ダウンロードしたファイルを展開したdocdiff-masterフォルダを基準に説明します。

  1. bin/docdiffを/usr/local/binにコピーする(あるいは/usr/binにコピー)
  2. libにある1フォルダ3ファイルを、Rubyのライブラリフォルダにコピーする

ライブラリフォルダとは、以下のパスになります。

/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0

これで、1でコピーした先にパスが通っていれば、docdiffコマンドとして稼働します。つまり、

docdiff --format=tty file1 file2

とすれば、カラーリングした結果でファイルの違いを文字単位で表示します。

なお、これをsvn上で使いたいので、次のようなことをしています。まず、上記、ダウンロードしたdocdiffファイルを/usr/local/binにコピーしたとして、/usr/binに以下のようなスクリプト「docdiff」を作ります。もちろん、実行権限を与えておきます。

#/bin/sh
/usr/local/bin/docdiff --format=tty $6 $7

こうすれば、svnでのコマンドで

svn diff -r PREV --diff-cmd=/usr/bin/docdiff file

とすることで、たとえば、こんな感じに見えます。このコマンドだと、現在のファイルとRevision 15のファイルを比べていて、赤は消えたもの、青は追加されたものです。黄色の代わりに緑になるという感じです。

shot0180

ブログを整理しました

会社員時代はブログは書いていなかったのですが、独立してしばらくしてから、だいたい2010年あたりからブログを書いていました。最初は、Mac OS X Server Snow LeopardのWikiを使っていたのですが、Lionへはうまく移行できたものの、その後に失敗(アカウントを消した)とか、Mountain Lionのときに変な場所に移行したとか、いろいろあって、2013年2月からはWord Pressで運用しています。

さらに、Mavericksに移行しようとして決定的な失敗をしてしまい(とほほ)。「過去のブログを見るだけ」のWebサーバとしても機能しなくなりました。FileMaker ServerをWebで動かしているのでどっちに転んでもやっぱり両方の用途に使うのはかなりしんどいです。ということで、日曜日に過去のブログをサルベージしました。PostgreSQLのデータベースからダンプして、手作業も入りながらのコピペで移行しました。INTER-Mediatorのブログは思考のプロセスを思い出すのに必要なこともあり、この関連記事は全部以降しました。他に、受けたとか、今でも意味があるというのはみんな移行しましたが、OS X Server関連はもういいかということで省略としました。

そんなわけで、過去の記事が突然、Twitter公開とかでよみがえってしまってすみませんでした。これで、ここ何年かの消えた記事が復活して一安心です。

[IM]メールをポストする機能を追加

2014/2/15にコミットしたINTER-Mediatorでは、メールの送信を機能として組み込みました。つまり、メール送信の処理をプログラムを一切しなくても、宣言的な記述だけでできるようになりました。

まず、メールはサーバで送ります。送信方法は、PHPのmail関数を使う方法なので、UNIX系ならsendmailコマンドをたたく方法になります。一方、これだとSMTPサーバへの転送ができないので、qdsmtpも組み込みました(Thanks to Mr. Spok)。SMTP認証はPlainのみの対応となっています。Windowsの場合はmail関数がすでにSMTPですので、php.iniにサーバ情報などを書くことで対処できます。なお、Windows環境はチェックしていないので、何かあれば知らせてもらえると助かります。

ただ、これだけではだめだろうというのはご存知の方はお分かりかと思いますが、昔作っていたOMEというメールソフトにはPHPのクラスもあったので、それをUTF-8で動くように改造してエンコードなどをさせるようにしました。ちなみに、さらにその前に『メール送信システムの作り方大全』という書籍も書いていて、その中の一部のクラスを使いやすいようにしたのがOME.phpです。この本、もう10年以上前なのですね…。

定義ファイルに指定可能なキーワードは以下の通り全て列挙します。しかしながら、すべてを記述することはないです。

IM_Entry(
    array(   // Contexts
         array(
            'name' => 'request',
            'send-mail' => array(
                 'new' => array(
                    'from' => '',
                    'to' => 'email',
                    'cc' => '',
                    'bcc' => '',
                    'subject' => '',
                    'body' => '',
                    'from-constant' => 'Officer <info@msyk.net>',
                    'to-constant' => 'msyk@me.com',
                    'cc-constant' => 'businessmatching@cocoa-study.com',
                    'bcc-constant' => '',
                    'subject-constant' => 'Cocoa勉強会ビジネスマッチング申し込み',
                    'body-constant' => 'テストメール',
                    'body-template' => 'welcome.txt',
                    'body-fields' => 'name,compnay,email,tel',
                    'f-option' => true,
                    'body-wrap' => 68,
                 )
             )
         )
    ),
    array(   // Options
        'formatter' => array(...),
        'smtp' => array(
            'server' => 'mysmtp.msyk.net',
            'port' => 587,
             'username' => 'msyktest@msyk.net',
            'password' => 'oshienai',
        )
    ),
    array('db-class' => 'PDO'),
    false
);

メールを送信するタイミングの指定

‘send-mail’キーの配列の次のレベルのキーとして、’load’ ‘edit’ ‘new’のいずれかを指定できます。それぞれ、データベースからの読み込み時、更新時、新規レコード作成時を意味し、コンテキストに対するそれぞれのタイミングでメールを送信します。いずれも、データベース処理が終了してからメールの送信にかかります。上記の例では、新規レコード作成時に、メールが送信されます。

宛先や送信者の指定

宛先の指定は、’to’ないしは’to-constant’キーに指定します。もし、宛先が一定のものであれば、’to-constant’キーに指定をしてください。’to’キーにはフィールド名を指定します。データベース処理の結果、たとえば新規レコードの場合には新しいレコードが1つ作成されて、そのレコードの内容から’to’キーに指定したフィールドより宛先のデータが取り出されます。編集も原則は1レコードです。一方、読み出しの場合は1レコードにならないかもしれませんが、その場合は最初のレコードから取り出します。むしろ、1レコードに絞り込むコンテキストにするのがメールを送る場合には妥当だと考えられます。

メールアドレスは「名前 <アドレス>」ないしは「アドレス」の2つの形式のみのサポートになります。’to-constant’キーに対する値、あるいは’to’キーで指定されるフィールドの値は、このどちらかの形式にしてください。

cc、bccについてもまったく同様のルールです。’to’と’to-constant’の両方の指定があれば、’to-constant’が優先されます。cc、bccでも-constantが優先となります。

fromについても、fromとfrom-constantキーがあり、設定や動作等は同じです。ただし、UNIXでSMTPサーバを使わない場合だと、通常はソース側のFrom:は無視されて、UNIXアカウントそのものをFrom:として設定してしまいます。ただし、サーバ側で許可されていれば「’f-option’ => true」の指定を定義ファイル内に記述することで、sendmailコマンドの-fパラメータを指定して、送信者の指定が可能です。

件名と本文の指定

件名は、subjectあるいはsubject-constantのいずれかのキーに指定します。toなどと同じルールです。

メールの本文は、定義ファイル内に指定した通りに送信する’body-constant’、フィールドの内容をそのまま送信する’body’に加えて、テンプレートの処理も可能です。優先順はテンプレート、body-constant、bodyの順になりますので、不要なフィールドは消しておきましょう。

テンプレート処理をするには、テンプレートのファイル名をbody-templateキーに指定します。このとき、テンプレートのファイルは、定義ファイルのあるディレクトリを基準に検索します。つまり、定義ファイルといっしょに何らかのテキストファイルを億としたら、body-templateキーの値はファイル名だけでかまいません。

テンプレートのファイル内では、そのファイルの内容を本文にしますが、フィールドの値との置き換えも可能です。置き換えたい箇所に@@1@@、@@2@@のように、アットマーク2つに囲まれた1から始まる整数を指定します。テンプレートのファイルはUTF-8で保存します。

フィールドについては、’body-fields’キーに、半角のカンマで区切って指定します。最初が1で、順次番号が増えるようになります。例で言えば、emailフィールドの値は、テンプレート内の@@3@@と置き換わって表示されます。’body-fields’キーを省略すると、テンプレートのファイル通りにメールが送信されます。

本文は一定の長さで改行を入れます。既定値では72バイトですが、’body-wrap’キーで異なる値にできます。0に設定すると改行しません。ここで、バイト数ですが、実際のバイト数ではなく、日本語は2バイト、英語は1バイトと数えた結果で示しています。実際のエンコードはUTF-8なので、嘘と言えば嘘のカウントになりますが、おそらくこうして指定をすることに慣れている人が多いので、ここでは実態とは関係ない数値ではありますけども実用的という意味で「2バイトルール」でカウントしたものとします。

UNIXの場合のSMTPサーバの指定

定義ファイルのIM_Entry関数の第3引数のオプション領域に’smtp’キーで配列を指定します。その他のキーは、前記の例の通りで、キーを見れば意味は分かると思います。もし、SMTP認証をしない場合は、serverとportだけを指定します。認証する場合は、server, port, username, passwordを指定します。したがって、2つないしは4つの要素があるかのどちらかになります。

SMTPサーバの指定は、params.phpファイルでも指定が可能です。変数名として、$sendMailSMTPの定義し、値は’smtp’の右側の配列と同様に指定をします。params.phpファイルでの指定よりも、定義ファイルの指定が優先されます。どこにもSMTPサーバの設定がない場合には、mail関数での送信になります。

Windowsの場合は、’smtp’の指定やparams.phpファイルでの指定は一般には不要ですが、もし設定すれば、mail関数ではなく、qdsmtpによるメール送信ができます。

送信されるメールの文字セット

基本的にはメールはUTF-8でエンコードして送られます。ISO-2022-JPの指定はOME.phpではできるのですが、必要なら定義ファイルでの指定ができるようにしようと思います。リクエストがなければUTF-8固定で行きます。

ヘッダについては、base64のインラインエンコードを、ASCIIコード以外の文字について行います。本文はそのままですが、ヘッダのContent-TyleのcharsetにUTF-8という文字を付けます。つまり、本文はbase64等でのエンコードは行いません。

ファイルの添付は実装する予定はありません。ファイルを送りたいのなら、そのリンクを送るようなアプリケーションの動作にしましょう。

Internet Explorer 8にまた苦しめられる

Web系のお仲間の皆さんも同様にいつも苦しめられていると思われるIE8ですが、ここ最近にあったいくつかのはまりポイントを自分の備忘録としてもまとめておきます。まあ、あと数年はIE8からは逃れられないということで。

  • jQuery 2.0を入れたら動かない(対応ブラウザからはずれている)。慌てて1.10に戻す
  • JavaScriptではObject.keysという記述が使えない
  • 要素のid名と同一のグローバル変数が作られる

特に最後のは苦労しました。メッセージを見る限りは、「オブジェクトでサポートされていないプロパティまたはメソッドです。」と出ます。プログラムはこんな感じ。INPUTタグ要素で、idが「yourname」になっていると思ってください。

yourname = document.getElementById("yourname").value;

まさかgetElementByIdが使えないのかと思ったら、使えます。他の箇所では動いている。valueがない訳は絶対にない。当然右辺を疑うわけですが、必死に検索した結果、問題は左辺でした。つまり、以下の条件が満たされると発生されるトラブルだったのです。

  • IE8でJavaScriptでプログラムを組む
  • ページ内の要素のid属性と同一の変数を、何も定義しないでJavaScript側で使う

どうやら、IE8は、id属性と同一名のグローバル変数を勝手に定義するようです。上記のプログラムは、つまり、勝手に定義しているyourname変数が何らかのオブジェクトを記録していて、そのオブジェクトが書き換えに対応していないためにエラーが出ていると思っていいようです。

対処法は「var yourname」のように頭にvarを付けるか、ページにリンクされたjsファイル等でグローバルとして「var yourname;」のように変数定義することで回避できます。自分自身のグローバルでも、同一名称の変数は後から定義した方のストレージが有効になるので、IEが勝手に作るグローバル変数は無視されるようになるということです。つまり、変数定義を必ずしろというプラクティスをしていれば、エラーに合わないのですが、こう書いてしまったらエラーになってしまうよということですね。

講義でのペアプログラミングの使いどころ

今年度のJavaの講義では、ペアプログラミングを導入して、演習に取り組む時間を比較的多く取ってみました。そして、必須課題として、その感想を聞きましたが、総合的に良かったあるいはどちらでもないというのが33%、残りの67%は「よくなかった」という感想でした。理由は知らない相手や、理解度の違う相手との演習は思った以上に神経を使うということで、それほど効果的ではないという感想でした。全員に利点とデメリットも書かせましたが、ほぼ、同じような答えで、よくなかったと感じた人たちも利点がある点は理解しています。なんかうっとおしからいやだ…ということではなく、きちんと理由を考えさせた上で、総合評価させています。

1つあるのは、友達関係にない相手と組ませることになるのは、確かに大変かもしれません。とは言え、講義運用上どうしてもそれは必要になります。レベルが違う人と組むのは、それなりに悪い事ではないと思うのですが、「課題を行う」というまじめな学生達のゴールにとっては足かせと感じたのかもしれません。ただ、他人がどう考えるのかということが理解できる点は良かった点として挙げられていました。

今年度は比較的多くペアプロをやりましたが、来年度は、限定的にやろうかと思っています。アジャイルのプラクティスは、形のないソフトウエアを作るプロセスを進化させるいちばん有力な手法だと感じています。ただ、プログラミングの初心者でできそうなプラクティスはペアプロではないかというのが当初の考えです。しかしながら、まずは基礎力をつけてレベルを比較的揃えてからやるというのが重要なようです。また、講義全体の進行度合いとはある程度独立した課題を与えるひつ模様もあると感じました。つまり、講義の流れは追えている学生もいれば、遅れている学生もいるということで、そこで一様でなくなる可能性があるということです。来年度は、「ペアプロの日」つまり、ペアプロで課題だけをやる日を1回か2回確保しようと思っています。

ようするにペアプロが機能する状況を、講師が作った上で、させないといけないという当たり前の結論なのですが、現場の開発と教育の現場の違いはまさにそういうところではないかと感じました。