ラベル x の投稿を表示しています。 すべての投稿を表示
ラベル x の投稿を表示しています。 すべての投稿を表示

2010/06/08

install-rurema

Rubyの新リファレンスマニュアルをコマンドラインから簡単に引くためのツールを書いた

うわっこれいいな。早速 install

http://github.com/yhara/myrurema

README を読むと gem を使ってインストールできるとあったんですが、ちょっと gem 苦手な為 gem を使わないで動せないものかな?と、try してみました。 (OS X 10.6.3)

$ git clone git://github.com/yhara/myrurema  rurema
$ cd rurema/myrurema/bin
$ vim rurema
# shebang を自分の ruby 1.9.2 のパスに修正。#!/usr/bin/env ruby #  changed
$ pwd
/path/to/rurema/myrurema/bin

# とりあえず

$ ./rurema
Usage: rurema [options]
         --init                       initialize rurema
         --update                     update documents and database
...(略)

# README を読みながら
# Init

$ ./rurema --init --ruremadir=/path/to/rurema/data

# これを実行すると ~/home に.subversion ディレクトリができた。

try

$ ./rurema Array#index
You don't have a database for ruby 1.9.2.
109 Make it now? [y/n]
...略

y としたけど ~/home/.rurema を作っていないのだからアップデートできない。

$ ln -s /path/to/rurema/data ~/.rurema

シンボリックはってみた

# Update

$ ./rurema --update --ruremadir=/path/to/rurema/data

# この時勢いよくファンが回りはじめてちょっと不安になった。$ top してみると ruby(OS X に標準インストールされてる方) 一時的に50% 台になったりしつつも基本的には10% 台で動いてた。ずっとみていたら急に90% 近くなってあ”と思ったとたんに終了してほっとした。

# try

$ pwd
$ /path/to/rurema/myrurema/bin
$ ./rurema Array#index
Array#index
--- index(val)           -> Integer | nil 
--- index {|item| ...}   -> Integer | nil 

指定された val と == で等しい最初の要素の位置を返します。
等しい要素がひとつもなかった時には nil を返します。
...(略)


わい
動かすことができたのでエイリアスにしちゃう。

$ vim ~/.bashrc
# alias 'rurema'='/path/to/myrurema/bin/rurema'

$ source ~/.bashrc
$ rurema String#size
String#size
--- length -> Integer
--- size -> Integer

文字列の文字数を返します。バイト数を知りたいときは bytesize メソッドを使ってください。

@see [[m:String#bytesize]]


コマンドラインからるりまをみることができました。うれしいな。便利だなー。

+++ まとめ +++

# Download rurema 
$ git clone git://github.com/yhara/myrurema rurema
$ cd rurema/myrurema/bin

# shebang を自分がインストールした ruby 1.9.2 のパスに修正。#!/usr/bin/env ruby #  changed
$ vim rurema

# 確認 & ヘルプ
$ ./rurema

# database directory
$ mkdir /path/to/rurema/data

# リンク作成
$ ln -s /path/to/rurema/data ~/.rurema

# init and update
$ ./rurema --init --rubyver=1.9.2 --ruremadir=/path/to/rurema/data
$ ./rurema --update --rubyver=1.9.2 --ruremadir=/path/to/rurema/data

# みてみる
$ ./rurema String#size

# alias
# $ vim ~/.bashrc 
# $ source ~/.bashrc


参照
http://ja.wikipedia.org/wiki/Subversion
SnowLeopard には標準でSubversion入っていた。知らなかった。

2010/05/16

self.send()[1]

gdata-1.1.1 を読んでいたら gdata-1.1.1/lib/gdata/client/base.rb に

41           self.send("#{key}=", value)

とあった。

それで
クラスを初期化する際 hash をもちいてインスタンス変数を一気に設定したい場合について考えてみた。

1) 最初にgdataでも使われている self.send() を使った場合

  3 class My_1
  4   attr_writer :id, :name
  5   attr_reader :name
  6   def initialize(h={})
  7     h.each{|k,v| self.send("#{k}=", v)}
  8   end
  9 end
 10 
 11 h = {:id=>'123', :name=>'abc'}
 12 p My_1.new(h)


実行結果
#<My_1:0xxxxxxxx @id="123", @name="abc">

ハッシュのキーと値がinstance 変数に設定されていることがわかる。
また attr_writer によって :id と :name 以外のkey を受け付けないよう設定されている。
これを確認する為、
h = {:id=>'123', :name=>'abc', :title=>'ddd'}
に変更し実行してみると
...(NoMethodError)

:title は attr_writer に定義されていないので instance 変数として定義できないことが確認できた。

2) 次に self[]= をつかってinstance 変数を設定するクラスの場合

 15 class My_2
 16   attr_writer :id, :name
 17   attr_reader :name
 18   def initialize(h={})
 19     h.each{|k,v| self[:"@#{k.downcase}"] = v}
 20   end
 21    alias []= instance_variable_set
 22    alias [] instance_variable_get
 23    private :[], :[]=
 24 end
 25 p My_2.new(h)


実行結果

#<My_2:0xxxxxxxx @id="123", @name="abc">

My_1 の場合と全く同じ結果を得ることができる。
では、My_1 の場合と同様に h を変更し
h = {:id=>'123', :name=>'abc', :title=>'ddd'}
として実行してみるとどうなるか?

実行結果

#<My_2:0xxxxxxxx @id="123", @name="abc", @title="ddd">


attr_writer とは無関係になんなく :title が定義されてしまった。
15行目のattr_writer :id, :name は class My_2 においては無意味のようだ。

では、あたかも attr_writer を設定したかのようにさせるにはどうすればいいのだろうか?

 14 class My_2
 15   @@ins_keys = [:id, :name]
 16   @@ins_keys.each{|x| attr_reader x}
 17   def initialize(h={})
 18     h.each{|k,v|
 19       key = k.downcase.to_sym 
 20       self[:"@#{key}"] = v if @@ins_keys.index(key)}
 21   end
 22   alias []= instance_variable_set
 23   alias [] instance_variable_get
 24   private :[], :[]=
 25 end
 26 h = {:id=>'123', :name=>'abc', :title=>'ddd'}
 27 p m = My_2.new(h)
 28 p m.name

実行結果

#<My_2:0xxxxxxxx @id="123", @name="abc">
"abc"


@@ins_keys を定義し19行目に if @@ins_keys.has_key?(k) を追加することで
attr_writer に「似た」役目をはたしてもらうことにした。
attr_reader は16行目にまとめた。
配列の要素を全て attr_reader にした。
配列の要素をチョイスして attr_reader したい場合はさらに2行加える必要あり。

@@ins_keys に登録されていない :title は定義されなくなった。
つまり定義したい instance 以外 が定義されるようなことはおこらないという意味で My_1 と同じ結果を得られるようになった。
ただし、My_1 ではerrorが返ってくるが My_2 では error にはならない。
error を返す必要があれば20行目直前に raise unless @@ins_keys.index(key) などすればいいのかも。

+++ メモ +++

0) self[] を initialize で使用しつつどの key を instance 変数として定義するかをちゃんと制御したい時
attr_writer で設定したつもりになっていてもそれは意味をなさないので、別途 式を用意するなどする必要がある。
あるいは最初から My_1 のような方法を採用した方がいいかも。
あるいは通常どおりに def initialize で @id = nil などと定義しておいて instance_variable_defined? を使う。

1) (派手に間違えているかもしれない)書きながら浮かんだイメージ
self.send()
は、一旦廊下に出て attr_writer ドアをノックしてから self 部屋に入るが、
self[]=
は、既にself 部屋の内側に入っていて attr_writer ドアの存在を意識していない。
といったようなイメージ。

2) git にあげてある 2010-amazon-api-jp に、上記の内容を反映する予定は未定。

続き

2010/04/21

2010-amazon-api-jp

SnowLeopard で OpenSSL がバージョンアップしたことに伴い
amazon-jp-api を作り直した。
=>
2010-amazon-jp-api

[参考になったURL]
OpenSSL SHA 256 の使い方はhttp://diaspar.jp/node/239 を参考にしました。

[主な変更点]
1, Mac OS X 10.6.3 で SHA256 を使えるようになったことに伴う変更。
module AmazonAuth => 新規に作ったモジュール。認証用。
2, 設定ファイル => 2つのモジュールにわけた。
3, class AwsItem => インスタンス変数の持ち方の変更。
4, class AmazonAccess => アマゾンにアクセスしデータを獲得したのちに AwsData.new(data).add_data でアイテムまで生成していたが、アイテム生成は他のクラスに移動させて、このクラスはアマゾンにアクセスしデータを獲得するだけのクラスに変更した。
5, class AwsDataWriter => 新規に作ったクラス。マーシャルデータを変更するためのクラス。
6, class AwsDataReader => 新規に作ったクラス。マーシャルデータを読み込んで表示させるためのクラス。
7, module AmazonAuth => 新規に作ったモジュール。アマゾン認証を行うためのもの 。

