EmEditorでGoogle IMEの再変換機能をマクロで自動化する方法はありますでしょうか？


EmEditorでGoogle IMEの再変換機能をマクロで自動化する方法はありますでしょうか？

お世話になっております。

Google IMEの再変換機能で1行ずつ自動で選択して再変換を繰り返すというマクロは可能でしょうか？

例文

「それに、たいしてまけるひとは、おおいので、  
まけのげんいんをぶんせきすることは、いみが、ある。  
ひとつひとつは、つまらないしっぱいでも、  
あつめるとほうそくせいが、みえてくる。  
にほんけいざいは、「ちょうきていたい」に、  
はいったといわれ、そのげんいんは、  
「せいさんせいがひくいからだ」とか  
「いのべーしょんがたりないからだ」といわれる。」

このような短い文章が延々と続きます。

1行全部選択→再変換確定→次の行に移動して1行全文選択→再変換確定→これを延々と繰り返す

このように変換しやすい短く区切ったひらがな文をあらかじめマクロで作っておき、自動で最初から最後まで再変換→確定を繰り返すという方法です。

一発では正確にならず誤変換もありましたが、正確さより一発で自動的に最後まで変換していけることを希望しています。

Google IMEで手動ではかなりうまくいきました。

よろしくお願いいたします。

それに、大して負ける人は、多いので、  
負けの原因を分析することは、意味が、ある。  
一つ一つは、つまらない失敗でも、  
集めると法則性が、見えてくる。  
日本経済は、「長期停滞」に、  
入ったと言われ、その原因は、  
「生産性が低い体」とか  
「イノベーションが足りないからだ」と言われる。」




変換エンジンを YahooAPI にして、変換ファイル名の変更と、文字数対策を追加してみました。

  * マクロ利用法  
・このマクロ本体は SJIS で保存。  
・アプリケーションIDを取得してソースリスト先頭の Appid に設定する。  
<https://e.developer.yahoo.co.jp/register>  
例: [Yahoo! ID連携 v1] アプリケーションの種類 クライアントサイド（Yahoo! ID連携 v1）, 利用者情報 個人, アプリケーション名
<適当に>, サイトURL <無記入>, アプリケーションの説明 <無記入>, ガイドライン <同意する>  
・目的のドキュメントを開いてマクロを実行する、変換終了時に自動で変換ファイルをオープンする。

  * 仕様、制限  
・Yahoo の仕様により一行の最大文字数は80文字(ひらがな換算時)まで  
かな漢字変換Web APIは、24時間以内で1つのアプリケーションIDにつき50000件のリクエストが上限
<https://developer.yahoo.co.jp/appendix/rate.html>  
・一行単位で変換、  
一行の文字数が多い場合 "。↓▽▼" で分割して、それを最大文字数以内に収まる範囲で連結して処理、  
それでも文字数が多い場合 "、, " で更に分割して、それを最大文字数以内に収まる範囲で連結して処理、  
それでも最大文字数を超える場合 EmEditorのアウトプットバーに行番号を出力。  
・出力はドキュメントのディレクトリにファイル名 "再変換済み +{ドキュメントのファイル名}" として第一候補の連結文字列(一発変換)を出力。  
・入出力は UTF-8

