トップ 追記 RSS feed

継続にっき

2004|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|12|
2006|01|03|05|06|08|09|10|12|
2007|01|02|03|05|07|12|
2008|10|

2008-10-14 (Tue)

))) MercurialからGitへ

Git(ギット)勉強会メモに触発されてGitの利用を再検討。

  • indexバッファ
  • stash
  • rebase, reset, commit --amend
  • bisect
  • logの-pオプション

あたりの機能が便利そうなので乗り換えることにした。 以前評価したときはCogitoでラップする必要があったりと使いづらいものだったけれど、 最近のバージョンはインターフェースもこなれていて悪くない。 ただ、Mercurialのリビジョンナンバー(ローカルでのみ有効な連番ID)相当の機能がないのが残念といえば残念か。

以下、試していて気になったポイントについて。

リポジトリの変換

Gitのアーカイブに含まれるcontrib/hg-to-git/hg-to-git.pyで変換が可能。

git diのようにサブコマンド名の短縮が出来ない

「.gitconfigでaliasを設定すればよい」という解決策がすぐに見つかるものの、 それだとzsh上で補完が効かなくなるという問題がある。

これはグローバルエイリアスを設定して解決。

$ alias -g ann=annotate
$ alias -g ci=commit
$ alias -g co=checkout
$ alias -g di=diff
$ alias -g st=status

Ubuntu 8.04のzshだと補完関数が古くてstashなどをサポートしてない

CVS HEADでは実装されているので、 そこから_gitを持ってきてfpathに配置すればOK。

revertとreset

CodeRepos::Share ? Trac参照。

revertの機能がMercurialのそれと異なるので注意。

$ hg revert --no-backup

に対応するコマンドは

$ git reset --hard (HEAD)

になる。


2007-12-02 (Sun)

))) JScript(WSH 5.6)小ネタ

車輪の再発明のような気もするけれど。

JavaScriptフレームワーク prototype.jsを使う

次のようなWSFファイルを作成する。

<job id="sample">
  <script language="JScript" src="pre_prototype.js"/>
  <script language="JScript" src="prototype.js"/>
  <script language="JScript" src="post_prototype.js"/>
  <script language="JScript">
    (3).times(function(i) {WScript.Echo(i)});
  </script>
</job>
実装

prototype.jsはブラウザで動かすことを前提とした作りになっているために、そのままではWSHでロードすることができない。 適当にダミーオブジェクトを定義する必要あり(pre_prototype.js)。

// For prototype.js version 1.6.0
var document = {
    createElement:  function() {return {appendChild: function(){}}},
    createTextNode: function() {return {}},
    createEvent:    function() {return {__proto__: {}}},
    write:          function() {return {}},
    getElementById: function() {return {}}
};
var window = {};
var navigator = {appVersion: ""};
var Element = {};

また、オートメーションオブジェクトにtoStringプロパティが定義されておらず Object.inspectの呼び出しに失敗するので、該当関数を再定義してみる(post_prototype.js)。

Object.extend(Object, {
    inspect: function(object) {
        try {
            if (object === undefined) return 'undefined';
            if (object === null) return 'null';
            return object.inspect ? object.inspect() :
                                   (object.toString ? object.toString() : "#<UnknownObject:" + object + ">");
        } catch (e) {
            if (e instanceof RangeError) return '...';
            throw e;
        }
    }
});

Railsのbreakpoint(ruby-breakpoint)もどき

ruby-breakpointはコード中に"breakpoint"と書いておくと実行時にその環境でreplに突入してくれるというもの。 オリジナルは複数行にわたる入力やdRubyを用いたリモートアクセスもサポートするが、そこまで考えなければ簡単に似たようなものが用意できる。

(function(i) {eval(breakpoint)})(0);

実行結果。

> i + 1
1
実装
var breakpoint =
    'for(;;) {' +
    '    WScript.StdOut.Write("> ");' +
    '    if (WScript.StdIn.AtEndOfStream) break;' +
    '    var expr = WScript.StdIn.ReadLine();' +
    '    try {' +
    '        WScript.StdOut.WriteLine(Object.inspect(eval(expr)));' +
    '    }' +
    '    catch (e) {' +
    '        WScript.StdOut.WriteLine("Error Code: " + e.number);' +
    '        WScript.StdOut.WriteLine(e.description);' +
    '    }' +
    '}';

例外発生時にスタックトレース取得

例外をキャッチしてスタックトレースを付与する関数でラップする。