[変更されていない点]
1, ローカルで使うもの。
2, Ruby 1.9.1 だけで動き Ruby 1.8 系はサポートしていない。
3, マーシャルデータを使用している。
4, 指定したEAN の本やCDのデータをアマゾンから受け取ることができるがアマゾンサーバに対して検索はできない。
5, README に書いたオプション引数はそのまま。

[少しだけ気になっている点]
1, もともとのものは force_encodig を使わないように 変更している。今回もこの状態でうまくいったので受け取ったXMLデータが valid? かどうかだけチェックするにとどめ encode 変換は行っていない。このことによってなにか弊害があるのかないのかは謎。
2, timeout を使っている。使わないバージョンも作ってみたがあっさり挫折。
3, exec を使っている。exec を使わないバージョンを考えてみたがわからなくなって中断。
4, send を使っている。最近使い方を覚えたため、使ってみたかったから使っているにすぎない。あえて使う必要はないのかもしれない。

[このブログ内の関連する投稿]
=> http://midorex.blogspot.com/2009/06/amazon-web-with-ruby-191.html
=> http://midorex.blogspot.com/2009/08/amazon-product-advertising-api.html
=> http://midorex.blogspot.com/2009/12/forceencoding.html
=> http://midorex.blogspot.com/2008/12/amazon-aws-with-ruby191.html

[Amazon ラベルをもつ全ての投稿]
Amazon

2010/04/03

はじめての send

ISBN: 978-4048678841 | リファクタリング:Rubyエディション (大型本)

この本、私は対象読者ではなかった。飛ばし読みしていたらあっという間に p.165 までたどり着いてしまった。

そこで目にしたもの
p.165

サンプル
引数をまとめたHash を受け付けて、それらの引数をインスタンス変数に代入する SearchCriteria クラスがあるものとする。

とあり
p.166

Class.send :include, CustomInitilizers


send って何?といろいろ試してみた。

  1 #!/usr/local/bin/ruby191
  2 # coding: utf-8
  3 
  4 module Items
  5   module Setup
  6     def base(h)
  7       h.each{|k,v| self["@#{k}"] = v}
  8     end
  9     alias []= instance_variable_set
 10     alias [] instance_variable_get
 11   end
 12   class Music
 13     def initialize(h)
 14       self.base(h)
 15     end
 16   end
 17   class Book
 18     def initialize(h)
 19       base(h)
 20     end
 21   end
 22   Object.send :include, Setup
 23 end
 24 
 25 h = {:isbn=>'978xxx', :title=>'book-title', :price=>'1000'}
 26 p b = Items::Book.new(h)
 27 h = {:isbn=>'077xxx', :title=>'music-title', :price=>'2000'}
 28 p b = Items::Music.new(h)
 29 p b['@title']

=>
#<Items::Book:0xxxx @isbn="978xxx", @title="book-title", @price="1000">
#<Items::Music:0xxx @isbn="077xxx", @title="music-title", @price="2000">
"music-title"


最近知った あのaliasを使ってみた。

そして
「プログラミング言語 Ruby」p.285
を読み直した
Book.public_send :include, Setup
にしてもOKだった。

さらに
「Ruby Way」( Second edition)
にて send を探してみたら p.350 にsort_by のカスタムバージョン例の中で send を使う例があった。

self.sort{|x,y| x.send(sym) <=> y.send(sym)


この場合、x はArrayの要素でその要素のひとつひとつには Preson.new() Object が入っていて、
で、Presonの@name は attre_reader で読み込めるようになっている。ここがミソ。従ってソート対象として:name を指定することができる、と。
attre_writer :name だったらこれは成功しないだろう。
p.350 をジーとみているとうっかり send(@name)なのだと勘違いして理解しそうになるが、
send は「シンボル」を受けつけるのだから、send(@name) ではダメ。

+++ まとめ +++
send or public_send (Ruby 1.9) はシンボルを受けつける

module XXX
  module Setup ... end
  class Book ... end
  class Music ... end
  Object.send :include, Setup
end

Object.send とした場合は module が内包する[全て]のクラスのinclude メソッドに Setup module をおくりつけたことになる、と。
Object.send を Class.send としてみたら
`initialize': undefined method `base'
のエラーになった。

module XXX
  module Setup ... end
  class Book ... end
  class Music ... end
  Book.send :include, Setup
end

とした場合は module XXX が内包するBook クラスに[だけ]Setupをおくったことになる
従ってこの場合

module XXX
  module Setup ... end
  class Book
    include Setup
  end
end

と全くおなじ、と。

2010/03/18

git-clone-port

memo

github.com で公開されてるプロジェクトを clone したい時
TCP 9418
が出て行くのを許可されてないと clone できない。

2010/03/16

The Catcher in the Rye

「The Catcher in the Rye」by J.D. Salinger
は二人の訳者によって日本語に訳されています。

ISBN: 978-4-560-07051-2 | ライ麦畑でつかまえて | J.D.サリンジャー | 野崎孝訳
ISBN: 978-4-560-04764-4 | The Catcher in the Rye | J.D.サリンジャー | 村上春樹訳

下記は、両者の相違を通しイチ読者としての勝手で野暮な感想を述べたものです。

1) 書き出し
野崎孝訳 p.5

もしも君が、ほんとうにこの話を聞きたいんならばだな、まず、僕がどこで生まれたかとか、チャチな幼年時代はどんなだったかとか、そういった<<デーヴィッド•カパーフィールド>>式のくだんないことから聞きたがるかもしれないけどさ、

村上春樹訳 p.5

こうして話を始めるとなると、君はまず最初に、僕がどこで生まれたかとか、どんなみっともない子ども時代を送ったかとか、僕が生まれる前に両親が何をしていたかとか、その手のデイヴィッド•カッパーフィールド的なしょうもないあれこれを知りたがるかもしれない。


2003年春。村上春樹訳の「The Catcher in the Rye」のこの冒頭の1行目を目にした時、この本は私がかつて読んだあの「ライ麦畑でつかまえて」とマルッキリ!違う本だぞと瞬時に認識しました。正直に言うと、みてはいけないものをみてしまった感に襲われました。その日からあっというまに何年か経過してしまいました。

サリンジャーのこの作品についてふれることは私にはちょっとヘビーなので、できれば永久に避けたいと思っていましたが村上春樹訳「The Catcher in the Rye」が手元にあったことで何かが変わりました。

2) 走ることへの衝動
野崎孝訳 p.11

何のために駆けたりなんかしたのか、自分でもよくわかんないーたぶん、なんということもなく、ただ駆けたくて駆けたんだろう。
いやあ、スペンサー先生の家につくが早いか、いきなり僕はベルを鳴らしたね。

村上春樹訳 p.12

なんでわざわざ走らなくちゃならないのか、自分でもそのへんはよくわからないけど、たぶんただ走りたかったんじゃないかな。
やれやれ、やっとの思いでスペンサー先生の家にたどり着くと、僕はすごい勢いで玄関のベルを鳴らした。


この文の前後ははしょりましたが、主人公はまるで10歳くらいの子どものように突然走り出します。冬の寒い日、ふいに何かに背中を押されれたかのようにして、ぶったおれるかと思うくらいの勢いで走り出すわけですが、村上春樹氏の訳はこの年頃のこの感覚をすっかり忘れてしまったか、もともとそれを知らない人(たぶん走るのが好きじゃなかった人)が訳したかのような印象をうけます。

村上春樹氏が書いた小説の中に、貧乏を経験したことのある人間かそうでないかはそれを知っている人間にはすぐわかる(正確にはこのとおりではない)、
といったようなことを主人公に語らせている作品が確かあったと思うのですが...もう子どもじゃないと自覚してるのに、無性に駆け出したくなったことがある人間か、そうでないかは、この訳の違いを読むとわかるような気がします。

3) 会話
野崎孝訳 p.52

「おれにわかるはずないだろ。どいてくれ。おまえ、おれのタオルに坐ってるじゃねえか」と、ストライドレイターは言った。僕は奴の間抜けなタオルの上に坐ってたんだ。

村上春樹訳 p.56

