RubyPico開発日誌3 - getsを実装する

Popup.input()を使えば今でもプログラムに入力を渡すことはできるのだが、ポップアップ中は後ろの画面にアクセスできなくなってしまうのが不便。という訳でgetsを実装したい。

puts "Please input >>>"

while l = gets
  break if l.empty?
  puts l
end

puts "The end."

iConsoleがそれっぽい画面だったので参考に軽く実装。それっぽい画面にはなった。

f:id:tuto0621:20160819021650p:plain

しかしいくつかの不満が残る。(上から致命度が高い)

  • プログラム起動直後に[_inputField becomeFirstResponder]すると入力がソフトウェアキーボードの下に隠れてしまう
  • LINEのように複数行入力できるようにしたい
  • getsを使用しないときは入力部分は非表示にしたい(OR とても小さくしたい)、代案としては入力不可

いくつかモンキーパッチを試してみたがうまくいかない。この辺りでiOSのUI周りのプログラムに対するレベルアップが必要な気がしてきた。

cocoapodsで参考になりそうなpodsを探すと以下が良さそう。

知りたいことは以下。

  • 非storyboardでAutoLayoutを使ったUIの構築
  • プログラム起動直後にフォーカスを移してもUIがソフトウェアキーボードの下に隠れないように
  • 複数行の入力

その他、今は使わないけど面白そうな機能。

  • Autocompletion (絵文字の補完)
  • Markdonw Formatting
  • Typing Indicator (プログラムからの入力補助に使えるかも?)
  • Panning Gesture
  • Shake Gesture
  • External Keyboard (キーボードショートカット)

しばらく時間をかけてコードを読んでみよう。まずは動かすところから。

RubyPico 0.8 リリース - mainが不要に、画像がputs可能に

RubyPico 0.8 をリリースしました。以前に紹介したようにメインルーチンをmain関数で囲まずに実行できるようになり、よりRubyらしく書けるようになりました。

puts "Hello, RubyPico!"
puts "http://rubypico.ongaeshi.me"
puts Image.load("chat_ruby.png")

f:id:tuto0621:20160816111155p:plain

アプリ内のサンプルコードは全て新しい書き方に書き直されているので詳しくはそちらを参考にしてください。

RubyPico

RubyPico

  • ongaeshi
  • 仕事効率化
  • 無料

mainが不要に

CRubyと同じように書けるようになったため、Webや書籍のサンプルコードをコピペで動かすことができるようになりました。例えばこれは初めてのRuby内の素数を求めるサンプルコードですが、そのままRubyPicoで動かすことができるようになります。

(2..100).each do |candidate|
  sqrt = Math.sqrt(candidate)
  factor_found = (2..sqrt).any? {|i| candidate % i == 0}
  if factor_found then
    print "#{candidate} は合成数\n"
  else
    print "#{candidate} は素数\n"
  end
end

f:id:tuto0621:20160815214622p:plain

旧コードの動かし方

main関数を明示的に呼び出すようにしてください。

def main
  .
  .
  .
end

# プログラムの最後にmain呼び出しのコードを追加
main

チャットの方は動かなくなってしまいます、すいません。手元にもたくさんのチャットコードがあり悩んだのですがCRubyと同じ感覚で使えることを優先することにしました。

なお、チャットUIのようにプログラムに対して画面をオーバーレイせず入力を渡す仕組みは別途用意する予定です。

画像をURL指定で表示できるように

Image.pick_from_libraryでフォトライブラリから、Image.load(path)サンプル画像を表示することができましたが、加えてURLを指定して画像を表示することができるようになりました。

URL = "http://rubypico.ongaeshi.me/images/rubypico_icon.png"
logo = Image.load(URL)
puts logo

複数の画像の出力が可能に

最初の実行結果でお気付きの方もいるかもしれませんが、テキストと画像を混在して出力させることができるようになりました。さらに複数枚の画像を出力することもできます。サンプルのimage.rbは選択した画像の右下にRubyPicoのロゴ画像を重ねて表示させています。

# # image
#
# ## Description
# Display image and overray with logo

puts "image"
image = Image.pick_from_library
# image = Image.load("sample.jpg")
puts image

puts "logo"
URL = "http://rubypico.ongaeshi.me/images/rubypico_icon.png"
logo = Image.load(URL)
puts logo

puts "overray"
overrayed_image = Image.render(image.w, image.h) do
  image.draw(0, 0, image.w, image.h)

  w = image.w / 8
  h = logo.fith(w)

  img = logo.sepia
  img.draw(image.w - w,
           image.h - h,
           w,
           h)
end
puts overrayed_image

