Land of Lisp の Kindle(mobi) ファイルを改善する

Land of Lisp いう面白い本があるわけです。

Land of Lisp: Learn to Program in Lisp, One Game at a Time!

Land of Lisp: Learn to Program in Lisp, One Game at a Time!

翻訳本

Land of Lisp

Land of Lisp

もあるものの、英文に抵抗がなければO'Reilly のサイトから購入すると
PDF, epub, mobi 全てがDRM フリーで購入できるいので、そちらがオススメ。
shop.oreilly.com

ただ、オリジナルmobiファイルのままだと

  • 画像が小さくみずらい
  • 丸数字の大きさがまちまちで体裁が悪い

が気になるため、epub から改めてmobiを作成することにした。
結果はこちらGitHub - dogatana/kindle-Land-of-Lisp: Improve readerbility of Land_of_Lisp.mobi based on Land_of_Lisp.epub

これで読むのが楽になった(気がする)。

バイスとしてのKindleは好きだが、やはりDRMフリーの電子書籍が購入できるのは嬉しい。

るびまのKindle化完了(54号まで)

Kindle化、次はいよいよ sicp-j (和田版)の仕上げをするか、RHGの手直しとするか。

読む本はKindleに丸々1年困らないくらいのキューができているのだが。。

パーフェクトRuby 読書録

ローカル変数かメソッドか

紛らわしい例。これは以前とあるコミュティーでも質問が出た件。
アクセッサを利用しているつもりがそうならない例。
以来 @val のように明示的にインスタンス変数として参照しているが、最近呼んだ本では、あまり良くない例とされている。クラス内部のメソッドからでも隠蔽したほうが良いのか?

> irb --simple-prompt
>> class Hoge
>>   attr_accessor :val
>>   def test
>>     val
>>   end
>>   def test=(v)
>>     val = v
>>   end
>> end
=> :test=
>> h = Hoge.new
=> #<Hoge:0x3312060>
>> h.val = 10
=> 10
>> h.val
=> 10
>> h.test
=> 10
>> h.test=(20)
=> 20
>> h.test
=> 10
>> h.test = 30
=> 30
>> h.val
=> 10
>>

Fixnum の object_id は数値そのもの?

試してみる

>> '%x' % 0x1000.object_id      
=> "2001"                       
>> '%x' % 0x10000.object_id     
=> "20001"                      
>> '%x' % 0x100000.object_id    
=> "200001"                     
>> '%x' % 0x1000000.object_id   
=> "2000001"                    
>> '%x' % 0x10000000.object_id  
=> "20000001"                   
>> '%x' % 0x100000000.object_id 
=> "186e94c"

確かにそうなっている模様。0x1000000 の次がFixnumとBignumとの境目。

組み込み変数 __dir__

2.0以降で追加された __dir__ だが、便利かも?

*****@*****-PC C:\usr\sandbox
> type test.rb               
puts $0                      
puts __FILE__                
puts __dir__                 

*****@*****-PC C:\usr\sandbox
> ruby test.rb               
test.rb                      
test.rb                      
C:/usr/sandbox

制御構造

  • begin .. end while は do while の動作
  • for v in x の v は for以降でも参照可能(スコープの変化なし)
  • 大域ジャンプは catch / throw
  • begin / rescue / else / ensure ensure 以外は値を返せる



Ruby Reference Manul を Kindleファイルにしてみた

ruby-list メーリングリストに投稿 [ruby-list:50379] Ruby 2.3.0 Reference Manual for Kindle したが、Ruby Reference Manual を Kindle 化してみた。

以前
Amazon CAPTCHAを読んだ際、『次はリファレンスマニュアルを読むこと』といった記述があったのを記憶していてずっと気になっていた。

が、実際のプログラミングの際には、chm ファイル版か、検索で事足りるため、なかなか通読する気になれなかたので、例によって例の如く html ファイルから変換した次第。

変換では

  • spine (本文)ファイルをどうするか
  • ナビゲーションをどう構成するか
  • httpで始まるリンクをどうするか

などの問題もあり、特にナビゲーションについては、リンクの設定の仕方によって kindlegen がエラーを吐くのが原因不明で、結局問題になる下の階層の項目を削除して回避。

マニュアル自体は独特の形式(rd 形式?)で記述されていて、それをBitclust というツールで

に変換できるらしい。
ただし、html 以外はうまく行かないかもしくは期待している内容と異なるファイル群となるので、もう少し調べが必要もある。

リファレンスマニュアルのメーリングリストも活動停止状態のようで、さてどうしたものか。

公開されている C++11の文法と機能 をKindleファイルへ変換してみた

ここ何年もC++は使ったことがなかったが、偶然 本の虫: C++11参考書の公開:C++11の文法と機能 を発見。
https://github.com/EzoeRyou/cpp-bookで内容が公開されているとのことであるので、kindle.rb の使い方を思い出すのも兼ね、Kindle形式(mobiファイル)へ変換してみた。

結果はこちら https://github.com/dogatana/cpp-book/tree/kindle

今日 GFDL を確認したところ、改変した際に改変者の表記が要求されるのが分かり、表紙画像他を修正。
TODO には書いたものの Paperwhite 向け修正までは手が回らない。。

2016/8/23 追記

ライセンスに関する表記の修正と、表紙画像の高解像度化実施

たのしいRuby 第5版