「よくわからねよ、そんなこと。とにかくそこをどいてくれよ。お前な、俺のタオルの上に座ってるんだぜ」とストライドレイターは言った。僕はたしかに彼のくだらないタオルの上に座っていた。


奴の間抜けなタオルがいかに間抜けになるか?はストライドレイターにいかにカッカして言い放ってもらうか、にかかっていると思います。そして奴の間抜けなタオルにはちゃんと間抜けになってもらってコールフィールド的な笑いを読者に受け止めてもらわないと、ここではなにもかもが台無しなんだと思います。
で、野崎孝訳では「...じゃねえか」と「...坐ってたんだ」がその役割を果たしています。

が、村上春樹訳では、「... に座ってるんだぜ」と、...ぜ、が使われていることと、その直前に「とにかく」って単語が加わることでストライドレイターのカッカが薄く間延びしたものになってしまっています。また「僕はたしかに...」と「たしかに」って単語が加わることで、間抜けなタオルの間抜けさは間抜けでもなんでもないただの退屈なタオルになりさがってしまってます。この感覚。
コールフィールド特有の奴に対するワライはすべってませんか?

4) 時間に関するジョーク
野崎孝訳 p.59

...まるでこっちが恩恵を施されてるみたいな感じなんだ。
奴は支度するのに、五時間ばかしかかった。

村上春樹訳 p.64

... 君はきっとアックリーの方がこっちに恩恵を施していると思うだろうよ。
アックリーが出かける支度をするのに、だいたい五時間かかった。


この抜粋された文だけを、今、生まれて初めて目にした方はアックリーが支度をするのに5時間かかったのが、ジョークだなんてピンとこないんだろうけれども、最初からこの作品を読んできている読者にはこれがコールフィールドのジョークだとすぐにわかります。野崎孝訳においては。
村上春樹訳によってこの作品を初めて読んでいる読者が、これがジョークだとすぐにわかるものなのかどうか、私には疑問です。

他にもこれと同じように、実際とは無関係なおおげさな数字が書かれている箇所がいくつかあって、そのたびに読者はちょっとクスッとなります。
野崎孝訳p.312

校長の姿は見えなかったけど、百歳ばかしの年取った女の人が、...

これも同様のパターン。

5) 叫び
野崎孝訳 p.84

「ガッポリ眠れ、低能野郎ども!」

村上春樹訳 p.89

「ぐっすり眠れ、うすのろども!」


おそらく、読者はここで一旦お茶をいれるか一旦本を閉じるか、俺も(or私も)寝るわと電気を消すなどすると思うんだけども
「ああ、ガッポリ寝るわ、豚のようにね」(笑)
などと冗談を言いかえしたくなるのは野崎孝訳であって村上春樹訳を読んでいてもそんな気持ちにはなれそうにありません。私は。

ガッポリってところが、ちょっといいわけです。このちょっとした笑い「クスッ」感がとてつもなく大事なのです。どれだけ大事かというと、なにはともあれ、なにをさしおいても大事、としかいいようがありません。しかもそんな馬鹿げた声が静かな廊下にこだましちゃってたところが尚面白いわけです。

このニュアンスを持つか持たないかが両者の大きな違いのようにも感じます。とらえどころが難しいけども決定的な違い。主人公コールフィールドは始終まともな話ができる人と話をすることに飢えていますが、同じ作品を訳したにもかかわらず、村上氏の訳ではその切実感が薄いのはこのあたりにも秘密があるような気もします。

6) 恩師との会話
野崎孝訳 p.284

「英語はどうだった?英語をしくじったなんて言おうものなら、さっさと出て行ってもらうからな。この若き作文の天才め」

村上春樹訳 p.303

「英語の成績はどうだった?もし君が英語を落としたというのなら、すぐさまこの場を退出していただくことになる。なにしろ君は作文に関しては文句なしのエースだったもんな」


野崎孝訳では、さっさと出て行ってもらうからな... と一瞬すごみをきかした先生が、 この...天才め、と言い放つと同時に笑顔になっている様がよく伝わってきます。先生の顔をみながら主人公の顔も少しほほえんでいるのが(視覚的に)よくみえるような気がします。この先生が冗談好きな明るい人間だってことも一瞬に理解できるし、主人公がなぜこの人を訪ねたのかもよくわかります。それで安心して私も主人公が座った椅子の隣にこしかけたい気持ちになります。

しかし村上春樹訳で読むと、この先生、なんともまわりくどい言い方をする人だなって印象を持ちかねません。退場していただく、と品のある言い方で書かれているせいか先生の陽気さが半減してしまってます。読者である私はそこに同席したいなど感じません。
これでは、なぜ主人公がこの人に会いにやってきたのかが読者に伝わりにくいのではなかろうか?と心配になります。

この文によって、読者はなぜ主人公はこの人に会いにやってきたのかを知ることができるので、ここは話の構成上でも重要なんじゃないかと思います。
その後、この恩師の家を出ていくことになる出来事とのギャップを浮き彫りにする上でも大切に感じます。

...

全体を通して、村上春樹訳では重要な何かが「ガッポリ」ぬけおちているように感じます。単語の多さとまるで反比例しているのは興味深いところです。

野崎孝訳ではコールフィールド独特のささやかな笑いや、ちょっとした気の利いた言い回しなんかによって、この少年がどういう人物かってことが読者には手にとるようにわかるようになっていると、私は思うのですが、そのあたりのおもしろみが村上訳からは消えさってしまっているように思います。

たとえば「やれやれ」って言葉を村上春樹氏の小説の中に登場する主人公が口にした時、それはまるで彼によく似合う服のようだから、読んでいてなんのさしさわりも感じないし、むしろほどよく彼の気持ちが伝わってきます。こういう時にこういう感じ方をするのが彼なんだなとぐっと彼に近づきますが、サリンジャーの主人公は「やれやれ」が似合うような主人公じゃないと思うんです。決して。彼はそんなにクールでもないし。

ディケンズの名作をくだらないって言ってのけちゃう少年。しいていえば、夏目漱石なんてくだらない、あたりまえだろって言っている少年と同じなわけです。
日本語の「やれやれ」が持つニュアンスを多少の笑いを含んで言えるような人物が、
「その手のデイヴィッド•カッパーフィールド的なしょうもないあれこれ...」
あるいは
「そういった<<デーヴィッド•カパーフィールド>>式のくだんないこと」
と、斬って捨てるような言い方をするだろうか?と、違和感を感じます。
例えば「そういった<<坊ちゃん>>的なくだらないこと...」
などとは、そういう人は言わない、いや、言えないんじゃないのかな。

だから、そもそも「やれやれ」などとコールフィールドが心の中で口にすることができていたのなら、この小説自体生まれなかったんじゃないの?とも思うのです。「やれやれ」と心の中でつぶやきつつその場をやりすごすことができるかできないか、そのハードルを超えるか超えないかの、違い。そのハードルこそがコールフィールドにとってはとてつもなく巨大で重要で真っ暗な出来事として描かれていると、私は思うので、そこをまるっきり無視しちゃっうのならこの作品の存在自体を否定しかねないのではないか?と考えてしまいます。
実際、野崎孝氏は一度も「やれやれ」なんて使わないで訳を完了させてしまってますしね。ところどころ言葉遣いの古さは否めないけど。

私は作品の主人公とほぼ同年齢に野崎孝氏訳の「ライ麦畑でつかまえて」に巡り会えてよかったと思ってます。大人になってからこの作品を読んだ人の感想をどこかで信用していない悪い癖がついてしまったのは、それはしかたのないことだと言いかねないほど。

2010/03/08

NASAが...

NASAが1000日後にアバターを月に送り込む予定
によると

もしヒューマロイドを月に送り込み、科学者達自身での探索が可能になったら、それは全ての科学者を実際に月に送り込むのと同じくらいの意味があります
。科学者達が彼ら自身で探索し研究の対象となるサンプルを探すことができるのです。遠隔操作はほんの3秒くらいのタイムラグだそうですよ。

だそうだ。

ヒューマロイドがロビイになったりしませんように。
ディヴになったりしませんように。
ハーヴィーになったりしませんように。
どうかロボットデカルトさまになったりしませんように^^;

instance_variable

http://ujihisa.blogspot.com/2009/12/left-hand-values-in-ruby.htmlを読んで試してみたこと。

  1 #!/usr/local/bin/ruby191
  2 # coding: utf-8
  3 
  4 class Diary
  5   def initialize
  6     @title, @date = nil, nil
  7   end
  8   alias [] instance_variable_get
  9   #alias []= instance_variable_set
 10   def []=(i, v)
 11     instance_variable_set(i, v) if i_defined?(i)
 12   end
 13   def i_defined?(i)
 14     instance_variable_defined?(i)
 15   end
 16 end
 17 
 18 d = Diary.new
 19 d['@title'] = "NewTitle"
 20 d['@date'] = Time.local(2010,02,01)
 21 d['@ddd'] = 'ddd'
 22 p d['@title']
 23 p d
 24 # =>
 25 # "NewTitle"
 26 #<Diary:0xxxx @title="NewTitle", @date=2010-02-01 00:00:00 +0900>


