共通処理の呼び出しとは?
- マクロからもjScript側からも処理を別ファイルから呼び出す機構が用意されていない
- 配列でmapやforEachで書きたいけど、毎回ポリフィル書くの面倒
- 似たような処理をコピペで持っていくのも面倒。
注意事項
- evalを使ってグローバル関数を読み込むだけのものなのであまり良いものでもない。
- とはいえ無いよりはあった方が楽にはなるので、マクロユーザにとってはメリットはあるはず。
やりかた
cookie.jsの用意
- サクラエディタマクロのクッキー機能を用いて、暗黙的なimport/exportを実現する
- 必ず、confフォルダの配下に作成してください。
conf/cookie.js
var readAll = function(filePath,charset){
var adTypeText = 2;
var adReadAll = -1; //全行モード
var adCRLF = -1;
var stream = new ActiveXObject("ADODB.Stream");
stream.type = adTypeText;
stream.charset = charset || 'Shift-jis';
stream.LineSeparator = adCRLF;
stream.open();
stream.loadFromFile(filePath);
try{
var text = stream.readText(adReadAll);
}finally{
stream.close();
}
return text;
}
function saveData(keyId,data){
var result = Editor.SetCookie("document",keyId,data);
if(result != 0){
throw new Error("set cookie Error!! result=" + result);
}
}
/*
* マクロのホームディレクトリを取得する
* このマクロの配置している1階層上を取得しiniファイルに書き出す。
*/
function loadMacroHomeDir(){
var path = Editor.ExpandParameter("$M").split("\\conf\\cookie.js").join("")
//cookieの保存
Editor.setCookie("document","szMACROFOLDER",path)
return path
}
(function(){
//マクロホームフォルダの取得
var szMACROFOLDER = loadMacroHomeDir();
// load用モジュール
saveData("module",readAll(szMACROFOLDER + "/conf/module.js"));
// 共通関数モジュール・・・ここにパスを書けば関数の追加が可能
saveData("util",szMACROFOLDER + "/common/util.js");
})();
module.jsの用意
- Cookieに読み込んだファイル情報やパスを元に読み込み処理を実現する。
- module.load('util')等で、呼び出しができる。
- パスの構成上、confフォルダ配下に作成してください。
conf/module.js
(function(){
module = {}
var adTypeText = 2;
var adReadAll = -1; //全行モード
var adReadLine = -2; //行単位モード
var adCRLF = -1;
module.load = function(keyId){
var filePath = Editor.GetCookie("document",keyId);
if(!filePath){
throw new Error("failed to load module!![" + keyId + "]");
}
eval(module.readAll(filePath));
}
/**
* 全行取得
* KB単位のファイルに使用。
**/
module.readAll = function(filePath,charset){
var stream = new ActiveXObject("ADODB.Stream");
stream.type = adTypeText;
stream.charset = charset || 'Shift-jis';
stream.LineSeparator = adCRLF;
stream.open();
stream.loadFromFile(filePath);
try{
var text = stream.readText(adReadAll);
}finally{
stream.close();
}
return text;
}
/**
* 行単位に取得
* 大容量でも処理可能
*/
module.readLines = function(filePath,charset,callBack) {
var stream = new ActiveXObject("ADODB.Stream");
stream.type = adTypeText;
stream.charset = charset || 'Shift-jis';
stream.open();
stream.LineSeparator = adCRLF;
stream.loadFromFile(filePath);
try{
var count = 1; // 行番号
while (!stream.EOS) {
callBack(stream.readText(adReadLine),count++);
}
}finally{
stream.close();
}
}
})();
呼び出される共通処理の定義
- パスの構成上、common配下に作成してください。
common/util.js
(function(){
var splitValue = "\t"
util = {}
util.topUpper = function(value){
var head = value.substring(0,1).toUpperCase();
var body = value.substring(1,value.length);
return head + body;
}
util.topLower = function(value){
var head = value.substring(0,1).toLowerCase();
var body = value.substring(1,value.length);
return head + body;
}
//単語単位のコブ文字を生成
var humpType = function(value,key){
var arrayParam = value.split(key);
var strResult = "";
for (var i = 0; i < arrayParam.length; i++){
var head = arrayParam[i].substring(0, 1).toUpperCase()
var inner = arrayParam[i].substring(1, (arrayParam[i].length)).toLowerCase();
strResult += head + inner;
}
return strResult;
}
util.isSnake = function(value){
if(!util.isSplit(value)){
return false;
}
return value.indexOf("_") >= 0;
}
util.isKebab = function(value){
if(!util.isSplit(value)){
return false;
}
return value.indexOf("-") >= 0;
}
util.isSplit = function(value){
if(value.indexOf(splitValue) >= 0){
return false;
}
return true;
}
util.isHump = function(value){
if(!util.isSplit(value)){
return false;
}
//大文字小文字が混在しているか
return value.toUpperCase () != value && value.toLowerCase();
}
var humpCalc = function(value_,func){
var value = value_;
var snake = util.isSnake(value);
var kebab = util.isKebab(value)
if(snake || kebab){
if(snake){
value = humpType(value,"_");
}
if(kebab){
value = humpType(value,"-");
}
} else {
value = util.isHump(value) ? value : func(value.toLowerCase());
}
value = func(value)
return value
}
var splitCalc = function(value,callBack){
var list = value.split(splitValue);
var result = [];
for(var i=0;i < list.length;i++){
// result.push(humpCalc(list[i],func));
result.push(callBack(list[i]));
}
return result.join(splitValue);
}
util.camel = function(value){
return splitCalc(value,function(value){
return humpCalc(value,util.topLower);
});
}
util.pascal = function(value){
return splitCalc(value,function(value_){
return humpCalc(value_,util.topUpper);
});
}
util.snake = function(value){
return splitCalc(value,function(value_){
if(util.isSnake(value_)){
return value_.toLowerCase()
}else if(util.isKebab(value_)){
return value.split("-").join("_").toLowerCase();
}else{
var tmpStr = value_.substring(0, 1) + value_.substring(1).replace(/([A-Z])/g, "_$1");
return tmpStr.toLowerCase(); // 一旦小文字化してしまう
}
});
}
util.setter = function(value){
return splitCalc(value,function(value_){
return "set" + util.pascal(value_);
});
}
util.getter = function(value){
return splitCalc(value,function(value_){
return "get" + util.pascal(value_);
});
}
util.convertMember = function(value){
var obj = {};
obj.camel = util.camel(value);
obj.pascal = util.pascal(value);
obj.snake = util.snake(value);
obj.set = util.setter(value);
obj.get = util.getter(value);
return obj;
}
util.template = function(obj){
if(!(obj instanceof Function)){
return null;
}
var list = obj.toString().split("\r\n");
list.pop();
list.shift();
return list.join("\r\n")
}
util.maxLineCount = function(){
return Editor.GetLineCount(0) + 1;
}
util.loopC = function(callBack){
var maxCount = util.maxLineCount();
var results = [];
for(var i=1;i < maxCount;i++){
var origin = Editor.GetLineStr(i);
var strLine = origin.split(/[\r\n]/g).join('')
var value = callBack(strLine,i,origin);
if(value === false){
break;
}
results.push(value);
}
return results;
}
util.loop = function(callBack){
var maxCount = util.maxLineCount();
var results = [];
for(var i=1;i < maxCount;i++){
var origin = Editor.GetLineStr(i);
var strLine = origin.split(/[\r\n]/g).join('')
var value = callBack(strLine,i,origin)
results.push(value);
}
return results
}
puts = function(value){
Editor.TraceOut(value);
//常に表示
Editor.ActivateWinOutput();
}
echo = function(value){
Editor.TraceOut(value,0x02);
//常に表示
Editor.ActivateWinOutput();
}
})();
Cookie.jsの設定
- 今回のキモとなる部分で、設定しだいではうまく動かない。
- Cookie.js自体は自動実行機能を用いて実行される。
- 実行された結果、Cookieに必要な情報を格納しておく。
- 各マクロを実行時にそのCookieを参照して実行する流れ。
実際に実行する
hoge.js
eval(Editor.GetCookie("document","module"))
module.load("util");
// sample code
var list = util.loopC(function(value,index,original){
return value;
});
puts(list);
実行結果
json2.jsを試す。
- jScriptだけだと、JSONのparseやstringfyが出来ません。(IE上は出来たか忘れた)
- よって、JSONのポリフィルのjson2.jsを入れることで、JSONの操作が可能となります。
jsを任意フォルダに配置する
conf/cookie.js 抜粋
(function(){
//マクロホームフォルダの取得
var szMACROFOLDER = loadMacroHomeDir();
// load用モジュール
saveData("module",readAll(szMACROFOLDER + "/conf/module.js"));
// 共通関数モジュール・・・ここにパスを書けば関数の追加が可能
saveData("util",szMACROFOLDER + "/common/util.js");
// 以下を追加
saveData("util",szMACROFOLDER + "/common/json2.js"); // pathは配置したパスに設定してください
})();
hoge.jsを修正
hoge.js
eval(Editor.GetCookie("document","module"))
module.load("util");
module.load("JSON"); // loadを追加
// sample code
var list = util.loopC(function(value,index,original){
return value;
});
var str = JSON.stringify(list,null,3)
puts(str);
var ary = JSON.parse(str);
puts(ary);