MacのFinderで隠しファイル表示

ちょっと必要なことがあったので。
Lionでもokです。


ターミナルで行います。

まず、隠しファイルを表示するとき。

$ defaults write com.apple.finder AppleShowAllFiles TRUE
$ killall Finder


こちらは非表示に戻すとき。

$ defaults write com.apple.finder AppleShowAllFiles FALSE
$ killall Finder


丸パクリ参考にさせていただいた
http://d.hatena.ne.jp/shunsuk/20090714/1247567640

Ext JS 4でのクラス定義

ということで概観をつかむためにThe Class System - Sencha Docs - Ext JS 4.0を読んだノート。
というか妥協した和訳。でも(゚ε゚)キニシナイ!!

0. 目次

    1. 概説
    2. 命名規約
    3. ハンズオン
    4. エラーハンドリングとデバッギング

1. 概説

Ext JS 4 :
300以上のクラス、20万人以上のデベロッパ
以下のような共通のコードアーキテクチャを提供しようとしている

  • 使いやすく、学びやすい
  • 迅速な開発、簡単なデバッグ、苦痛のないデプロイ
  • よく組織化され、拡張性がありメンテナンスしやすい


JavaScript :
クラスレス、プロトタイプ指向
→ 柔軟性が最大の特徴
→ 実装がばらけやすい
→ コストが予測不可能 && 理解、保守、再利用がしにくい(統一された構造がなければ)


一方、
クラスベース :

  • OOPで最もポピュラー
  • 強い型付け、カプセル化、標準的なコーディング規約 → 時間がたっても予測可能で、拡張性があり、スケーラブル
  • JavaScriptのような動的な機能はない


Ext JS 4では両者の短所を隠し、長所のみを得ることができる。

2. 命名規約

命名規約に従うことでコードを読みやすい状態で保つことができる

1) クラス
  • クラス名は英数字のみ。専門用語でない限り数字は非推奨。
MyCompany.useful_util.Debug_Toolbar  // だめ
MyCompany.util.Base64  // ok
  • トップレベルの名前空間とクラス名 : UpperCamelCase
  • 頭文字語 : UpperCamelCase
  • その他 : 全て小文字
MyCompany.form.action.Autoload
Ext.data.JsonProxy  // JSONProxyとしない
MyCompany.util.HtmlParser  // HTMLParserとしない
MyCompany.server.Http  // HTTPとしない

※ Senchaが配布したもの以外はトップレベルの名前空間にExtを使わない。

2) ソースファイル

クラス名はファイルパスに紐付けされる
→ 1ファイルに1クラス

Ext.util.Observable  // @path/to/src/Ext/util/Observable.js
Ext.form.action.Submit  // @path/to/src/Ext/form/action/Submit.js
MyCompany.chart.axis.Numeric  // @path/to/src/MyCompany/chart/axis/Numeric.js

// (/path/to/src = そのアプリケーションでクラスを配置しているディレクトリ)

全てのクラスは1つのディレクトリ下に置き、適切な名前空間に分ける

3) メソッドと変数

英数字のみのlowerCamelCase。専門用語でない限り数字は非推奨。頭文字語も同様。

encodingUsingMd5();
getHtml();  // getHTML()としない
getJsonResponse();  // getJSONResponse()としない
parseXmlContent();  //parseXMLContent()としない

var isGoodName;
var base64Encoder;
var xmlReader;
var httpSearver;
4) プロパティ

lowerCamelCase。
ただし定数は全て大文字。

Ext.MessageBox.YES = "YES"
Ext.MessageBox.NO = "No"
MyCompany.alien.Math.PI = "4.13"

3. ハンズオン

1. 宣言

1.1) 今までの方法
今まで : クラスの生成 = Ext.extend

var MyWindow = Ext.extend(Object, { ... });

他のクラスを継承していることは分かりやすい
が、直接継承でない場合、configurationやらstaticsやらmixinをうまいことするAPIがなかった(todo)
(Other than direct inheritance, however, we didn't have a fluent API for other aspects of class creation, such as configuration, statics and mixins.)


また下のようなときは

My.cool.Window = Ext.extend(Ext.Window, { ... });
  1. My.coolが存在していること
  2. Ext.Windowが存在し、読み込まれていること

に注意しなければならない。
1 : Ext.namespace(Ext.ns)で解決 ← 毎回書くのは面倒
(※ Ext.namespace = オブジェクトやプロパティがまだ存在していなければ再帰的に作成するメソッド)

Ext.ns('My.cool');
My.cool.Window = Ext.extend(Ext.Window, { ... });

2 : 簡単ではない
← Ext.Windowの直接/間接の継承において依存関係がある(再帰的に)
→ 以前のver.では一部の機能を使うだけでもライブラリ全体をインクルード


1.2) 新しい方法
Ext JS 4ではExt.defineで全て解決

