久々にPHPで適当なコードを書く。

1〜2年くらいぶりにPHPでコード書いた。

  • 最初&$mとか書いてた
  • JavaScriptと違って''は\がエスケープシーケンスとして働かないので正規表現パターンを文字列で書くには便利かも
  • preg_match_all()便利だな
  • はてな記法忘れててMarkdownのつもりでリストの'-'を'*'と書いて恐ろしいことになった

http://ideone.com/5SOBuJ

<?php
echo 'php_ver: ' . phpversion() . "\n";

$pattern = '/^\^\s([a-z])\1+$/m';
$subject = "^ aaa\n^ bbb\n^ ccc";

preg_match_all($pattern, $subject, $m, PREG_SET_ORDER);

foreach ($m as $v) {
    echo "{$v[0]}\n";
}
?>

前回IEを起動してからの経過時間を表示する

殆どIEを使うことがないので、前回の起動からどれだけ経ってるか調べるBookmarkletを書いてみました。IE8以上で動きます。


javascript:(function(l,k,t,d,_){(d=t-l[k])&&(d=new Date(d))&&alert('前回の起動から'+(((_=d.getUTCMonth())?_+'ヶ月':'')+((_=d.getUTCDate()-1)?_+'日':'')+((_=d.getUTCHours())?_+'時間':'')+((_=d.getUTCMinutes())?_+'分':'')||d.getUTCSeconds()+'秒')+'経過しています。');l[k]=t})(localStorage,'__last_startup',+new Date)


前回のクリック時の日時をlocalStorageに入れ、経過時間を計算しているだけです。
したがって正確には、「前回このBookmarkletをクリックしてからどれだけ経過したか」を表示するBookmarkletです。

SakuraEditor 2.0.0.2のマクロAPIに関する変更点

サクラエディタマクロを書く際にhttp://www.geocities.jp/maru3128/SakuraMacro/を参考にしていたが、更新日時が2006年と随分古かったので、今使っているサクラエディタのバージョンのAPIを調べてみた。


以下のドキュメントを比較して、増減したAPIを調べた。

削除されたAPI
  • ReplaceAllLine
追加されたAPI
  • ChangeWrapColm
    引数: VT_I4
    戻り値: なし
  • ExecExternalMacro 名前を指定してマクロ実行
    引数: VT_BSTR, VT_BSTR
    戻り値: なし
  • ExitAllEditors 編集の全終了
    引数: なし
    戻り値: なし
  • FileReopenCESU8 CESU-8で開き直す
    引数: VT_I4
    戻り値: なし
  • GetSaveFilename 保存時のファイル名を返す
    引数: なし
    戻り値: VT_BSTR
  • GroupClose グループを閉じる
    引数: なし
    戻り値: なし
  • InsFile キャレット位置にファイル挿入
    引数: VT_BSTR, VT_I4, VT_I4
    戻り値: なし
  • IsCurTypeExt 指定した拡張子が現在のタイプ別設定に含まれているかどうかを調べる
    引数: VT_BSTR
    戻り値: VT_I4
  • IsSameTypeExt 2つの拡張子が同じタイプ別設定に含まれているかどうかを調べる
    引数: VT_BSTR, VT_BSTR
    戻り値: VT_I4
  • KeywordTagJump キーワードを指定してダイレクトタグジャンプ機能
    引数: VT_BSTR
    戻り値: なし
  • NextGroup 次のグループ
    引数: なし
    戻り値: なし
  • PrevGroup 前のグループ
    引数: なし
    戻り値: なし

// PrintDialog

  • PutFile 作業中ファイルの一時出力
    引数: VT_BSTR, VT_I4, VT_I4
    戻り値: なし
  • SelectCountMode
    引数: VT_I4
    戻り値: なし
  • SelectLine 1行選択
    引数: VT_I4
    戻り値: なし
  • TabCloseLeft 左をすべて閉じる
    引数: なし
    戻り値: なし
  • TabCloseOther このタブ以外を閉じる
    引数: なし
    戻り値: なし
  • TabCloseRight 右をすべて閉じる
    引数: なし
    戻り値: なし
  • TabJointNext 次のグループに移動
    引数: なし
    戻り値: なし
  • TabJointPrev 前のグループに移動
    引数: なし
    戻り値: なし
  • TabMoveLeft タブを左に移動
    引数: なし
    戻り値: なし
  • TabMoveRight タブを右に移動
    引数: なし
    戻り値: なし
  • TabSeparate 新規グループ
    引数: なし
    戻り値: なし
  • TextWrapMethod テキストの折り返し方法
    引数: VT_I4
    戻り値: なし
  • ViewMode ビューモード
    引数: なし戻り値: なし
  • WindowList ウィンドウ一覧ポップアップ表示
    引数: なし戻り値: なし

// WordReference

C# 2010 Express Edition で構成マネージャーを表示し、リリースビルドを行う

C# 2005 Express Edition, C# 2008 Express Editionとはまた操作の仕方が変わったようで少し戸惑ったが、なんとか見つけた。


自分はインストール後特に何も設定することなく使用していたのだけど、どうやらC# 2010 Express Editionには設定の種類が2つあるらしい。基本設定と上級者設定だ。どちらの設定かによってUIが変化し、リリースビルドを行う手順が変化する。

この2つの設定は、ツール(T) > 設定(S) から切り替えられる。


