Automatorをかなりつかったりするようになった

それとこのまえのG*なとこでもお話したのですがAutomatorでGroovyをつかったりするようになりました.これはシェルからGroovyスクリプトをうごかすんじゃなくてAutomatorに組み込むっていう方式のことです.つかGroovyだけじゃなくてウラではiconvとかrubyもつかったりしてるわけなので正確にはAutomatorを使うようになったというほうがいいでしょう.

スクショを見ていただければ分かるのですが11インチのせまい画面のデスクトップを使うってのはなかなか大変なので,iPhoneのホーム画面ととらえることによって「やりたいこと」をデカいアイコンにまとめてしまおう的な発想です.そのためにAutomatorをつかってますって話.たとえば社内のsambaサーバを全部まとめて一気にマウントしたり,作業用のテンポラリなフォルダを無ければつくってFinderで開いたり,そのフォルダを週ごとにzipしてwebDAVに保管したり,limechattwitterみたりAIMつかったりするためのゲートウェイを起動したりとか.Automatorでポスト専用のtwitterクライアントもつくったりした.

macだと特殊なファイルエンコーディングなのでそのままGroovyをうごくかせるかっていうと,そうではないのでこのあたりの話をフォローアップとして書こうかなと思ってたけど未だできてません.時間を見てじぶんの備忘録の意味でも早々に書きたいとおもいます.

あと夜のライブコーディングもぼちぼち再開できればいいかなーと.

仕事用のケータイがGalaxy Tabになった

田舎と都会をいったりきたりするなかでどうしても持ち運びのことを考えてしまい,11インチのmacbook airに移行しました.それほど濃くないことであれば(DTP寄りのこと以外)MBAでやっちまう方向に.なので作業環境が13インチから11インチにダウンサイジングしたのにもかかわらずケータイ電話は巨大化したわけですね.

ここからいちばん近い来来亭はどこだと琵琶湖湖畔で佇むおれ*1


import processing.core.*
import javax.swing.JFrame

class App extends PApplet{
  PImage img
  Integer px
  Integer py

  void setup(){
    size(342,367)
    img = loadImage("ore.jpg")
    offset = 0
    px = 4
    py = px*2
  }

  void draw(){
    disp()
  }

  def disp = {
    def mp = this.&triangle
    (0..width).step(px){w->
      (0..height).step(py){h->
        def pos = w+h*img.width
        noStroke()
        fill(img.pixels[pos])
        if(w%py==0){
          //triangle(w-px as Float, h as Float, w as Float, h+py as Float, w+px as Float, h as Float)
	  mp.call([w-px, h, w, h+py, w+px, h]*.toFloat())
        }else{
	  //triangle(w-px as Float, h+py as Float, w as Float, h as Float, w+px as Float, h+py as Float)
	  mp.call([w-px, h+py, w, h, w+px, h+py]*.toFloat())
        }
      }
    }
  }	
}

app = new App()
app.init()
jframe = new JFrame(title:"hello",resizable:true).with{
	add(app)
	pack()
	defaultCloseOperation = JFrame.EXIT_ON_CLOSE
	resizable = true
	visible = true
}

こんど出るgroovy1.8beta3からクロージャのメモ化ができるみたいで「うわー」とか思って.とりあえずってことで1.8beta2試してます.ちなみにメモ化については以前の記事のなかでガチでやってますがこれが標準でついてくるってホントになにを考えてるんでしょう(もつのろん最大の賛辞です)

いまさらだけどメソッドポインタ(this.&triangleてやつ).すでに1.7系でcurryがおもろいかんじになっていたり,1.8から関数合成できたりするのでメソッドポインタ(じぶんのイメージだとメソッドのクロージャ化)がこれからかなり変態的に使うことができるようになるんじゃ… という期待をしております

引数をとるものは配列もとってくれないとご機嫌ナナメになる派であり,いままでas Floatを書くのメンドーだったしcollectのショートハンド(て認識でいいのかな)の*を併用して こんなんでもいけそうね的なかんじで.わかりやすいコードかどうかは別として個人的には書いたあとにスッキリ感がありました

*1:ちなみにyoupyさんTきてるみたいですね

3Dなgroovysh

珍幹線コーディングの成果物.3DなgroovyshをつくってQuickTime Player7をうごかしてます

QuickTime Player 7 vs Groovy from nbqx on Vimeo.

QuickTime Player7はいろいろいじくるところがあるので,もうちょっとがんばってみる予定です.もつのろん珍幹線でー



import processing.core.*
import javax.swing.JFrame

class Zutazuta extends PApplet{
  PImage pic
  Integer mod = 10

  void setup(){
    size(480,640)
    colorMode(RGB)
    pic = loadImage("pic.jpg")
    noLoop()
  }
	
  void draw(){
    def dv = height / mod
    for(int k=1; k<=mod; k++){
      def noiz = Math.floor(random(0,mod))
      for(int i=0; i<width; i++){
        for(int j=dv*k-dv; j<dv*k; j++){
	  Integer y = j-(dv*k-dv) + dv*noiz
	  Integer pos = y*width+i
	  set(i,j,pic.pixels[pos])
	}
      }
    }
  }
}

app = new Zutazuta()
app.init()
jframe = new JFrame(title:"Zuta-Zuta",resizable:true).with{
  add(app)
  pack()
  defaultCloseOperation = JFrame.EXIT_ON_CLOSE
  resizable = true
  visible = true
}

この体勢からグリッチ


ExtendScript Isolator (ただしコンセプトデザイン)

