日本オリンピック代表カタール戦を観ながら,misima 旧字・旧仮名遣い変換 SOAP Web Service 秀丸クライアント対応に取り組んだ。秀丸でテキストの選択範囲を,ネットワーク越しに私の misima SOAP サーバに転送し,サーバが旧字・旧仮名変換し返却して来た結果テキストで書き換える,というもの。ホームのカタールが勝負強さを発揮して,見事後半残すところ 13 分で追いつき,逆転。日本が信じられない負け方をした。信じられない勝ち方は見たことがないが。ロスタイムでなんとハンドで PK を献上するなんて,まあ優しい日本人らしいかわいいところか。こんなのでオリンピックに出場できたとしても,よいものだろうか。それはよいとして,秀丸用のマクロができた。秀丸バージョンは 7.03 である。
misima SOAP Web Service 秀丸クライアント方式
秀丸はマクロ実装において,テキスト選択範囲を外部プログラムの標準入力に渡すことができる。賢明な仕様だと感心した。でも,その文字コードがどうも Shift_
ならコード変換すればよい,という考え方は,UTF-8 から Shift_
しようがないので,クリップボード経由で外部プログラムとテキストを連絡する方式にした。秀丸も UTF-8 を含むいくつかの文字コードをサポートしている。エンコードの異なる複数の秀丸文書間,あるいは他のアプリとの間でコピー&ペーストができないとなると,さすがに使い物にならない。よってもって,クリップボードのエンコーディングは Unicode で管理可能な作りになっていると想像できるからである。
という次第で,クリップボードからデータを読み取り,misima SOAP 変換をコールし,変換結果をクリップボードにストアする Java プログラム misima
ここでもうひとつ障碍が発生。マクロから java プログラムを起動するとどうしても「コマンドプロンプト」の画面が変換中に立ち現れてちょっとみっともない。秀丸のマクロ Tips を検索したら "> nul" でこれを抑止できるような記事を見つけてこれを試してみたが,ダメであった。これまたしようがないので,引数に指定したプログラム (ここでは Java) を,コンソールプログラムとしてでなく,バックグラウンドプロセスとして起動する短いランチャプログラムを C で書いた (下記・秀丸マクロコード中の misimalaunch)。Borland C++ 5.5 の無償お試しコンパイラが役立った。全部 C で書けばよいのだけど,クリップボード,SOAP を操作する Windows アプリを C/C++ で書く気力はいまの私にはない。[ misima
秀丸マクロ
misima SOAP Web Service クライアント秀丸マクロコードを以下に示す。このマクロそのものは,選択テキストをクリップボードに切り出し,runsync2 命令でもって外部プログラムをコールし,その結果によって書き換えられたクリップボードデータを再び編集エリアにペーストするだけのものである。
// // misima SOAP Web Service 秀丸クライアント // Copyright (c) 2007 isao yasuda, All Right Reserved. // // misima パラメータ: 旧字(UTF-8),旧仮名,用字・用語,単純変換指定 $param = "-kyit -s c "; // 文字列が選択されていないならエラー終了 if (!selecting) { message "文字列を選択してください"; endmacro; } // クリップボードに切り出し cut; // misima SOAP サーバコール // - misimalaunch: コマンドプロンプト画面抑止ランチャ // - misimaSoapCbClient: Java クリップボード SOAP クライアント runsync2 "misimalaunch javaw misima.misimaSoapCbClient " + "-u http://yasuda.homeip.net/services/misimaSoapConnector " + $param; // 異常終了の場合,対象テキストを戻して終了 if (!result) { message "実行に失敗しました"; endmacro; } // クリップボードの misima 変換結果をペースト paste; // 失敗時は cut した時で戻るはず
Java プログラム・コード
サーバに対する変換要求を実際に処理している SOAP クライアントプログラムは,秀丸マクロ runsync2 命令の引数にある Java クラス misima
Java コードを掲載しておく。ただし,misima
misima
よって,秀丸に限らず,クリップボードの Unicode 文字列をペーストできるアプリなら,クリップボードに文字列をコピーしたあと,以下のように misima
(アプリで変換したいテキストをコピーないしカット) C:¥Documents and Settings¥user> java misima.misimaSoapCbClient ¥ -u http://yasuda.homeip.net/services/misimaSoapConnector -kyit -s c C:¥Documents and Settings¥user> (アプリでペーストすると変換結果が得られる)
さらに言えば,秀丸 runsync2 と同じような,外部プログラムを起動できるマクロ機構を有するアプリならば,秀丸とまったく同じ方式で misima SOAP Web Service クライアントマクロを書くことができるはずである。
// -*- coding: utf-8; mode: java; -*- package misima; import java.io.*; /** * <pre> * misima SOAP WebService クライアント クリップボード版 * $Id: insomnia.txt 222 2014-03-27 11:23:12Z isao $ * Copyright (c) 2005-2007, isao yasuda, All Rights Reserved. * ---- * 旧仮名・旧字変換支援 misima SOAP WebService にアクセスする. * </pre> * @author 安田 功 (Isao YASUDA) * @version $Id: insomnia.txt 222 2014-03-27 11:23:12Z isao $ */ public class misimaSoapCbClient { /** テキスト最大文字数 */ private static final int MAXSIZE = 8000; /** misimaSoapCbClient を新たに作成する.*/ public misimaSoapCbClient(){} /** main メソッド */ public static void main(final String[] args) { /** misima 変換対象テキスト */ String rt = null; /** misima 変換結果テキスト */ String ct = null; /** 出力対象テキスト */ String res = null; /** misima オプション解析 */ misimaParameter mp = new misimaParameter(args); /** クリップボードから対象テキストを読み, 送信テキストにセットする. */ misimaClipboard mcl = new misimaClipboard(); rt = mcl.getmisimaClipboard(); /** テキスト長最大値オーバーか0の時は入力を出力にセットする. */ int rlen = rt.length(); if (rlen > MAXSIZE || rlen == 0) { if (rlen > MAXSIZE) { System.err.println("入力が大き過ぎます(" + rlen + " 文字)"); } else { System.err.println("入力がありません."); } res = rt; } /** misima SOAP Server に接続する. */ else { misimaSoap ms = new misimaSoap( mp.getParameter(), rt, mp.getEndpoint()); ct = ms.misimaSoapTransaction(); /** 変換結果が null の時,入力を戻す. */ if (ct == null) { System.err.println("出力が空でした."); res = rt; } /** 変換結果を出力バッファにセットする. */ else { res = ct; } } /** 変換後テキストをクリップボードに書く. */ mcl.setmisimaClipboard(res); System.exit(0); } }
misimaClipboard クラスは AWT クラスライブラリのクリップボード操作クラスを使っている。中核をハイライト表示で示す。
// -*- coding: utf-8; mode: java; -*- package misima; import java.awt.*; import java.awt.event.*; import java.awt.datatransfer.*; /** * <pre> * misima SOAP WebService クリップボードアクセス * $Id: insomnia.txt 222 2014-03-27 11:23:12Z isao $ * Copyright(c) 2005-2007, isao yasuda, All Rights Reserved. * ---- * クリップボードの読み書きを行う. * </pre> * @author 安田 功 (Isao YASUDA) * @version $Id: insomnia.txt 222 2014-03-27 11:23:12Z isao $ */ public class misimaClipboard { /** クリップボード */ private Clipboard cb; /** 転送可能形式 */ private Transferable st; /** セレクションデータ */ private StringSelection ss; /** クリップボード取得文字列 */ private String rt; /** クリップボードインスタンスを新たに生成する. */ public misimaClipboard() { //クリップボードオブジェクトの取得 cb = Toolkit.getDefaultToolkit().getSystemClipboard(); } /** * クリップボードからテキストを取得し,返却する. * @return クリップボードから取得した文字列 */ public String getmisimaClipboard() { //クリップボードからトランスファに格納 st = cb.getContents(this); try { rt = (String) st.getTransferData(DataFlavor.stringFlavor); } catch (Exception e) { System.err.println(e.toString()); } return rt; } /** * テキストをクリップボードに出力する. * @param settext クリップボードにセットすべき文字列 */ public void setmisimaClipboard(String settext) { //取得テキストでセレクションを生成 ss = new StringSelection(settext); //セレクションをクリップボードに書く cb.setContents(ss, ss); } }
misimaSoap クラスは AXIS SOAP Web Service クラスライブラリを使用している。misima SOAP の WSDL で要求される二つの引数(misima オプション及び変換対象テキスト),misima SOAP Web Service サーバのエンドポイントを受けて,サーバへの要求送信,変換結果の受信,呼び出し元への返却を行う。
// -*- coding: utf-8; mode: java -*- package misima; import java.util.regex.*; import javax.xml.rpc.*; import javax.xml.rpc.encoding.TypeMappingRegistry; import javax.xml.rpc.encoding.TypeMapping; import javax.xml.rpc.encoding.XMLType; import javax.xml.namespace.QName; /** * <pre> * misimaSoap SOAP 接続 * $Id: insomnia.txt 222 2014-03-27 11:23:12Z isao $ * Copyright(c) 2005-2007, isao yasuda, All Rights Reserved. * ---- * 旧仮名・旧字変換支援 misima SOAP サーバに接続する. * </pre> * @author 安田 功 (Isao YASUDA) * @version $Id: insomnia.txt 222 2014-03-27 11:23:12Z isao $ */ public class misimaSoap { /** エンドポイント */ private String endpoint; /** 第一パラメータ(コマンドライン引数) */ private String mReq1 = null; /** 第二パラメータ(変換対象テキスト) */ private String mReq2 = null; /** * Soap 接続を新たに作成する. * @param reqParam misimaコマンドライン引数 * @param reqText 変換対象テキスト * @param ep エンドポイント */ public misimaSoap(String reqParam, String reqText, String ep) { endpoint = ep; mReq1 = reqParam; mReq2 = reqText; } /** * Soap 接続を新たに作成する. * @param reqParam misimaコマンドライン引数 * @param reqText 変換対象テキスト */ public misimaSoap(String reqParam, String reqText) { endpoint = "http://yasuda.homeip.net/axis/services/misimaSoapConnector"; mReq1 = reqParam; mReq2 = reqText; } /** * misima SOAP 通信 * @return 変換結果テキスト */ public String misimaSoapTransaction() { /** SOAP 接続オブジェクト */ Call call = null; /** SOAP サーバ変換結果文字列 */ String mResult = null; try { /** Service オブジェクトを生成する. */ ServiceFactory factory = ServiceFactory.newInstance(); Service service = factory.createService(new QName("misima")); /** Call オブジェクトを生成する. */ call = (Call) service.createCall(); } catch (Exception e) { System.err.println("SOAP オブジェクト生成に失敗しました: " + e); return null; } try { /** エンドポイントを設定する. */ call.setTargetEndpointAddress(endpoint); /** オペレーションを設定する. */ call.setOperationName(new QName("misimaConvert")); /** パラメータを設定する. */ call.addParameter( "op1", XMLType.XSD_STRING, ParameterMode.IN); call.addParameter( "op2", XMLType.XSD_STRING, ParameterMode.IN); call.setReturnType(XMLType.XSD_STRING); /** Web サービスを起動する. */ mResult = (String) call.invoke(new Object[]{mReq1, mReq2}); } /** 例外処理. */ catch (Exception e) { System.err.println("WebService 中にエラーが発生しました: " + e); return null; } return mResult; } }
付記
まだ Java プログラムも C プログラムもプロトタイプなので,misima オプション指定などもう少しチューニングしてから公開するつもりでいる。Windows のエディタとして大きなシェアを持っている秀丸エディタでも,これで misima 変換がサポートできそうである。
次は Mac OS X で人気のある Jedit X 向けに misima SOAP 変換マクロ (AppleScript) に取り組む予定である。AppleScript は Apple Event Manager で SOAP や XML-RPC をサポートしているので,秀丸よりもっと簡単にサポートできると思う。
参考文献
秀丸マクロの実装にあたり,以下の書籍を参考にした。
2015.8.18 付記
最近の Web Service の主流は RESTful ではないかと思う。RESTful は SOAP と比べ,XML に依存せず簡便に実装できるメリットがあると思う。弊サイトの misima SOAP Web Service はセキュリティの課題(要するに,限定公開とするための認証機構を実装できていなかったこと)もあり,その後公開を停止した。現在,misima RESTful Web Service が稼働している。
misima RESTful Web Service は Web ブラウザ,GNU Emacs,Microsoft Word 2003 / 2007,秀丸エディタから直接 misima 旧字・旧仮名遣い変換をサポートしている。ただし,変換実行に際して usercode(友人にだけ配布した非公開キー)を指定する必要があり,限定ユーザしか利用できない。
misima RESTful Web Service のサーバ実装(Java Servlet),各種クライアント実装については,弊ブログの以下の記事を参照いただきたい。
- JAX-RS - misima RESTful Web Service の実装 (Apache Wink)
- misima RESTful Web Service for GNU Emacs, LaTeX
- misima RESTful Web Service: Microsoft Office 2007
- misima RESTful Web Service: Microsoft Word クライアント
- misima RESTful Web Service: 秀丸エディタ用クライアント
- misima RESTful Web Service: Java クライアント (Apache Wink)
- misima RESTful Web Service: Perl クライアント (REST::Client)