画像をコピー、カメラロールに保存したい場合はその画像を長押ししてください。

f:id:tuto0621:20160816111239p:plain

「初めてのRuby」をRubyPicoで実際に動かしながら読む

RubyPico向けの入門記事を書きたくて、Rubyの入門書を改めて色々と読み直している。まずはずっと気になっていた「初めてのRuby」を購入。

初めてのRuby

初めてのRuby

pdfはHonyomiに突っ込んだのでいつでも検索できるようになった。こういう振り返り記事を書くときはとても役に立つ。

f:id:tuto0621:20160815214402j:plain

今回初の試みとして

  • iPadでpdfを表示 (こっちは紙の書籍でもKindleでもよい)
  • iPod touchでRubyPicoを実行

させてサンプルコードを実行しながら読み進めた。今申請中の0.8からはmain不要でスクリプトを書けるようになり、大分CRubyと同じ雰囲気で書けるようになったからだ。例えば書籍内で紹介されていた素数か判定する以下のプログラムはそのままRubyPicoで実行することができた。

(2..100).each do |candidate|
  sqrt = Math.sqrt(candidate)
  factor_found = (2..sqrt).any? {|i| candidate % i == 0}
  if factor_found then
    print "#{candidate} は合成数\n"
  else
    print "#{candidate} は素数\n"
  end
end

実際にコードを打ち込んで挙動を確認しながら読み進めると理解が一段深くなる。ifにはthenをつけない、{|i| }{ |i| }派、みたいな自分のスタイルに置き換えても同じように動くことを確認していけるのもよい。

f:id:tuto0621:20160815214622p:plain

書籍自身の感想としては、RubyコミッタのYuguiさんが書いただけあってRubyの深いところまで理解した上でRuby初心者(この書籍は他言語を習得しているけどRubyを初めて使う人を対象に書かれている)向けの内容が厳選されており大変読みやすい。私は割と必要なスクリプトを書くために実践的にRubyを覚えてしまったところがあるので、基礎的な知識がポッカリ抜けている部分がありそれらを補完することができた。String#[regexp]とかString#%とか知らなかったけどこれからは積極的に使っていこうと思う。私が使い慣れているC++C#などの静的言語と比較しながら説明してくれるのもわかりやすかった。

特に面白かったのは7章のメソッドと8章のオブジェクトとクラスで、なんとなく使っていたブロック付きメソッドとProc型の違いブロックを引数として受け取る方法などがすごく短いページに(ここ重要)簡潔にまとめられていて大変よかった。8章などRubyの強力なメタ機能をささえるクラス、オブジェクト、特異、モジュールといったコア要素の一通りの説明がたった22Pに収められていて必要に応じてまた読み返したいと思う。あとモジュールの説明で2つの目的があってMix-in(これはよく見かける)と名前空間の提供(これ割と見かけない)というのをちゃんと章を分けて説明してくれていて大変安心した。他の人のコード読んだりすればモジュールを名前空間として使ってよいのはなんとなく分かるのだけどそれを章立てして説明してくれているのは初めてみたので(多分書いてあるのだけど私が今まで見落としていた)。

と、いう訳ですでにRubyに慣れている人でも「初めてのRuby」は大変おすすめです。短いページ数に必要な情報が凝縮されているのでさっと読んだ後に必要に応じて簡単に読み返せるのもよいです。

※ 余談ですが最近はたくさんの情報が網羅されてページ数の多い本よりも必要な情報が短いページに凝縮された本の方を好むようになってきました

夏休みの宿題でRubyPicoを再開

思ったことを最速でブログに書く環境もだいぶ整備できたのでRubyPicoの開発に戻る。まずは夏休みを使ってmain無しで動く最新のRubyPicoをリリースしたい。そのあとで書きかけのスマホではじめるRubyプログラミングを書く。プログラミングを学びたい人がRubyだけで色々なものを作れるようにしていく予定。

雑記: 洋書の読み方

Create Your Own Programming Languageを紹介したときに洋書読むの大変そうという話をよく聞いたので自分が使った教材を紹介する記事を書き始めた、が以外と長くなっているのでもう一息。端的に言うと

  • 「英語じゃないと読めないけどどうしても読みたい文章」を頑張って見つける
  • 基本からわかる英語リーディング教本
  • English Grammar in Use Book
  • 英単語アプリ mikan

みたいな感じです。

自分でプログラム言語を書いてみたい人は「Create Your Own Programming Language」がおすすめ

