LoginSignup
2
2

More than 5 years have passed since last update.

pruntプラグインの書き方

Posted at

この記事を読んで分かること

  • pruntプラグインのデザインコンセプト
  • pruntプラグインの書き方
  • Cakeや他のCLIとのコラボ

pruntのデザインコンセプト

pruntプラグインは

  • a) 配列を捌く関数、または
  • b) (a) を返すファクトリー

である。

pruntプラグインの書き方

例えば .coffee だけを戻すフィルターを書きます。

prunt.read('src/*')
  .then(coffeeFilter) # <== これをかきます
  .then(compileCoffee)

パターン(a): 配列を捌く関数

path = require 'path'

coffeeFilter = (files) ->
  # files = [file1, file2, file3... ]
  files.filter (file) ->
    path.extname(file.filename) is '.coffee'

これを拡大してどんな拡張子にも対応できる様にしますと

パターン(b): (a) を返すファクトリー

path = require 'path'

filter = (extension) ->
  (files) ->
    files.filter (file) ->
      path.extname(file.filename) is extension

使用例

coffeeFilter = filter '.coffee'

prunt.read('src/*')
  .then(coffeeFilter) # <== これをかきます
  .then(compileCoffee)

pruntプラグインの書き方 +α

以上のサンプルで分かる様にpruntではファイルクラスを使ってファイルを抽象化しています。

ファイルクラス

一つのファイル(正しくはファイルインスタンス)にはfilenamedirnamecontentisDirtyと四つのプロパティが有ります。isDirtyはファイルがディスクと同期されているかを表すバイナリフラッグで、コンテンツを変更すれば自動的に旗が立ち上がります。その他は説明する必要が有りませんので省略させて戴きます。

prunt.read('src/*.coffee')
  .then (files) ->
    files.forEach (file) ->
      file.isDirty is true # false
      file.content = 'foo'
      file.isDirty is true # true
    return files

又、ファイルにはfile.rename()file.chdir()、二つのメソッドを持っており、使う必要性は全く無いが、お役に立てれば嬉しい限りです。

非同期処理

ではlessコンパイラを書きましょう。lessコンパイラはコールバックで結果を返してくれます。

less = require 'less'
less.render file.content, (result) ->
  file.content = result

ではQ.jsを使ってpromiseを生成しましょう。

Q = require 'q'

exports.less = (options = {}) ->
  (files) ->
    queue = files.map (file) ->
      Q.nfcall(less.render, file.content) # <= returns a promise
        .then (css) ->
          # promise ですから結果をいじるのも簡単です。
          file.content = css
          file.rename file.filename.replace '.less', '.css'
    return Q.all(queue)

promiseを使っているだけに非同期処理は簡単です、その簡単さが売りです

Cakeや他のCLIとのコラボ

以下の三つだけ紹介させて戴きます。

  • Cake
  • Optimist
  • Commander

Cake

cakeはcoffee-scriptと共にインストールされるビルドツールです。CakefileMakefileのcoffee版です。

Cakefile
{read} = prunt = require './index'

option '-o', '--output [DIR]', 'directory for compiled code'

task 'build', 'build prunt', (options) ->

  concat = prunt.concat {filename: 'index.coffee', dirname: options.output}
  coffee = prunt.coffee() # use default options
  write = prunt.write() # use default options

  read('src/*.coffee')
    .then(concat)
    .then(coffee)
    .done(write)

cakeを実行するとタスクとオプションが表示されます。

$ cake
Cakefile defines the following tasks:

cake build                # build prunt

  -o, --output       directory for compiled code

substack/node-optimist

browserifyの中の人が作ったライブラリです

build.js
#!/usr/bin/env node
var argv, coffee, concat, write;

argv = require('optimist')
  .usage('prunt build tool.\nUsage: $0')
  .demand('b')
  .alias('b', 'build')
  .describe('b', 'build prunt')
  .argv;

prunt = require('./index');

if (argv.build) {

  concat = prunt.concat({
    filename: 'index.coffee',
    dirname: '.'
  });

  coffee = prunt.coffee();
  write = prunt.write();

  read('src/*.coffee')
    .then(concat)
    .then(coffee)
    .done(write);
}

実行するとこうなります。

$ chmod +x build.js
$ build.js
prunt build tool.
Usage: node ./test.js

Options:
  -b, --build  build prunt  [required]

Missing required arguments: b

visionmedia/commander.js

expressとmochaの中の人が作ったライブラリです

build.js
#!/usr/bin/env node
var coffee, concat, program, prunt, write;

program = require('commander')
  .version('0.1.1')
  .option('-b, --build', 'build prunt')
  .parse(process.argv);

prunt = require('prunt');

if (program.build) {
  concat = prunt.concat({
    filename: 'index.coffee',
    dirname: '.'
  });
  coffee = prunt.coffee();
  write = prunt.write();
  read('src/*.coffee')
    .then(concat)
    .then(coffee)
    .done(write);
}

実行するとこうなります。

$ chmod +x build.js
$ build.js --help

  Usage: test.js [options]

  Options:

    -h, --help     output usage information
    -V, --version  output the version number
    -b, --build    build prunt
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2