日付の入ったファイル名でメモをとる
普段の仕事中いろんなメモ(ログやコピペの断片)を取りながらやりたい派なのですが、メモのファイル名をいちいち考えるのが面倒くさかったりします。一つのファイルに書き続けてもいいのですが、ファイルを開くのが重くなってくるし、後で検索したりするのも面倒です。
最初は Evernote で毎日新しいノートを作成したりもしていたのですが、
- Evernote はプレインテキスト編集が出来ない
- Dropbox とかに同期して他の端末でも見れるようにしたい
- grep などのコマンドラインツールと組み合わせて使いたい
- vim で書きたい(切実)
という事もあって、今日の日付でテキストファイルを作成する gem を作りました。
daily-txt https://github.com/bonar/daily-txt
gem install daily-txt
初回起動時に以下の設定ファイルを作成します。
$ cat ~/.daily_txt_config.json { "home": "/Users/bonar/daily_txt", "editor": "/usr/bin/vim", "color": true }
引数なしで起動すると、指定したエディタで「今日のファイル」を開きます。
daily-txt
-l で今まで保存したファイルの一覧を返します。.daily_txt_config.json の home 以下に text/YYYY/MM のディレクトリを切って保存します。
$ daily-txt -l | head /Users/bonar/daily_txt/text/2016/09/2016_09_05.txt /Users/bonar/daily_txt/text/2016/09/2016_09_02.txt /Users/bonar/daily_txt/text/2016/09/2016_09_01.txt /Users/bonar/daily_txt/text/2016/08/2016_08_31.txt /Users/bonar/daily_txt/text/2016/08/2016_08_30.txt /Users/bonar/daily_txt/text/2016/08/2016_08_29.txt /Users/bonar/daily_txt/text/2016/08/2016_08_25.txt /Users/bonar/daily_txt/text/2016/08/2016_08_24.txt /Users/bonar/daily_txt/text/2016/08/2016_08_23.txt /Users/bonar/daily_txt/text/2016/08/2016_08_22.txt
メモが一箇所にまとまっていると、検索やバックアップが捗ります。home を Dropbox の同期ディレクトリ内にしておけばバックアップも自動で取れます。
$ daily-txt -l | xargs grep hoge /Users/bonar/daily_txt/text/2016/05/2016_05_13.txt:# hoge
会社で日報を書いていた時期があったのですが、「その日1日の作業」ですらその日の終わりには忘れている事が多いので、日付単位でメモが残るのはなかなかいいものです。
数値を単位で分割する
何かのコマンド出力とかで、バイト数や秒数などとても大きな数値が表示される事があります。
62945280+0 records in 62945280+0 records out 32227939482 bytes transferred in 4340.259756 secs (7425358 bytes/sec)
これをパッと見た時に、32227939482 が果たして 3GB なのか 300MB なのか把握できないことがよくあります。秒数に関しても(4340 sec くらいなら暗算できますが)同様のケースがあります。
df -h みたいな human readable な出力を用意しているコマンドもありますが全てではないので、なかなか厄介です。今までは irb とかでちまちま計算していたのですが、与えられた数字を単位に分割するコマンドを作ってみました。
インストール
gem install unit_split
バイト数
$ unit_split -b 32227939482 30 GB 14 MB 981 KB 154
秒数
$ unit_split -s 50000 13 hour 53 min 20
日本の単位(これもパッと見分からないことがある)
$ unit_split -j 123534590029342 123 cho 5345 oku 9002 man 9342
この gem をインストールすれば、カーソルで4桁ずつ数字を選択する生活とおさらばだ!
git における stage, commit, branch
git は難しいと良く言われます。僕もそう思います。個人的には Pro Git Pro Git 日本語版電子書籍公開サイト の説明が最高に分かり易いのでとてもオススメです。
コマンド体系であったりトラブルシューティングであったり色々な視点があると思うのですが、どちらかというと git 特有の世界観が掴めるとぐっと理解が進むような部分があるなと感じていました。初歩的な内容ではありますが、特に、stage, commit, branch に関して「新しく git に入ってきた人が、これを知っておくとスムーズ」と思った物を書いてみます。
(変な所があったらツッコミをお願いします)
stage と local repository
svn 等と同じく git でも多くの場合チーム全員で共有する中央レポジトリがあります。ただ、そこに修正を送り込む前に stage と local repository があるというのが git の特徴的な所です。git に触れ始めた頃はわけもわからず git commit -a していたのですが、stage と local repository をうまく使う事でコミットを整える事が出来るようになります。
以下は、origin という remtote repository が登録された状態で master ブランチを編集しているという想定の図です。
stage は次にコミットするものを一時的にのせておく発射台です。手元(Local change)でファイルを編集し、git add でファイルを stage に追加します。やっぱりやめたという時は git reset で stage から降ろします。修正の一時的な置き場である stage がある事で、修正を意味のある単位に纏める事が出来るのがとても便利です。コミットログも書き易くなります(「今日の作業分」よさらば)。
ちなみに stage, local repository 間の差分は以下のコマンドで確認します。
git diff # 手元の修正と stage の差分 git diff --cached # stage と local repository の差分 (= --staged)
git commit すると stage にある内容が local repository にコミットされます。まだこの時点では全ては自分のマシンの中の出来事なので好きに修正する事が出来ます。コミットした内容を取り消したい場合は戻したい地点のコミットハッシュ(一つ前のコミット)を指定して、
git checkout master git reset --soft {commit hash}
で local repository の master の状態が指定した地点まで戻ります。--soft はローカルのファイルの状態は変えません(git status で差分が出る)が、--hard だとローカルのファイルもその地点の状態に更新します(変更が失われる)。
この後 git push origin master すると、local repository 内の master ブランチが remote repository の master に送信されます。svn だと local の修正からいきなり remote repository に行く感じなので大分違いますね。
git fetch すると remote repository の内容が local repository の origin/master(repository名/ブランチ名)ブランチに落ちてきます。いきなり local repository の master ブランチに入らないところが特徴的です。この状態で
git diff master..origin/master
することで local/remote repository の master の差を確認する事が出来ます。これを確認した上で
git checkout master git merge origin/master
すると remote repository の master の内容を local repository に取り込む事が出来ます。この fetch & merge を一度に行うのが git pull です。
コマンドは少しややこしいのですが、どちらかというと上記のような登場人物がいるという事と、その位置関係をイメージとして知っておく事が重要なのかなと思います。
コミットはスナップッショット
特に svn から git に来ると、「svn は revision というスナップショットの集合で歴史が出来るけど、git はコミットという差分の集合で歴史が出来ている」という理解に至りがちな気がしますが、これは正確な理解では無いと思います。git のコミットもスナップショットだからです。
実際にコミットオブジェクトの中身を見るのが分かり易いです。例えば以下のように、README.txt に line1, line2, line3 というテキストを一行ずつコミットしていくようなシチュエーションを考えます。
$ mkdir gitsample $ cd gitsample $ git init Initialized empty Git repository in /Users/bonar/git/gitsample/.git/ $ echo "line 1" >> README.txt; git add README.txt; git commit -m "line 1" [master (root-commit) c5d5c04] line 1 1 file changed, 1 insertion(+) create mode 100644 README.txt $ echo "line 2" >> README.txt; git add README.txt; git commit -m "line 2" [master 8a61b67] line 2 1 file changed, 1 insertion(+) $ echo "line 3" >> README.txt; git add README.txt; git commit -m "line 3" [master 6c946b8] line 3 1 file changed, 1 insertion(+)
$ git log commit 6c946b8e1bc1f988b7d795517be3cb62aa963bdb Author: bonar <bonamonchy@gmail.com> Date: Wed Sep 3 22:39:58 2014 +0900 line 3 commit 8a61b6756863c292d94791e87b8765fd788d18c8 Author: bonar <bonamonchy@gmail.com> Date: Wed Sep 3 22:39:51 2014 +0900 line 2 commit c5d5c04376593fdb76754996d0322dd0005cd797 Author: bonar <bonamonchy@gmail.com> Date: Wed Sep 3 22:39:42 2014 +0900 line 1
例えば line3 のコミットオブジェクトは具体的には .git/objects/6c/946b8e1bc1f988b7d795517be3cb62aa963bdb に保存されています。コミットオブジェクトの中身を詳しく見るには、git cat-file -p でコミットハッシュを指定します。
$ git cat-file -p 6c946b8e1bc1f988b7d795517be3cb62aa963bdb tree bf3461315080f6ca4e73ab1eb42f3389415758c6 parent 8a61b6756863c292d94791e87b8765fd788d18c8 author bonar <bonamonchy@gmail.com> 1409751598 +0900 committer bonar <bonamonchy@gmail.com> 1409751598 +0900 line 3
tree, parent と、コミットのメタ情報(author, comment)でコミットが構成されていることがわかります。tree というのはその時点でのファイルの一覧とそのハッシュ値が記録されたもので、まさにスナップショットです。この中身も git cat-file で確認する事が出来ます。
$ git cat-file -p bf3461315080f6ca4e73ab1eb42f3389415758c6 100644 blob a92d664bc20a04b1621b1fc893d1196b41182fdf README.txt $ git cat-file -p a92d664bc20a04b1621b1fc893d1196b41182fdf line 1 line 2 line 3
ファイルの中身そのものもハッシュ値と対応する形で blob として .git/object 以下に格納されています。
重要なのは、コミットオブジェクトが「どのファイルがどのように変更されたか」を直接的に記録している訳ではないという点です。例えば git show するとこのコミットでの差分が出ますが、
$ git show 6c946b8e1bc1f988b7d795517be3cb62aa963bdb commit 6c946b8e1bc1f988b7d795517be3cb62aa963bdb Author: bonar <bonamonchy@gmail.com> Date: Wed Sep 3 22:39:58 2014 +0900 line 3 diff --git a/README.txt b/README.txt index 7bba8c8..a92d664 100644 --- a/README.txt +++ b/README.txt @@ -1,2 +1,3 @@ line 1 line 2 +line 3
これは parent のコミットオブジェクトが持つ tree との比較によって得られます。つまり上記は line 3 の tree と line 2 の tree の比較結果です。この事は line 3 のコミットと同じ tree を持ち、且つ parent が line 1 のコミットオブジェクトを作ってみると分かります。新しいコミットオブジェクトは git commit-tree で作成出来ます。
$ git commit-tree -p c5d5c04376593fdb76754996d0322dd0005cd797 -m "line 3'" bf3461315080f6ca4e73ab1eb42f3389415758c6 446e26265ba55c115dce2f62407a481e44010968 $ git cat-file -p 446e26265ba55c115dce2f62407a481e44010968 tree bf3461315080f6ca4e73ab1eb42f3389415758c6 parent c5d5c04376593fdb76754996d0322dd0005cd797 author bonar <bonamonchy@gmail.com> 1409752954 +0900 committer bonar <bonamonchy@gmail.com> 1409752954 +0900 line 3'
新しく作ったこのコミットを git show すると、同じ tree を持っているにも関わらず line1 と line3 の差分が出ます。
$ git show 446e26265ba55c115dce2f62407a481e44010968 commit 446e26265ba55c115dce2f62407a481e44010968 Author: bonar <bonamonchy@gmail.com> Date: Wed Sep 3 23:02:34 2014 +0900 line 3' diff --git a/README.txt b/README.txt index 89b24ec..a92d664 100644 --- a/README.txt +++ b/README.txt @@ -1 +1,3 @@ line 1 +line 2 +line 3
「コミットの差分」というのが parent コミットとの関係で決まる相対的な物であるという事が分かります。これは git のコミットがその時点でのファイル全体のスナップショットであることを表していて、「コミット」という言葉の語幹からはイメージ出来ないものかもしれません。この認識は merge を行う際にとても重要になります。
ブランチはコミットを指すポインタ
ブランチは単に特定のコミットハッシュに名前をつけた物でしかなく、特定のコミット郡に名前をつけてグルーピングしておく入れ物ではありません。
例えば以下のようなブランチ群を考えます。
1 のコミットの後に branch A が切られ、4, 5, 6 と3つのコミットをした後に branch B が切られ、7, 8 というコミットが行われた状態です。この状態において、branch A というのは 6 のコミットを指すポインタで、branch B は 8 のコミットを指すポインタです。
.git/refs/heads を見ると、ブランチの HEAD のコミットハッシュが書かれたファイルがあります。これがブランチの正体です。
$ ls -1 .git/refs/heads
branch_a
branch_b
master
$ cat .git/refs/heads/branch_b
9c15300bc1789e9f3ddbf4fc32f3965813879828
ここで branch B を master に merge しようとした場合、「branch B を checkout した後にこのブランチに対して行った修正である 7, 8 が master に入るのだろう」と思いがちです。しかし実際に起こる事は「branch B というポインタが指しているコミット(=8)の tree を master に merge する」になります。8 の時点でのスナップショットが master に merge されるわけなので、4, 5, 6 の修正も入る事になります(branch B の修正じゃないのに!)。
とても当たり前の事なのですが、「ブランチという箱に差分を入れている」という脳内イメージだと、上記のような勘違いに至りがちです(僕もよくします)。特に merge する際には「ブランチはコミットへのポインタであって、コミットはスナップショットである」という認識に立ち戻ると訳が分からなくなる事が少ないかなと思いました。
次号:「git rebase とは何なのか」に続く
ruby ブロック内からの return
例えば受け取った配列内を一つずつ見ていって偶数の場合のみ puts する、という処理をしようとして以下のようなコードを書いたとします。
def print_evens(nums) nums.each do |num| return if 1 == (num % 2) puts num end end print_evens((1..10).to_a)
each に与えられたブロックの最初の行で奇数の場合はブロックの処理を終え(次の num の実行に移り)、そうじゃない場合(偶数の場合)には puts num するという意図ですが、このコードを実行しても何も表示されません。
ブロック内の return で print_evens メソッドそのものを抜けてしまうからです。
意図した動きにするためには return を next に変える必要があります。
def print_evens(nums) nums.each do |num| next if 1 == (num % 2) puts num end end print_evens((1..10).to_a)
2 4 6 8 10
break にした場合には each のループのみを抜けて print_evens は抜けず、次の文に制御が移ります。
驚くほど当たり前の事を書いている感じなのですが、JavaScript のコードと行き来しているとこういうミスをしてしまいがちで、特に文法エラーになるわけでもないので分かりにくいバグとして潜伏しがちかなと思いました。
また、next が値を受け取れるという事は見逃されがちです。これはとても便利に使えて、例えば fizzbuzz を以下のように書けます。
def multiple?(a, b) !!(0 == (a % b)) end def fizzbuzz(nums) nums.map do |num| next "fizzbuzz" if multiple?(num, 3) && multiple?(num, 5) next "fizz" if multiple?(num, 3) next "buzz" if multiple?(num, 5) next num end end puts fizzbuzz((1..20).to_a)
ブロック内で最後に評価される値を意図した物にしようとしてネストが深くなったり複雑化するよりは、next で早めに返す方が見通しがいい、という局面は結構ありそうですね。
PaceSlider - 片手でペース計算
ランニングをしていて、以下のように思う事はありませんか?
- ハーフマラソンを1時間45分で走るには、どれくらいのペースで走ればいいんだろう
- 6'30/km のペースで 100マイルのレースを走ったらどれくらいのタイムになるだろう
- ゴールまであと 20km、制限時間が3時間 ということは、必要なペースはいくつだろう
なかなか厄介な計算です。こういう計算をしたい事が結構あるのですが、なかなか暗算出来るようにならないので、JavaScript で計算機を作りました。以下から使用可能です。
まず距離を選択して、スライダーを動かします。するとペースと時間が連動して変化します。
あとは自分が目指すペースやタイムまでスライドして行くだけです。キロメートルとマイルの両方に対応し、1km〜160km までの任意の距離を設定可能です。
スライダーを左右の端にくっつけると時間とともにペースが増減する、っていうのが工夫したポイントです。iPhone 5 でしか動作確認していないので、他の端末だと何かおかしいかもしれません。
ペース計算機は巷に色々ありますが、入力フォームが多かったり、少しずつずらして調節する、というのがやりにくい UI になっている事が多いです。ペースの計算は「速さ/時間/距離」の三項の関係性ですが、PaceSlider では「速さと時間をいじって距離を調節する」という部分を切り捨てて簡素化したという点が特徴です。僕のユースケースではそれは必要なかったからです。「自分が使えればいい」と考えると気楽ですね。
たったこれだけのものでも、UI 等を自分なりに考えて作るのは意外と時間がかかるものです。
が、逆に基本的な部分は良いパーツが既にあるのでだいぶ楽ですね。UI は boottrap を使ってますし、ファイルは S3 に置いています。
本当に楽ですね。良い時代です。
YAPC::Asia 2013 に参加してきました!
Perl と関係ない話題も多くて、色々な人と技術の同窓会みたいな とても楽しい2日間でした。
ベストスピーカーは yusukebe さん、myfinder さん、kazeburo さんでしたね。
yusukebe さんのは聴けなかったのですが、myfinder さんのテストを並列実行する話は恐らく色々な人にとって現実的な課題だし、具体的な内容だったので面白かったですね。しかも凄く良い声でした。
フルテストも50msで終わらせたい 〜 FreakOutの取り組み 〜 - YAPC::Asia Tokyo 2013
kazeburo さんの話は Monoceros の紹介に加えて、PSGI Server の選び方や実装方法に関して step by step で説明されていて、かなりイメージし易かったですね。「なんか出来るかも」という気がしてきて刺激されました。
PSGI/Plack・Monocerosで学ぶハイパフォーマンスWebアプリケーションサーバの作り方 - YAPC::Asia Tokyo 2013
あと印象に残ったトークといえば hiratara さんの型の話ですね。かなり楽しみに言ったのですが、正直まったく理解出来ず、久々に打ちのめされました。型システム入門を呼んで出直します。
Types and Perl Language - YAPC::Asia Tokyo 2013
- 作者: Benjamin C. Pierce,住井英二郎,遠藤侑介,酒井政裕,今井敬吾,黒木裕介,今井宜洋,才川隆文,今井健男
- 出版社/メーカー: オーム社
- 発売日: 2013/03/26
- メディア: 単行本(ソフトカバー)
- クリック: 68回
- この商品を含むブログ (8件) を見る
Perl と Ruby
rubyist との座談会企画がとても面白かったです。
YAPC::Asia Tokyo 2013 特別座談会 「Rubyの良いところ語ってください 〜そんなPerlで大丈夫か?〜」 - YAPC::Asia Tokyo 2013
結論としては「適材適所だよね」という事で、そうですよね、と感じました。webアプリのパフォーマンス全体で見れば言語自体の性能差は小さいし、言語そのものの生産性という話も 現在のコード資産や担当者の熟練度、採用コスト等の話になってしまうので客観的な評価になり辛い傾向があると思います。
RubyKaigi に行った時に特徴的だなと思ったのが、「みんなが良いデフォルトを使用している」感じです。rails/rspec/bundler/capistrano みたいなツールをみんなが使っていて、その辺りを知っている前提で話が進んでいて凄いなと思ったのを思い出しました。
Perl で良いコードを書くためには訓練された CPANソムリエになる必要があり、そこへ至る道がよく見えない、という辺りが個人的には難しいポイントなのかなと感じました。
- 作者: 牧大輔
- 出版社/メーカー: 翔泳社
- 発売日: 2009/02/10
- メディア: 大型本
- 購入: 25人 クリック: 534回
- この商品を含むブログ (113件) を見る
- 作者: 冨田尚樹,タナカユカリ
- 出版社/メーカー: ワークスコーポレーション
- 発売日: 2011/04/08
- メディア: 単行本(ソフトカバー)
- 購入: 20人 クリック: 2,028回
- この商品を含むブログ (20件) を見る
一定レベルの Perl Hacker の間では「こういう時はこれだよね」というコンセンサスがあって、実際は問題ないのかもしれません。
再発見した Perl の良さ
「イケてる ruby」と「停滞する Perl」というコンテキストで語られがちだけど、座談会で tokuhirom さんが言っていた、
という言葉が Perl の魅力を非常に端的に表しているなと思いました。言語としての機能が少なくて、それを補うようなモジュールの集合体が Perl という言語全体を作っている。そこに沢山の小さなプロジェクトがあって、誰もがちょっとした成功を掴むチャンスがある、というワクワク感が Perl 文化圏にはある気がします。rubygems と CPAN の存在感の違いかもしれません。
また、そういった構造ゆえに外部の言語(やツール)の良い所を持ってこようという動きも活発で、言語自体の大きな変化が無いにも関わらず色々な話題が定期的に出てきている気がします。
この「みんながヒーロー」な感じが Perl の魅力なんだなと再確認しました。
Kindle Paperwhite と 紙の本の素晴らしさ
念願だった Kindle Paperwhite を購入しました。
噂通りの見やすさで素晴らしい端末でした。Kindle が来てから僕の読書量もかなり増えました。読書に対するスタイルを一変させる力があると感じました。具体的に以下のような点が素晴らしかったです。
良い点
とても見やすく疲れない
E-Ink は本当に目が疲れず、素晴らしいの一言です。ライトもついているので寝ながら読む事ができ、ついつい深夜まで本を読んでしまいます。タブレットのような透過光メディアには無い圧倒的な優位性です。
沢山入るので、いくつもの本を気分に合わせて平行して読める
これも非常に大きなメメリットで、通常の読書体験から大きく向上した点です。
何冊も入れておけるので、その時の気分に合わせて読む本を変える事が出来ます。この事で常に何か読みたい本が読める状態になっているので、ぐっと読書が身近になりました。
完成されたエコシステム
Amazon の Kindle ストアで 1-Click 購入すると、Wi-fi に接続されたデバイスに勝手にダウンロードされて読める状態になっています。検索等も使い慣れた Amazon のインターフェイスで行えますし、無料でサンプルが読めて サンプル読了後に製品版の購入ダイアログが出たりと システム全体として非常に高いレベルで完成されていると思います。
安い
これほどのデバイスが 8000円 で購入出来るなんて凄いですね。
手触りもしっとりしていて安っぽくないです。ふちも大きく取られていて持ちやすく、マットな素材で滑りにくいです。
物足りない点
逆に以下の点は少し物足りないと感じました。
動作のもっさり感
iPhone のヌルヌルしたUIのような体験を期待しているとガッカリすると思います。タッチへの反応は鈍く、少し遅れて画面が切り替わるような感じです。
本を読む分には問題ないですが、本を検索する時には「もうちょっとキビキビ動いて欲しいな」と感じる事もあります。まあ、これは「電子書籍リーダーであってスマホじゃない」という点を考えれば許容出来る範囲かなと個人的には思いました。
bookscan で自炊
コンテンツが少ないので bookscan で自炊しました。プレミアムプランに申し込んだのですが、送付用の段ボールを送ってくれたり、スキャンと同時に Kindle 用の最適化をしてくれたりしてとても楽でした。
ただし、Kindle Paperwhite の画面サイズだと、B5サイズ(「Effective C++」 とか)くらいでかなりきついです。まあ頑張ればギリギリ識別出来るかな、、という感じです。
B6サイズ(「いかにして問題を解くか」とか)だとかなり奇麗に読めます。
中間の A5 とかはちょっと小さいけどなんとか読める感じですね。
ただし、Kindle ストアで販売されている書籍はもちろん文字もくっきりで大きく見やすいので、それと比べてしまうと自炊で作成した PDF はかなり辛いな、というのが僕の印象です。
技術書とかは B5 サイズが多いと思うのですが、これらを本格的に読むならもうちょっと大きい画面が欲しいですね。
紙の書籍の素晴らしさ
紙の書籍の良さを語る際にはかならず「紙の質感」や「余白のメモ」みたいな事が語られがちですが、個人的にはこれらはあんまり魅力を感じないんですよね。。
むしろ、Kindle の読書で一番もどかしく感じたのは「ザッピング」です。
目次をぱらっと見て、全体を俯瞰して見る。読み進めて行って、何か分からない事があったときにいったん目次に戻ってどこかの章をた見返して、また戻る、という行った事がし辛いんです。もちろん目次や指定したページへのジャンプは出来るのですが、ページ遷移がもっさりしているのでなかなか思うように行きません。
紙の本のように高速にページをめくりながら目的のもの探すということが、技術書を読む上では個人的に結構重要なので、この点は苦しいなと感じました。新書や小説のように最初から常にシリアルに読み続けるタイプの読書であれば気にならないかもしれません。
Kindle の素晴らしさ
Kindle の E-Ink は素晴らしいですが、1冊の本を読む体験ではやはり紙の書籍にはかなわないと感じています。
ただしその差は小さく、「同時に沢山持ち運べる」というメリットが買っているかもしれません。少なくとも僕の場合はより細切れに色々な本を読むようになりました。
また、場所と取らないという点も重要です。家の本棚はもういっぱいで新しい本が入れられず、結構深刻な問題です。何万冊もの本が印刷されずに済み、本棚のスペースが節約出来るんだとするとそれだけで素晴らしい事です。
あとは Kindle ストアが充実してくれるか、色々なストアでオープンなフォーマットのデータが販売されるようになって、大体の本はオンラインで買える、という状態になれば最高ですね。
というわけで、Kindle Paperwhite オススメです。