☆LucidのGnome-Sudokuにパッチをあてる

Lucid(Ubuntu 10.04)のGnome数独(Gnome-sudoku 2.30)はKarmicで悪化した経過時間の表示が修正されています。
Karmicの時はセルの上側にメモ用の数字を入力すると経過時間がやたら増えたのですが、これも直っているようです。
(完全ではないようで、多少修正されています。)
しかし、残念ながら特定の場合にコンフリクトした値が赤くならないバグと終了判定が正しくないバグが残っています。
(すでにGnomeの新しいリビジョンでは修正されているので次のリリースでは修正されているはずです。)
これを修正するパッチを用意しました。

gnome-sudoku.2.30.0-0ubuntu6.patchをダウンロードして下記の要領でパッチしてください。
ファイルは ~/Download ディレクトリにダウンロードした前提で記述しています。

$ cd /usr/lib/python2.6/dist-packages/gnome_sudoku
$ sudo patch -p1 < ~/Download/gnome-sudoku.2.30.0-0ubuntu6.patch

注意点はgnome-games-commonとgnome-sudokuパッケージの両方にダブってsduoku.py,timer.pyが含まれていることです。
実際に使われているのはgnome-games-commonの方のsduoku.py,timer.pyですのでパッチを当てるファイルを間違わないように気をつけてください。

suoku.pyに対するパッチの内容はGnomeで実際に適用されたものではなく、私が書いたものです。
gitの使い方を多少学んだのですが、2.30からいくつかコミットが行われていてどれが該当するのかわからなかったのでorz.
(Gnomeで実際に適用されたパッチの方が良かった気がするのですが)
timer.pyの方の修正はGnomeで行われた修正を取り込みました。
こちらは変更が少ないのでgitで変更したコミットが簡単に特定でしました。

gnome-games$ find ./ -name 'timer.py'
../gnome-sudoku/src/lib/timer.py
gnome-games$ git blame -L '/^        if currently_timing:/,+1' -- ./gnome-sudoku/src/lib/timer.py
f235e03e (Jim Ross 2010-03-31 03:53:55 -0400 142)         if currently_timing:
gnome-games$ git log f235e03e^..f235e03e
commit f235e03e98e960a69627f5b4afacb9f14d599bad
Author: Jim Ross <jimbo@dimensia.com>
Date:   Wed Mar 31 03:53:55 2010 -0400

    sudoku: Fixed mark timing
    
    The problem is, when the main window is not active(timer paused) and
    the auto-save kicks in - the timer always gets restarted in mark_timing().
    
    This patch fixes it by storing the current value of self.is_timing at the st
    of mark_timing() and then checking it before calling resume_timing().
    
    Fixes bug #562782
gnome-games$ git show f235e03e
commit f235e03e98e960a69627f5b4afacb9f14d599bad
Author: Jim Ross 
Date:   Wed Mar 31 03:53:55 2010 -0400

    sudoku: Fixed mark timing
    
    The problem is, when the main window is not active(timer paused) and
    the auto-save kicks in - the timer always gets restarted in mark_timing().
    
    This patch fixes it by storing the current value of self.is_timing at the st
    of mark_timing() and then checking it before calling resume_timing().
    
    Fixes bug #562782

diff --git a/gnome-sudoku/src/lib/timer.py b/gnome-sudoku/src/lib/timer.py
index bd5e2de..c37511a 100644
--- a/gnome-sudoku/src/lib/timer.py
+++ b/gnome-sudoku/src/lib/timer.py
@@ -132,13 +132,15 @@ class ActiveTimer (gobject.GObject):
         self.resume_timing()
 
     def mark_timing(self):
+        currently_timing = self.is_timing
         self.pause_timing()
         if self.active_time < 1:
             self.active_time = 1
         # dirty hack: never let total time be less than active time
         if self.active_time > self.total_time:
             self.total_time = self.active_time
-        self.resume_timing()
+        if currently_timing:
+            self.resume_timing()
 
     def finish_timing (self):
         self.mark_timing()

☆LucidのNautilusに再びエンピツのトグルボタンを