initialize をとりさり i_defined? もとりさってみる

 29 class Diary
 30   alias [] instance_variable_get # instance_variable_defined?
 31   alias []= instance_variable_set
 32 end
 33 
 34 d = Diary.new
 35 d['@title'] = "NewTitle"
 36 d['@date'] = Time.local(2010,02,01)
 37 p d

% ./try.rb
#<Diary:0xxxx @title="NewTitle", @date=2010-02-01 00:00:00 +0900>

勉強になった。

self.instance_variable_set
にしなくちゃいけないと思っていた。
instance_variable_set
だけで動くなんて知らなかった!

alias [] instance_variable_get
これでinstance の値をとれるなんて!

instance_variable_get
のところを
alias [] instance_variable_defined?
に変えてみたら値をとるかわりに定義されているか否かを true or false で返してくれた!びっくり。

alias [] instance_variable_get
alias []= instance_variable_set
alias [] instance_variable_defined?

のようなことをしてみたくなったが
[] methods
は1度使ってしまったら2個目は使えない。の overwrite されちゃう。あたりまえかも。
1回目の [] と
2回目の [] を
区別させる方法はない? ぽい。

2010/03/04

部分変更重要

入門Git のp.57-58 を読みながら試してみたこと

# 複数のファイルが git diff に表示されていた場合、git add -p する際にファイル名を指定することもできた。
% git add -p filename
% git add -p
してすぐにリターンするとヘルプをみることができた。

思い通りに hunk が分かれていなかった場合は s 選択するとより細かく分割してくれるようだ。今回のコミットに反映したい箇所は y で反映したくない時は n。 q で終了。

% git diff --cached
今からコミットする内容を確認

% git commit -v
変更箇所の詳細内容をみながらコミット文を作成できる。書式ルールは

1行目が要約文
2行目空行
3行目以降に詳細文

これからは要点と合致した commit を心がけようと思った。

2010/02/26

UTF8-MAC [2]

UTF8-MAC みなおし。

要は \\ があればいいんでしょ?とお気楽な発想を展開してみました。
が、以下は非常によろしくないことをしている可能性あり。
あくまでも実験なので試さない方がいいです。おい

macustr.rb

  1 #!/usr/local/bin/ruby19
  2 # coding: utf-8
  3 
  4 exit unless Encoding.default_external.name == 'UTF-8'
  5 
  6 require 'nkf'
  7 def macustr(line)
  8   str = String.new # p str.encoding
  9   line.chars.entries.each{|x| str << "\\" + x}
 10   #line.codepoints.entries.each{|x| str << "\\" + [x].pack("U*")}
 11   mustr = NKF::nkf('--ic=UTF-8 --oc=UTF8-MAC', str)
 12   return mustr
 13 end
 14 
 15 ARGF.each{|line|
 16   exit unless line.encoding.name == "UTF-8"
 17   next unless line.valid_encoding?
 18   mustr = macustr(line.strip)
 19   next unless  mustr.valid_encoding?
 20   sh = system("mkdir #{mustr}")
 21   print "Maked Directory: #{line}" if sh
 22 } 
 23 


line 4 : 環境変数LANGが UTF-8 でない場合はおいかえす。
line 16: 読み込んだ文字列が UTF-8 でなければすぐ終了。
line 17: valid でなければ次
line 18: def macustr に一行わたす
line 9 : 冒頭に"\\" を付け加えて一文字ずつ str に追加。最初は line 10 にしたのだが line 9 にしておいた。
line 11: str を UTF8-MAC に変換
line 19: valid でなければ次
line 20: mkdir コマンド
line 21: コマンドが成功したらメッセージ表示

./macustr.rb utf8_text.txt

を実行すると utf8_text.txt を一行ずつ読み込み
同名のDirectory を同じ階層に作成します。
utf8_text.txt は UTF-8 で保存されたテキストファイル。

[2010-02-27]
s/chomp/strip/g

[2010-03-08]
追記
# 失敗例

  1 #!/usr/local/bin/ruby19
  2 # coding: utf-8
  3 # test-encode.rb
  4 
  5 text = 'utf8-text.txt'
  6 # % cat utf8-text.txt 
  7 # and two &three
  8 
  9 File.open(text, "r:utf-8"){|f|
 10   f.each_line{|x|
 11     #  行末\n や行頭\s を削除
 12     line = x.strip
 13     # print out
 14     puts "Line: \"#{line}\"| Encoding: #{line.encoding}| Valid: #{line.valid_encoding?}\n"
 15     puts "# Calling encode\n"
 16     # encode で変換
 17     mustr = line.encode("UTF8-MAC")
 18     # print out
 19     puts "String: \"#{mustr}\"| Encoding: #{mustr.encoding}| Valid: #{mustr.valid_encoding?}\n"
 20     print "# Calling system\n"
 21     # Directory 作成
 22     sh = system("mkdir #{mustr}")
 23     puts "Result: #{sh}\n--\n"
 24   }
 25 }
 26 
 27 =begin
 28 % ./test-encode.rb 
 29 Line: "and two &three"| Encoding: UTF-8| Valid: true
 30 # Calling encode
 31 String: "and two &three"| Encoding: UTF8-MAC| Valid: true
 32 # Calling system
 33 sh: three: command not found
 34 Result: false
 35 
 36 % ls -F
 37 and/            test-encode.rb* two/            utf8-text.txt
 38 =end


17行目

mustr = ine.encode("UTF8-MAC")

mustr = line.force_encoding("UTF8-MAC")

にしても同様の結果だし

require 'nkf'
mustr = NKF::nkf('--ic=UTF-8 --oc=UTF8-MAC', line)

としてみても結果は同じ

検索して次を読んでみたけど よくわかってないというか...。
<http://redmine.ruby-lang.org/issues/show/1411>
<http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-dev/40233?help>

+++ 感想 +++

通常 Mac OS X を使用する上で自ら日本語名のフォルダを作る人はあまりいないだろうし、スペースが混入した文字列をわざわざフォルダの名前にする人もあまりいないはずなので、じゃあ一体どういった場面で上のような必要が生じるかというと
ずばり
iTunes のための iTunes による Folder 生成 | File 生成なのかな? と。
2010/03/08 現在ではこれ以外の場面で UTF8-MAC への変換なんて一般的には必要とされてないことなのかもしれません。

ただ、今後 iPad が登場しまた新しくiのつく名前のアプリケーションがでてきたりすると UTF8-MAC への変換に対する需要は増えるかもしれませんね?電子書籍を買って読むための iBooks.app が OS X に搭載される日は案外近い将来かもしれません。
iPad

それで、例えば iBooks.app が生成するであろう著書名のついたファイルにアクセスする際、もしも著書名に\& や\s が含まれていたり日本語だったりしたらRuby からそれらのファイルにアクセスしようとするのはちょっと困難がありそうです。いまの iTunes ファイル群と同様に。
# Ruby からはそういうファイル群にアクセスしないから大丈夫...といった意見の人もいるかもしれません。
# あるいは上に書いた失敗例を[ちゃんとした]成功例にする方法を私が知らないだけのことなのかもしれません。
# macustr.rb は一見成功してるようにみえるけどもちゃんとはしていないだろうし。

はたまた違う観点からみた場合、セキュリティ的にどうなんだろう?って問題も私にはよくわからないけどきっとあるんだろうと思います。そっちが優先された上で現在こうなっているのであればこのままの方がうれしい人も多いのかもしれません?。

ということで、幾日経過後のまとまりのない&とりとめないのない感想でした。

# 私が間違った認識をしている可能性は多分にあります。何かお気付きの方はコメントお願いします。

2010/02/24

mdiary 最近の変更点

  5     def initialize(arg)
  6       @err = false
  7       k, @h = nil, Hash.new
  8       arg.each{|x| m = /^-(.*)/.match(x); (m) ? (k = m[1].to_sym; @h[k] = nil) : @h[k] ||= x}
  9     end


arg は ARGV の値

% .mdiary-run.rb -d 2010-01 -s music

を実行した場合 arg は

arg = ["-d", "2010-01", "-s", "music"]

になる。line 8 はこの配列を

