2009年7月14日火曜日

つばめ

ツバメがいっぱい(日曜日の夕方)

090712_161029


翌朝一羽しかいなくなってた(帰りに見たらまた居たから飛ぶ練習でもしてるのかも)
P1010613

2009年7月11日土曜日

2009年7月6日月曜日

ATOKの電子辞典をFirefoxで引く(Jetpack)

Jetpackで何か作ってみたかったので作ってみた。
OperaでATOK 2007 for Windowsの電子辞典を使うためのツールが必要。

ステータスバーにATOKのアイコンが出ます。
テキストを選択した状態で、アイコンをクリックすると電子辞典の検索を行います。

本当はコンテキストメニューに登録して呼び出すのがやりたかったんだけど、
Jetpackでやる方法がわからなかったので、この形にしました。

(function() {
var cmd = 'c:\\path\\to\\GetTextOperaLClick.exe';

var convert = function(s, charset) {
var ccls = "@mozilla.org/intl/scriptableunicodeconverter";
var cif = Components.interfaces.nsIScriptableUnicodeConverter;
var c = Components.classes[ccls].getService(cif);
c.charset = charset;
return c.ConvertFromUnicode(s);
}
var lookup = function(s) {
var fcls = "@mozilla.org/file/local;1";
var fif = Components.interfaces.nsILocalFile;
var pcls = "@mozilla.org/process/util;1";
var pif = Components.interfaces.nsIProcess;
var file = Components.classes[fcls].createInstance(fif);
file.initWithPath(cmd);
var process = Components.classes[pcls].createInstance(pif);
process.init(file);
var args = [convert(s, "shift_jis")];
process.run(false, args, args.length);
}

jetpack.statusBar.append({
html: '<img id="icon_img" src="http://www.atok.com/favicon.ico />',
width: 30,
onReady: function(doc) {
$('#icon_img', doc).css({
cursor: "pointer",
});
$(doc).click(function() {
var w = jetpack.tabs.focused.contentDocument.getSelection();
if (w.length) {
lookup(w);
}
});
}
});
})();

選択するだけで検索する版(使いにくい)
アイコンをクリックすると、機能のon/offができます。
無効(初期)状態では、アイコンが半透明になっています。
有効になっているときは、テキストを選択してマウスのボタンを離すと電子辞典の検索が動きます。
(クリックイベントが発生したときに、選択されているテキストの長さで判断してます)

(function() {
  var cmd = 'c:\\path\\to\\GetTextOperaLClick.exe';
  var enabled = false;

  var convert = function(s, charset) {
    var ccls = "@mozilla.org/intl/scriptableunicodeconverter";
    var cif = Components.interfaces.nsIScriptableUnicodeConverter;
    var c = Components.classes[ccls].getService(cif);
    c.charset = charset;
    return c.ConvertFromUnicode(s);
  }
  var lookup = function(s) {
      var fcls = "@mozilla.org/file/local;1";
      var fif = Components.interfaces.nsILocalFile;
      var pcls = "@mozilla.org/process/util;1";
      var pif = Components.interfaces.nsIProcess;
      var file = Components.classes[fcls].createInstance(fif);
      file.initWithPath(cmd);
      var process = Components.classes[pcls].createInstance(pif);
      process.init(file);
      var args = [convert(s, "shift_jis")];
      process.run(false, args, args.length);
  }

  jetpack.statusBar.append({
    html: '<img id="icon_img" src="http://www.atok.com/favicon.ico />',
    width: 30,
    onReady: function(doc) {
      $('#icon_img', doc).css({
                   cursor: "pointer",
                   opacity: 0.4
      });
      $(doc).click(function() {
        var elem = $('#icon_img', doc);
        var a;
        if (enabled = !enabled) {
          a = 1;
          $(jetpack.tabs.focused.contentDocument).click(function() {
            var w = jetpack.tabs.focused.contentDocument.getSelection();
            if (w.length) {
              lookup(w);
            }
          });
        } else {
          a = 0.4;
          $(jetpack.tabs.focused.contentDocument).unbind('click');
        }
        elem.css({opacity: a});
      });
    }
  });
})();