[code]

    #title "one-hit wonder"
    #tooltip "一括漢字変換"
    
    var Appid = ""; // *** Yahoo APPID ***
    var RequestWait = 200;      // リクエスト間隔制限
    var SizeLimit = 80;         // 変換文字数制限
    
    var flagOutputBar = OutputBar.Visible;
    var recCount = 0;   // リクエスト回数カウンター
    
    function putOutBar( num, mes ){
        OutputBar.Visible = true;
        OutputBar.writeln( num + ": " + mes );
        flagOutputBar = true;
    }
    
    // デベロッパーネットワークトップ > テキスト解析 > かな漢字変換
    // https://developer.yahoo.co.jp/webapi/jlp/jim/v1/conversion.html
    function yahooApi( str ){
        if( Appid == "" )   return "";
        recCount ++;
    //  return str + "||";          // DEBUG
        var rval = "";
        try {
            var uri = "https://jlp.yahooapis.jp/JIMService/V1/conversion";
            uri += "?appid=" + Appid;
            uri += "&sentence=" + encodeURIComponent( str );
    
            var xhr = new ActiveXObject("Msxml2.ServerXMLHTTP");
            xhr.open( "GET", uri, true );
            xhr.setRequestHeader( "User-Agent", "EmEditor " + editor.Version + "; Yahoo AppID " + Appid );
    //      xhr.setProxy( 2, "127.0.0.1:8080", "" );
            xhr.send();
            for( var rty = 1000; xhr.readyState != 4 && rty > 0; --rty ){ xhr.waitForResponse(100); }
            if( xhr.readyState == 4 ){
                if( xhr.status == 200 ){
                    var dom = new ActiveXObject("Msxml2.DOMDocument");
                    dom.async = false;
                    dom.loadXML( xhr.responseText );
                    var segs = dom.getElementsByTagName("Segment");
                    for( var i = 0; i < segs.length; i++ ) {
                        var para = segs[i].getElementsByTagName("Candidate");
                        rval += para[0].text;
                    }
                } else if( xhr.status == 403 ){
                    alert( "Web APIのリクエスト回数制限に到達、00:00にリセット" );
                    ravl = "\x08";
                }
            } else {
                xhr.abort();
                alert( "Error abort" );
                ravl = "\x08";
            }
        } catch (e) {
            alert( "Error( " + e.message + " )" );
            ravl = "\x08";
        }
        return rval;
    }
    
    // 簡易文節分割
    function splitSeg( rg, str ){   // rg = /^(.*?[。↓▽▼])(.+)$/,  /^(.*?[、　 ])(.+)$/
        var para = [];
        var wrk = str;
        var m;
        while( m = wrk.match( rg ) ){
            if( m[1] != "" ){ para.push( m[1] ); }
            wrk = m[2];
        }
        if( wrk != "" ){ para.push( wrk ); }
        return para;
    }
    
    // 変換処理本体
    function comv_main( strPath ){
        var fh = new ActiveXObject("ADODB.Stream");
        fh.Type = 2;
        fh.Charset = "UTF-8";
        fh.Open();
    
        document.selection.StartOfDocument();
        for( var yPos = 1; yPos <= document.GetLines(); ++ yPos ){
            document.selection.SetActivePoint( eePosLogical, 1, yPos ); // 実行状況が分かるようにカーソルを動かす。無くても良い。
            var str = document.GetLine( yPos );
            var m = str.match( /^(\s*)(.*?)(\s*)$/ );
    //      if( m != null && m[2] != "" ){
            if( m[2] != "" ){
                str = m[2];
    //          alert( str.length );
                if( str.length >= SizeLimit ){
                    var wrk = "";
    
                    var para2 = splitSeg( /^(.*?[。↓▽▼])(.+)$/, str );       // 分割文字 '。','↓','▽','▼'
                    var str3 = "";
                    for( var i = 0; i < para2.length; ++ i ){
                        str3 += para2[i];
                        if( i+1 < para2.length && str3.length + para2[i+1].length < SizeLimit ){ continue; }
    
                        if( str3.length >= SizeLimit ){
                            var para3 = splitSeg( /^(.*?[、　 ])(.+)$/, str3 );       // 分割文字 '、','　',' '
                            var wrk4 = "";
                            for( var j = 0; j < para3.length; ++ j ){
                                wrk4 += para3[j];
                                if( j+1 < para3.length && wrk4.length + para3[j+1].length < SizeLimit ){ continue; }
                                if( wrk4.length >= SizeLimit ){
                                    putOutBar( yPos, "SizeOver '" + wrk4 + "'" )
                                }
                                var yconv = yahooApi( wrk4 );
                                if( yconv == "\x08" ){ return; }    // Error
                                Sleep( RequestWait );
                                wrk4 = "";
                                wrk += yconv;
                            }
                        } else {
                            var yconv = yahooApi( str3 );
                            if( yconv == "\x08" ){ return; }    // Error
                            Sleep( RequestWait );
                            wrk += yconv;
                        }
                        str3 = "";
                    }
                    str = wrk;
                } else {
                    var yconv = yahooApi( str );
                    if( yconv == "\x08" ){ return; }    // Error
                    Sleep( RequestWait );
                    str = yconv;
                }
                fh.WriteText( m[1] + str + m[3], 1 );
            } else {
                fh.WriteText( "", 1 );
            }
        }
        fh.SaveToFile( strPath, 2 );
        fh.Close();
        return 0;
    }
    
    //////////////////////////////////////////////////////////////////////////////
    // MAIN
        var strPath = document.Path + "\\再変換済み　" + document.Name;
        OutputBar.Clear();
        OutputBar.Visible = true;
        var docReadOnly = document.ReadOnly;
        document.ReadOnly = true;
    
        comv_main( strPath );
    
        document.selection.StartOfDocument();
        document.ReadOnly = docReadOnly;
        OutputBar.writeln( "\n*** API リクエスト回数 : " + recCount ); flagOutputBar = true;   // 不要ならこの行を削除
        if( ! flagOutputBar ){ OutputBar.Visible = false; }
        editor.OpenFile( strPath, 0, eeOpenAllowNewWindow );    // 変換ファイルを開く
    
    
