Rubyで外部コマンドの出力をGtk::TextViewに表示

外部コマンドの出力をパイプで取得してそのままGTKのテキストビューに表示するプログラムを書いてみました。
単純な方法でやっているので、ただ単に標準出力を表示するだけですが、
リアルタイムに出力を取得しているので、少しずつ出力されるコマンドは少しずつ表示されるようになっています。
ruby -v」を実行して、結果(Rubyのバージョン)を表示するコードを書いておきます。
IO.popenでパイプで接続してコマンドを実行し、それからeachで一行ずつ読み出して追加しています。
すぐに終わるコマンドではあまり関係ないかもしれませんが、すぐには終わらないコマンドで、一行ではなく一文字ずつ出力されるコマンドでは修正する必要があるかもしれません。

require 'gtk2'

Gdk::Threads.init
Gtk.init

window = Gtk::Window.new
window.set_size_request(320, 240)

buffer = Gtk::TextBuffer.new
view = Gtk::TextView.new(buffer)

window.add(view)
window.show_all

thread = Thread.start {
  IO.popen("ruby -v") { |pipe|
    pipe.each { |line|
      buffer.insert_at_cursor(line)
    }
  }
  buffer.insert_at_cursor("プロセスが終了しました")
}

window.signal_connect("delete_event") {
  thread.kill
  Gtk.main_quit
}

Gtk.main
thread.join

Haskellコンパイラ「jhc」をビルド

Haskellコンパイラの「jhc」をビルドしてみました。
Ubuntuでやってみました。
方法は、jhcの公式サイトの http://repetae.net/computer/jhc/building.shtml ここを参考に書いてみました。

必要なライブラリのインストール

jhc自身もHaskellで書かれているので、コンパイルGHCが必要です。
さらに、Haskellライブラリ「binary」「zlib」「utf8-string」「readline」「fgl」が必要です。
これらのライブラリは、「sudo cabal install ライブラリ名 --global」としてインストールしましたが、これが正しいのかはよくわかりません。
さらに、Ubuntuのパッケージから「libghc6-regex-compat-dev」をインストールする必要がありました。これは普通にapt-getでインストールできます。

コンパイル

まずは適当なディレクトリで「wget http://repetae.net/dist/jhc-0.7.6.tar.gz」でソースをダウンロードしてから、
「tar xzf jhc-0.7.6.tar.gz」で解凍します。
コンパイルは普通に、configureとmakeを使ったコンパイルです。

./configure --prefix=/usr/local
make

makeの最後に、全てのソースのコンパイルが終わりリンクしている時(Linkingと出てきた時)に「Killed」というメッセージが出てきてしまいましたが、jhcが出来ていたので一応成功だと思います。
インストールも普通に「sudo make install」です。

使ってみる

main = putStrLn "Hello World"

hello.hsという名前で保存したこんなソースを「jhc hello.hs -o hello」でコンパイルしてみましたが、
GHCコンパイルした場合よりも小さいバイナリを出力するようです。

Pureの「reduce」がすごい

Pure言語には、「reduce」というマクロがあります。(PureではLispのようなマクロが使える)

これは、「与えられた式をもう一度評価する」というマクロです。一見単純なようですが、たくさんの応用ができそうです。
簡単な使い方を紹介します。

foo expr = reduce expr with
  a = 10;
end;

このように関数fooを定義します。
この関数は、「a=10が定義された状態でexprをもう一度評価してその結果を返す」という関数です。
「foo (2*a);」とすると、a=10が定義された状態で2*aが評価され、「2*10」となり、「20」が返ります。
さらに、

bar expr = (reduce expr with a = 2; end), (reduce expr with a = 4; end);

一行にまとめたので少し読みにくいですが、こんな関数も作れます。
「bar (10+a);」で、「12,14」が返ります。

これを利用すれば、さらにおもしろいプログラムが作れそうです。

括弧ゴルフにPureで挑んでみた