function func1(i, j) {
    (function () { func2("foo") })([]);
}

function func2(i, j) {
    throw new Error("ERROR");
}
func2 = throwsInformationalError(func2);


var Test = Class.create({
    func3: throwsInformationalError(function(i, j) {
        this.func4("bar");
    }, "func3"),

    func4: throwsInformationalError(function(i, j) {
        throw new Error("ERROR");
    }, "func4")
});

それぞれ呼び出したときの実行結果。

func1();

 test.wsf(149, 10) Microsoft JScript 実行時エラー: ERROR
 --- Stack Trace ---
 func2('foo')
 [anonymous]([])
 func1()


(new Test()).func3()

 test.wsf(149, 10) Microsoft JScript 実行時エラー: ERROR
 --- Stack Trace ---
 func4('bar')
 func3()
実装
Object.extend(Function.prototype, {
    getName: function () {
        if (this.name) return this.name;
        var regmatch = this.toString().match(/^function\s*(\w+)/);
        return regmatch ? regmatch[1] : '[anonymous]';
    }
});

function throwsInformationalError(fn, fn_name) {
    function _throwsInformationalError() {
        try {
            return fn.apply(this, arguments);
        }
        catch (e) {
            if (! e.informational) {
                var stack = [];
                for (var i = arguments.callee; i; i = i.caller) {
                    var args = [];
                    for (var j = 0; j < i.arguments.length; j++) {
                        args.push(Object.inspect(i.arguments[j]));
                    }
                    var _fn = (i == arguments.callee) ? fn : i;
                    if (_fn.getName() != "_throwsInformationalError") {
                        stack.push(_fn.getName() +"(" +  args.join(", ") + ")");
                    }
                }
                e.description += "\n--- Stack Trace ---\n" + stack.join("\n");
                e.informational = true;
            }
            throw e;
        }
    };
    if (fn_name) {
        fn.name = fn_name;
    }
    return _throwsInformationalError;
}
  • util.js(breakpointとセット。ロードにはprototype.jsが必要)

foreach

JScriptのfor...in文とVBScriptのFor Each...Next文は言語仕様的には似たようなものだけど、 その実装には決定的な違いがある。その差を埋めるためにEnumeratorが用意されてはいるけれど、 それでもなおカバーしきれないオブジェクトが存在する。ADSIによる属性アクセスなどがそれ。

> var o = GetObject("LDAP://DC=example,DC=com")
#<UnknownObject:>
> o.objectClass
[object Object]
> for (var i in o.objectClass) {WScript.Echo(i)}
undefined
> new Enumerator(o.objectClass)
オブジェクトがコレクションではありません。

ここで各要素にアクセスする方法を調べてみるも、MicrosoftのサンプルはVBScriptでFor Each...Nextしているものばかり。 しょうがないのでVBScript側でFor Each...Next文相当のプロシージャを用意しておいてWSFファイルで読み込んで利用する。 *1

Sub foreach(obj, fn)
  Dim i
  For Each i In obj
    Call fn(i)
  Next
End Sub

JScript側からはこのように。

> foreach(o.objectClass, function(i) {WScript.Echo(i)})
top
domain
domainDNS
undefined

*1 ただ、この例ならばo.objectClass.toArray()とやればアクセス可能。


2007-07-06 (Fri)

))) Mercurialが0.9.4でシンボリックリンクをサポート

Mercurial 0.9.4 released!より。 あまり取り上げられていないようだけど、地味に使いづらいところだったのでありがたい。


2007-05-19 (Sat)

))) mobileimapをアクセスキーに対応させる

クイックハックだけどなかなか便利に。

--- mobileimap.in.orig  2005-05-22 16:04:40.000000000 +0900
+++ mobileimap.in       2007-05-19 21:55:10.000000000 +0900
@@ -862,7 +862,7 @@
                           :seq => seq)
       begin
         generate_from_line(g, seq, nmessages) +