Lucid(Ubuntu 10.04)のNautilus(2.30)では"text location bar"と"button bar"を切り替えるエンピツのトグルボタンがなくなってしまいました。
さるお方にアドバイスを頂いて、どなたかPPAで公開してくれる事を願ってPatchをLaunchPadに投稿したのですが、
今のところPPAにアップしてくれた方はいらっしゃらないようです。
ということで自分でパッケージをビルドしたものを公開してみます。
この投稿に提示した操作により損害が発生しても保障はいたしません。適用は自己責任でお願いいたします。

nautilus_2.30.0-0ubuntu4_i386.deb
nautilus_2.30.1-0ubuntu1_i386.deb

本来はパッケージ名を変えたりすべきなのですだと思うのですが、なにぶん良くわからないのでそのままです。
ダウンロードして下記のようにすれば、元々のパッケージと置き換えられます。

# ファイル名はバージョンに合わせて読み替えてください
$ sudo dpkg -i nautilus_2.30.1-0ubuntu1_i386.deb
$ pkill nautilus
※ログイン時にバックグラウンドでnautilusが起動されているのですが、これがいる限り新しいバイナリのnautilusは起動できません。

ソースからビルドしたい方はUbuntu Weekly Recipe 第16回を参照してビルドできる環境を整えてください。
ビルドできる環境が整ったら下記のようにしてビルドします。
正規の手続きではないと思うのですが、一応パッケージは作成されます。
(最後のほうで"running debsign failed"と出るのですが、パッケージは生成されています。)
ディレクトリの名称は適当に置き換えてください。 パスに日本語が含まれていると失敗するかもしれません。ディレクトリ名は英数字だけにしておくのが無難だと思います。

# ディレクトリ名はnautilusである必要はありません
$ mkdir nautilus
$ cd nautilus
# ソースの取得と展開
$ apt-get source nautilus
# ビルドに必要なパッケージの取得
$ sudo apt-get build-dep nautilus
# パッチのダウンロード
$ wget http://launchpadlibrarian.net/44697678/nautilus-2.30.0_add_location_togglebutton.patch
# ディレクトリはバージョンに合わせて読み替えてください。
$ cd nautilus-2.30.1/
# パッチの適用
$ patch -p1 < ../nautilus-2.30.0_add_location_togglebutton.patch
# ビルドの実行
$ debuild -r fakeroot

パッケージのメタ情報を何もいじらなかったせいか、更新がなくてもアップデートマネージャに更新対象として表示されてしまいます。
バージョンがまったく変わっていないときは手動でチェックを外さないと元に戻ってしまうみたいです。

☆Twitterのタイムラインをマージする

Twitterのタイムラインをマージしたいと思って、下記のようなスクリプトを書きました。
毎度初心者レベルなものですいません。
作った環境はUbuntu Karmic Koala。
libdatetime-format-dateparse-perl パッケージを導入していることが前提です。
導入した覚えがない場合は下記のようにして導入してください。
これを使う理由は☆Twitter の投稿時刻をPerlでローカル時刻にするを見てください。

$ sudo apt-get install libdatetime-format-dateparse-perl

tw_merge.shtw_merge_rev.pl をダウンロードして、実行権限をつけ、下記のようにして使います。
~/tmp というディレクトリを作るか、tw_merge.sh の HTML_TMP_DIR の指定を適当に変えてください。
スクリプトで作成したファイルは残ったままになるので、ときどき手動で削除してください。

使用例
$ tw_merge.sh _hito_ mizuno_as pores_n ikunya seotch henrich
$ tw_merge.sh 'cc_jp?max_id=11149920499&per_page=20' 'henrich?max_id=11149420427&per_page=24' 'Say_no?max_id=11150167435&per_page=4'
$ tw_merge.sh 'HPLinuxJP?max_id=11248010182&per_page=7' 'henrich?max_id=11192408823&per_page=2' 'henrich?max_id=11247481244&per_page=3'

ブラウザで結果が表示されます。
結果はTwitterのWeb表示とは逆順になります。
通常と同じ順番が場合はtw_merge_rev.plの下から4行目
「sort keys %TWEET」の部分を「reverse sort keys %TWEET」に修正してください。

最初の例の場合、リストと違って発言の多い人と少ない人でズレがでてきてしまうのが難点です。
揃えたい場合はper_pageでTweetの数を調整します。
古い時期の発言を揃えて見たい場合はmax_idを使います。