2009年7月1日水曜日

1passでpygmentsの出力したhtmlにスタイルを埋め込む

前作ったやつは、スタイル出力、HTML出力、スタイル埋め込みという手順を踏む必要があって面倒なので、pygmentsのAPIを使って一発で処理するようにしてみた。
前のは出力されたcssとHTMLを処理するのでstyle, lexerなんかは好きにすればよかったけど、
今回は1passなのでそこら辺の指定をできるようにしてみた。


from pygments import highlight
from pygments.lexers import get_lexer_by_name, get_lexer_for_filename
from pygments.formatters import get_formatter_by_name
from xml.etree.ElementTree import ElementTree, XML
import cssutils
from cssutils.css import CSSRule
from sys import stdout
from optparse import OptionParser

def write(filename, style_name='colorful', formatter_name='html', lexer_name=None, out=stdout):
    fmtter = get_formatter_by_name(formatter_name, style=style_name)
    if lexer_name:
        lexer = get_lexer_by_name(lexer_name)
    else:
        lexer = get_lexer_for_filename(filename)
    css = cssutils.parseString(fmtter.get_style_defs())
    rules = dict([(x.selectorText, x.style.cssText.replace('\n', '')) for x in css.cssRules if x.type == CSSRule.STYLE_RULE])
    tree = ElementTree(XML(highlight(open(filename).read(), lexer, fmtter)))
    for elem in tree.getiterator():
        c = elem.get('class', None)
        if c:
            style = rules.get('.'+c, None)
            if style:
                elem.attrib['style'] = style
    tree.write(out)

if __name__ == '__main__':
    optparser = OptionParser(usage=u'usage: %prog [options] file')
    optparser.add_option('-S', '--style', dest='style', help='style', default='colorful')
    optparser.add_option('-f', '--formatter', dest='formatter', help='formatter', default='html')
    optparser.add_option('-L', '--lexer', dest='lexer', help='lexer')
    options, args = optparser.parse_args()
    if len(args) == 1:
        write(args[0], options.style, options.formatter, options.lexer, stdout)
    else:
        print '** no input file specified **'
        optparser.print_help()

2009年6月29日月曜日

ハードディスク買った

外部電源の外付けハードディスクだと、つなぐのが面倒でバックアップをサボりがちだったので、
バスパワーで動くUSB接続のハードディスクをさがしていた。

ちょうど、来月分の生協のチラシにHDPS-U500がのっていたので、これでいいかな?と思っていたら、
土曜日に寄った川崎のヨドバシで同じものがポイント20%還元になってた(ポイント分引けば9000円切ってる)ので買ってしまった。

8G/残りでパーティションを分けて、8Gの方からTrueImage(Home 10)を起動できるようにした。
手順は簡単で、TrueImage が起動する USB-HDD ( USB メモリ ) の作り方をそのままやればできた。
基本的にWindows上でバックアップするけど、復旧のこと考えるとこうしておいた方が安心。
(私の環境は1スピンドルでUSBが3ポート。USB光学ドライブはUSBを2ポートふさいでしまうので、HDDをつなぐと全部埋まる)



2009年6月23日火曜日

2009年6月4日木曜日

pygmentsの出力したhtmlにスタイルを埋め込む

ここでソース張っても色とかつけるのが大変なので、pygmentsのhtml出力とcssを結合するスクリプトを書いてみた。

embedstyle.py

import sys
from xml.etree.ElementTree import ElementTree
import cssutils
from cssutils.css import CSSRule

css = cssutils.parseFile(sys.argv[2])
rules = dict([(x.selectorText, x.style.cssText.replace('\n', '')) for x in css.cssRules if x.type == CSSRule.STYLE_RULE])

tree =  ElementTree(file=open(sys.argv[1]))
for elem in tree.getiterator():
    c = elem.get('class', None)
    if c:
        style = rules.get('.'+c, None)
        if style:
            elem.attrib['style'] = style
tree.write(sys.stdout)


使用例
スタイル生成→HTML出力→結合