Ext.define(className, members, onClassCreated);

className : クラス名
members : クラスメンバのコレクション
onClassCreated : オプションの関数。依存関係を解決し、クラスが完全に生成された時にコールバックされる

Ext.define('My.sample.Person', {
    name: 'Unknown',

    constructor: function(name) {
        if (name) {
            this.name = name;
        }

        return this;
    },

    eat: function(foodType) {
        alert(this.name + " is eating: " + foodType);

        return this;
    }
});

var aaron = Ext.create('My.sample.Person', 'Aaron');
    aaron.eat("Salad");  //alert("Aaron is eating: Salad");

注意
newよりもExt.create()でインスタンス生成を推奨
← 動的ローディングが出来る

2. Configuration

Ext JS 4ではconfigプロパティを使うことができる

  • configurationは他のクラスメンバーから完全に隠蔽される
  • configプロパティのgetter, setterはプロトタイプに自動生成される
  • applyメソッドも生成される。自動生成されたsetterは値をセットする前にapplyメソッドを呼び出す → 値をセットする前に何か処理をしたい場合applyメソッドをオーバーライドする(下のapplyTitle, applyBottomBar)
    Ext.define('My.own.Window', {
    /** @readonly */
    isWindow: true,

    config: {
        title: 'Title Here',

        bottomBar: {
            enabled: true,
            height: 50,
            resizable: false
        }
    },

    constructor: function(config) {
        this.initConfig(config);

        return this;
    },

    applyTitle: function(title) {
        if (!Ext.isString(title) || title.length === 0) {
            alert('Error: Title must be a valid non-empty string');
        }
        else {
            return title;
        }
    },

    applyBottomBar: function(bottomBar) {
        if (bottomBar && bottomBar.enabled) {
            if (!this.bottomBar) {
                return Ext.create('My.own.WindowBottomBar', bottomBar);
            }
            else {
                this.bottomBar.setConfig(bottomBar);
            }
        }
    }
});

使用例

var myWindow = Ext.create('My.own.Window', {
    title: 'Hello World',
    bottomBar: {
        height: 60
    }
});

alert(myWindow.getTitle());  // "Hello World"

myWindow.setTitle('Something New');

alert(myWindow.getTitle());  // "Something New"

myWindow.setTitle(null);  // "Error: Title must be a valid non-empty string"

myWindow.setBottomBar({ height: 100 });  // height -> 100
3. Statics

Staticなメンバはstaticsコンフィグを用いて定義する

Ext.define('Computer', {
    statics: {
        instanceCount: 0,
        factory: function(brand) {
            // 'this' in static methods refer to the class itself
            return new this({brand: brand});
        }
    },

    config: {
        brand: null
    },

    constructor: function(config) {
        this.initConfig(config);

        // インスタンスのselfプロパティは自身のクラスを指す
        this.self.instanceCount ++;

        return this;
    }
});

var dellComputer = Computer.factory('Dell');
var appleComputer = Computer.factory('Mac');

alert(appleComputer.getBrand());  // "Mac"  (自動生成されたgetterを使用)

alert(Computer.instanceCount);  // "2"

4. エラーハンドリングとデバッギング

Ext JS 4にはデバッグとエラーハンドリングに役立つ機能がいくつかある

  • Ext.getDisplayName()は任意のメソッドのディスプレイ名?を取得する → 例外生成時にクラス名やメソッド名を記述できて便利
throw new Error('['+ Ext.getDisplayName(arguments.callee) +'] ここにメッセージを記述');
  • Ext.define()で定義したメソッドやクラスで例外が生成された場合、コールスタックでそのメソッド名やクラス名を確認することができる(WebKitベースのブラウザ(Chrome, Safari)のみ)

Chromeの例

DelphiでMap関数ぽいもの

日曜なのに出勤だったので、ついカッとなってやった


※ map関数は、引数に関数と配列*1を取って、配列のそれぞれに対して与えられた関数を適用させる関数のこと


引数に関数を渡すため、あらかじめ手続き型を宣言しておく(参考: Delphiでコールバック - 飲む、寝る。)。

