JDEEを使ってみる
Android書くときに、Eclipseもいいんだけど、やっぱり手馴れたエディタを使いたいよねってことでJDEEを試してみる。
というわけで、自分用コマンドリファレンス。
インストール
http://jdee.sourceforge.net/
JDEEとelibをダウンロードしてmake install
設定
Android SDK にもパスを通しておく
JDKのバージョンとか場所は適宜。書いてあるのはUbuntu環境でのもの。
;; jdee (add-to-load-path "elib") (add-to-load-path "jdee/lisp") (autoload 'jde-mode "jde" "Java Development Environment for Emacs" t) (setq auto-mode-alist (cons '("\.java$" . jde-mode) auto-mode-alist)) ;; cedet (add-to-load-path "cedet/cogre") (add-to-load-path "cedet/common") (add-to-load-path "cedet/contrib") (add-to-load-path "cedet/ede") (add-to-load-path "cedet/eieio") (add-to-load-path "cedet/semantic") (add-to-load-path "cedet/speedbar") (add-to-load-path "cedet/srecode") (setq semantic-load-turn-useful-things-on t) (load "cedet") ;;(semantic-load-enable-code-helpers) ;; jde-mode-config (custom-set-variables '(jde-jdk-registry (quote (("1.6.0.24" . "/usr/lib/jvm/java-6-sun/")))) '(jde-global-classpath (quote ( "~/lib/android-sdk/platforms/android-4/android.jar" "~/lib/android-sdk/platforms/android-7/android.jar" "~/lib/android-sdk/platforms/android-8/android.jar" "~/lib/android-sdk/platforms/android-10/android.jar" "~/lib/android-sdk/platforms/android-11/android.jar" )))) (add-hook 'jde-mode-hook '(lambda () (c-set-offset 'arglist-intro '+) (c-set-offset 'arglist-close 0) (c-set-offset 'topmost-intro-cont 0) ;; new line on annotation (c-set-offset 'func-decl-cont 0) (setq indent-tabs-mode nil) (setq c-basic-offset 4) (setq c-set-style "java") )) ;; custom variables (setq compilation-window-height 8) (setq bsh-vm-args '("-Duser.language=en")) (setq jde-import-auto-sort t) ;;; ant on jdee (setq jde-build-function '(jde-ant-build)) (setq jde-ant-enabled-find t) (setq jde-ant-program "/usr/bin/ant") (setq jde-ant-read-target t) ;;; check style on jdee (setq jde-checkstyle-option-rcurly (list "alone")) (let ((elem (assq 'encoded-kbd-mode minor-mode-alist))) (when elem (setcar (cdr elem) "")))
コマンドリファレンス
- テンプレート生成
Key | Event |
---|---|
M-x jde-gen-class | クラスのテンプレート生成 |
M-x jde-gen-xxx | テンプレート自動生成 |
M-x jde-gen-get-set or M-x jde-wiz-gen-get-set-method | Getter/Setter 生成 |
M-x jde-wiz-implement-interface | インターフェースの実装ひな形生成 |
C-c C-v C-o | オーバーライドメソッドのひな形生成 (jde-wiz-override-method) |
- コンパイル/デバッグ/ビルド
Key | Event |
---|---|
C-c C-v C-c | コンパイル |
C-c C-v C-r | 実行 |
C-c C-v C-b | antビルド |
C-x ' or M-g n | 次のエラー箇所へジャンプ |
M-g p or M-g M-p | 前のエラーへジャンプ |
C-c C-v C-d | デバッガ起動 |
M-x jde-bug-set-breakpoint | カーソル位置にブレークポイントを設定 |
M-x jde-bug-clear-breakpoint | カーソル位置のブレークポイント解除 |
M-x compile => ant -emacs | build.xmlに従ってビルド |
M-x compile => ant -emacs junit | junitの実行 |
コンパイルエラー表示行でC-m | エラー行へジャンプ |
- Import
Key | Event |
---|---|
C-c C-v z | 必要なimportをすべて追加する (jde-import-all) |
C-c C-v C-z | import文単体の挿入 |
M-x jde-import-kill-extra-imports | 不要なimport文を削除 |
- Edit
Key | Event |
---|---|
C-c C-v C-. | コード補完 (jde-complete) |
C-c C-v C-l | println |
C-c C-v C-y | カーソル位置のクラスのソースを表示 |
C-c C-v C-w | カーソル位置のクラス名のマニュアルを表示 |
C-c C-v j | Javadocコメント生成 |
C-c C-v C-s | Speedbar起動 |
C-c C-v C-n | JDKのドキュメントを表示 |
C-c C-v C-w | クラスのJDKドキュメントを表示 |
C-c . | 編集スタイルの切り替え |
- Othres
Key | Event |
---|---|
M-x jde-chckstyle | checkstyle |
C-c C-v C-f | プロジェクト内のgrep検索 (jde-find) |
M-x jde-find-dig | 実行時に設定可能なgrep検索 |
M-x jde-bsh-exit | BeanShellの終了 |
Linux Kernelをビルドする
環境: Ubuntu 11.04 (VMWare fusion)
準備
$ sudo apt-get install build-essential $ sudo apt-get install kernel-package libncurses-dev ncurses-dev libqt3-mt-dev
ソースを用意する
$ sudo apt-get install linux-source-2.6.38 $ cd /usr/src $ sudo tar xvfj linux-source-2.6.38.tar.bz2 $ cd linux-source-2.6.38
バグフィックス
via https://bugs.launchpad.net/ubuntu/+source/linux/+bug/505420
$ ln -s /usr/src/linux-source-2.6.38/ubuntu /ubuntu
config
いったん設定初期化してから設定画面を立ち上げる。
$ sudo make mrproper $ sudo make menuconfig
変更するconfig
Core i7 の 4coreでこんな感じの設定にしてみた。
Processor type and features: Processor family > Core 2/newer Xeon Maximum number of CPUs > 8 Preemption Model > Preemptible Kernel(Low-Latency Desktop) Timer frequency >1000Hz
現在の設定をそのまま使うとき
$ sudo cp /boot/config-2.6.35-24-server .config $ sudo make oldconfig
コンパイル
revisionは数値のみ指定できるみたい。適当に日付を指定。
$ make-kpkg clean $ make-kpkg -j8 --initrd --revision=yyyymmdd kernel_image kernel_headers
20~30分かかりました。
インストール
$ dpkg -i ../linux-image-2.6.38_yyyymmdd_amd64.deb
再起動して完了。
TokyuRuby会議03で酔ってきました
というわけで、先週日曜に開催されたTokyuRuby会議03で盛大に酔いを晒してきました。
http://regional.rubykaigi.org/tokyu03
当日の様子: http://togetter.com/li/143092
勧められるがままにビールを空けていたら、いつのまにやら・・・
本当にすいません。
さて、本人は全く覚えてないのですが、抽選LT用に作っていた資料で話したらしいです。お酒って怖いですね。
一応資料上げておきます。
http://gomlog.com/docs/tqrk03/slides.html
最近はAndroid漬けな日々なので、それとRubyをからめてRubotoの紹介です。
迷惑をかけた方々、すみませんでした。
スタッフの皆様、おつかれさまでした。
メソッドの呼び出し方
PHPでは、static宣言なしでもメソッドのstatic呼び出しができてしまう。
で、どっちが速いの?という話。
メモリの使用量も比べてみたかったけど、速さのみ。
<?php require_once 'Benchmark/Timer.php'; class MyTest { public function myMethod() { return; } public static function staticMethod() { return; } } $max = 100000; $timer = new Benchmark_Timer(); $t = new MyTest(); $timer->start(); for($i = 0; $i < $max; $i++) { MyTest::staticMethod(); } $timer->setMarker('static'); for($i = 0; $i < $max; $i++) { MyTest::myMethod(); } $timer->setMarker('static2'); for($i = 0; $i < $max; $i++) { $t->myMethod(); } $timer->setMarker('instance'); $timer->stop(); $timer->display(); /* ------------------------------------------------------ marker time index ex time perct ------------------------------------------------------ Start 1293934691.81032700 - 0.00% ------------------------------------------------------ static 1293934691.85720200 0.046875 21.74% ------------------------------------------------------ static2 1293934691.99593900 0.138737 64.35% ------------------------------------------------------ instance 1293934692.02592700 0.029988 13.91% ------------------------------------------------------ Stop 1293934692.02593700 0.000010 0.00% ------------------------------------------------------ total - 0.215610 100.00% ------------------------------------------------------ */
$ php --version PHP 5.3.3 (cli) (built: Aug 22 2010 19:41:55)
static宣言なしのメソッドをstaticに呼ぶのは遅いってことかしら。
ちなみにrubyだとこうなった。
static methodは存在しないので、class method。このへんはうろ覚えなので、ちょっと自信ない・・・
require 'benchmark' class MyTest def myMethod 1 + 2 end def self.classMethod 1 + 2 end end module MyModule def moduleMethod 1 + 2 end end module MyModule2 def moduleClassMethod 1 + 2 end end max = 100000; Benchmark.bmbm(10) do |x| t = MyTest.new x.report("instance: ") { max.times do t.myMethod end } x.report("class : ") { max.times do MyTest::classMethod end } MyTest.class_eval { include MyModule } t = MyTest.new x.report("module : ") { max.times do t.moduleMethod end } MyTest.extend MyModule2 x.report("module class : ") { max.times do MyTest::moduleClassMethod end } end
Rehearsal --------------------------------------------------- instance: 0.040000 0.000000 0.040000 ( 0.043314) class : 0.050000 0.000000 0.050000 ( 0.049375) module : 0.040000 0.000000 0.040000 ( 0.042887) module class : 0.050000 0.000000 0.050000 ( 0.045320) ------------------------------------------ total: 0.180000sec user system total real instance: 0.040000 0.000000 0.040000 ( 0.042020) class : 0.040000 0.000000 0.040000 ( 0.046069) module : 0.040000 0.000000 0.040000 ( 0.041350) module class : 0.040000 0.000000 0.040000 ( 0.045474)
$ ruby --version ruby 1.8.7 (2010-08-16 patchlevel 302) [i686-darwin10]
Google Readerの"v"で背面にタブを開くChrome拡張を作りました
た。
Google Reader Open entry in background tab - Google Chrome extension gallery
いくつか既存のがあるのですが、1度に複数タブが開いてしまったりキーが他のだったりで自分の使い方にはあわなかったので、
作ってしまいました。
とりあえず最低限の機能だけ付けて公開しています。
バグとかこうして欲しいみたいなのがあったらコメントでください!
雑感とか
- Chrome 拡張は開発しやすい。デバッガが素敵!!
- Javascriptをまともに書いたことなかったので、DOMのイベントリスナ周りで四苦八苦
- Star openerも付けたい
- キーも入れ替えられるようにしたい
東京Ruby会議#03に行ってきた
とても内容が濃く、充実した会議(講義?)でした!
スタッフ・講師の皆様お疲れ様でした。
セッションがかなりヘビーというか、Rubyの実装周りの話がてんこ盛りで
ついていくのがやっと or ついていけてない部分もありました。
でも、勉強になる部分がとても多かったです。
勉強不足を痛感したので、さらに頑張ろうっと。
会議自体へのフィードバック
- 喫茶無償++
- 今度はGCの話とか聞いてみたい!
というわけでメモ公開。
聞くだけでもいっぱいいっぱいだったので、正確ではないかもしれません。
Yuguiさん メタプログラミング
- メタプログラミングとは
- Rubyにおける特性
- 道具立て
- 用例
メタプログラミングとは
プログラムをプログラミングすること
- ループ
- 繰り返し
- 例としてのアクセサ
- getter/setter をメタプロ
Rubyの特性
- S式ではない!
- First Class Object
- コンパイルがない
非S式
- メタプログラミングといえばLisp
- Rubyには?
- ブロック
- proc
- 文字列
- 文字列を生成してeval
- eval<<-EOS, binding,FILE, __LINE__+1を渡して、スタックトレースを読めるようにする
- ブロック
コンパイルがない
- 実行時間とコンパイル時間が同一=隠蔽している
- 内部的にはASTに変換、1.9ではコンパイルしている
- 副作用が気軽に使える
- classは定義ではなく、副作用を持つ式である
- クラスの継承元すら動的に定義できる
- メソッド定義も条件式で分岐させるなど
- 動的すぎるため、最適化が難しい。rubyを遅くしている原因のひとつ
- C++では?
- Templateでできる。けどつらい。
- コンパイル時に決まってしまう
- Boost MPLライブラリを使う
- 副作用の代表格: IO
ex.) Rake
task :a, do... end
道具立て
- class
- 特異クラス
- callable object
- eval族
- method_missing, send
class
- Classクラスのインスタンス
- クラス階層
- BasicObject
- Object
- Module
- Class
- 特異メソッド
- クラスのあるインスタンスにだけ存在するメソッド
- クラスメソッドとして頻繁に使用
- 特異クラス
- 元クラスから継承したクラスに内部的に付け替える
- 特異クラスの定義イディオム
eigenclass = (class << obj; self end)
- 特異メソッドは内部で特異クラスを定義している
obj = Object.new
class << obj
def foo; end
end
- クラスメソッド
- 実際はClassオブジェクトの特異メソッドを定義している
- つまり親クラスの特異メソッドとして扱われているだけ。特殊な定義ではない。
- クラスのクラスはメタクラス
- 全てのクラスはClassクラスの特異クラス
- 図が欲しい。 => yuguiさんのflikr
- メタクラスのクラスはメタメタクラス
- boot時にメタクラスを全て作るとメモリがなくなる。
- 高位のメタクラスはオンデマンドで作成
呼び出し可能オブジェクト
- Object
- Proc
- Method
- UnboundMethod
- Continuation
- 相互変換可能
eval族
- eval
- instance_eval
- class_eval
- current class
- TOP LEVEL
- self: main
- current class: Object
- class expr
- self: the class
- cc: the class
- def expr
- self: insatnce
- cc: NONE
- コンテキストについて
- instance_eval
- self: instance
- cc: eigenclass
- レシーバの特異クラス
- class_eval
- self: class
- cc: class
- eval
- コンテキストはbindingに依存 (引数で指定)
用例集
メソッド定義
- define_methodでのブロック定義より、eval+heredoc の方が実行速度は早い
- railsはeval多用
- define_methodならシンタックスハイライトとかシンタックスエラーを検出
メソッドをまとめて定義
- 継承元クラスで実装が必要なメソッドにまとめてエラー定義
クラス定義
DSL
- メソッド内でサンドボックスとなるオブジェクトを提供し、そこにModuleをextend。instance_evalで評価することで
そのメソッド内のみでModuleの機能を使用可能
モジュール定義
- サンドボックス定義
- 評価するブロック内で変数を定義されたりしても、予期せぬ書き換えなどが防げる
def sandbox(block)
Module.new(&block)
end
- リモートのdrbのプロセス状態を、手元の端末からirb相手側のプロセスにinstance_eval流し込み
- drbのポートを不用意に開けておくとものすごく危険!
Rails 3 ハンズオン 松田さん
Rails 3とは?
- beta版がリリースされている
インストール
- gitプロトコルが通らない!
- gemが入らない!
- 環境は事前に準備しておきましょう。
アプリケーションを作成
- コマンド出力がカラフル
- .gitignore がデフォルト
- 今後のバージョン管理はgitで!
- .gitkeep もある
- Model名にする予定のものはアプリケーション名にできない
- Rubyのクラス名に使えないものはアプリケーション名にできない
HTML5準拠
- jsが綺麗になった
Model
- validates がカラムを基準にかけるようになった
- Rails 3 はedgeを使いましょう!*1
- 松田さんによるRails 3 ハンズオン サンプルアプリケーション
A Reintroduction to Ruby i17n 成瀬さん
- 日本に生まれたことを後悔したくなるらしい
- 字体としては、JISでは同じだがUnicodeでは別
- 符号化文字集合 = コードポイント
- 文字符号化方式: 符号化文字集合の番号をバイト列に変換する
- エンコーディングとは?
- Charset: 各エンコーディングに名前をつけて管理するためのもの
- 現実と仕様の乖離も存在する
- 用語の整理
I18N
- 略語まとめ
- L10N (地域化)
- I18N (国際化)
- M17N (多言語化)
歴史
- ASCIIが始まり
- 拡張してみた
- 大量の文字集合が・・・
- 敵を知る。知った上で個別撃破
- ISO 646 – 分裂の始まり
- Unicode
- 1つのUnicode文字列には複数の言語を混ぜられない
- フラットな空間にすべての文字を入れる
- 漢字統合: 言語の指定が必要
- ASCIIも言語の指定が必要
- Unicode以前の文字コードは?
- CP932
円記号問題
波ダッシュ問題
- U+301C (WAVEDASH)
機種依存文字
処理系の問題
- 内部コードをどうするか?
- UCS正規化: 内部では特定の1つに変換する
- 内部コードを統一
- 入出力時に変換を行う
- CSI (Code Set Independent): それぞれの文字コードに対応する
- UCS正規化: 内部では特定の1つに変換する
Ruby1.9
- 文字単位での処理
- 正規表現エンジンが鬼車に
- 文字型はなく、1文字Stringを使う
- 文字型に必要なもの
- コードポイント、エンコーディング
- 1.9.1-p3xxや1.9.2では\wがASCIIのみにマッチするようになった
- 適切にencodingを設定しておく
Magic Comment
- デフォルトはASCII
- ERBにも必要
<%= #coding : utf-8 %>
IOとEncoding
- 入出力のEncodingを指定する
- open (‘text.txt’, ‘r:UTF-8’)
- ネットワークではバイナリ扱い => 強制指定 (force_encoding)する
- socketやnet系のライブラリで必要
- 濫用は避けましょう
- KCODEはやめましょう
- UTF- {16, 32} はエンディアンの指定が面倒なので未サポート
エンコーディング
- ASCII互換
- ASCII非互換
- ダミー
エンコーディング変換
- SJISとWindows-31Jは混同しやすい
- M17N未対応のライブラリを使った時など
- ASCII-8BIT でかえされるので、明示的にエンコーディングを指定する
Ruby 1.9 での課題
- 携帯絵文字: 対応中
- 結合文字
- 複数のコードポイントを1文字として扱う。濁音や半濁音など
- 異体字セレクタ (IVS): Ideographic Variation Sequence
- 結合文字同様、複数のコードポイントを1文字扱いする必要がある
- 1つのStringに2つの言語を入れたい
- 文字幅
- 言語に依存して期待される幅が異なる
- Unicode大文字小文字
- ASCIIでしか動作しない
- String#sort
- デフォルトでは文字コード順
- 文字集合によって並び順が変わってしまう
- sort_byで指定する
Open 3 のはなし 田中 哲 (akr)さん
- Rubyからのプロセス起動
- 問題点: system, IO.popen…
- 解決
- spawn メソッドの追加
- open3ライブラリの追加
プロセス属性
- ファイルディスクリプタ
- 0:標準入力, 1: 標準出力, 2: 標準エラー出力
- Unixのプロセス起動はforkとexecを組み合わせる
- 2つのコマンドの間にプロセス属性を変更することで、パイプやリダイレクトを実現する
- Unix以外ではプロセス属性変更のために引数が複雑になりがち
Rubyで実現したいこと
API案
既存のメソッドを拡張する?
- forkは非Unixでは動きそうにない
- system: プロセスを待たないようにするのは変
- IO.popen: パイプなしは変
- `command`: 構文上、指定を付加しづらい
新しいメソッドを作る
- 要求が衝突する
- よくやることを簡単にできる
- なんでも可能なのが欲しい
- => ひとつのメソッドで全ての要求を満たすのは困難
- 高位・低位APIへ分割
ライブラリのレイヤ
- どのレイヤのライブラリを提供するか?
- 高位になるほどライブラリの自由度が高く「賢い」
- 低位になるほど詳細な制御が可能になる
低位API: spawn
- OS固有の機能も利用可能
- OS間で共通の機能については差を気にしなくてよいくらいには高位
既存メソッドへの不満
- 既存メソッドはシェルを呼び出す
- シェルを呼びたくないこともある
基本の使い方
spawn(env, command, option)
pid = spawn("make all")
Process.wait pid
- 引数を分けて与えるとシェルを経由しない
spawn("make", "all")
- 最初の引数を配列にするとargv0も指定できる
- リダイレクト
spawn("make all", :out => "make.log")
spawn("make all", :err => :out)
spawn("make akk", :out => :err, :err => :out)
- パイプ
IO.pipe {|r,w|
spawn("ls", :out => w)
spawn("sort -r", :in => r)
}
spawn({LC => 'env'}, "ls -l")
spawnのデザイン
- 多機能なものが単一関数でいいのか?
- 簡単なことが難しくなっていいのか?
- posix_spawnの複雑な引数を吸収している
- 将来の拡張に耐えられるか?
- キーワード引数
- fdの扱いは適切か?
- 最終的な状態を指定する
- 3番以降のfdを継承しない
- 子と親のfdの関係を書く
- fork はメモリ内部もコピーする
- Rubyでforkを避ける理由
- NetBSD4ではforkした子プロセスではスレッドが動かない
- Ruby1.9 ではタイマースレッドというスレッドを常に必要とするから
spawnのまとめ
- プロセスを起動するプリミティブ
- fork + プロセス属性変更 + exec
高位API: open3
- とりあえずシェルのパイプラインくらいまで提供
- シェルの嫌なところは避ける
- パイプよりも複雑な用途は今後の課題
- 標準添付ライブラリ
- 3つの標準パイプでコマンドと通信する
- 命名はPerl由来
Open3.popen3("command") {|i, o, e|
# some script
}
既存のopen3nの問題
- ゾンビの回収とdouble fork
- 親がwaitせずに死ぬと、子はinitの養子になる
- initはwaitしまくって亡骸を回収する
- 意図的にdouble forkすることでゾンビを防止
- double forkの問題点
- pidを得られない: シグナルを送りづらい
- 終了ステータスを得られない
- open3 類が乱立
解決法
- Process.detach によってwaitスレッドを生成することで解決
- 標準エラー出力はパイプにしない方がよいことも多い
- ひとつのパイプにして提供して、制御しやすくもできる
Open3で解決した問題
※ (問題自体を書き逃した)
- Open3.capture*
- Open3.popen2e*
- Open3.pipeline*
- spawnによるパイプラインは厄介
- 大学の試験になるくらい
- shell ライブラリ
- shellの記法を模したDSL
*1:帰宅後にedgeの環境用意したけど、まだ試せていない