[/code]




[Google 日本語入力](https://www.google.co.jp/ime/cgiapi.html)
を参照してドキュメント一発変換マクロを作ってみました。

  * マクロ利用法  
目的のドキュメントを開いてマクロを実行する。

  * 仕様、制限  
出力はドキュメントのディレクトリにファイル名 Gconv.txt (OutlPath) として第一候補の一発変換を保存する。  
入出力は UTF-8

[code]

    var OutlPath = "Gconv.txt";
    
    function googleConv( str ){
        var rval = "";
        try {
            var uri = "http://www.google.com/transliterate";
            uri += "?langpair=ja-Hira|ja";
            uri += "&text;=" + encodeURIComponent( str );    // パーセントエンコード
    
            var xhr = new ActiveXObject("Msxml2.ServerXMLHTTP");
            xhr.open( "GET", uri, true );
            xhr.setRequestHeader( "User-Agent", "EmEditor " + editor.Version );     // 必要のない設定
    //      xhr.setProxy( 2, "127.0.0.1:8080", "" );
            xhr.send();
            for( var rty = 1000; xhr.readyState != 4 && rty > 0; --rty ){ xhr.waitForResponse(100); }
            if( xhr.readyState == 4 ){
                if( xhr.status == 200 ){ rval = xhr.responseText; }
            } else {
                xhr.abort();
                alert( "Error abort" );
            }
        } catch (e) {
            alert( "Error( " + e.message + " )" );
        }
        return rval;
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    // MAIN
        var fs = new ActiveXObject( "Scripting.FileSystemObject" );
        var strPath = document.Path + "\\" + OutlPath;
        var fh = fs.OpenTextFile( strPath, 2, true, -1 );
        var docReadOnly = document.ReadOnly;
        document.ReadOnly = true;
    
        document.selection.StartOfDocument();
        for( var yPos = 1; yPos <= document.GetLines(); ++ yPos ){
            var str = document.GetLine( yPos );
            var m = str.match( /^(\s*)(.*?)(\s*)$/ );
            if( m != null && m[2] != "" ){
                str = m[2];
                var gconv = googleConv(str);
                Sleep( 300 );
                if( gconv == "" )   break;  // Error
                var jdata = JSON.parse( gconv );
                str = "";
                for( var i = 0; i < jdata.length; ++ i ){
                    str += jdata[i][1][0];
                }
                fh.WriteLine( m[1] + str + m[2] );
            } else {
                fh.WriteLine( "" );
            }
            document.selection.SetActivePoint( eePosLogical, 1, yPos ); // 実行状況が分かるようにカーソルを動かす。無くても良い。
        }
        fh.Close();
    
        document.selection.StartOfDocument();
        document.ReadOnly = docReadOnly;
    
[/code]