type
    TProc = procedure(p: Pointer);

引数の型が違うたびに宣言するのは面倒*2なのでポインタ型にして、関数はラッパーを作ってそれを渡すことにしてみた*3

procedure Map(proc: TProc; args: array of Pointer);
var
    i: Integer;
begin
    for i := 0 to High(args) do
        proc(args[i]);
end;

procedure Main;

    procedure WrappedShowMessage(p: Pointer);
    begin
        ShowMessage(String(p^));
    end;

var
    s1, s2, s3: String;
begin
    s1 := '1';
    s2 := '2';
    s3 := '3';
    Map(@WrapedShowMessage, [@s1, @s2, @s3]);
end;

もうちょっと洗練させないと使うことはなさそうだけど…

*1:別に配列に限らないとは思うけど

*2:Map関数もoverloadしなきゃだし

*3:Delphi6なので無名関数が無い

Ext JS 4 の Ext.Ajax.request で同期通信する

最近、業務でExt JSを使ってまして。
サーバとはExt.Ajax.requestを使って非同期に通信してるのだけど、同期でしたいときもあるわけです。


Ext.Ajax.requestのオプションで指定できるかと思ったけど、APIドキュメントでは見つからず。
さらにフォーラムで開発チームの人が

As has beeb mentioned many times. Synchronous operation is neither supported nor desirable. Use callbacks to continue processing after the return of data.
How to make synchronous AJAX request using Ext library?

って言ってて、無いものだと諦めかけてたのです。

それ、async: falseで出来るよ

です。
ソース*1を見てみると、asyncというパラメータをXMLHttpRequest.openの第3引数に渡してて、それはどうやらオプションから取得しているみたい*2
ので実際にasync: falseを指定してやると同期通信になった。

注意

古いバージョンは見てないので、元々あったのか新しく加わったのかは分からないです。
バージョンを固定するのでなければあんまり使わないほうがよいかも。

                                                                                                      • -


以下は検証時のソース*3
Ext.Ajax.requestでasync: falseを指定し、test.php(5秒スリープするだけ)にPOSTでアクセスするだけ。
結果が帰ってきて、コールバックの実行が終わるまで、他の操作は行えなかった。
@test.html

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>test</title>
        <link rel="stylesheet" type="text/css" href="../ext-4.0.2a/resources/css/ext-all-gray.css"  />
        <script type="text/javascript" src="../ext-4.0.2a/bootstrap.js" ></script>
        <script type="text/javascript">
            Ext.onReady(function() {

                btn1 = Ext.create('Ext.button.Button', {
                    renderTo: 'btn1'
                });

                btn1.on('click', function() {
                    Ext.Ajax.request({
                        url: 'test.php',
                        method: 'POST',
                        async: false,    // <- ここ
                        success: function () {
                            alert('done!');
                        }
                    })
                });
            });
        </script>
    </head>
    <body>
        <div id="btn1"></div>
    </body>
</html>

@test.php

<?php

sleep(5);

*1:4.0.7(GPL版)

*2:デフォルトはtrue

*3:職場だったので4.0.2だけど多分大丈夫…!

Delphiでコールバック

※ 環境はDelphi 6

JavaScriptを触ってると、Delphiでもコールバックが使いたくなってきた。
調べてみると、わりと簡単にできるようだ。

コールバック(英: Callback)とは、プログラミングにおいて、他のコードの引数として渡されるサブルーチンである。
コールバック (情報工学) - Wikipedia


コールバック関数は、呼び出し先で何らかのイベントが発生した場合の処理を指定する目的で使われることが多い。コールバック関数を使うと、イベントの発生を検知するための処理と、そのイベントが起こった時に実行すべき個々の処理を分離して記述することができる。
コールバック関数とは - IT用語辞典 e-Words

手続き(関数)を渡す場合

まず、手続き型を宣言する。引数が違えば、違う手続き型として宣言しなければならない。

type
    TProc = procedure;

実装例

procedure MyProc;
begin
    ShowMessage('This is MyProc');
end;

procedure CallProc(Proc: TProc);
begin
    Proc;
end;

procedure Main;

    procedure MyInnerProc;
    begin
        ShowMessage('This is MyInnerProc')
    end;

begin
    CallProc(MyProc);       // "This is MyProc"
    CallProc(@MyInnerProc); // "This is MyInnerProc"
end;

関数内関数はポインタにして渡す。(そのまま渡すとコンパイル時エラーになる)
また、親関数の変数を扱おうとすると実行時エラーになる。

