[tmux] tmux を使ってみることにした

べつに screen で不満があるわけでもないけど、なんか流行ってるし tmux 入門した。
インストールは特に何も考えず

$ brew install tmux

Arch Linux なら

$ sudo pacman -S tmux

でOK.
で、設定晒してみる

set -g default-terminal "screen-256color"
set -g prefix C-t
set -g buffer-limit 20
set -g history-limit 50000
set -g status-bg yellow
set -g status-fg black
set -g status-utf8 on
set -g status-right ''
setw -g window-status-current-bg green
setw -g window-status-current-fg black
setw -g mode-keys vi

unbind C-b

bind C-n next-window
bind C-p previous-window
bind C-c new-window
bind d confirm-before "detach"
bind k confirm-before "kill-window"
bind \; command-prompt
bind t command-prompt

bind C-t copy-mode
bind C-y paste-buffer
bind y paste-buffer
bind -t vi-copy C-a start-of-line
bind -t vi-copy C-e end-of-line

bind s split-window -v
bind Space split-window -v
bind C-Space split-window -v
bind v split-window -h
bind Enter split-window -h
# bind C-Enter split-window -h

bind n swap-pane -D
bind p swap-pane -U
bind b break-pane
bind o select-pane -t .+
bind C-o select-pane -t .+
bind C-h select-pane -L
bind C-j select-pane -D
bind C-k select-pane -U
bind C-l select-pane -R
bind -r H resize-pane -L 3
bind -r J resize-pane -D 3
bind -r K resize-pane -U 3
bind -r L resize-pane -R 3

bind = select-layout even-horizontal
bind + select-layout even-vertical
bind - select-layout main-vertical
bind _ select-layout main-horizontal

いろいろ悩んだけど結局こんな感じ。 pane という概念が screen にはなかったので斬新な感じですね。

$ man tmux

が詳しいので、もっとちゃんと見れば新しい使い方が見つかるかもしれない。

[Ruby] Ruby の for と each の違いは変数のスコープ

ハマったのでメモ。 for と each の違いです。

t = []
for i in [1,2,3]
# [1,2,3].each do |i|
  t << Thread.new do
    puts "start #{i}"
    sleep i
    p Thread.current
    puts "end #{i}"
  end
end

p t

while t[0].alive?
end

t[1].kill
t[2].kill

p t

こいつに thread.rb とか名前つけて、実行

