読者です 読者をやめる 読者になる 読者になる

レガシーコード生産ガイド

私に教えられることなら

Squeak5.0/Pharo4であるクラスの全メソッドのソースをクリップボードに

Smalltalk Pharo Squeak

ブログ等に貼るために、Smalltalkのクラスのメソッド定義を手軽にコピーしたい。

クラスの定義はFileOutでファイルに書き出せるけど、いちいちファイルからコピーするのも面倒だし、あまりブログ等で眺めるのには適してない表示になる。

コピペも面倒だし、Smalltalkでやろう。

手順は

  1. あるクラスの全メソッドのソースを文字列として取得
  2. 表示を加工、文字列に連結
  3. クリップボードにコピー

の3つ。

1. ソースを文字列として取得

クラスオブジェクトにmethodsDo: [:method | ... ]とメッセージを送るとそれぞれのメソッドを操作できる。

メソッドはCompiledMethodオブジェクトで、SqueakならgetSource、PharoならsourceCodeメッセージによってソースを取得できる。

今回はOrderedCollectionを用意しておいて、それぞれのソースコードを追加することにする。

| src |
src := OrderedCollection new.
"Squeak" Object methodsDo: [:method | src add: method getSource ].
"Pharo"  Object methodsDo: [:method | src add: method sourceCode ].
src.

inspect itした結果

f:id:phaendal:20160508215035p:plain

これであるクラスのインスタンスメソッドは取得できる。

クラスメソッドも取得する。対象のクラスオブジェクトにclassメッセージを送り、メタクラスを対象にする。

Pharoでの例

| src |
src := OrderedCollection new.
Object class methodsDo: [:method | src add: method sourceCode ]. "クラスメソッド"
Object       methodsDo: [:method | src add: method sourceCode ]. "インスタンスメソッド"
src.

2. 表示を加工、文字列に連結

  1. クラス名もコメントにして付加
  2. 空行で一つの文字列に連結

と加工してみる。

1については、クラスオブジェクト nameで取得できる。

2だけど、

  • Squeakの場合は 連結する文字列のコレクション joinSeparated: 改行2つの文字列
  • Pharoの場合は 改行2つの文字列 join: 連結する文字列のコレクション

と逆のメソッドが用意されている。好きな方を勝手に付け加えてもいいんじゃないでしょうか。

全て併せて、次のように書いてみた。Pharoでの例。(print itするならもっとメソッドが少ないクラスの方が良いでしょう)

| cls src cr |
src := OrderedCollection new.
cr := Character cr asString.
cls := Object. "対象のクラスオブジェクト"

"クラスメソッド"
src add: '"-----', cls name, ' class-----"'.
cls class methodsDo: [ :m | src add: m sourceCode ].

"インスタンスメソッド"
src add: '"-----', cls name, '-----"'.
cls methodsDo: [ :m | src add: m sourceCode ].

(cr, cr) join: src. "inspect it"

Squeakで自作クラスをinspect itした結果(クラスメソッドは無い)

f:id:phaendal:20160508221428p:plain

3.クリップボードにコピー

これは簡単で、Squeak/Pharo共通でClipboard default clipboardText: 文字列とメッセージを送ればいい。

以下は全部合わせて、ついでにブロッククロージャでまとめて、クリップボードにコピーするコード。2つの自作クラス(PhStGrammarPhStParser)を対象にしている。Squeakでの例。

| src cr getter str|
src := OrderedCollection new.
cr := Character cr asString.

getter := [:c :s |
    s add: '"-----', c name, ' class-----"'.
    c class methodsDo: [:m | s add: m getSource ].
    s add: '"-----', c name, '-----"'.
    c methodsDo: [:m | s add: m getSource ]].

getter value: PhStGrammar value: src.
getter value: PhStParser  value: src.

str := src joinSeparatedBy: (cr, cr).

Clipboard default clipboardText: str.
広告を非表示にする