Firefox AddonであるVimperatorの解説(主に開発視点)

FrontPage > プラグイン開発 > addUserCommand_for2.0pre


コマンド登録方法

以下の関数でコマンド登録が可能
liberator.modules.commands.addUserCommand
commands.addUserCommand
または
liberator.modules.commands.add
commands.add
addメソッドはVimperator自身が使用するメソッドである。また、addメソッドの場合第5引数がなく、既に存在するコマンドの置き換えは不可能である。

addUserCommandの全体の構造

commands.addUseCommand(
  ["he[llo]","h"],  // コマンド名
  "description",     // コマンドの説明
  function(args, bang, count) {... },  // コマンド本体の処理(functionオブジェクト)
  {  /* extras */
    completer : function (context, args) {  // 補完関数
   context.anchor = false;     // (省略可)
      context.ignoreCase = true;  // (省略可)
      context.title = ["url", "title"];
      context.completions = [
        ["候補1URL", "候補タイトル1"],
        ["候補2URL", "候補タイトル2"],
      ];
    },
    options : [
     [["-optionA", "-a"], 
      OPTION_ANY,  
      function(arg) {... },      // オプション値の正当性をチェックする関数?
      function(context) {... },  // 
     ]],
    argCount: "*",       // "0"|"1"|"+"|"?"|"*"
    hereDoc: false,      // ヒアドキュメントとして受け取るか
    bang: false,         // !を許可するか
    count: false,        // 回数指定で実行可能か
    literal: false       // リテラルとして扱うか
  },
  replace               // 既存のコマンドを置き換えるかどうか
);

引数

  1. names(Array):コマンド名となる文字列の配列
  2. description(String):コマンドの簡易説明
  3. action(Function):実行されるfunctionオブジェクト
  4. extra(Object):補完機能やコマンド引数などを格納するオブジェクト(オプション)
  5. replace(Boolean):既に存在するコマンドの場合、置き換えるか否か(オプション)
names
以下の様なコマンドを登録するとhelloworld,hello,hwの3つのコマンド名で実行可能になる。
commands.addUserCommand(
    ["hello[world]","hw"],
    "print hello world",
    function(){
        liberator.echo("Hello World");
    }
);
コマンド名となる文字列の後部を[]で囲むと省略可能とされてhelloworld,helloの2つに展開される。
["[hello]world"]["hello[worl]d"]のようなものは無効。
description
概要を説明する文。コマンド補完時に使用される程度。
action
実際のコマンドの動作を受け持つfunctionオブジェクト。
以下の引数を受け取ることが出来る
  1. コマンド引数をliberator.modules.commands.parseArgsでパースした結果(オブジェクト)
  2. コマンド後部!の有無を示す真偽値
  3. コマンド頭部のある数値
version1.2preまでと異なり、第一引数に渡るコマンド引数はextraオブジェクトのoptionsargCountなどの内容によって変化し、パースされた結果(object)となるので注意
extra
どれもオプションであるので無くても構わないが、気の利いたコマンドを作ろうとしたらextraオブジェクトの理解は必須となるだろう。
extraオブジェクトには以下のメンバーを持たせると意味がある。
completer
タブ補完時に実行され、補完値を返すfunctionオブジェクト
options
コマンド引数をパースするときに用いられる配列
argCount
コマンド引数の数を定義する文字列
hereDoc
ヒアドキュメントで引数を渡せるかどうかの真偽値
bang
コマンドが"!"を使用するかどうかの真偽値
count
コマンドがrange(コマンド先頭の数値)を使うかどうかの真偽値
literal
コマンドがargCountより多い引数を必要とするかどうかの真偽値
replace
既にそのコマンドが存在しているときに上書きするか否かの真偽値。
通常は特に必要ないだろう。

completer

コマンド引数の補完機能を受け持つ関数(functionオブジェクト)を定義する。

ルール