@h = {:d=>"2010-01", :s=>"music"} 

のようなハッシュにするためのもの。

arg = ["-d", "2010-01", "-l", "3"] だった場合
@h={:d=>"2010-01", :l=>"3"}

arg = ["-d", "2010-01", "-l"] だった場合
@h={:d=>"2010-01", :l=>nil}
になる。

line 7-8 をくだいて書くと

  1 # arg = ["-d", "2010-01", "-s", "music"]
  2 k, @h = nil, Hash.new
  3 arg.each{|x| 
  4   m = /^-(.*)/.match(x)
  5   if m
  6     k = m[1].to_sym
  7     @h[k] = nil
  8   else
  9     @h[k] ||= x
 10   end
 11 } 


line 4: x が '-' で始まっていたら m の値は #<MatchData "-d" 1:"d">
line 5: m の値に何か入っていたら(マッチしたら)
line 6: k に m の1番目のマッチの値を代入。
line 7: ハッシュキーが k で 値が nil のペアを @h に格納。
line 8: m の値に何もはいっていなければ(マッチしなかったら)
line 9: @h[k] が nil の場合は x を代入。@h[k] の値が nil でなく何か値が入っていたら何もしない。

+++ memo +++

1) @h[k] ||= x

line 9 の @h[k] ||= x を @h[k] = x にしてしまうと
あやまって
arg = ["-d", "2010-01", "xxx", "-s", "music"]
が与えられてしまった時
@h = {:d=>"xxx", :s=>"music"}
になってしまう。これでは意図した結果と異なる為 ||= にしている。

2) k = nil

line 2 の k = nil を書き忘れ
line 2 は @h = Hash.new だけだった場合
arg = ["-d", "2010-01", "-s", "music"] を与えると
@h={:d=>nil, nil=>"2010-01", :s=>nil}
になってしまう。
なぜなら...
{} の外側に k が存在していなければ k は {} の中だけで使える変数となり
m == nil でなければ
k = m[1].to_sym なので k には m[1].to_sym が代入されるが

m == nil だった場合、すなわち else 節においては
k = nil が代入されてしまうから。そして
line 9: @h[k] ||= x
で nil を ハッシュキーとしたペア(nil=>"2010-01")を @h に格納することになってしまう。

だから{} の外側の k = nil はとても大切。
外側で定義された k があることによって else 節においても k は m[1].to_sym を保持していてくれる。

[2010-02-26]
arg.each{|x| m = /(^-(.*))/.match(x); (m) ? (k = m[2].to_sym; @h[k] = nil) : @h[k] ||= x}
arg.each{|x| m = /^-(.*)/.match(x); (m) ? (k = m[1].to_sym; @h[k] = nil) : @h[k] ||= x}

2010/02/22

UTF8-MAC

ここを読んで

私も perl でためしてみました。
% cat test.pl

#!/usr/bin/perl
while(<>) {
    chop;
    print "Making a folder $_...\n";
    mkdir();
}

% cat 02.txt

ABC_a'bc 織田 信長
ABC_e'fg 豊臣 秀吉
ふげふが リファレンス& ドロー


% ./test.pl 02.txt
Making a folder ABC_a'bc 織田 信長...
Making a folder ABC_e'fg 豊臣 秀吉...
Making a folder ふげふが リファレンス& ドロー...

わざと\s や ' や濁点や & を入れてみましたがちゃんとおかしな名前のフォルダが出来上がりました。

で、Ruby ではどうなのでしょ。
% cat test.rb

#!/path/to/ruby19
# coding: utf-8
ARGF.each{|line|
  system ("mkdir #{line}")
}


% ./test.rb 02.txt

% ./test.rb 02.txt 
sh: -c: line 0: unexpected EOF while looking for matching `''
sh: -c: line 1: syntax error: unexpected end of file
sh: -c: line 0: unexpected EOF while looking for matching `''
sh: -c: line 1: syntax error: unexpected end of file
sh: ドロー: command not found

こうなるのは予測していたので

http://gihyo.jp/dev/serial/01/ruby/0004?page=2 を読み直し

#!/path/to/ruby19
# coding: utf-8
require 'nkf'
ARGF.each{|line|
  ustr = NKF::nkf('--ic=UTF-8 --oc=UTF8-MAC', line)
  system ("mkdir #{ustr}")
}

nkf を使ってみました。が、最初と同じエラーが現れ ふげふが/ リファレンス/ の2のフォルダができました。

結果をみると \s のところでパスが区切られてしまったようなので
gustr = ustr.gsub(/\s/, "\\ ")
を挟んでみたものの ”&” でまたパスを区切られてしまいました。結局エラーになりそうな文字(て何?)を全て gsub しないとだめなのかもしれません。いやいやそんなことじゃなく正しい指定(nkf の)さえ分かればいいだけのことなのかもしれません。
あーわからない。

このままで話が終わるのはなんだか後味が悪いので AppleScript で Ruby を呼んでみました。

tell application "Finder"
  activate
  set cf to choose file with prompt "読み込みたいテキストファイル_UTF-8_を選択してください。"
  set dst to choose folder with prompt "保存先フォルダを選択してください。"
  set f to quoted form of POSIX path of cf
  set rubyfile to quoted form of POSIX path of (((folder of file cf) as text) & "ioread.rb")
  # ---------------------------
  try
    set str to do shell script "/usr/bin/ruby" & space & rubyfile & space & f
    set ary to paragraphs of str
    if (count of ary) > 3 then # this line
      return display dialog "体力の限界です。" buttons {"OK"} default button 1 with title "Oh, NO "
    end if
    repeat with fname in ary
      make new folder at (dst) with properties {name:fname}
    end repeat
  on error error_str
    display dialog error_str buttons {"OK"} default button 1 with title "Error"
  end try
end tell
# return AppleScript's version => "2.1.1"

% cat ioread.rb 
#!/usr/bin/ruby
f = ARGV[0]
print nil unless f
ary = IO.readlines(f)
ary.delete("\n")
print ary

% ls -F
ABC_a'bc 織田 信長/                                  ふげふが リファレンス& ドロー/
ABC_e'fg 豊臣 秀吉/


ちゃんとおかしな名前のフォルダができました。
テストなんでフォルダの数は3つまでに制限かけておきました。# this line のところ。


+++ 追記 +++
2010-02-22
しばらくしたら思いつきました。文字ごとに gsub してみようと。

% cat 02.txt

ABC_&a'bc 織田 信長
ABC_e'fg 豊臣 秀吉
ふげふが リファレンス& ドロー


test.rb

  1 #!/path/to/ruby19
  2 # coding: utf-8
  3 
  4 require 'nkf'
  5 def ex(line)
  6   mu = String.new("")
  7   ary = line.each_char{|x|
  8     gx = x.gsub(
  9       /[\s\'\(\)\+\!\&\,\[\]\;]/,
 10       " "=>"\\ ", "'"=>"\\'",
 11       "("=>"\\(", ")"=>"\\)",
 12       "+"=>"\\+", "!"=>"\\!",
 13       "&"=>"\\&", "."=>"\\.",
 14       "ï"=>"\\i", ","=>"\\,",
 15       "["=>"\\[", "]"=>"\\]",
 16       ";"=>"\\;"
 17     ) 
 18     mu << gx
 19   } 
 20   p macustr = NKF::nkf('--ic=UTF-8 --oc=UTF8-MAC', mu)
 21   p macustr.encoding
 22   system ("mkdir #{macustr}")
 23 end
 24 
 25 ARGF.each{|line| ex(line)}


% ./test.rb 02.txt

"ABC_\\&a\\'bc\\ 織田\\ 信長"
#<Encoding:UTF8-MAC>
"ABC_e\\'fg\\ 豊臣\\ 秀吉"
#<Encoding:UTF8-MAC>
"ふげふが\\ リファレンス\\&\\ ドロー"
#<Encoding:UTF8-MAC>


% ls -F

02.txt                                               test.rb*
ABC_&a'bc 織田 信長/                                 ふげふが リファレンス& ドロー/
ABC_e'fg 豊臣 秀吉/


line 10 "'" を "\\'" とスラッシュバックスラッシュ2つにしてみたらうまくいった。それがなぜなのかは分かっていない。
こういうのは力技と呼ばれることなんだろう。

UTF8-MAC [2] へ続く


[2011-02-19]

2010-02 時点での敗因はただ単にchomp しわすれとsystem コマンド発行する引数を'' で囲まなかったこと。それだけ。びっくりする愚かなおち。
nkf とかね関係ありません...。
それにしても今読み返してつくづく...単純ミスから泥沼していく様は自分でもあきれました。

% cat a.txt
ふげふが &どろー
% cat test.rb
# coding: utf-8

ARGF.each{|x|
  s =  "\'#{x.strip}\'"
  p sh = system("mkdir #{s}")
}
% ruby -v test.rb a.txt
ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]
true
% ls
a.txt                            test.rb                          ふげふが &どろー