「どれだけ括弧を使わずに書けるか」を競う「括弧ゴルフに、Pureを使って挑戦してみました。

括弧は、「()」も「[]」も全く出てきません。0個です。

階乗は大きい数(intだとオーバーフローしてしまうもの)も普通に出てくるので、それに対応するのに苦労しました。

「$」を使ったり、一行にまとめるのではなくwhenを使ってローカル変数を使ったりしたので、普通はこんな書き方はしないと思います。

Pureには「実は演算子として実装されている」というものが多いので、うまく使えばいろいろな書き方ができそうです。

多分、もう少し綺麗な書き方ができたと思います。

using system;

limit = flip sscanf "%d" $ argv!1 if argc == 2;
limit = 1 if argc == 1;
limit = throw invalid_argument otherwise;

fact 0L = 1L;
fact n = n * fact x when
  x = n - 1L;
end;

__show__ x::bigint = init $ str x;

p x = printf "%s! = %s\n" $ a, b when
  a = str x;
  b = str $ fact x;
end;

do p $ 1..limit;

UbuntuでD言語からSDLとOpenGLを組み合わせて使ってみた。

方法はほとんど変わっていません。
ほぼメモのような感じなので、D言語SDLOpenGLを使う関係の記事はまとめたほうがよかったかもしれません。
ですが書き直すのが面倒なので書いてしまいます。

前回と前々回の作業を行った後に行ったので、それを前提に書いています。
ライブラリのインストールやD言語用ライブラリの準備は前回や前々回を読んでください。

ライブラリのフォルダをコピー

今回の作業用ディレクトリの中に、前回、前々回の作業用ディレクトリの中にあるSDLディレクトリ、openglディレクトリをコピーしました。

コードを書いて使ってみる

ウィンドウタイトルを設定するSDL_WM_SetCaptionはC言語の関数なので、D言語のstringやnullがそのまま使えず苦労しました。
ウィンドウタイトルの英語には自信がないので、間違っているかもしれません。

import SDL;
import opengl;
import std.stdio;
import std.string;

void draw()
{
  glClear (GL_COLOR_BUFFER_BIT);
  glBegin (GL_LINE_LOOP);
  glVertex2d (-0.9, -0.9);
  glVertex2d (0.9, -0.9);
  glVertex2d (0, 0.9);
  glEnd ();
  SDL_GL_SwapBuffers();
}

void main()
{
  if (SDL_Init(SDL_INIT_VIDEO) < 0) {
    writefln("SDL初期化エラー");
    return;
  }
  SDL_WM_SetCaption(cast(char*)toStringz("Using SDL and OpenGL with D"), cast(char*)0);
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  SDL_Surface *screen = SDL_SetVideoMode(320, 240, 32, SDL_OPENGL);
  if (screen == null) {
    writefln("画面初期化エラー");
    return;
  }
  glClearColor(0.0, 0.0, 255.0, 0.0);
  int done = 0;
  SDL_Event e;
  while (!done) {
    while (SDL_PollEvent(&e)) {
      done = e.type == SDL_QUIT;
    }
    draw();
    SDL_Delay(1000/30);
  }
  SDL_Quit();
}

コンパイルには、「dmd sdlgl.d -ISDL -Iopengl -L-lSDL -L-lGL」というコマンドを使いました。
コンパイルすると「sdlgl」という実行ファイルができます。
実行すると、青い背景に白い線で三角形が描画されます。

UbuntuでD言語からOpenGLとGLUTも使ってみた。

SDLの時の方法はSDL以外にも使えそうだったのでやってみました。

GLUTをインストール

Ubuntuならaptで簡単です。

sudo apt-get install freeglut3-dev

D言語用ライブラリの準備