読み終わった。たった100Pにプログラム言語を作るための基礎(字句解析、構文解析、ランタイム、インタプリタ仮想マシン、ネイティブコンパイルまで!)が一通り学べ、さらに本書で作った実際に動くプログラミング言語がついてくる。 $39.99 とちょっと高いがプログラム言語を作る勉強代だと考えれば最も安くそして早く(ドラゴンブックは1090P)学べるのではないだろうか。洋書なのが難点だが半分くらいはソースコードなので苦労しながらなんとかなりました。(日本語訳出てほしいなぁ)

書籍内で作る言語は2種類で

  • Awesome
    • Rubyの構文にPythonのインデントブロックを混ぜ合わせたようなオブジェクト型
  • Mio
    • Ioを参考にしたメッセージ型

言語自体はどちらもRubyで書かれているが紹介される概念は特に言語の制約を受けないものが多い。

よかったところ

yaccやbison, JVM系の構文解析ツールなど実際に言語開発者によく使われているツール群の紹介が前半にたくさんあったのがよかった。この手のツールはあまりインターネットを漫然とサーフィンしているだけだとなかなか知る機会がないため。

「6. Runtime Model」の章。ものすごい数のプログラミング言語があるけどランタイムモデルの数はそこまで多くないということが分かった。これらと字句解析、構文解析の組み合わせで様々な言語が生まれる。(もちろん実際の言語はもう少し複雑でプロトタイプ型の特徴をもったクラス型、みたいな感じにいいとこどりだったりすると思うけど。)

  1. Procedural (手続き型、Cとか)
  2. Class-based (クラス型、Ruby, Python, C++, Javaとか、今だと一番多い?)
  3. Prototype-based (プロトタイプ型、JavaScript、実装がとてもシンプルに書けるのが特徴)
  4. Functional (関数型、Haskell, Lisp)

プログラム言語ってそれぞれ全然違うように見えて内部の実装の基礎的なところはかなり同じ概念で作られていることが多いので、プログラム言語を作ることに興味がない人でも、どんな基礎概念をベースに作られているのか、これらをたたき台に次はどんな言語が生まれるのか?と言ったことが分かるようになるのでおすすめです。

おまけ

こんなところにもmatzパワーが。

f:id:tuto0621:20160804002429p:plain

さらにこの本を読んで感動した Jeremy Ashkenas さんが書籍内のサンプル言語をたたき台に作った言語が CoffeeScript だというのだからすごい。(たしかに Awesome と CoffeeScript はちょっと似ているところがある。)

追記

書籍内では字句解析(lex)の部分はRuby正規表現を使って自前で作成、構文解析(yacc)の部分はRacc(Rubyで書かれたyacc)を使ってやっています。ツールのインストールにつまずきにくいのでよいですね。

この本を購入するには、著者のページのあのフォームにクレジットカード番号を入力して購入するしかないでしょうか? (少々、不安なフォームに見えるので・・・)

PayPalのアカウント作ってそこから購入するのがおすすめです。海外で買い物するならPayPalは作っておいて損はないと思います。

ファイル内のidの有無で新規か更新かを自動で判別できるように

ちょっとずつ自分好みの改善を加えていく。

使い方

新規作成

$ hw 001.md
http://ongaeshi.hatenablog.com/entry/2016/08/03/002228 (New)

更新

$ hw 001.md
http://ongaeshi.hatenablog.com/entry/2016/08/03/002228

記事を書き換えていくだけなら特にオプションも気にせずに実行すればよいということです。

これももう少し使ってみてよさそうだったらMRに出してみようかな。

hatenablog gemでタグ付きの文章が出力できない問題を解決した

色々とコード書き換えながら試したいのでローカルにbundle installする。

$ bundle install --path vendor/bundle

これでvendor/bundle以下にあるgemファイルを書き換えることでライブラリの挙動を変えたりpしながら調べることができる。

コードを読んでいくとxmlにエスケープが入っていないことが分かった。rubyでシンプルなXML escape。なので以下のようにエンコード関数を渡すことで動くようになった。

def entry_xml(title = '', content = '', categories = [], draft = 'no', updated = '', author_name = @user_id)
  .
  .
  xml % [e(title), author_name, e(content), updated, categories_tag, draft]
end

足したe()関数はこんな感じ。

def e(str)
  str.encode(xml: :text)
end

うまく行ったぜー、とプルリクエスト送ろうと思ったらkymmt90/hatenablogにあるコードと中身が違う、あれ?よくみるとbundle installで入っているのはhatenablog-0.2.1だけど最新はhatenablog-0.2.2であることに気がついた。これはもしかして・・・結局マージリクエストは以下のようになった。

Update hatenablog to 0.2.2 by ongaeshi · Pull Request #2 · kymmt90/hatenablog-writer

これで以下のようなタグ付きのテキストも問題なく投稿できるようになった。

<html>
</html>