図書館にあった たのしいRuby 第5版 を読む。
手元の本は第2版で1.8が対象だったのだが、1.9以降のStringの仕様変更の理解がずっと浅いように感じているので、第3部を中心に落ち穂拾い的にあちこち読んで見る。
以下気になった点のメモ。1.8でもあったものかどうかは調べていないが、知らないことが多い。

第12章 数値(Numeric) クラス

これまで有理数複素数を使う機会はなく、スルーしていた部分。

有理数複素数
r = Rational(2, 3)
p r.to_f
p [r.numerator, r.denominator]
r2 = 1.3r
p r2
c1 = Complex(1, 2)
c2 = 3i
c = c1 + c2
p c
p [c.real, c.imaginary]

数値の型変換 Numeric#round

四捨五入する位置を指定する引数がある

p 12.34.round(1)
p 12.34.round(-1)
p 12.34.round

第13章 配列(Array) クラス

Array.new あれこれ。
Array.new       # => []
Array.new(3)    # => [nil, nil, nil]
Array.new(3, 0) # => [0, 0, 0]
Array.new(3, [0, 0, 0])    # => 各要素は同じオブジェクトを指す
Array.new(3) { [0, 0, 0] } # => 各要素は別のオブジェクト
Array.new(3) { |i| i * 2 } # => [0, 2, 4]
Array#values_at
a = %w(a b c d e)
a.values_at(0, 2, 4) # => ["a", "c", "e"]

第14章 文字列(String) クラス

ヒアドキュメント
def hear_test
  s1 = <<EOS
    string
EOS
  s2 = <<-EOS
    string
  EOS
  s3 = <<~EOS
    string
  EOS
  p s1, s2, s3
end

hear_test

<<~ は 2.3.0から追加とのこと

全角英数を半角へ、かつ半角カナを全角カナへ

仕事でよく出てくるパターン。NKFでうまくいく。

s = "これがコレガコレガABC123 abc123"
p s                   # => "これがコレガコレガABC123 abc123"
p NKF.nkf('-wZ1X', s) # => "これがコレガコレガABC123 abc123" 

第15章 ハッシュ(Hash) クラス

Hash#store, Hash#fetch
h = Hash.new('')
h[:p]                  # => ''
h.fetch(:p)            # => KeyError
h.fetch(:p, '(undef)') # => '(undef)'
デフォルト値
  • Hash.new(value)
  • Hash.new { |hash, key| }
  • Hash#fetch(key, value)

Hash.new にブロックを渡す例

h1 = Hash.new('')
h2 = Hash.new do |hash, key|
  hash[key] = key.upcase
end

第16章 正規表現(Regexp) クラス

Unicode文字プロパティを使った文字クラス指定
/\p{Hiragana}/
/\p{Katakana}/
/\p{Han}/

使うことはないだろうと思う。

マッチ結果

$&, $1 ではなく Regexp.last_match を使うのも良さそう。
(Matchdata#to_a)

第17章 IOクラス

Fileオブジェクトを作成せずに読み書きする方法

File.read('in.txt', { encoding: 'utf-8' }) # option のハッシュも使えるようだ
File.write('out.txt', '漢字まじり', { encoding: 'utf-8' }) 

File.binread('in.bin')                     # バイナリファイルの場合
File.binwrite('out.bin', '漢字混じり')

他のコマンドとのやり取り

第18章 FileクラスとDirクラス

実際に使うときにヘルプを見れば良し。

第19章 エンコーディング(Encoding)クラス

1.8から1.9で変化の大きかったところ。
ファイルを扱う際は気をつけているが、ARGVのエンコーディング変換は時々忘れる。

第20章 TimeクラスとDateクラス

実際に使うときにヘルプを見れば良し。

第21章 Procクラス

Proc, ラムダ式について メタプログラミングRuby 第2版 を読むほうが良い。

pdf ファイルからイメージファイルを取り出す(ruby, poppler)

ruby で pdfファイル内のテキスト、図の情報を取り出すのをどうするか。
簡単なのは poppler みたいなので、試して見る。
poppler 自体は他の gem のインストール時に勝手に入っているので問題なし。
ただし日本語を含むものはエラーが出るので poppler-data が必要のようだ。

Windows上のRubyで日本語PDFを読むためにpoppler-dataをインストールする方法 - アイデアの甕 を参考にさせてもらった。
Poppler の下の方にある、poppler-data のリンク
(本日現在で https://poppler.freedesktop.org/poppler-data-0.4.7.tar.gz )を解答したフォルダを
poppler にリネームして、poppler-gem の下に置けば良い。

こちらの環境では次のフォルダの下ということにになる。
C:\Programs\ruby\lib\ruby\gems\2.3.0\gems\poppler-3.0.8-x86-mingw32\vendor\local\share

テキストの取り出しは至って簡単。
イメージの取り出しは、pdf に格納されているままということではなく、write_to_pngpng ファイルとして書き出すことになる。
image_mapping メソッドがページ内のイメージ数の取得に使えそうだが、[]を返すので、nil になるまでループを回すしかなさそう。

require 'poppler'

if ARGV.empty?
  puts 'usage: rb get_image.rb file [files...]'
  exit
end

ARGV.each_with_index do |file, file_num|
  file = file.encode 'utf-8'
  doc = Poppler::Document.new file
  doc.pages.each_with_index do |page, page_num|
    puts "file: #{file}, page: #{page_num}"
    image_num = 0
    loop do
      img = page.get_image image_num
      break unless img
      filename = "#{File.basename(file, '.*')}_#{page_num}_#{image_num}.png"
      img.write_to_png filename
      image_num += 1
    end
  end
end