たとえばJavascriptでCSアプリのなにかしら処理を書く場合.「こういうデータがあって,こういうふう(みための変更だったりテキスト出力ファイルだったり)にしたい」というインプットとアウトプットがあるわけです.実際の処理をかくときはこのインプットからアウトプットまでの道程をコードという断片でつないであげるということになるんだとおもいます.つまりスクリプト処理ってものは小さなスクリプト処理のあつまりととらえられるといえるかもしれません.

唐突なのですが以下の動画をまずは.

ミキサー(したの段にあるUREIとかいてあるもの)とアイソレータ(うえの段に鎮座する3つのツマミがついてるやつ)をいじくってる動画なんですが,"High", "Mid", "Bass"のそれぞれのツマミをいじくると特定の音域が無くなったり強調されたりしちゃってますよね.

あんまり詳しいことをかくとなんの記事だかわからなくなっちゃうので省略しますが,アイソレータは「音域を分離するもの」と考えていただければいいかとおもいます.つまり「高い音」「まんなかの音」「低い音」の3つにわけて,それを個別にあつかえるものです.

(ちなみにイコライザってものもあるのですが,もともと音色って幅広い周波数の波形をもっているので,それを個別に調整するってものです.アイソレータはその特定音域の逆位相の波形を使って打ち消したり・もちあげたりするので根本的な仕組みが異なります)

前おきが長かったんですが,今回のおはなしではこの「分離する」ってのがキーです.

つまりスクリプト処理そのものを小さなスクリプト処理ごとに分離して書けるようにしてしまおうというおはなしです.まずはInDesign向けのこんなソースをば.

sample1.jsx

//step1
"組版単位とかマージン・段組などのアプリケーションの初期設定をする"

//step2
"ドキュメントがなければ新規で作成,開いているドキュメントがあればそれを処理の対象にする"

//step3
"対象になるドキュメントのページ数を表示する"

jsxとありますがテキストが書いてあるだけです.これが分離された状態.このファイルをつぎのように書きかえまっせ.

sample2.jsx

#target InDesign
#include "/path/to/isolator.jsx"

//step1
"組版単位とかマージン・段組などのアプリケーションの初期設定をする".define("/path/to/初期設定.jsx");

//step2
"ドキュメントがなければ新規で作成,開いているドキュメントがあればそれを処理の対象にする".define(function(){
	var doc;
	return doc
});

//step3
"対象になるドキュメントのページ数を表示する".define(function(doc){
	alert(doc.pages.length+"ページあるよ");
});

EasyScript.execScript();

おや? なにかがヘンですね.で,気にせずこんなかんじにします.

sample3.jsx

#target InDesign
#include "/path/to/isolator.jsx"

//step1
"組版単位とかマージン・段組などのアプリケーションの初期設定をする".define("/path/to/初期設定.jsx");

//step2
"ドキュメントがなければ新規で作成,開いているドキュメントがあればそれを処理の対象にする".define(function(){
	var doc;
	if(app.documents.length==0){
		doc = app.documents.add();
		alert("新規ドキュメントを追加したよ")
	}else{
		doc = app.activeDocument;
		alert("いま開いているドキュメントを対象にするよ");
	}
	return doc
});

//step3
"対象になるドキュメントのページ数を表示する".define(function(doc){
	alert(doc.pages.length+"ページあるよ");
});

EasyScript.execScript();

しれっとisolator.jsxをincludeすると,こんな具合にかけますよ.sample1.jsxの段階のものを実際にはスクリプトがかけないオペレータさんから「こんなことやりたいな」とこんなかんじでもらえればそれを埋めながらスクリプトをかいていけます.しかも小さい処理の内容はコメントじゃなくてテキストそのまま.おーDSLじゃん!! defineの引数にはコードをそのまま書いたり,外部ファイルを指定したりもできるように.

分離できるとはいうけれど,分離する基準は様々です.難易度であったり使いまわしするってのが基準だったり.つかい方いろいろな「めんつゆ」状態ですね.

こんな邪悪なことができるislator.jsxのソースは以下です.

//Extend Script Isolator
//すこしだけDSLっぽくindesign javascriptをかけるようにする

EasyScript = {};
var FUNCS = this.FUNCS = {};

//コメント兼関数名を定義するのに
String.prototype.define = function(fn){
	var name = this;
	if(fn instanceof Function){
		FUNCS[name] = fn;
	}
	//Functionオブジェクトじゃなければファイルパスとして扱う
	else{
		var file = new File(fn);
		if(file.open("r")){
			try{
				var c = file.read();
				FUNCS[name] = eval("("+c+")");
				file.close();
			}catch(e){alert(e);alert("'"+name+"'は実行エラーっぽいから無視したよ")}
		}else{alert("'"+name+"'はファイルを読み込めなかったぽいから無視したよ");}}};

//定義されたすべての関数を実行
EasyScript.execScript = function(arg){
	var p = null;
	if(arg!=null) p = arg;
	for(var k in FUNCS){
		if(p!=null){
			p = FUNCS[k](p);}
		else{
			p = FUNCS[k]();}}};

//defineした関数の中でつかうことで途中でとめることができるよ
EasyScript.interrupt = function(){
	alert("EasyScript: 中断しました");
	exit();}

どちらかというと「ざっくりとスクリプト処理のプロトタイプをつくりたい」みたいなときにつかえたりするかもしれません.じぶんはそうしてます.

あともっと重要なのはこれがDTPスクリプティングアジャイル開発へのヒントになるかもってことです.つかいまわしできるものはモジュールに,DTPDRY原則でいきまっしょいというアイデアの出発点だとおもっております.