メソッドを渡す場合

同様に手続き型を宣言するが、末尾に「of Object」を付加する。

type
    TStrProc = procedure(s: String) of Object;

    TMyClass = class(TObject)
    public
        greet: String;
        constructor Create(s: String);
        procedure MyProc(msg: String);
    end;

    THisClass = class(TObject)
    public
        procedure HisProc(CallBack: TStrProc);
    end;

実装例

constructor TMyClass.Create(s: String);
begin
    greet := s;
end;

procedure TMyClass.MyProc(msg: String);
begin
    ShowMessage(greet + msg);  // privateな変数にも触れる
end;

procedure THisClass.HisProc(CallBack: TStrProc);
begin
    if Assigned(CallBack) then  // <> nil ではなくAssignedを使う
        CallBack('This is Callback');
end;

procedure Main;
var
    Mine: TMyClass;
    His: THisClass;
begin
    Mine := TMyClass.Create('Hi, ');
    His := THisClass.Create;

    His.HisProc(Mine.MyProc);  // "Hi, This is Callback"

    His.Free;
    Mine.Free;
end;

関数内関数は型違いとしてコンパイル時エラーになる。(ポインタにしてもコンパイル時エラー)
もちろん、コールバックがよばれる前にインスタンスが解放されていると実行時エラーになる。
また、関数が割り当てられているかの判定にはAssignedを使う(func <> nil としない)。

Node.jsでHello worldするまで

Mac OS X 10.7 Lionでヤってます。

Homebrewのインストール

下のコマンドでインストールする。

ruby -e "$(curl -fsSL https://gist.github.com/raw/323731/install_homebrew.rb)"

「Press enter to continue」を表示されるのでエンターキーをッターン!!する。

終了後、成功確認の代わりにバージョンを確認

brew -v

「0.8」のように表示されればok。
ちなみにHomebrewは /usr/local/bin にインストールされているが、標準でパスが通っている場所なので設定は特に必要ない。

何はともあれリストのアップデートをしておく。

brew update

インストール

Homebrewを使ってインストールする。

brew install node.js

インストール中に

Homebrew has NOT installed npm. We recommend the following method of installation:
curl http://npmjs.org/install.sh | sh

After installing, add the following path to your NODE_PATH environment variable to have npm libraries picked up:
/usr/local/lib/node_modules

と表示されているので、下のコマンドでnpmをインストール。
npmはperlで言うところのCPANにあたるらしい。

curl http://npmjs.org/install.sh | sh

NODE_PATHを設定する。
.bash_profileに以下の行を追加すればよい。

export NODE_PATH=/usr/local/lib/node_modules

Hello World!!

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World!!\n');
}).listen(8000, "localhost");
console.log('Server running at http://localhost:8000/')

上のコードをserver.jsとかで保存し、

node server.js

を実行した後、 http://localhost:8000 にアクセスするとHello Worldが表示される。

const部に関数を宣言する

Stack Overflow内のConst function in Delphiを簡単に訳してまとめてみた。



質問は、

const
    function1: function(const S: String): String = SomeVariable1;

は何をしていて、何のために書かれているのか。というもの。


何をしているのか

普通、定数は

const
    Pi = 3.1415;
    s  = 'This is example';

のように記述されるが、

const
    Pi: Extended = 3.1415;

のようなtyped constantsもある。

なので上の例では
function1に"function(const S: String): String"型のSomeVariable1関数を割り当てていることになる。

※ このとき、SomeVariable1はconst宣言より前に定義されていなければならない。

//例.
function SomeVariable1(const S: String): String;
begin
  result := S + '!';
end;

const
  function1: function(const S: String): String = SomeVariable1;


何のためなのか

2つの理由が考えられる。
1. コードが{$J+}*1(型付き定数を割り当て可能)で書かれていて、「定数」はどこかで別の値が割り当てられている*2。もしfunction1がvariableとして宣言されていたら、ユニットのinitialization部で初期化されなければならないが、他のユニットのinitialization部が先に実行されて、その中でfunction1「関数」がよばれているかもしれないことを考えるとそれでは遅すぎる。

2. 関数名をfunction1からSomeVariable1に変更したが、容易に変更できないサードパーティのコードがあるため、エイリアスを宣言するワンライナーとして使っている。*3

*1:J言語か?

*2:この文はよくわからなかった

*3:質問者によれば今回は2つ目の理由だったようだ