-          g.a(:href => url) {
+          g.a(:href => url, :accesskey =>  nmessages - nth(seq) + 1) {
           emphasize(g, compact_subject(get_subject(seq)).escapeHTML)
         } + g.hr
       rescue Exception => e
@@ -1436,6 +1436,7 @@
             " " + g.a(:href => "#bottom") { "↓" } +
             g.br + generate_seen_mode(g) + g.hr +
             generate_search_form(g) +
+            g.a(:name => 0, :href => "#0", :accesskey => 0) { "→" } + g.br +
             generate_list(g, nmessages, messages) +
             navi + " " +
             g.a(:href => generate_url(:command => "folders",
@@ -1725,6 +1726,7 @@
               g.a(:href => "#bottom") { "↓" } + " " +
               generate_seen_mode(g) + " " + g.hr +
               generate_fsearch_form(g) +
+              g.a(:name => 0, :href => "#0", :accesskey => 0) { "→" } + g.br +
               folders.map {|folder|
               line = g.font(:color => @seq_color) { sprintf("%03d", i) } +
                 if get_unseen_nmessages(folder) > 0 then
@@ -1733,7 +1735,8 @@
                   " "
                 end +
                 g.a(:href => generate_url(:folder => folder,
-                                          :unseen_only => @query.unseen_only)){
+                                          :unseen_only => @query.unseen_only),
+                    :accesskey => i){
                 simplify_folder_name(folder)
               } + g.br
               i += 1

2007-03-29 (Thu)

))) お知らせ

明日からしばらくIP unreachableな状態が続きそうです。


2007-02-22 (Thu)

))) VistaでSleipnir 1.66をHTTPに関連づけるには

メモ。

[HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice]
"Progid"="Sleipnir.API"

2007-01-18 (Thu)

))) インクリメンタルサーチ対応 Gauche ユーザリファレンス

ちょくちょく利用されているようなので、Gauche 0.8.9リリースにあわせて更新。

ついでに任意のバージョンのドキュメントを用意したい人向けにこの生成方法について簡単に書いておきます。 キモはisearch.html中の<table id="all">の中身なんですが、この部分はHTML化されたGaucheユーザリファレンスを適当なディレクトリに展開したあとその中で

grep 'class="summary-letter"' gauche-refj*|\
  grep --only-matching 'gauche-refj_[0-9]*\.html'|sort|uniq|\
  xargs grep --no-filename '^<tr><td></td><td valign="top"><a href="gauche-refj'|\
  sed 's/a href/a target="ref" href/g'

としたものを埋め込んでいます。あとは必要なファイルを落として同じディレクトリに置けば完成。


2007-01-06 (Sat)

))) /etcのバージョン管理 with Mercurial

CVSによるオープンソース開発にも話題が出てるけど、 実際にやってるって話をとんと聞かない/etcのバージョン管理。これをMercurialを使って試してみた。

この用途にCVSやSubversionではなくMercurialを使うメリットは少なくとも2つ考えられる。

  • cd /etc;hg init で用意が完了する。最初のimportとcheckoutがいらないので導入コストが低い。
  • 管理ディレクトリがトップディレクトリ中の.hgのみしかないのでアクセスコントロールが楽。CVSなどはサブディレクトリごとに管理ディレクトリを作成する。

試してないけど、サーバ間で変更の同期を取るのにも使えるかも。

))) hg logでsummaryではなくdescriptionを出力する

で、初めて本格的にMercurialを使い始めたのだけど、いろいろカスタマイズしたいところが出てきた。

標準のhg logの出力は次のような形で、コミットメッセージはそのsummary(=1行目)が出力される。 つまり、コミットメッセージが複数行に渡る時はそのすべてを確認することが出来ない。

changeset:   3:b9d48fc01c60
user:        User <user@example.com>
date:        Thu Jan 05 21:00:27 2007 +0900
summary:     commit message line1.

-vオプションを使うというのも一つの手だけど、もう少し柔軟に何とかならないものかと調べてみると--styleオプションが使えそうだということが分かった。

hg log [OPTION]... [FILE]
options:
     --style           display using template map file

オリジナルのテンプレートはDebianの場合/usr/share/mercurial/templates/map-cmdline.defaultにあるのでそいつをカスタマイズして使えばいいみたい。

# mkdir ~/.hg
# cp /usr/share/mercurial/templates/map-cmdline.default ~/.hg/map-cmdline.custom
# vi ~/.hg/map-cmdline.custom

-changeset = 'changeset:   {rev}:{node|short}\n ... summary:     {desc|firstline}\n\n'
+changeset = 'changeset:   {rev}:{node|short}\n ... description:\n{desc|strip}\n\n'

# cd /etc
# hg log --style ~/.hg/map-cmdline.custom

 changeset:   3:b9d48fc01c60
 user:        User <user@example.com>
 date:        Thu Jan 05 21:00:27 2007 +0900
 description:
 commit message line1.
 commit message line2.

うん、出来た。標準でこのフォーマットを使いたいなら次のようにする。

# vi ~/.hgrc

 [defaults]
 log = --style /root/.hg/map-cmdline.custom