pygmentize -f html -S colorful > test.css
pygmentize -o embedstyle.html embedstyle.py
python embedstyle.py pkglist.html test.css > out.html


これで出力したのがこのページのコード



ubuntu/debianのインストール済みパッケージリストを整形して出力する

ディスクの空きがちょっと減ってきたので、サイズが大きいパッケージを知りたくて作ってみた。

python-aptとprettytable使ってます。


#!/usr/bin/python


import apt
from prettytable import PrettyTable

pt = PrettyTable(["package", "version", "size"])
pt.set_field_align("package", "l")
pt.set_field_align("version", "r")
pt.set_field_align("size", "r")
pt.set_padding_width(1)

SizeToStr = apt.SizeToStr

for v in sorted([x.installed for x in apt.cache.Cache() if x.isInstalled], key=lambda v: v.installed_size):
    pt.add_row((v.package.name, v.version, SizeToStr(v.installed_size)))

print pt


出力


+----------------------------------------------------------+------------------------------------------+-------+
|                         package                          |                 version                  |  size |
+----------------------------------------------------------+------------------------------------------+-------+
| adobe-certs                                              |                                 1.0.8210 |     0 |
| adobeair1.0                                              |                               1.5.1.8210 |     0 |
| tweetdeckfast.f9107117265db7542c1a806c8db837742ce14c21.1 |                                     0.22 |     0 |
| gnuplot                                                  |                                  4.2.5-2 | 20.5k |
| uim                                                      |                                1:1.5.3-1 | 20.5k |
(省略)
| texlive-latex-extra-doc                                  |                    2007.dfsg.17-2ubuntu1 |  110M |
| openoffice.org-core                                      |                         1:3.1.0-3ubuntu2 |  113M |
| llvm-dev                                                 |                 2.5+svn20090504-0ubuntu1 |  117M |
| ghc6                                                     |                          6.10.3-2ubuntu1 |  148M |
+----------------------------------------------------------+------------------------------------------+-------+



2009年6月3日水曜日

print >>sys.stderrによる出力をloggingで出したい

sys.stderrにメッセージを出力しているモジュールがあって、それを書き換えずに何とかしたいので考えてみた。

とりあえずうまくいったけど、いいのかわからない。
(追記
すっかり忘れてたけど、sys.stderrをほかの変数で参照してたらだめだった。当たり前なんだけど…
別モジュールで、from sys import stderrなら
モジュール名.stderrを書き換えればOK)

import sys
import logging
from StringIO import StringIO

class redir(object):
  def __init__(self, f):
    self.f = f
    self.eol = True
  def write(self, buf):
    if buf == '\n':
      if self.eol:
        self.f('')
      else:
        self.eol = True
    else:
      self.eol = False
      self.f(buf)

print >>sys.stderr, "hoge"
logging.basicConfig(filename='hoge.log', level=logging.DEBUG)
sys.stderr = redir(logging.error)
print >>sys.stderr, "hoge1"
print >>sys.stderr
print >>sys.stderr, "hoge2"

これで、最初の出力(hoge)はstderrに、以降の出力(hoge1,改行のみ,hoge2)はhoge.logに出力される。


調べ方メモ
6.6. The print statementを見て、出力先のオブジェクトにwriteが必要なことと、(必要なときは)最後に'\n'がくることはわかった。
writeに渡されるバッファに最後の改行が含まれているのか、改行だけ別に呼ばれるのか気になるので調べてみた。

適当な関数を作って、disで調べた。

>>> import dis
>>> def f():
...  print >>None, None,
...
>>> def fln():
...  print >>None, None
...
>>> def fnl():

...  print >>None

...

>>> dis.dis(f)

  2           0 LOAD_CONST               0 (None)

              3 DUP_TOP

              4 LOAD_CONST               0 (None)

              7 ROT_TWO

              8 PRINT_ITEM_TO

              9 POP_TOP

             10 LOAD_CONST               0 (None)

             13 RETURN_VALUE

