スクリプトエディタ拡張プラグイン

きっかけはjunkiさんのツイッタ―での『XSIのJScriptでファイルパスを書くときにフォルダ区切りは \ ではなく \\ にするわけですが、どっかからコピペしたパス文字列の \ を \\ に書き換えていく過程が実に苦痛なのですが、楽にする良いアイデアはないでしょうか?』という呟き。
良いお題だったのもあり、ツイッタ―では大いに盛り上がったようです。
最終的に示されたのは

というもの。バッチファイルを作ってクリップボードにコピーする際に、変換しちゃおうというものですねー。
うむ。合理的。

自分は盛り上がってる時間帯を逃してしまい、やっちまった感満点だったのですが、自分なりのアプローチでなにか出来ないか探ってみました。
で、辿り着いたのがSoftimageのスクリプトエディタ用のコマンドを作るというもの。
よくよく考えてみたらDCCツール作業者を対象にしたプラグインは数多くあれど、ツール作成者を対象としたスクリプトエディタを拡張するコマンドって見たことないんですよね。
スクリプトエディタが操作できるのかどうかも最初は良く分からなかったので、どうやったらいいのか小一時間悩みましたがなんとか出来ました。

プラグインファイルをどこかにアップすればいいと思うんですが、いい場所が良く分からなかったのでコードそのまま貼り付けます。
(何処か共同でまとめられたら使う側としても便利じゃないかなー??とか思ったり…。)

function XSILoadPlugin( in_reg )
{
	in_reg.Author = "mochio" ;
	in_reg.Name = "ScriptEditor_ExpansionMenu Plug-in";
	in_reg.Major = 1;
	in_reg.Minor = 0 ;

	//***メニュー登録
	in_reg.RegisterMenu( siMenuScriptEditContextID , "ScriptEditor_ExpansionMenu" );
	//***コマンド登録
	in_reg.RegisterCommand("ScriptEditor_ChengePathString_Clipboard","ScriptEditor_ChengePathString_Clipboard");
	in_reg.RegisterCommand("ScriptEditor_ChengePathString_SelectedText","ScriptEditor_ChengePathString_SelectedText");

	return true;
}

function XSIUnloadPlugin( in_reg )
{
	Logmessage( in_reg.name + " has been unloaded." );
	return true;
}

//--------------------------------------------------------------------------
// 右クリックメニュー登録部分
//--------------------------------------------------------------------------
//ポップアップメニューの登録
function ScriptEditor_ExpansionMenu_Init( in_ctxt )
{
	var menu = in_ctxt.source;

	menu.name = "ExpansionMenu(JScript)";
	
	//共通メニュー
	menu.AddCommandItem("クリップボードの文字列の「\\」を「\\\\」として貼り付け","ScriptEditor_ChengePathString_Clipboard");
	menu.AddCommandItem("選択範囲を「\\」を「\\\\」に変換","ScriptEditor_ChengePathString_SelectedText");
}

//--------------------------------------------------------------------------
// コマンド
//--------------------------------------------------------------------------
function ScriptEditor_ChengePathString_SelectedText_Init( in_ctxt )
{
	var oCmd;
	oCmd = in_ctxt.Source;
	oCmd.Description = "";
	oCmd.ReturnValue = true;
	return true;
}

//選択範囲を変換
function ScriptEditor_ChengePathString_SelectedText_Execute(){
	var oSEditor = LF_GetScriptEditor();
	var sSelText = oSEditor.GetAttributeValue("selectedtext");
	LF_StringPaste(sSelText);
}

function ScriptEditor_ChengePathString_Clipboard_Init( in_ctxt )
{
	var oCmd;
	oCmd = in_ctxt.Source;
	oCmd.Description = "";
	oCmd.ReturnValue = true;
	return true;
}

//クリップボードから貼り付け
function ScriptEditor_ChengePathString_Clipboard_Execute(){

	// クリップボードに文字列を設定
	var jp;
	if (!jp) jp = {};
	if (!jp.raindrop) jp.raindrop = {};
	if (!jp.raindrop.frog) jp.raindrop.frog = {};
	jp.raindrop.frog.clipboard || (function ()
	    {
	        // コマンドのID
	        var OLECMDID_COPY = 12;
	        var OLECMDID_PASTE = 13;
	        var OLECMDID_SELECTALL = 17;

	        // IE の初期化
	        var _internetExplorer = new ActiveXObject ('InternetExplorer.Application');
	        _internetExplorer.navigate ("about:blank");
	        while (_internetExplorer.Busy)
	            WScript.Sleep (10);

	        // textarea 要素を作成する
	        var _textarea = _internetExplorer.document.createElement ("textarea");
	        _internetExplorer.document.body.appendChild (_textarea);
	        _textarea.focus ();

	        jp.raindrop.frog.clipboard = {
	            // クリップボードに文字列をコピー
	            setText: function (text)
	            {
	                _textarea.innerText = text;
	                _internetExplorer.execWB (OLECMDID_SELECTALL, 0);
	                _internetExplorer.execWB (OLECMDID_COPY, 0);
	            },

	            // クリップボードより文字列を取得
	            getText: function ()
	            {
	                _textarea.innerText = "";
	                _internetExplorer.execWB (OLECMDID_PASTE, 0);
	                return _textarea.innerText;
	            },

	            // IE を解放
	            release: function ()
	            {
	                _internetExplorer.Quit ();
	            }
	        };
	    }());

	//クリップボード内の文字列を取得
	var GetStg = jp.raindrop.frog.clipboard.getText();

	jp.Quit;//開放…できてんのか???
	jp = null;
	
	LF_StringPaste(GetStg);
}

//文字列を変換してスクリプトエディタに貼り付ける
function LF_StringPaste(in_Stg){
	in_Stg = in_Stg.replace(/\\(?!\\)/g , "\\\\");
	in_Stg = in_Stg.replace(/\\\\\\/g , "\\\\");//後読み対応してないので、\\\となってしった場合に\\に戻す
	var oSEditor =  LF_GetScriptEditor();
	oSEditor.SetAttributeValue("inserttext" , in_Stg);
}

//スクリプトエディタを取得する
function LF_GetScriptEditor(){
	var l = Desktop.ActiveLayout;
	for(var i = 0; i < l.Views.count; i++){
		if(l.Views(i).type == "Script Editor"){
			var oSEditor = l.Views(i);
			return l.Views(i);
		}
	}
}

適当にファイルにコピーしてプラグインとして読まれるところに放り込んで下さい。
スクリプトエディタ上で右クリックをすると、専用のメニューExpansionMenu(JScript)が追加されています。

今回用意したのは
クリップボード上にある文字列(ctrl+cとかでコピーしておいたパス)の\を\\に変換した状態で貼りつける、というコマンド

既にスクリプトエディタ上にある文字列の中の\を\\に変換する、というコマンド

の2つです。
2つ目の選択範囲の文字列を変更するものに関しては、複数行も問題なくいけます。
右クリックからコマンドを実行するのは多少手間なので、コマンドをショートカットに登録しておくとよいかもしれません。

さらに拡張すれば、標準のスクリプトエディタにはない「選択範囲の置換」「正規表現を使った置換」といった機能も追加できそうな予感です。
しかし、何でこういう標準的にあってもよさそうな物が搭載されてないかな…。
是非オートデスク様にはこう言ったところも改善していただきたいところですね。