自分が調べた環境では、以下の手順で切り替えることができた。
(WinXP SP3, x86(32bit), C# 2010 Express Edition)

  • 基本設定
    • デバッグビルド
      [ソリューション エクスプローラー]のソリューション名を右クリックし、コンテキストメニュー構成マネージャー(O)...を選択、開いた[構成マネージャー]ダイアログで[アクティブ ソリューション構成(C): または 下のリストビューの各プロジェクトの構成を"Debug"に切り替える
      インストール直後の状態ではこちらが選択されているので、デバッグ実行・ソリューションのビルドともにどちらを行ってもデバッグビルドが行われることに注意
    • リリースビルド
      上の設定時に"Release"を選択すればいい
  • 上級者設定


検索してもそれらしい結果が出てこなかったので一応メモ。

検索キーワード

  • "C# 2010 Express 構成マネージャ 表示"
  • "C# 2010 Express ビルド構成 表示"
  • "C# 2010 Express Edition Release ビルド"

JsUnit 2.2をGoogle Chromeで使う

最近のGoogle Chromeだとインラインフレームとクロスドメイン制限の関係でJsUnitが動かない。

解決法としては、(ローカル)サーバにJsUnitとテストコードを置いて実行する。

動作確認した環境

スタックトレースを取得

Google Chrome 10.0.648.204で確認

方法1: Error#stackプロパティから取得 (ただし文字列形式なのでパースが必要)

スタックトレースの出力形式

例外クラス名※1: メッセージ※2
    at 例外が発生したメソッド名※3 (メソッドが呼び出されたファイル名:行番号※4:位置※5)※6
    at 例外が発生したファイル名:行番号※4:位置※5
※注釈
[1]例外クラス名  Error#nameプロパティの値
[2]メッセージ    Error#messageプロパティの値
[3](省略)        コンストラクタの場合、"new メソッド名"となる
[4]行番号        例外が発生したメソッド/コンストラクタの行番号(1〜)
[5]位置          例外が発生したメソッド/コンストラクタの最初の1文字の位置(1〜)
[6](省略)        この行はネストしているメソッドの数だけ増える (0行〜)
// スタックトレースを取得
function Hoge(){
	function Fuga(){
		throw new Error('えらー');
	}
	return new Fuga();
}

try{
	Hoge();
}catch(e){
	var raw_stacktrace = e.stack;
	var stacktrace = parse_stacktrace(raw_stacktrace);
}

// スタックトレースを出力
console.log('生のスタックトレース');
console.log(raw_stacktrace);
console.log('');

console.log('加工後のスタックトレース');
console.log(JSON.stringify(stacktrace, null, 2));
console.log('');

console.log('get_stacktrace()');
console.log(JSON.stringify(get_stacktrace(), null, 2));

/** Error#stack()のスタックトレース文字列をパース
 * @param  {string}  Error#stack()の戻り値
 * @return  {Array}  スタックトレース
 */
function parse_stacktrace(st){
	var res = [];
	
	var traces = st.split(/\r\n?|\n/).slice(1);
	for( var i=0, l=traces.length-1; i < l; ++i ){
		var m = /^\s*at\s+((?:new\s+)?[$_a-z][$\w]*)\s+\(([\s\S]+\/)([^\/]+):(\d+):(\d+)\)$/i.exec(traces[i]);
		res[i] = {
			method: m[1], 
			dir: m[2], 
			fname: m[3], 
			path: m[2]+m[3], 
			line: m[4], 
			pos: m[5]
		};
	}
	
	var m = /^\s*at\s+([\s\S]+\/)([^\/]+):(\d+):(\d+)$/.exec(traces[traces.length-1]);
	res[res.length] = {
		dir: m[1], 
		fname: m[2], 
		path: m[1]+m[2], 
		line: m[3], 
		pos: m[4]
	};
	
	return res;
}

/** スタックトレースを取得 */
function get_stacktrace(){
	var st = new Error().stack.split(/\r\n?|\n/).slice(2), 
		res = [];
	for( var i=0, l=st.length-1; i < l; ++i ){
		var m = /^\s*at\s+((?:new\s+)?[$_a-z][$\w]*)\s+\(([\s\S]+\/)([^\/]+):(\d+):(\d+)\)$/i.exec(st[i]);
		res[i] = {method: m[1], dir: m[2], fname: m[3], path: m[2]+m[3], line: m[4], pos: m[5]};
	}
	var m = /^\s*at\s+([\s\S]+\/)([^\/]+):(\d+):(\d+)$/.exec(st[st.length-1]);
	res[res.length] = {dir: m[1], fname: m[2], path: m[1]+m[2], line: m[3], pos: m[4]};
	return res;
}


実行結果 (Google Chrome 10.0.648.204で確認)

生のスタックトレース
Error: えらー
    at new Fuga (file:///C:/fakepath/get_stacktrace.js:34:9)
    at Hoge (file:///C:/fakepath/get_stacktrace.js:36:9)
    at file:///C:/fakepath/get_stacktrace.js:40:2

加工後のスタックトレース
[
  {
    "method": "new Fuga",
    "dir": "file:///C:/fakepath/",
    "fname": "get_stacktrace.js",
    "path": "file:///C:/fakepath/get_stacktrace.js",
    "line": "34",
    "pos": "9"
  },
  {
    "method": "Hoge",
    "dir": "file:///C:/fakepath/",
    "fname": "get_stacktrace.js",
    "path": "file:///C:/fakepath/get_stacktrace.js",
    "line": "36",
    "pos": "9"
  },
  {
    "dir": "file:///C:/fakepath/",
    "fname": "get_stacktrace.js",
    "path": "file:///C:/fakepath/get_stacktrace.js",
    "line": "40",
    "pos": "2"
  }
]

get_stacktrace()
[
  {
    "dir": "file:///C:/fakepath/",
    "fname": "get_stacktrace.js",
    "path": "file:///C:/fakepath/get_stacktrace.js",
    "line": "56",
    "pos": "28"
  }
]
方法2: console.trace()から取得

未調査です