trac のインストールをしてみました。環境は Debian sid。apt-get で取ってこれます。
% sudo apt-get install trac
まず、Subversion のリポジトリを作っておきます。
% mkdir -p ~/var/svn/trac-test % svnadmin create ~/var/svn/trac-test
次に、trac のプロジェクトを作ります。
% mkdir -p ~/var/trac/test % trac-admin ~/var/trac/test initenv Creating a new Trac environment at /home/ani/var/trac/test Trac will first ask a few questions about your environment in order to initalize and prepare the project database. Please enter the name of your project. This name will be used in page titles and descriptions. Project Name [My Project]> Test Project Please specify the absolute path to the project Subversion repository. Repository must be local, and trac-admin requires read+write permission to initialize the Trac database. Path to repository [/var/svn/test]> /home/ani/var/svn/trac-test Please enter location of Trac page templates. Default is the location of the site-wide templates installed with Trac. Templates directory [/usr/share/trac/templates]> Creating and Initializing Project Failed to create environment. [Errno 17] File exists: '/home/ani/var/trac/test' Failed to initialize database. 1
どうやら、trac のプロジェクトディレクトリは前もって作っておいてはいけなかったみたい。
% rmdir ~/var/trac/test % trac-admin ~/var/trac/test initenv
とすると、今度は成功。
Apache で動かす例が多いみたいですが、とりあえずお試しなので tracd で動かしてみます。
% tracd ~/var/trac/test Traceback (most recent call last): File "/usr/bin/tracd", line 329, in ? main() File "/usr/bin/tracd", line 301, in main httpd = TracHTTPServer(server_address, TracHTTPRequestHandler) File "/usr/lib/python2.3/SocketServer.py", line 330, in __init__ self.server_bind() File "/usr/lib/python2.3/BaseHTTPServer.py", line 100, in server_bind SocketServer.TCPServer.server_bind(self) File "/usr/lib/python2.3/SocketServer.py", line 341, in server_bind self.socket.bind(self.server_address) File "<string>", line 1, in bind socket.error: (13, '\xb5\xf6\xb2\xc4\xa4\xac\xa4\xa2\xa4\xea\xa4\xde\xa4\xbb\xa4\xf3')
ああそうか、port 80 は一般ユーザでは無理。
% tracd --port 10080 ~/var/trac/test
この状態で http://localhost:10080/ にアクセスするとプロジェクト一覧が見えます。 http://localhost:10080/test で、test プロジェクトにアクセスできました。
ただのにっきで紹介されていた 「折り返す pre」の CSS を設定してみました。
これはいいですね。
white-space: -moz-pre-wrap; /* Mozilla */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ white-space: pre-wrap; /* CSS3 */ word-wrap: break-word; /* IE 5.5+ */
アメリカには13年周期や17年周期で大量発生するセミがいて、 どうしてそんな周期で大量発生するのかというのを解説した本。
作者である吉村仁氏の論文 "The evolutionary origins of periodical cicadas during ice ages." が 元になっているそうです。
一言で言うと、氷河期の厳しい環境の中では、種の存続のためには他の個体と同時に羽化することが重要だが、 そのとき周期が素数だと、他の周期の種との交雑が起こりづらいから、というのが答らしいです。
このあたりをシミュレーションで遊んでみるのも面白そうな感じ。
特に難しいところはなく、気軽に読める本です。
CodeWeb - 画像をアップロードする前にサムネイルを表示させる。より。
ファイルアップロードのフォームに onchange を設定して、サムネイルを表示させるという JavaScript です。
以下のような感じに修正すると、IE と Firefox で動くようになりました。(Windowsで確認) → サンプル
function imgchange(e) { e = e ? e : event; var elem = e.target ? e.target : e.srcElement; document.getElementById("thumbnail").src = 'file://' + elem.value.replace(/\\/g, '/'); document.getElementById("thumbnail").style.display = "inline"; }
Opera も試してみましたが、elem.value の値がファイル名だけでディレクトリ名が含まれないため、 動かないようです。
elem.style.left = x + " px";
みたいな記述をしてしまって、Firefoxで動かないので悩んでしまった。(IEだと動く)
正しくは、
elem.style.left = x + "px";
とスペースなしで書かないといけない。
「JavaScript&DHTMLクックブック」には「styleオブジェクトのpositionプロパティは変更できない」と書いてあるけど、実際には変更できるみたい。
HTML の要素が階層をなしているとき、下の階層にイベントが起こると 上の階層にも順番にイベントが発生する。
これを防ぐには、IE だと cancelBubble = true で、 DOM だと stopPropagation() を使う。
var f = function(e){ e = e ? e : event; if(typeof e.cancelBubble !== 'undefined'){ e.cancelBubble = true; } else if(e.stopPropagation){ e.stopPropagation(); } alert('hogehoge'); } document.getElementById('foo').onclick = f; document.getElementById('bar').onclick = f;
<div id=foo> aaa <div id=bar> bbb </div> </div>
http://mput.dip.jp/mput/?date=20051007#p01 より。 グラフ理論はあまり知りませんが、ちょっと考えてみました。
紙でごにょごにょやってみたらできました。 以下のとおりに接続できるのでグラフ的です。
.abcdefg a.*****. b*..*... c*.....* d**..*** e*..*... f*..*..* g..**.*.
こんな感じでいいのかな……? 接続行列の第i行成分の和が与えられた配列のi番目(1-origin)になることを考えて、 接続行列を上から埋めていきます。
def make_comb(size, num) raise "error" if size < num if size == num [Array.new(size, 1)] elsif num == 0 [Array.new(size, 0)] else make_comb(size-1, num-1).map{|e| [1] + e} + make_comb(size-1, num).map{|e| [0] + e} end end class Array def graphical? return false if self.any?{|e| e < 0 or self.size <= e} return true if self.size == 1 and self.first == 0 make_comb(self.size - 1, self.first).each do |b| partial = [] self[1..-1].zip(b){|x| partial << (x[0] - x[1])} return true if partial.graphical? end return false end end p [5, 2, 3, 2, 3, 2, 5].graphical?
Haskellは知らないです。いかんなぁ。
能をつかんとする人、「よくせざらんほどは、なまじひに人に知られじ。う ちうちよく習ひ得て、さし出でたらんこそ、いと心にくからめ」と常に言ふめ れど、かく言ふ人、一芸も習ひ得ることなし。
未だ堅固かたほなるより、上手の中に交りて、毀り笑はるゝにも恥ぢず、つれ なく過ぎて嗜む人、天性、その骨なけれども、道になづまず、濫りにせずして、 年を送れば、堪能の嗜まざるよりは、終に上手の位に至り、徳たけ、人に許さ れて、双なき名を得る事なり。
天下のものの上手といへども、始めは、不堪の聞えもあり、無下の瑕瑾もあり き。されども、その人、道の掟正しく、これを重くして、放埒せざれば、世の 博士にて、万人の師となる事、諸道変るべからず。
JavaScript で格子を塗り潰す練習をしていたら、何となくライフゲームを 思い出したので作ってみました。
function LifeGame(size){ this.initialize(size); } LifeGame.prototype.initialize = function(size){ this.LivingColor = "#aaa"; this.DeadColor = "#eee"; this._size = size; this._draw_ready = false; this._cells = []; this._next_cells = []; this._canvas = []; this._timer_id = null; var x, y, a; for(x = 0; x < size; ++x){ a = []; for(y = 0; y < size; ++y){ a[y] = Math.floor(Math.random() * 2); } this._cells[x] = a; this._next_cells[x] = []; this._canvas[x] = []; } } LifeGame.prototype._getNumberOfLivingNeighborhoods = function(x, y){ var x_next = (x == this._size - 1) ? 0 : x + 1; var x_prev = (x == 0) ? this._size - 1 : x - 1; var y_next = (y == this._size - 1) ? 0 : y + 1; var y_prev = (y == 0) ? this._size - 1 : y - 1; return this._cells[x][y_prev] + this._cells[x][y_next] + this._cells[x_next][y] + this._cells[x_prev][y] + this._cells[x_prev][y_prev] + this._cells[x_prev][y_next] + this._cells[x_next][y_prev] + this._cells[x_next][y_next]; } LifeGame.prototype.step = function(){ var x, y; for(x = 0; x < this._size; ++x){ for(y = 0; y < this._size; ++y){ var n = this._getNumberOfLivingNeighborhoods(x, y); switch(n){ case 3: this._next_cells[x][y] = 1; break; case 2: this._next_cells[x][y] = this._cells[x][y]; break; default: this._next_cells[x][y] = 0; } } } for(x = 0; x < this._size; ++x){ for(y = 0; y < this._size; ++y){ this._cells[x][y] = this._next_cells[x][y]; } } } LifeGame.prototype.draw = function(){ if(!this._draw_ready){ this._drawInit(); } for(x = 0; x < this._size; ++x){ for(y = 0; y < this._size; ++y){ this._canvas[x][y].style.backgroundColor = this._cells[x][y] ? this.LivingColor : this.DeadColor; } } } LifeGame.prototype._drawInit = function(){ var e; var p = document.getElementById('lifegame'); for(x = 0; x < this._size; ++x){ for(y = 0; y < this._size; ++y){ e = document.createElement('div'); with(e.style){ position = 'absolute'; left = x * 20 + 'px'; top = y * 20 + 50 + 'px'; width = '20px'; height = '20px'; backgroundColor = this._cells[x][y] ? this.LivingColor : this.DeadColor; border = "none"; } this._canvas[x][y] = e; p.appendChild(e); } } this._draw_ready = true; } LifeGame.prototype.start = function(objname){ if(!this._timer_id){ this._timer_id = setInterval('(function(){ ' + objname + '.step(); ' + objname + '.draw(); })()', 300); } } LifeGame.prototype.stop = function(){ if(this._timer_id){ clearInterval(this._timer_id); } this._timer_id = null; } function init(){ game = new LifeGame(30); game.draw(); document.getElementById('start').onclick = function(){ game.start('game'); } document.getElementById('stop').onclick = function(){ game.stop(); } } var game; window.onload = init;
JavaScript で「クラス」相当のことをするにはいろいろやり方があるようですが、
ClassName.prototype.instance_method = function(){ ... }
でインスタンスメソッドを定義していくことによりできるようです。
ちょっといやなのがタイマー処理の setInterval のところで、 これをうまくクラスでラップする方法が分かりませんでした。
setInterval('function(){ this.step(); this.draw(); }', 300);
とやってもうまくいきません。
setInterval() の第1引数にはクロージャが渡せたみたいです。 よって、下のようにすることでタイマーまわりの記述がきれいになりました。
LifeGame.prototype.start = function(){ if(!this._timer_id){ var self = this; this._timer_id = setInterval(function(){ self.step(); self.draw(); }, 300); } }
JavaScript で setInterval をラップする Timer クラスを書いてみました。(似たコードが大量に書かれてそうですが)
function Timer(obj, funcname){ this.interval = 1; this._timer_id = null; this._obj = obj; this._funcname = funcname; } Timer.prototype.start = function(){ if(!this._timer_id){ var self = this; this._timer_id = setInterval(function(){ self._obj[self._funcname](); }, this.interval); } } Timer.prototype.stop = function(){ if(this._timer_id){ clearInterval(this._timer_id); this._timer_id = null; } } Timer.prototype.isRunning = function(){ return this._timer_id ? true : false; }
というクラスで
var t = new Timer(obj, 'func'); t.start();
と書けます。
new Timer(obj.func) のように書きたかったのですが、どうしてもうまく動かすことができなかったため (obj.func 内の this が変なところを指してしまう)、このようなコンストラクタになってます。 うまい方法ないかなぁ。
category_to_tagプラグインを導入してみました。しばらく試してみようと思います。
先日、Timer クラスを
new Timer(obj.func)
のように書けないのかと悩みましたが、 指向性メモ::2005-07-24::クロージャとOOPとJavaScriptの謎仕様 を見て、それが無理であるということが分かりました。
しかしこれをふまえて考えてみると、obj.func() と書いたときは 何で func の中の this が obj だと分かるのかな…… 仕様書を読んでみないといけないようです。
参加した。
いきなり、/.Jのスレッドのはなしから始まる。
JVN が全然知られていないそうなので、宣伝のためにリンク。 http://jvn.jp/
以下のスクリプトで悩み中。
function C(){ this.str = 'C'; } C.prototype.f = function(){ alert('C ' + this.str); } function D(){ this.str = 'D'; } D.prototype.f = function(){ alert('D ' + this.str); } D.prototype.foo = function(){ var c = new C(); c.f(); var bar = c.f; bar(); this.hoge = c.f; this.hoge(); } var str = 'global'; var d = new D(); d.foo();
順に、'C C', 'C global', 'C D' になるのですが、なぜこうなるのかが まだ納得できない。うーむ……
前回の続き。
仕様書の和訳を見ながらしばらく悩んでいた。
function C(){ this.str = 'C' } function D(){ this.str = 'D' } C.prototype.f = function(){ alert(this.str) } D.prototype.f = function(){ alert(this.str) } D.prototype.foo = function(){ var c = new C(); c.f(); var bar = c.f; bar(); this.hoge = c.f; this.hoge(); } var str = 'global'; var d = new D(); d.foo();
11.2.3 関数呼出し によると
something()
という関数呼出しにおいては、this は GetBase(something) になる(GetBase は本当の関数ではなく、仕様の説明上の表記。 8.7 Reference 型 のところに書いてある)。 c.f() の場合は GetBase(c.f) は c だし、this.hoge() の場合は GetBase(this.hoge) は this (つまり d) になる。 だから、c.f() のときは 'C' が出るし、this.hoge() のときは 'D' が出る。
よく分からないのは、bar() に 'global' になること。
var で変数を定義したときにそれの GetBase が何になるかが仕様書を読んでも分からない。
マウスは、マイクロソフトの IntelliMouse Explorer (チルトホイールになる前のやつ)を使っていますが、手の脂でゴムが膨らんだのか、ホイールがまわりづらくなってきたので、サポートに電話して交換してもらうことにしました。
交換手順は http://www.wikiroom.com/msmouse/index.php?%C0%BD%C9%CA%BE%F0%CA%F3%A1%A6%A5%B5%A5%DD%A1%BC%A5%C8 にまとまっています。
電話した結果、使っているモデルはもう在庫切れで、 現行のチルトホイールモデルの品物が送られてくることになりましたが、 ホイールが手になじむかどうかちょっと心配。
しばらく読むのが止まってしまっていましたが、再開。 今日は Chapter 8 まで。
やはり、英語の本は読むスピードが段違いに遅くなってしまう。 この本は、かなり読みやすい英語なんですけどね。
クラスを編集したあと、WEBrick を再起動しないと挙動がおかしいことが あるような気がする……
PHPを使う必要が出てきそうなので、自宅に環境を入れて練習することにしました。
調べてみると、PHP/Apache/MySQLあたりの環境をひとまとめてインストールできる XAMPPというものがあるそうなので、それを入れることにしました。
インストーラ版をダウンロードしてインストール。次へを押していくだけで終了。 とりあえずサービスにはしないでおきました。
XAMPP Control Panel から Apache を起動して http://localhost/ に接続すると、XAMPP の画面を見ることができました。
とりあえず今日はインストールだけ。
http://bloghome.lovepeers.org/daymemo2/?date=20050223#p02 より。
maildropfilter の syntax check をするには
% maildrop -V 9 .mailfilter < mail.txt
とする。
maildropfilter は、一見 C 言語風の文法であるが、 空白や改行を自由に入れることはできない。
使っている 3.0 のホイールがまわらなくなったのでサポートが送ってくれる ことになった IntelliMouse Explorer 4.0 が到着した。
確かに、ホイールがとてもやわらかい。 ちょっとまわしただけで反応する。
ドキュメントのスクロールには悪くないと思うけど、 マウスホイールで何かを切り替えるようなものにはちょっとつらいなぁ。 タブブラウザのタブ切り替えとか。
サイドボタンが前作より上の方になってしまったのもちょっと違和感があるが、 これは慣れれば何とかなる範囲か。
簡単に使った感じでは、3.0 の方がよかったように思う。
arino氏の臨時日記より。
function hogeConstructor(a) { this.a = a; } hogeConstructor.prototype.hogeMethod = hogeMethod(); function hogeMethod() { alert(this.a); }
function hogeConstructor(a) { this.a = a; this.hogeMethod = function() { alert(this.a) }; }
function hogeConstructor(a) { this.hogeMethod = function() { alert(a) }; }
上から順に(1),(2),(3)とします。
JavaScriptに触ってまだ日も浅く、arino氏の主張をいまひとつちゃんと理解できていない点もあるのですが、 どうやら特に(1)の手法を批判していて、(3)のように書くべきだということのようです。
scopeチェインにあれば十分かthisに入ってなきゃいけないかの違い
というのは、(1)や(2)だと h = new hogeConstructor('hoge') とやったときに h.a が見えてしまうのに対し (3) だと a は見えないということなので、確かに (3) の手法の方がよさそうです。
自分は、過去の日記を見れば分かるように (1) のスタイルで書いてきてましたが、 (2) や (3) でなく (1) を選んだのは、h.hasOwnProperty('hogeMethod') が false になるのが (1) だけだからというのが理由でした。 (Effective JavaScript - 3.2 コンストラクタとプロトタイプ に、String もそうなんだから、と書いてあったので、JavaScript ではそういうものだと思って。それ以外のサイトでも見たような気がする)
しかし改めて考えてみると、hasOwnProperty() は false にならないといけないものなのかなぁ。 true になったときの具体的な害はあるのだろうか。
普段は Meadow2 を使っていますが、 そろそろ Meadow3 を視野に入れていこうかと思います。
elisp にいくらか修正が必要なようなので、しばらくはテスト。
http://mibai.tec.u-ryukyu.ac.jp/~oshiro/Programs/elisp/kill-summary.el
結構前から使ってますが、便利です。(確か、高林さんの連載か何かで見たんだったかな)
Meadow3 だと truncate-string を truncate-string-to-width に変更する 必要がありました。 このパッチを当てた状態でも、Meadow2 で動きます。
Index: kill-summary.el =================================================================== --- kill-summary.el (リビジョン 136) +++ kill-summary.el (作業コピー) @@ -231,7 +231,7 @@ () (setq kill-summary-list (append kill-summary-list (list n))) (insert (format "%2d:%s %s\n" n lines - (truncate-string + (truncate-string-to-width (mapconcat (lambda (y) y) strtmp kill-summary-newline-notation) w))) (setq prev str)
http://www.sodan.org/~knagano/emacs/minibuf-isearch/
mini buffer で isearch ができる。1.1 から 1.6.1 に更新した。 Meadow2/3 ともに問題なし。
Meadow2 では windows.el を使っていたが、Meadow3 で動かなかったので ElScreenを 使うことにした。
netinstall でインストール。問題なく動作。
Meadow3 では、アクティブでないウィンドウの modeline に 独自の face を設定できるようになったようです。
'mode-line-inactive に設定します。
Meadow2 には存在しないので、facep で存在をチェックします。
(set-face-background 'modeline "navy") (set-face-foreground 'modeline "white") (if (facep 'mode-line-inactive) (progn (set-face-background 'mode-line-inactive "#374d94") (set-face-foreground 'mode-line-inactive "white")))
_ arino [3行で終わる事を8行かけていて、理由は実害があるかどうか分からない、というのも不思議な状況だと思います。 (JS界隈..]
_ yanagi [実害があるという確信は持てなかったのですが、 実害がないという確信も持てなかったので、 だったらネイティブオブジェク..]