ruby 1.9.2
でも同様の結果。

2010/02/17

git push error

% git push origin master
を実行したら

 ! [rejected]        master -> master (non-fast-forward)

error: failed to push some refs to (...略) 
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again.  See the 'non-fast-forward'
section of 'git push --help' for details.


となってしまった。思い当たることとしては OS を再インストールして git repository へのパスを変えてしまったことと git のバージョンをあげたこと。

% git push --help

/non-fast-forward
next していたら次のような文章があった。

       There is another common situation where you may encounter non-fast-forward rejection when you try to push, and it is possible even
       when you are pushing into a repository nobody else pushes into. After you push commit A yourself (in the first picture in this
       section), replace it with "git commit --amend" to produce commit B, and you try to push it out, because forgot that you have pushed A
       out already. In such a case, and only if you are certain that nobody in the meantime fetched your earlier commit A (and started
       building on top of it), you can run "git push --force" to overwrite it. In other words, "git push --force" is a method reserved for a
       case where you do mean to lose history.

辞書をひきつつ 2 回読んでみたけどもなぜこうなってしまったのか?や、どうすればいいのか?は読み解けない。

Google にて "non-fast forward"
を検索してみたところ
http://blog.digital-squad.net/article/132085683.html

こういうときは --forceオプションをつけてやることで強制的にpushできる。
git push origin master --force

とありまして --force をつけて試してみるとあっさり git push に成功しました。とても助かりました。
一時は ssh-keygen で鍵を作りなおさなくちゃいけないのかと思った。

さて、落ち着いてから上の英文を読みなおすと

you can run "git push --force" to overwrite it. In other words, "git push --force" is a method reserved for a
       case where you do mean to lose history.

... "git push --force" はあなたが歴史を失うケースに備えての予備のメソッド?
間違えて読んでる可能性大だけど歴史を失うとはどういうことだろ。
OS 再インストールしてパスが変わってるから何かが失われたってことなのかな。何が?

% git log
ちゃんと動いてる。最初からのlog もみえてる。はて?

+++ 教訓 +++

% git push midore@github.com:midore/mblogger.git

などしても

...
Permission denied (publickey).
fatal: The remote end hung up unexpectedly

エラーになる。だからといって ~/.ssh/ の中の鍵のパーミションが関係してる?とか考えない。

remote 先を明示したい時は

% git push git@github.com:midore/mblogger.git


~/.gitconfig や ~/.ssh/ にゆるぎない自信があれば

% git push origin master

で OK.

[後日談]
入門Git(秀和システム) を読みましてこの時何がおこっていたか?を考えてみました。
p81 に non fast forward エラーについて解説がありました。

私の場合OS を入れ替える前にバックアップをとり、OS を新規インストールした後にこのバックアップから
local git repository を読み込んだわけだけどもバックアップした直後で新規インストールする直前に
github.com/midore/mdiary に対してgit push しちゃっていたのかもしれません(驚)
だとすればこの挙動はものすごく納得がいきます。
バックアップとった後に git push した記憶がない自分が怖い...

私がうっかり git push していたのならば上記の対処は正しいやり方じゃなかったようです。
% git pull
を使い
(pull 先は add remote した先を指し、clone したproject の場合は自動的にclone 元になるそうだ)
github.com においてあるリポジトリの最新コミットと手元のリポジトリのコミットをマージさせるべきでした。
git pull してみればどこで conflict していたか明らかになったはずなのでした。
(ただしgit push した記憶がない状態で pull する勇気をもてたかは不明)
conflict メッセージがでていたのならそのファイルを編集した上でcommit するべきだったのかもしれません。

2010/02/16

Remove resource fork in AppleScript

私は Twitter に参加していませんが何日か前に Google Reader で
急募: OS XのiTunesから、mp3ファイルを_リソースフォークなしに...
を見かけました。

早速 AppleScript で try

tell application "Finder"
  set src to quoted form of POSIX path of (choose folder)
  set dst to quoted form of POSIX path of (choose folder)
  set str to "ditto -v --norsrc  " & src & "  " & dst
  do shell script str
end tell

日本語名のフォルダを指定しても大丈夫でした。でもこれだけだと愛想がないのでいろいろ付け足し。

# remove-resource-forlk.scpt
tell application "Finder"
  # フォルダを選択
  set src to quoted form of POSIX path of (choose folder with prompt "リソースフォークをまるっと取り除きたいフォルダを選択してください。")
  # 保存先フォルダの選択
  set dst to quoted form of POSIX path of (choose folder with prompt "保存先であるフォルダを選択してください。")
  # コマンド文字列
  set str to "ditto -v --norsrc  " & src & "  " & dst
  if src is dst then
    set err_str to "指定したフォルダと保存先であるフォルダが同じです!異なるフォルダを選択してください。"
    display dialog err_str buttons {"OK"} default button 1 with icon 2 with title "Error"
    return
  end if
  set warn_str to "多くのファイルが含まれているフォルダを選択した場合時間がかかる(数分)場合があります。よろしいですか?"
  display dialog warn_str buttons {"OK", "Cancel"} default button 2 with icon 2 with title "Warning"
  try
  # コマンドの実行
  set res to do shell script str
  on error num
    display dialog "エラーが発生しました。" buttons {"OK"} default button 1
    return
  end try
  if res is "" then display dialog "おわりました。" buttons {"OK"} default button 1 with icon 1 with title "Success"
end tell


[用途]
フォルダに含まれるファイルからリソースフォークを削除したファイルを保存先フォルダに保存します。(もとのファイル名は維持されます。)
複数のフォルダを内包しているフォルダを指定した場合、保存先フォルダの階層は、もとのフォルダの階層を維持します。

# iTunes Music フォルダにあるミュージシャン(Artist) の名前がついたフォルダを選択すると、そこに含まれるアルバム名のついたフォルダにある音楽ファイル( 末尾に.m4a .mp3 などの名前のついたファイル)から、リソースフォークを削除したものを、保存先フォルダに保存します。
# ターミナルからコマンドを叩くことなく、操作できます。

[使い方]
Finder メニュ-> 移動-> アプリケーションを開く (Command + Shift + A でApplication フォルダ を表示)
->ユーティリティ ->AppleScript Editor.app(AppleScript エディタ.app) をダブルクリックで起動し新しいファイルを作り上記をコピー and ペーストします。

1, コマンドKey(⌘) + K でコンパイルします。
2, コマンドKey(⌘) + S で File 保存(必ずスクリプト として)
3, コマンドKey(⌘) + R で実行 です。

処理がおわると『おわりました。』と表示します。エラーが発生した場合は『エラーが発生しました。』と表示します。

複数のアルバムフォルダが含まれている ミュージシャン(Artist) のフォルダなどを選択するとファイル数にして何百曲などのファイルを処理することになります。その場合ものすごく時間がかかる(数分)こともあります。なので最初は下記の手順でテストしてみてどのくらい時間がかかるものかを体感してみてください。

[テスト手順]
(1) デスクトップに2つ新規フォルダを作りそれぞれ「SRC」「DST」と名付けておく。
(2) 「SRC」フォルダの中にリソースフォークを取り除きたいフォルダを1 つだけコピーしておく。
  その際極力ファイル数の少ないフォルダを選ぶ。
「DST」フォルダは空っぽのままにしておく。
(3) 保存しておいた AppleScript ファイルを開いてから コマンドKey(⌘) + R をおす。または「実行」ボタンを押す。
「リソースフォークをまるっと...」ときかれたら「SRC」を選ぶ。
「保存先...」 ときかれたら 「DST」を選ぶ。

処理している間はなんのメッセージも表示しません。
10 枚程のファイルを処理した場合 2,3 秒でおわります。

# 注意1:
OS X 10.5x 時代のファイルにはリソースフォークがついてるけど、Snow Leopard 時代に作ったファイルにはついてません。

# 注意2:
指定フォルダとしてミュージシャン(Artist)名のついたフォルダを指定し
保存先フォルダには適当な名前(「test」とか)のフォルダを指定し実行した場合

iTunes->詳細->”iTunes Media”フォルダを整理する
にチェックをいれてから保存先フォルダ(「test」とか)を iTunes に取り込むと本来のミュージシャン(Artist)名のついたフォルダ名に自動変換されます。
(iTunes 9.03)