与えられる引数、返すべき値にはルールがある。
与えられる引数
  1. context(Object)
  2. args(Array)
    • args.bang には(!の有無)(Boolean)
    • args[オプション名] にオプションの値
    • 各配列データに引数
補完タイトルの設定
第一引数のcontext にあるcontext.title
contenxt.title = ["名前"];
もしくは
context.title = ["名前","概要"];
の様に代入する。
補完リストの設定
第一引数のcontextにあるcontext.completions
context.completions = [
  ["候補値_1(String)","候補値_1の説明(String)"],
  ["候補値_2(String)","候補値_2の説明(String)"],
];
の様に代入する。

completer: function(context, arg){
  context.title = ["exampleplugin"];
  let allSuggestions = [
    ["foo","foo description"],
    ["bar","bar description"],
    ["hoge","hoge description"]
  ];
  context.completions = allSuggestions;
},
Vimperator内部で自動的にフィルタリングしてくれるので、特にこちらでフィルタする必要はない。

補完の大文字/小文字

context.completionsに代入する前に、context.ignoreCaseに真偽値を入れることで大文字/小文字の区別の制御が可能である。
trueを代入することでbAとしてもbarと補完することが可能になる。
デフォルトではcontext.ignoreCasefalseになっている。また、ユーザがwildcaseignoreに設定することでも可能。
completer: function(context, args){
	context.ignoreCase = true; //大文字/小文字の区別をなくす
	context.completions = [
		["bar","bar desc"],
		//...
	];
},

途中からも補完

通常、fooを補完したい場合、先頭から入力してタブ補完する必要がある。ooからは補完できない。これを制御するのが、context.anchoredだ。
デフォルトではtrueになっていて、最初からマッチしないと補完できない。falseを代入することで、補完対象に含まれていればリストに載るようにできる。
completer: function(context, args){
	context.anchored = false;
	context.completions = [
		// ...
	];
}

コマンド引数のパース

options

コマンド引数の解析時に用いられる。指定するとaction関数の第一引数が解析された結果となるので注意
パースされた結果、第一引数は文字列(String)ではなく、メンバーに
  • arguments: optionsで解析されなかった文字列の配列
  • optionsで解析されたオプション名とその値
を持つObjectとなる。
bmarkコマンドの例
言葉で説明しても分かり難い。実際にbmarkコマンドの例を見たほうが早かろう。
bmarkコマンドはブックマークするURLとタイトルやタグ、キーワードのオプションを指定することができる。
:bmark http://example.com/ -title Example -T example,Tag -k keyword
とすると解析された結果は
args = ["http://example.com"];
args["-title"] = "Example";
args["-tags"] = ["example","Tag"];
args["-keyword"] = "keyword";
となる。bmarkコマンドのoptionsの定義は以下の様になっている。
options: [
  [["-title",   "-t"], commands.OPTION_STRING],
  [["-tags",    "-T"], commands.OPTION_LIST],
  [["-keyword", "-k"], commands.OPTION_STRING, function(arg) { return /\w/.test(arg); }]
],
ソースコードに載せられている説明
細かい説明は省略。ソースコードに書かれている説明を載せておく
@param str: something like "-x=foo -opt=bar arg1 arg2"
"options" is an array [name, type, validator, completions] and could look like:
options = [[["-force"], OPTION_NOARG],
          [["-fullscreen", "-f"], OPTION_BOOL],
          [["-language"], OPTION_STRING, validateFunc, ["perl", "ruby"]],
          [["-speed"], OPTION_INT],
          [["-acceleration"], OPTION_FLOAT],
          [["-accessories"], OPTION_LIST, null, ["foo", "bar"]],
          [["-other"], OPTION_ANY]];