2006-12-09 (Sat)

))) Windows Vista Business レビュー

先月末に公開されたので少し触ってみた。 結論から言えば、いろいろと改善点は見られるもののどうにも微妙といった印象。

ネットワークドライブとWebDAV

純粋に機能の向上を評価できた数少ない機能の1つ。 XP Professionalにおける状況を以前書いたけど(その1その2)、 その辺の問題がきちんと解決されている。

シンボリックリンク

コマンドプロンプトの組み込みコマンドmklinkを使ってシンボリックリンクが作れるように。 これまでサポートされていたジャンクションとの違いはリンク/ジャンクション作成ツールにまとめられている。 ただ、一般ユーザで作成するにはあらかじめ「ローカルセキュリティポリシー」-「ローカルポリシー」-「ユーザー権利の割り当て」-「シンボリック リンクの作成」でユーザを登録しておかなければならない。

一見便利そうなんだけど、ファイルに対するシンボリックリンクは、リンク元の方を開いてから保存しようとすると新しいファイルとして保存されてしまうことがある(xyzzyで確認)。Vista付属のメモ帳ではきちんとリンク先が更新されたけど、アプリケーションによって扱いが変わってくるようではどう考えても実用的とは言えない。

UAC

これのおかげでOSインストール直後のさまざまな初期セットアップも標準ユーザーとしてログオンしつつ作業することが出来た。 事実上管理者として作業するしかなかったこれまでの状況と比べれば大きな進歩だけど、その仕様に「?」となるところも多々ある。

例えばWindows Vista: UAC の抜け道を考える4で挙げられている ファイル名の問題。setup.exeという実行ファイルについて、「管理者として実行」「実行しない」の2つの選択肢しかないので、 Cygwinを自身のホームディレクトリにインストールしたいなんて時にはインストーラをリネームするしかない。

その他気づいた雑多な事柄

  • 関連づけの設定はコンパネの「規定のプログラム」から。設定できる項目が従来に比べ非常に限定されている。
  • telnetコマンドは標準でインストールされない。コンパネの「プログラムの機能」-「Windowsの機能の有効化または無効化」から有効に出来る。
  • ファイアウォールでICMP Echo Requestを通すように設定するのが面倒になった。
    • 「セキュリティが強化されたWindowsファイアウォール」-「受信の規則」-「新規の規則」から新しい規則を作成する。ただし、このウィザード中ではICMPの設定は出来ないので一旦適当なダミーのルールを作成する必要がある。
    • 新しいルールを右クリック、プロパティを開いてプロトコルでICMPv4を選択、カスタマイズから「エコー要求」をチェック。

いろいろ書いたけど、では今Vistaを使うかと聞かれたら間違いなくNoだ。 というのも、ウィンドウの最大/最小化やメニューの表示などのアニメーションを無効にすることが出来なくなっているから*1。 正確には「無効にすることは出来る。再起動*2すると勝手に有効になる」。……どうしようもないね。

他にも、クラシックスタートメニューの「ログオフ(L)...」をクリックするとダイアログボックスが出ることなくログオフしたり、システムにグローバルな設定がユーザによって変わっているように見えたり、IE7が起動しなくなったりと完成度が高いとは言えない。 今後修正されることを期待。

追記(2007/02/17)

ウィンドウの最大/最小化やメニューの表示などのアニメーションを無効にすることが出来なくなっているから。 正確には「無効にすることは出来る。再起動すると勝手に有効になる」。

これ、やり方勘違いしていたからだったようだ。 これまではXPの時と同じように「システムのプロパティ」 - 「システムの詳細設定」から「パフォーマンス オプション」を開いていたのだが、 コンパネの「パフォーマンスと情報」から「視覚効果の調整」と進めないとだめらしい。

*1 Vistaの標準テーマだけにとどまらず、Windowsクラシックでも

*2 再ログオンかも


2006-10-15 (Sun)

))) PuTTY + Screen + Emacs 256色環境

せっかく256色使えるんだから、ということで 開発環境 Screen x PuTTY x Emacs x 256color : Hasta Pronto.orgを 参考に作業した。OSはDebian sarge。

リンク先の流れに沿って進めればいいんだけど、最後に/etc/screenrcにあるxterm用の設定をxterm-256color用に移植しないとscreenが きちんと動いてくれなかった。


2004|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|12|
2006|01|03|05|06|08|09|10|12|
2007|01|02|03|05|07|12|
2008|10|
トップ 追記 RSS feed