>>> dis.dis(fln)
  2           0 LOAD_CONST               0 (None)
              3 DUP_TOP
              4 LOAD_CONST               0 (None)
              7 ROT_TWO
              8 PRINT_ITEM_TO
              9 PRINT_NEWLINE_TO
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE
>>> dis(fnl)
  2           0 LOAD_CONST               0 (None)
              3 PRINT_NEWLINE_TO
              4 LOAD_CONST               0 (None)
              7 RETURN_VALUE
>>>

たぶん、PRINT_ITEM_TOがデータの出力で、PRINT_NEWLINE_TOは改行であろうことはわかる。
改行付きのprintがPRINT_ITEM_TOと、PRINT_NEWLINE_TOと二つに分かれているので、2回に分けてwriteが呼ばれそうなこともわかる。
ともかく、PRINT_ITEM_TOとPRINT_NEWLINE_TOは間違いなくキーワードなので調べると、PRINT_ITEM_TOPRINT_NEWLINE_TOは拡張版print statementで使われるのがわかる。それぞれ出力を行う命令なので、writeが二度呼ばれるものとして扱ってよさそう。

素直にそのままloggingすると、最後の改行までログに残ってしまうので邪魔。ただ、単純に'\n'だけ渡されたときに無視するようにすると、改行だけのやつ(fnlみたいなやつ)は捨てられてしまうので(ログに出すことしか考えていないので、許容できる場面もあると思うけど)簡単に対応しておく。

  • 前回の出力が改行じゃないときは無視(PRINT_ITEM_TO->PRINT_NEWLINE_TOで呼ばれる場合)
  • それ以外は空文字列を出力



2009年3月20日金曜日

KDEが使える環境でAIRアプリをKDE外から使う

まず結論。
dbusが使える環境で、kdewalletmanagerを起動した状態で、

KDE_SESSION_VERSION=4 KDE_FULL_SESSION=true /opt/TweetDeck/bin/TweetDeck

すればいける(環境変数の値は別のでもいいかもしれないけど調べてない)


以下経緯など
私のマシンでは、kubuntuのKDE4(4.2.1)はちょっと重いので
プログラムを書くのがメインな時はawesomeを使ってみることにした。
(まあ、それでも4.1.xの時と比べたらだいぶマシになった)

そこで困ったのが、AIRアプリであるTweetDeckが動かないこと。
WindowsでもLinuxでも動いて、しかもグループ分けが便利なので気に入って使ってる。
起動すると、次のようなメッセージが出て、画面は表示されるものの使えない状態になる。

$ /opt/TweetDeck/bin/TweetDeck
Unknown desktop manager, only Gnome and KDE are supported
.

Adobe AIRはいまのところKDEとGnomeしかサポートしていないらしい。
試しにKDEWM=/usr/bin/awesomeにして、KDEで使うWindow Managerを
awesomeしたらTweetDeckも動くけど、なんかしっくりこない。


しかたがないので、awesome単体で使える方法を調べることにした。

KDEでTweetDeckを起動するとKwalletが動くので、手動でkwalletmanagerを起動してから
TweetDeckを起動してみたが、また同じメッセージが出てだめだった。

straceを使ってKDEから起動するときと、awesome環境から起動するときの違いをみてみたら、
どうもdbusでkwalletを探してるっぽいことが分かった。

$ qdbus org.kde.kwalletd /modules/kwalletd org.kde.KWallet.localWallet
kdewallet

でも、kwalletmanagerを起動しておけば、ちゃんと見つけられるし、
awesome環境で起動するときは、そもそもkwalletを探していないようなので不足があるようだ。

何か無いかとAIRのディレクトリを探ろうかと思ったら、いきなりlibCore.soを見つけたので、
おもむろにstrings libCore.so | grep -i kdeしてみたら、
KDE_SESSION_VERSION, KDE_FULL_SESSIONが出てきた。
こいつらにKDEで見た値を入れたら動いてしまった。



2009年3月12日木曜日

パクチー食ってきた

P1010410
P1010411
P1010412
P1010413
P1010414
P1010415
P1010416
P1010417
P1010418
パクチー料理専門店のパクチーハウス東京に行ってきました。