オプション・タイプ
2番目の要素に指定するタイプ
OPTION_ANY
何でもOK。オプション値に文字列があればオプションの値になるし、無ければnullとなる
OPTION_NOARG
オプション値が指定されないことを期待するタイプ。解析結果のメンバーに入るが値はtrue
OPTION_BOOL
オプション値にon/offを期待し、値は真偽値となる。別の値の場合はNaNになる
OPTION_STRING
オプション値に任意の文字列を期待する
OPTION_INT
オプション値が数値であることを期待する(小数点を入れても無視される)
OPTION_FLOAT
オプション値が数値であることを期待する(OPTION_INTと違い、小数点OK)
OPTION_LIST
オプション値が","区切りのリストであることを期待すし、値は配列となる

argCount

コマンド引数解析時に用いられ、action関数の第一引数が解析された結果となるので注意
おそらくoptionsと共に用いられることになるだろう。コマンド引数解析でオプションとみなされずargumentsに入る値の数を定義するメンバーである。
指定すると意味のある値
"0"
arguments無し
"1"
argumentsの数がきっちりと1つ
"+"
argumentsの数が1個以上
"*"
argumentsの数が0個以上
"?"
argumentsの数が0固か1個

hereDoc

コマンド引数をヒアドキュメントで与えることが可能かどうかの真偽値。trueに設定すると
:command <<EOM
foo bar
hoge
EOM
とすることが可能になる。

bang

コマンドがbang(!)を使えるかどうかの真偽値。trueにしないと、実行時に!を付けるとエラーとなり、E477: No ! allowedというメッセージが表示される

count

コマンドがrange(先頭に付ける数値)を使えるかどうかの真偽値。''true'にしないと、2commandNameなどと実行した場合にエラーとなり、E481 No range allowedというメッセージが表示される

literal

argCountと一緒に用いられ、argCount数以降の引数を格納するかどうかの真偽値。trueにしないと、argCountが2で引数を3つ以上つけるとパースエラーとなってしまう。
autocmdコマンドの様に3つの引数を必要とするが2つ目までは固定的で3つ目からは一つの文字列として扱いたいときなどに有効(autocmdの場合はargCount: "2",literal: true となっている)

actionに渡る第一引数について

コマンドに第一引数に渡るコマンド引数はversion 1.2preまでと異なり必ずliberator.modules.commands.parseArgsでパースされる様になり、結果objectとして渡されるので少々複雑になった。
ここではその解説。

パースされて返るオブジェクトを以降argsとする。

argsオブジェクトのメンバ

argsオブジェクトはArrayである。0,1,2,,,に通常の引数が入るが、他に以下のメンバを持つ。
literalArg(String)
argCountに収まらない以降の引数の文字列(literal:trueの場合)
string(String)
引数全体の文字列
その他
optionsで与えたオプション名の第一要素をメンバ名として、String,Number,Arrayが入る

引用符

シェルと同じく引用符で括ると、引用符で閉じられるまでを一つの引数として扱ってくれる。
ダブルコートとシングルコートとでエスケープ文字(\)の扱いが異なり、挙動が変わることがあるので注意(注意するのはコマンド使用者だが)

tips

:echoコマンドを用いて開発時にはいろいろ試してみると良いだろう。
:echo commands.parseArgs("-a -s on foo1 foo2", [[["-all","-a"],commands.OPTION_NOARG],[["-switch","-s"],commands.OPTION_BOOL]], "*")
結果
args = ["foo1","foo2"];
args["-all"] = true;
args["-switch"] = true;
args.literalArg = "";
args.string = "-a hoge -s on";

このページへのコメント

bvlgari バッグ
bvlgari 時計 http://www.yxjcdp.com/

0
Posted by bvlgari 時計 2013年09月09日(月) 13:43:23 返信

Aw, this was a really nice post. In idea I want to put in writing like this additionally taking time and actual effort to make a very good article but what can I say I procrastinate alot and in no way seem to get one thing done. increase height http://www.deelsonheels.com/$2099_Dual_Air_Cushioned_Shoe_Lifts/p133745_317500.aspx

0
Posted by increase height 2013年05月25日(土) 00:02:58 返信

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Wiki内検索

メニューバー






どなたでも編集できます