[ターミナルで確認]

# % ditto -h
# % xattr -h

# 指定フォルダ: test-src
# 保存先フォルダ: test-dst


指定フォルダ内

% ls -FRl test-src/
total 0
drwx------  3 foo  staff  102  2 15 16:35 Makana/
drwx------  3 foo  staff  102  2  4 11:48 平沢 進/

test-src//Makana:
total 0
drwx------  17 foo  staff  578  2 15 16:33 Different Game/

test-src//Makana/Different Game:
total 92824
-rw-------@ 1 foo  staff  4428672  6  6  2009 01 Away.m4p
-rw-------@ 1 foo  staff   623834  2  4 18:09 02 Interlude I.m4p
-rw-------@ 1 foo  staff  3821305  6  6  2009 03 Mars Declares.m4p
# ... 略

test-src//平沢 進:
total 0
drwx------  4 foo  staff  136  2  4 11:48 時空の水/

test-src//平沢 進/時空の水:
total 15344
-rw-------@ 1 foo  staff  4542192  4  4  2008 01 ハルディン・ホテル.m4p
-rw-------@ 1 foo  staff  3311160  4  4  2008 10 金星.m4p

% xattr -x test-src/Makana/Different\ Game/01\ Away.m4p 
# => com.apple.FinderInfo

% xattr -x test-src/平沢\ 進/時空の水/01\ ハルディン・ホテル.m4p
# => com.apple.FinderInfo


AppleScipt 実行後
保存先フォルダ内

% ls -FRl test-dst/
total 0
drwx------  3 foo  staff  102  2 15 16:35 Makana/
drwx------  3 foo  staff  102  2  4 11:48 平沢 進/

test-dst//Makana:
total 0
drwx------  17 foo  staff  578  2 15 16:33 Different Game/

test-dst//Makana/Different Game:
total 92824
-rw-------  1 foo  staff  4428672  6  6  2009 01 Away.m4p
-rw-------  1 foo  staff   623834  2  4 18:09 02 Interlude I.m4p
-rw-------  1 foo  staff  3821305  6  6  2009 03 Mars Declares.m4p
# ... 略

test-dst//平沢 進:
total 0
drwx------  4 foo  staff  136  2  4 11:48 時空の水/

test-dst//平沢 進/時空の水:
total 15344
-rw-------  1 foo  staff  4542192  4  4  2008 01 ハルディン・ホテル.m4p
-rw-------  1 foo  staff  3311160  4  4  2008 10 金星.m4p

% xattr -x test-dst/Makana/Different\ Game/01\ Away.m4p
# => 何もかえってこない。

% xattr -x test-dst/平沢\ 進/時空の水/01\ ハルディン・ホテル.m4p
# => 何もかえってこない。


[2010-02-16]
s/errr_str/err_str/g
s/warm_str/warn_str/g
s/やめる/Cancel/g
[2010-02-18]
s/folk/fork/g

2010/02/11

Snow Leopard Re-Install memo

# backup
$ sudo launchctl bslist -j > default-launchctl-bslist.txt
# PRAM Clear
# $ sudo nvram -c -xp

0) Remove Extensions
# Bluetooth
$ sudo srm -rf /System/Library/Extensions/IOBluetooth*
# iSight
$ sudo srm -rf /System/Library/Extensions/Apple_iSight.kext/
$ sudo srm -rf /System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBVideoSupport.kext/

# Touch
$ sudo touch /System/Library/Extensions/

# blued
$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.blued.plist
$ sudo chmod 600 /usr/sbin/blued

$ sudo reboot

1) mDNSResponder.plist
$ ps aux | grep mDNS
# => ... /usr/sbin/mDNSResponder -launchd

$ sudo vi /System/Library/com.apple.mDNSResponder.plist
$ sudo vi /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist

        <array>
                <string>/usr/sbin/mDNSResponder</string>
                <string>-launchd</string>
                <string>-NoMulticastAdvertisements</string>
        </array>


# Reload com.apple.mDNSResponder.plist
$ sudo launchctl unload /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
$ sudo launchctl load /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist

$ ps aux | grep mDNS
# => .... /usr/sbin/mDNSResponder -launchd -NoMulticastAdvertisements

See: support.apple.com/kb/HT3789

2) change mode
$ man samba
$ apropos smbd

$ sudo chmod 600 /usr/sbin/nmbd
$ sudo chmod 600 /usr/sbin/smbd
$ sudo chmod 600 /usr/sbin/cupsaddsmb

$ sudo chmod 600 /usr/bin/smb*
$ sudo chmod 600 /usr/bin/nmblookup
$ sudo chmod 600 /etc/smb.conf
$ sudo chmod 600 /etc/smb.conf.template

# httpd
$ sudo chmod 600 /usr/sbin/httpd

# sshd
$ sudo chmod 600 /usr/sbin/sshd

# ftpd
# sudo chmod 600 /usr/libexec/ftpd

# nfsd
$ sudo chmod 600 /sbin/nfsd

# Apple FileServer
# $ ls -la /usr/sbin/AppleFileServer
$ sudo chmod 0 /System/Library/CoreServices/AppleFileServer.app/Contents/MacOS/AppleFileServer

# ae server (Apple Event)
# $ more /System/Library/LaunchDaemons/com.apple.eppc.plist
$ sudo chmod 0 /System/Library/Frameworks/CoreServices.framework/Frameworks/AE.framework/Versions/A/Support/AEServer

# Problem Reporter
$ sudo chmod 600 /System/Library/CoreServices/Problem\ Reporter.app/Contents/MacOS/Problem\ Reporter

See: http://www.macosxhints.com/

# Plug-Ins
$ ls -la /Library/Internet\ Plug-Ins/
$ sudo chmod 700 /System/Library/Frameworks/JavaVM.framework/Resources/JavaPluginCocoa.bundle
$ sudo chmod 700 /Library/Internet\ Plug-Ins/Flash Player.plugin
$ sudo chmod 700 /Library/Internet\ Plug-Ins/QuickTime Plugin.plugin
$ sudo chmod 0 /Library/Internet\ Plug-Ins/NP-PPC-Dir-Shockwave
$ ls -la /Library/Internet\ Plug-Ins/

3) launchctl unload
$ sudo launchctl unload -w /System/Library/LaunchDaemons/org.cups.cupsd.plist
$ sudo launchctl unload -w /System/Library/LaunchDaemons/org.x.privileged_startx.plist
$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.webdavfs_load_kext.plist

# com.apple.smb.server.preferences.plist com.apple.smb.sharepoints.plist com.apple.smbfs_load_kext.plist
$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.smb.sharepoints.plist
$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.smb.server.preferences.plist
$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.smbfs_load_kext.plist

$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.RFBRegisterMDNS_ScreenSharing.plist
$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.RFBRegisterMDNS_RemoteManagement.plist

$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.printtool.plist
$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.portmap.plist
$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.nfsd.plist
$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.RemoteDesktop.PrivilegeProxy.plist
$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.IIDCAssistant.plist

# 2010-03-30
$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.dashboard.advisory.fetch.plist

# /System/Library/Filesystems/AppleShare/check_afp.app/Contents/MacOS/check_afp
# $ more /System/Library/LaunchDaemons/com.apple.afpfs_checkafp.plist

# /System/Library/Filesystems/AppleShare/afpLoad
# $ more /System/Library/LaunchDaemons/com.apple.afpfs_afpLoad.plist

# /System/Library/PrivateFrameworks/SoftwareUpdate.framework/Resources/suhelperd
# $ more /System/Library/LaunchDaemons/com.apple.suhelperd.plist

$ sudo launchctl bslist -j
$ sudo lsof -i

4) Spotlight
# as admin-user
$ sudo chmod 600 /System/Library/CoreServices/Search.bundle/Contents/MacOS/Search
$ sudo mdutil -i off /Volumes/abc
$ sudo mdutil -E /Volumes/abc
$ sudo mdutil -s /Volumes/abc

See: http://www.macosxhints.com/article.php?story=20091030173117381

5) fseventsd
$ sudo touch /Volumes/abc/.fseventsd/no_log
$ sudo touch /Users/foo/.fseventsd/no_log
$ sudo chmod 644 /Users/foo/.fseventsd/no_log
$ sudo chown -R foo:staff /Users/foo/.fseventsd/

See: ファイルシステムイベントストレージの防止

# default value "ttyskeepawake" of pmset is 1.
$ sudo pmset ttyskeepawake 0

See: http://forums.applenova.com/showthread.php?t=33172

$ sudo reboot
$ Login as admin-user
$ syslog -w 120 | more