なかなか理解されることがないのですが、私はパクチーが大好きなのです。

Twitterで@macchaさんが行きたいと言ってたのに便乗させてもらう形で、
@beakmarkさん、@hidaqaさん、@macchaさん、 私の連れ、私の5人。

@beakmarkさん、@hidaqaさんは初対面なので緊張した。

経堂は通ったことはあるけど、降りたのは初めて。
上品ドライバーのせいで、道が狭くて迷いやすいイメージがずっと付いてたけど、
少なくとも駅前はそんなこと無かった。


お料理ですが、思ったより普通においしくて微妙に残念 笑
パクチーが絶対駄目という人以外は、無茶なオーダーしなければいけると思う。
辛いのが多かった気がするので、辛いのが駄目な人もちょっとつらいかも。

根っこが好きな私は、生姜の焼酎と牛蒡の焼酎をいってみました。
生姜はかなりアリで、牛蒡は微妙。
他にも珍しいドリンクがあったけど、私は非常にアルコールに弱いのでやめておいた。
真っ赤だったし…

お店の雰囲気は、ちょっと騒がしい(子供が元気に遊んでたり)けど、
楽しい感じで是非また行きたいと思いました。おいしいしね。

店長とかオーナーとかもおもしろかった。



もうじき立ち飲みが出来るスペースが出来るとか。

2009年3月6日金曜日

リラックマのバス

谷保から国立に向かうときにちょうど来たので乗った。
前の表示の所に絵を出しているのを初めて見た。

IMGP2451
IMGP2450

2009年2月26日木曜日

linux-2.6.28でのIEEE802.11a

Ubuntu 9.04のカーネルに2.6.28系が来ているので使っていたが、
2.6.28-8.21でCONFIG_WIRELESS_OLD_REGULATORY=nになった影響か、
家で使っている802.11aのチャンネルが使えなくなった。802.11b/gは使えた。

wireless.kernel.orgのキュメントによるとそういった情報をカーネル外に出して、udev経由で設定するようになったらしい。

どこかで見たけど、分離するようにしたのは、カーネル内に入っている情報はUS, JP, EUだけしかなく、しかもカーネルモジュールのパラメータ(cfg80211だな)でしか設定できないからだったはず。


カーネルイメージの依存関係でwireless-crdaが入ってきたが、
変更方法をみると、iwはまだubuntuにパッケージが無いし、wpa_supplicantも0.66だった。
しかもwpa_supplicantを直接使ってないので、wicd(最近NetworkManagerから乗り換えた)が
COUNTRY設定に対応してくれないと多分面倒っぽい。設定ファイルに一行足すだけかも知れないけど。

結局、debianのiw(と関連パッケージ)を入れて解決した。
設定は変更方法の所に書いてあった通りやればok.

sudo iw reg set JP

これをやったあとに今まで通りscanするだけで、自宅のAPが発見できるようになった。

追記
よく分からんが、環境変数COUNTRY=JPを設定して、
/sbin/crdaを実行するだけで設定できた。
iw無しでも平気だったようだ…
前やったときは駄目だったんだけどな…
(ちなみにwireless-crda 1.6は壊れてる。レポートしようとしたらすでにレポートされてた)



2009年2月3日火曜日

gnome-terminalをgnome外で動かす

wubiでセットアップした環境ではgnome上でgnome-terminalが問題なく使えるのに、
イメージを共有しているcoLinux側では、gnomeを動かしていないからか動かなくなった。


$ gnome-terminal
Failed to contact the GConf daemon; exiting.

検索してみると、gnome起動前にgconfにアクセスできないというのを見つけた。
GConf-2.22ならいけてGConf-2.24でこの状況になるらしい。
workaroundにしたがって次のようにする。


eval `dbus-launch --sh-syntax`
gconftool-2 --spawn

上記の二つのコマンドを実行しておけば、gnome-terminalが起動できる。

上記のコマンドを実行したセッションが生きている状態ならば、他のシェルからでも、
環境変数DBUS_SESSION_BUS_ADDRESSを設定するだけで大丈夫。