$ ruby thread.rb
start 1
start 2
start 3
[#<Thread:0x100169be8 sleep>, #<Thread:0x100169ad0 sleep>, #<Thread:0x1001699b8 sleep>]
#<Thread:0x100169be8 run>
end 3
[#<Thread:0x100169be8 dead>, #<Thread:0x100169ad0 dead>, #<Thread:0x1001699b8 dead>]

アレ?ちゃんと t[0] が終わってるんだし、そこは end 1 って出てほしいんだけど。
そこで、 for のところを each に変えて実行。

$ ruby thread.rb
start 1
start 2
start 3
[#<Thread:0x100169b20 sleep>, #<Thread:0x1001699b8 sleep>, #<Thread:0x100169850 sleep>]
#<Thread:0x100169b20 run>
end 1
[#<Thread:0x100169b20 dead>, #<Thread:0x1001699b8 dead>, #<Thread:0x100169850 dead>]

こんどはちゃんと end 1 が出る。
あれーと悩んでいたら、次のページを発見。

for =>そのfor文が定義されているスコープに対して、iを定義する
each=>eachブロック内でのみ生存する新たなスコープを用意し、そこでiを定義する

http://ipcom.withgood.net/wordpress/?p=484

つまり、この場合は i がグローバルになっちゃうので、 for のループごとに i の値が書き変わっちゃうのが原因でした。
3つめのスレッドを作った時点で i の値は 3 になり、1つめのスレッドが終了したときその i の値を参照するので 3 が出力されると。
Ruby では基本的に for ではなく each を使うのがよさそうですね。。

[Emacs] Emacs の popup.el を使って、 MacOSX の Dictionary.app から辞書をひく

Mac の Dictionary.app 便利ですね。
http://sakito.jp/mac/dictionary.html
なんかに使い方が書いてあって、 Emacs との連携も書いてあるのですがいかんせん新しいウィンドウを作ってしまうのがスマートでない。
popup.el なんていう素晴しいインターフェイスもあることだし、ここはひとつツールチップの中で表示させてみてはどうか。
と思って書いたのが以下です。
上記ページの dict.py が必要です。

;; dict.py is from http://sakito.jp/mac/dictionary.html
(defun dictionary ()
  "dictionary.app"
  (interactive)
  (let ((word (if (and transient-mark-mode mark-active)
                  (buffer-substring-no-properties (region-beginning) (region-end))
                (read-string "Dictionary: ")))
        (cur-buffer (current-buffer))
        (tmpbuf " * dict-process *"))
    (set-buffer (get-buffer-create tmpbuf))
    (erase-buffer)
    (insert word "\n")
    (let ((coding-system-for-read 'utf-8-mac)
          (coding-system-for-write 'utf-8-mac))
      (call-process "~/scripts/dict.py" nil tmpbuf nil word) ;; specify full pass of dict.py
      (let ( (str (buffer-substring (point-min) (- (point-max) 2))))
        (set-buffer cur-buffer)
        (popup-tip str :scroll-bar t))
      )))
(global-set-key (kbd "C-M-d") 'dictionary)

だいたい思い通りに動いているんだけど、問題点が2つほど。

  • ツールチップに入りきらない場合を考えて popup-tip のスクロールバーを表示させているのだけど、実際にスクロールする方法がわからない。
  • dict.py から辞書をひくとき、日本語で辞書をひくと例文まで取得できるけど英語でひくと例文までは取得できない。

1つめはキーマップ定義したりしてなんとかなるんじゃないかなーとか思っているんだけど。
とりあえず応急処置としては、

(popup-tip str :scroll-bar t :height 30)

とかやれば広くなるので、表示量が増えます。デフォルトは 15 です。
2つめは Dictionary.app の API が悪くて、 dict.py 中の

DCSCopyTextDefinition(None, word, (0, len(word)))

という箇所。こいつの挙動がよくわからない。
他に API あるんじゃないのと思って調べてみたけどよくわからなかった。
なので、あくまでざっくりと調べる用で本当にきちんと調べたいときは Dictionary.app から調べましょうということで。

[Ruby] Ruby

訓練のためにと思って Ruby を使ってあるプログラムを書いています。
一応専門がプログラミング言語理論とか型理論とかその辺で、Javaに慣れた身としては戸惑うことがたくさんあります。
というか動的型付け言語全般の話かもしれません。

特に慣れないのが

  • メソッドや変数に型注釈を付けない

という点。
型注釈、 Type Annotation っていうのは最大のドキュメンテーションです。
これがないコードがいかに読みにくいか。
自分の卒論は型推論の実装でしたが、そもそも型推論って理論的には面白いけど、(Type Annotation を付けないという点で)実用上そこまで意味があると思えないんですよね。

あとは、まあ Ruby ってどうなのと思うものもいくつかありまして、

  • 後置 if 読みにくい
  • unless の存在が許せない
  • 抽象クラスがない
  • メソッド内で @変数名 を使うとそれがインスタンス変数になる(クラス宣言時に最初にインスタンス変数を列挙できない)
  • private :変数名 とか attr :メソッド名 とかキモイ
  • あとやっぱり end キモイ

とか、そのへんですかね

まともに書き出してまだ1週間くらいで、まだまだ慣れない。。

[メモ] gitサーバの構築

あるプロジェクトで複数人でgitを使って開発しようということになったので、gitサーバを構築したメモ。環境はさくらVPS上の CentOS 5.4 です(゚∀゚)

1. gitインストール

まずgitをインストールします。。rootで作業。

remote# vi /etc/yum.repos.d/CentOS-Base.repo

して、以下を追加

[dag]
name=Dag RPM Repository for Redhat EL5
baseurl=http://apt.sw.be/redhat/el$releasever/en/$basearch/dag
gpgcheck=1
enabled=0
gpgkey=http://dag.wieers.com/packages/RPM-GPG-KEY.dag.txt

あとは

remote# yum --enablerepo=dag -y install git

でおk。ソースとってきて make && make install でも簡単らしいです(´∞`)

2. リポジトリ作成

/var/git 以下に置くことにしました。

remote# mkdir -p /var/git
remote# cd /var/git
remote# mkdir test.git
remote# git --bare init --shared

で、空のリポジトリができました。

remote# groupadd dev
remote# usermod -G dev user
remote# chown root:dev -R .

として dev グループの人用に設定します。サーバ側の設定は以上

3. クライアントからリポジトリを登録

ローカルで適当なリポジトリを作ってサーバ側に登録します。

local$ mkdir test
local$ cd test
local$ git init

空のリポジトリができます。次にリモートリポジトリの情報を登録します。

local$ git remote add origin ssh://user@server/var/git/test.git

でおkです。あるいは、 ssh://user@server の部分は .ssh/config のホスト名を指定しても大丈夫っぽいです。

local$ git remote add origin myhost:/var/git/test

こんな感じ。

local$ echo hoge > test.txt
local$ git add test.txt
local$ git commit -m "First commit"

で、ローカルのリポジトリに test.txt をコミットしました。これをサーバに転送します。

local$ git push origin master

と打って origin に master を push します。

4. 確認

うまく行ってそうなら、豪快にディレクトリごと削除してリモートから clone してみます。

local$ cd ../
local$ rm -rf test
local$ git clone ssh://user@server/var/git/test.git

これで元通り。