# fseventsd[xx] <Critical>: Logging disabled completely for device:1: /Users/foo

6) Login as User foo
% rm ~/.fseventsd/000000*
% mdutil -i off /Users/foo
% mdutil -E /Users/foo
% mdutil -s /Users/foo
% pmset -g

% syslog -w 30
# What is this warning ?
# (com.apple.ReportCrash) <Warning>: Falling back to default Mach exception handler. Could not find: com.apple.ReportCrash.Self

% more /System/Library/LaunchAgents/com.apple.ReportCrash.Self.plist

% launchctl list | grep Repo

-	0	com.apple.ReportPanic
-	0	com.apple.ReportCrash.Self
-	0	com.apple.ReportCrash


See: http://www.insanelymac.com/forum/index.php?showtopic=192563

# User foo
% mkdir ~/Library/LaunchAgents
# if you did't set umask
# % chmod 700 ~/Library/LaunchAgents

% cd ~/Library/LaunchAgents
% cp /System/Library/LaunchAgents/com.apple.ReportCrash.Self.Plist .

# User admin
$ su admin-user
$ cd /path/to/backup-dir/
$ sudo mv /System/Library/LaunchAgents/com.apple.ReportCrash.Self.Plist .

# logout and login as User foo
% syslog -w
# not found, "... (com.apple.ReportCrash) <Warning>: (...) Could not find: com.apple.ReportCrash.Self"

[2010-02-11]
# RemotManagement
# $ sudo srm -rf /System/Library/CoreServices/RemoteManagement/
# or
# cd /path/to/backup-dir/
# $ sudo mv /System/Library/CoreServices/RemoteManagement/ .

[2010-02-12]
# User foo
# % launchctl list | grep Remote
# => exist.

# Admin user
# $ grep 'Remote' /System/Library/LaunchAgents/*
# $ sudo mv /System/Library/LaunchAgents/com.apple.RemoteDesktop.plist /path/to/backup-dir/
# $ sudo mv /System/Library/LaunchAgents/com.apple.ScreenSharing.plist /path/to/backup-dir/

# reboot

# User foo
# % launchctl list | grep Remote
# => not exist.


[2010-05-31]
Apple Releases Snow Leopard Security Configuration Guide
http://blog.intego.com/2010/05/26/apple-releases-snow-leopard-security-configuration-guide/

Apple has released their Snow Leopard Security Configuration Guide,


Mac OS X Security Configuration Guides
http://www.apple.com/support/security/guides/

2010/01/07

Kindle DX

Kindle DXのニュース検索結果

日本は電子ブック戦争になぜ敗れたのか
http://ascii.jp/elem/000/000/487/487838/
ふーん pdf よめない?
あれ、こっちには読めるとあった。

読めるの読めないのどっち?ってことはあとでゆっくり調べることにして、

それにしても、最初の ascii の記事2ページ目で気になったこと

しかし電子ブックには在庫リスクなんてないのだから、こんな不合理なシステムを守る必要はない。それなのに彼らはアマゾンの参入を求めようとしない...


この文章の意味、私にはさっぱりわかりませぬ。
彼らって取り次ぎのこと?
アマゾンの参入をもとめようとしない?はぁ?
アマゾンさんも取り次ぎ業一緒にはじめませんか?楽しいですよって営業にいくの?なあほなね。
それともアマゾンさん、商品全部全部 すべからく取り次ぎとーしてくださいよっ!て言うってこと?まさかね。

ま、どうでもいけど、
ここでいわれてる不合理なシステム、すなわち再販制度にとっては、kindle は黒船以外の何者でもないのでしょうね。

あんまりなんでちょっと追記。(2010-01-08)

第一に
Kindle の物理的な特徴は、アマゾンに参入を求めるとか「認めるとか認めないとか」、そんな従来の井戸の中の蛙的価値観の枠の中で語ることを不可能至らしめてしまうであろうこと、そして Kindle の日本上陸とは、そういったレベルの出来事なんだってこと、を池田氏はちゃんと認識しているのかな?と疑問を持ってます。

第二に不合理なシステム(再販制度)を持つ業界と電気産業とは基本的に別々の業界である以上、書籍の再販制度の不合理な点と、電気産業が独自の規格で我の支配を広げたがる話とは、似ているようで全く似ていない似て非なる話なのに、それをごっちゃにして日本側陣営のようにしてる点でも、首をかしげてしまってます。
むしろ、不合理なシステムが不合理であることはえらい昔からわかってたことなので、それを変えることができないまま今日に至っているのは、なぜなのかにきりこんで欲しかったです。

第三に日本は取り残されると心配する心情は理解できなくもないけれども、ダイナミックな本の歴史の流れからみれば、そんな心配はささいな支流にすぎず、電気産業に肩入れしただけの単なる杞憂にすぎないと思う。Kindle のもたらす影響を考えれば 電機メーカー心配するより出版業界心配すべきだろ、とあきれています。
日本の再販制度 vs アメリカ発電子本屋の市場競争の行く末は、どちらかが許容するだの認めるだのなんてあまっちょろいもんじゃないでしょうに。

それに電子ブック戦争はこの日本ではこれからはじまるのだから、日本の電機メーカーが敗れたって言ってしまう(記事のタイトルにおいて)のは早すぎる結論なんじゃないのかな。Sony は先進的すぎて成功できなかったかもしれないけど日本においては今がチャンス到来なわけですし。
もっとも、電子ブック戦争といえば、Apple の未来のデバイス vs Kindle を意味するようになっている時代がくるのかもしれません。

とまれ、池田氏のトーンは時代の変化を受け入れているように読めるので、その点「だけ」は好感を持ってます。

2009/12/30

def max

github.com/midore/mdiary

個人が使うものなのであまり意味はないような気もするが、指定ディレクトリ内でのファイル上限数をもうけてみた。
bin/mdconfig に1ヶ月内に追加できるファイルの上限数を指定するメソッド default_file_count を追加し

mdconfig

def default_file_count
  90
end


当月ディレクトリ内のファイル数が default_file_count メソッドで指定した数を超えた場合
-a や -at でのファイル生成を抑制する。指定数に達している場合はその旨の文を返す。

万一、bin/mdconfig に default_file_count メソッドが存在しない場合(line 185)
ファイル上限数は 90 になる。(line 186)
1日平均2,3枚のファイルを生成すると仮定して 30 * 3

line 189 はなんかヘンなんだけど とりあえず...。

mdiary-main.rb
class Main

184     def max?
185       max = default_file_count if defined? default_file_count
186       max = 90 unless max
187       s = Dir.entries(@now_dir).select{|x| /\.txt$/.match(x)}.size
188       return false if s < max
189       print "too many files. Edit bin/mdconfig.\n"
190       return true
191     end


これに伴って
class Add < Main

221       return nil if max?

class ChoiceDir < Main

266     def base_view(n)
267       return nil if max?
...

273     def base_search(w, st=nil)
274       return nil if max?
...


としておいた。

あと

./mdiary-run.rb -s ""
./mdiary-run.rb -s ''

とかしたら無視するようにした。
line 132 あたり

2009/12/29

よみもの

ポール・グレアム「バージョン1.0
これ、めちゃくちゃおもしろかった。

「偉大な」執事とは何か?
と、小説の中の主人公が自問自答する場面を思い出した。なんでだろな...。あんまり関係ないと思うんだけど。

2009/12/28

unless a.nil?

このあいだ
github.com/midore/mdiary

mdiary-main.rb

378       return nil unless @st.nil? || @plus.nil?

だったのを

379       return nil if @st && @plus

に変えた。

前者と後者は同じ動きをする。どちらも
@st は nil ではなく、かつ、@plus もnil でなければ、return nil をかえす。

例えば

  1 # coding: utf-8
  2 
  3 a = 'a'
  4 b = 'b'
  5 print "a,b どちらも not nil です。\n" unless a.nil? || b.nil?
  6 print "a,b どちらも not nil でっす。\n" if a && b

実行すると

a,b どちらも not nil です。
a,b どちらも not nil でっす

となる。

前者(||を使用),後者(&&を使用)ともに

a は nilではない。かつ、b も nil ではない。
であれば print する。

と動く。ちょっと不思議だけど。

条件文が読みやすいのは && を使用した後者。
ただ、
if x
と書いて nil じゃなければとするより
unless x.nil?
と、nil なの?そうじゃないなら と書いてあった方が私にとってはわかりやすい時もあったりする。

...とはいっても || なのに「かつ」 を意図してるとなってると後になって自分がぎょっと驚いてしまうだろうから...変えた。