max_idやper_pageはあらかじめFirefoxで見たいところを選択して選択部分のソースをみて調べておきます。
(これが一番大変なのですが、簡単な方法が思いつきませんでした。)

一応リストもマージ対象に出来ます。 通常 user_name のところに user_name/list_name としてやればOKです。
(ちょっと表示がおかしくなりますが、読めないことはないです。)
リストが対象に入っている場合は、リストを引数の先頭にしてください。

tw_merge.sh
#!/bin/bash
HTML_TMP_DIR=~/tmp
OUT_HTML=${HTML_TMP_DIR}/TwitRev-`date '+%F-%H%M%S'`-$$.html

i=0
for arg in $*
do
  html=${HTML_TMP_DIR}/`echo $arg | sed -e 's#[/?&]#_#g'`.html
#  HTMLS="$HTMLS $html"
  HTMLS[$i]=$html
  wget -O - http://twitter.com/$arg |sed -e 's#</li>#</li>\n#;' > ${html}
  i=$(($i+1))
done

tw_merge_rev.pl ${HTMLS[*]} > $OUT_HTML
x-www-browser $OUT_HTML &
tw_merge_rev.pl
#!/usr/bin/perl
use DateTime;
use DateTime::Format::DateParse;
my $tzhere = DateTime::TimeZone->new( name => 'local' );

my $thumb_span_tmplt = <<'EOF';
<span class="thumb vcard author">
<a href="http://twitter.com/%s" class="tweet-url profile-pic url">
<img alt="%s" class="photo fn" height="48" src="%s" width="48" />
</a>
</span>
EOF


sub repTime
{
  my $gmt = shift;
  $dt = DateTime::Format::DateParse->parse_datetime($gmt);
  $dt->set_time_zone($tzhere);
}

my $is_header_saved = 0;
my $is_footer_saved = 0;
my (@HEADER, @FOOTER);
my (%TWEET);

for $twhtml (@ARGV){
    open TWHTML, $twhtml or die "$!:$twhtml\n";

    my $screen_name;
    my $url_screen_name;
    my $thumb_span;

    # search start of tweets.
    while(<TWHTML>){
      if(not $is_header_saved){
        s#<head>#<head><base href="http://twitter.com/" />#;
        push @HEADER, $_;
      }
      last if m#<ol id='timeline' class='statuses'>#;

      # build screen_name span
      if(!$screen_name and m#<meta content="(.+)" name="page-user-screen_name" />#){
        $screen_name = $1;
        $url_screen_name = qq(<strong><a href="http://twitter.com/$1">$1</a></strong>);
      }

      # buid thumb span
      if(!$thumb_span and m#<a href="/account/profile_image/.*src="([^"]+)"#){
        my $src_url = $1;
        $src_url =~ s#_bigger\.(\w+)$#_normal.\1#;
        $thumb_span = sprintf $thumb_span_tmplt, $screen_name, $screen_name, $src_url;
      }
    }
    $is_header_saved = 1;

    # save tweets
    OUTER:
    while(1){
      my($id, $tweet);
      while(<TWHTML>){
        last OUTER if m#</ol>#;
        $id = $1 if /id="status_(\d+)"/;
        s#(<span class="published timestamp" data="{time:'([^']+)'}">)[^<]+</span>#$1 . repTime($2) . "</span>"#e;
        $tweet .= $_;
        last if m#</li>#;
      }

      # add $url_screen_name and $thumb_span if not contained.
      if( $tweet !~ m#class="tweet-url screen-name"#){
        $tweet =~ s#<span class="status-body">#$thumb_span <span class="status-body" style="padding-left:48px;">#;
        $tweet =~ s#<span class="status-content">#<span class="status-content"> $url_screen_name#;
      }

      $TWEET{$id} = $tweet;
    }

    if(not $is_footer_saved){
        @FOOTER = $_;
        # save remaining
        while(<TWHTML>){
          push @FOOTER, $_;
        }
        $is_footer_saved = 1;
    }

    close TWHTML;
}

print @HEADER;
for (sort keys %TWEET){
    print $TWEET{$_};
}
print @FOOTER;