http://shinh.skr.jp/d/porting.html」の「OpenGL」をクリックしてzipファイルをダウンロードします。
そして、ダウンロードしたファイルを解凍すると「opengl」というディレクトリが出てくるので、
同じページの「glut」をクリックして「glut.d」をダウンロードし、それをopenglディレクトリの中に入れて、
そのopenglディレクトリを、適当に作っておいた作業用ディレクトリの中にコピーしておきます。

使ってみる

今回は、http://www.wakayama-u.ac.jp/~tokoi/opengl/libglut.html のコードを元に、
http://romanchu.blog105.fc2.com/blog-entry-191.html に書かれている方法を参考にしてD言語用にしたソースをコンパイルしてみます。

import opengl;
import openglu;
import glut;
import std.string;

char** args2argv(string[] args) {
  char **argv = cast(char**)new char*[args.length];
  for (int i = 0; i < args.length; i++) {
    argv[i] = cast(char*)toStringz(args[i]);
  }
  return argv;
}

void display()
{
  glClear(GL_COLOR_BUFFER_BIT);
  glFlush();
}

void init()
{
  glClearColor(0.0, 0.0, 1.0, 1.0);
}

int main(string[] args)
{
  int argc = args.length;
  char** argv = args2argv(args);
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(&display);
  init();
  glutMainLoop();
  return 0;
}

これを作業用ディレクトリに「gltest.d」で保存し、
これを「dmd gltest.d -Iopengl -L-lglut -L-lGLU -L-lGL」でコンパイルすると「gltest」という実行ファイルができます。
実行すると、青く塗りつぶされたウィンドウが出てきます。

UbuntuにD言語コンパイラDMDとDSSSをインストールしてみる

最近D言語はあまりやっていなかったのですが、なんとなくやりたくなったのでインストールしてみました。
自分が行った方法を適当にまとめてみます。
「/opt/dmd2」の中にインストールされるようになっています。

DMDのインストール

まずは、「http://www.digitalmars.com/d/download.html」から「dmd.2.048.zip」をダウンロードして、
ダウンロードしたディレクトリで

unzip dmd.2.048.zip
cd dmd2
sudo mv linux /opt/dmd2
sudo mv src /opt/dmd2/src

のようにしてインストールしました。
そして、シェルの設定に「export PATH=$PATH:/opt/dmd2/bin」を追加してパスを通しました。

DSSSのインストール

次に、「http://svn.dsource.org/projects/dsss/downloads/0.78/」から「dsss-0.78-x86-gnuWlinux.tar.bz2」をダウンロードして、
ダウンロードしたディレクトリに移動し、

tar jxvf dsss-0.78-x86-gnuWlinux.tar.bz2
cd dsss-0.78-x86-gnuWlinux
sudo cp * /opt/dmd2 -R

このように解凍、インストールしました。

設定の変更

一番苦労したのがここです。
一部、http://www.dsource.org/forums/viewtopic.php?t=4490 ここを参考にして設定しました。
「/opt/dmd2/etc/rebuild/default」の「gdc-posix」を「dmd-posix」に書き換えて、
「/opt/dmd2/etc/rebuild/dmd-posix」の「cmd=dmd -version=Posix -c $i」の行を「cmd=dmd -c $i」に、
「cmd=dmd -L--start-group -L-lphobos $i -of$o」の行を「cmd=dmd -L--start-group -L-lphobos2 $i -of$o」に変えました。
さらに、
「/opt/dmd2/bin/dmd.conf」の「-I%@P%/../../src/phobos」を「-I%@P%/../src/phobos」に、
「-I%@P%/../../src/druntime/import」を「-I%@P%/../src/druntime/import」に変えれば設定完了です。

コンパイルしてみる

ホームディレクトリの下に適当にディレクトリを作り、その中に「hoge.d」という名前で

module Main;
import std.stdio;

void main() {
  writefln("hogehoge!");
}

こんなプログラムを書きました。
そして、そのディレクトリで「dsss build hoge.d」というコマンドを実行すれば、「hoge」という実行ファイルができあがります。