ひらがな/カタカナ変換
ひらがな/カタカナ トグル変換
実行するごとに「ひらがな ⇔ カタカナ」の相互変換をします。
- ダウンロード >> 「ファイル:ひらがな/カタカナ変換.zip」(アイコン入り)
2020/06/24: 第2版(Mery ver 3.0.1 以降のマルチカーソル/複数選択範囲に対応)
2020/01/03: 初版
#title = "ひらがな/カタカナ変換"
#tooltip = "ひらがな/全角カタカナ のトグル変換"
#icon = "あア[1].ico"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl", 324
/**
* --------------------------------------------------------
* ひらがな/カタカナ トグル変換
* sukemaru, 2020/01/03 - 2020/06/24
* --------------------------------------------------------
* ※ Mery ver 3.0.1 以降の矩形選択範囲とマルチカーソル/複数選択範囲に対応
*/
// ---------- ▼ 設定項目 ▼ ---------- //
// ■ 選択範囲がないとき
var autoSelection = 1;
/**
* 0: なにもしない
* 1: カーソル位置の単語を自動選択
* 2: カーソル位置の行全体(表示行)を自動選択
* 3: カーソル位置の行全体(論理行)を自動選択
* 4: 文書全体を自動選択
*/
// ---------- ▲ 設定項目 ▲ ---------- //
var d = editor.ActiveDocument, s = d.selection;
if ( d.ReadOnly ) {
Status = " このドキュメントは書き換え禁止です。";
}
else if ( s.IsEmpty && ! autoSelection ) {
Status = " 選択範囲がありません。";
}
else {
editor.ExecuteCommandByID( 2189 ); // アクティブなペイン
var sx = ScrollX, sy = ScrollY;
// マルチカーソル/複数選択に対応
var arg = [ autoSelection ];
// 選択範囲が1つで矩形選択ではないとき
if ( ! s.Mode || s.Mode === 1 ) {
KanaGanaConv( arg );
}
// 矩形選択または複数選択のとき
else {
BeginUndoGroup();
AddUndo();
MultiFunction( KanaGanaConv, arg );
EndUndoGroup();
}
ScrollX = sx; ScrollY = sy;
}
/**
* 関数 KanaGanaConv( autoSelection )
* ひらがな/カタカナ トグル変換
*/
function KanaGanaConv( arg ) {
var autoSelection = arg[0];
var d = editor.ActiveDocument, s = d.selection;
var pos = s.IsEmpty ? s.GetActivePos() : -1;
// 非選択時には自動選択
if ( pos > -1 ) {
if ( autoSelection === 1 ) {
s.SelectWord();
}
else if ( autoSelection === 2 || autoSelection === 3 ) {
var posMode = autoSelection - 1;
s.EndOfLine( false, posMode );
s.SetAnchorPoint( posMode, 1, s.GetActivePointY ( posMode ) );
}
else if ( autoSelection === 4 ) { s.SelectAll(); }
}
var tp = Math.min( s.GetActivePos(), s.GetAnchorPos() );
var ty = s.GetTopPointY( mePosLogical );
var by = s.GetBottomPointY( mePosLogical );
var bx = s.GetBottomPointX( mePosLogical );
var a = 0;
if ( ty < by && bx === 1 ) {
by --; a = 1;
s.SetActivePoint( mePosLogical, d.GetLine( by, 0 ).length + 1, by );
s.SetAnchorPos( tp );
}
var st = tmp = s.Text;
if ( st ) {
// ひらがな → 全角カタカナ変換 「ゔ ゕ ゖ → ヴ ヵ ヶ」含む
tmp = st.replace( /う[゛゙\u3099]/g, "ヴ" )
.replace( /[\u3041-\u3096\u309D\u309E]/g, function( chr ) {
return String.fromCharCode( chr.charCodeAt( 0 ) + 0x60 );
} );
// ※ unicode 文字に対応できるときは「ヷ ヸ ヹ ヺ」に変換
if ( d.Encoding >= 65000 ) {
tmp = tmp.replace( /ワ[゛゙\u3099]/g, "\u30F7" ).replace( /ヰ[゛゙\u3099]/g, "\u30F8" )
.replace( /ヱ[゛゙\u3099]/g, "\u30F9" ).replace( /ヲ[゛゙\u3099]/g, "\u30FA" );
}
if ( st === tmp ) {
// 全角カタカナ → ひらがな変換
// ※ 「ヷ ヸ ヹ ヺ」は「かな+濁点」に分解する
tmp = st.replace( /\u30F7/g, "わ゛" ).replace( /\u30F8/g, "ゐ゛" )
.replace( /\u30F9/g, "ゑ゛" ).replace( /\u30FA/g, "を゛" )
.replace( /[\u30A1-\u30F3\u30FD\u30FE]/g, function( chr ) {
return String.fromCharCode( chr.charCodeAt( 0 ) - 0x60 );
} );
// ※ unicode 文字に対応できるときは「ゔ ゕ ゖ」に変換
if ( d.Encoding >= 65000 ) {
tmp = tmp.replace( /[\u30F4-\u30F6]/g, function( chr ) {
return String.fromCharCode( chr.charCodeAt( 0 ) - 0x60 );
} );
}
// ※ Shift_JIS などでは「ヴ ヵ ヶ → う゛ ヵ ヶ」
else {
tmp = tmp.replace( /\u30F4/g, "う゛" );
}
}
if ( st !== tmp ) {
// ブックマークを保存
var bmArray = GetBookmark( ty, by );
// 選択範囲を変換
s.Text = tmp;
// ブックマークを復元
RestoreBookmark( ty, by, bmArray );
s.SetActivePos( tp + tmp.length + a );
s.SetAnchorPos( tp );
}
else {
Status = " ひらがな/カタカナ がありません。";
if ( pos > -1 ) { s.SetActivePos( pos ); }
}
}
}
/**
* 関数 GetBookmark( ty, by )
* 指定された範囲のブックマークを収集
*/
function GetBookmark( ty, by ) {
var bmArray = [], bmY;
var s = editor.ActiveDocument.selection;
if ( ty < by ) {
var anc = s.GetAnchorPos(), act = s.GetActivePos();
if ( ty === 1 ) {
s.SetActivePoint( mePosLogical, 1, 2 );
if ( s.PreviousBookmark() ) {
bmY = s.GetActivePointY( mePosLogical );
if ( bmY >= ty && bmY <= by ) {
bmArray.push( bmY );
}
}
s.SetActivePos( 0 );
}
else { s.SetActivePoint( mePosLogical, 1, ty - 1 ); }
while ( s.NextBookmark() ) {
bmY = s.GetActivePointY( mePosLogical );
if ( bmY >= ty && bmY <= by ) {
bmArray.push( bmY );
}
else if ( bmY > by ) { break; }
}
s.SetActivePos( act ); s.SetAnchorPos( anc );
}
return bmArray;
}
/**
* 関数 RestoreBookmark( ty, by, bmArray, sel )
* 指定された範囲のブックマークを復元
*/
function RestoreBookmark( ty, by, bmArray, sel ) {
var bmCount = bmArray.length;
if ( bmCount ) {
var s = editor.ActiveDocument.selection;
var anc = s.GetAnchorPos(), act = s.GetActivePos();
s.SetActivePoint( mePosLogical, 1, ty );
s.ClearBookmark();
for ( var i = 0; i < bmCount, bmArray[i] <= by; i ++ ) {
if ( bmArray[i] < ty ) { continue; }
s.SetActivePoint( mePosLogical, 1, bmArray[i], false );
s.SetBookmark();
}
if ( sel ) {
s.SetActivePos( act ); s.SetAnchorPos( anc );
}
}
}
/**
* 関数 MultiFunction( Fn, arg1 )
* マルチカーソル(複数選択範囲)に対応させる
*
* 第1引数: Function; 選択範囲ごとに適用する処理の関数
* 第2引数以降: Function に渡す引数をまとめた配列
*/
function MultiFunction( Fn, arg ) {
var d = editor.ActiveDocument;
var s = d.selection;
// 矩形選択範囲は行に分ける
var sMode = s.Mode;
if ( sMode === meModeBox ) {
var act = s.GetActivePos(), anc = s.GetAnchorPos();
}
s.Mode = meModeMulti;
// 選択範囲の座標を取得
var sCount = s.Count;
var Sel = [];
for ( var i = 0; i < sCount; i ++ ) {
Sel[i] = {
act: s.GetActivePos( i ),
anc: s.GetAnchorPos( i )
};
}
// 各選択範囲を処理;
for ( var i = 0, diff = 0, dl; i < sCount; i ++ ) {
dl = d.TextLength;
s.SetActivePos( Sel[i].act + diff );
s.SetAnchorPos( Sel[i].anc + diff );
Fn( arg ); // KanaGanaConv() 関数
// Fn() の残した選択範囲(またはキャレット位置)を回収
Sel[i].act = s.GetActivePos();
Sel[i].anc = s.GetAnchorPos();
diff += d.TextLength - dl; // 文字数の増減量(累積)
}
// 矩形選択範囲を復帰(文字数が変化していた場合はズレる)
if ( sMode === meModeBox ) {
s.SetAnchorPos( anc );
s.SetActivePos( act, true );
s.Mode = meModeBox;
}
// マルチカーソル(複数選択範囲)を復帰
else {
for ( var i = 0; i < sCount; i ++ ) {
s.AddPos( Sel[i].anc, Sel[i].act );
}
}
}
以下、参照 >> 『テキスト整形』マクロ
ひらがな → カタカナ変換
#title = "ひらがな → カタカナ変換"
// e.g. 「あいうえお」 → 「アイウエオ」
var s = document.selection;
if( s.Text ) {
s.Text = s.Text.replace( /[\u3041-\u3096\u309D\u309E]/g, function( t ) {
return String.fromCharCode( t.charCodeAt( 0 ) + 0x60 )
});
}
カタカナ → ひらがな変換
#title = "全角カタカナ → ひらがな変換"
// e.g. 「アイウエオ」 → 「あいうえお」
var s = document.selection;
if( s.Text ) {
s.Text = s.Text.replace( /[\u30A1-\u30F3\u30FD\u30FE]/g, function( t ) {
return String.fromCharCode( t.charCodeAt( 0 ) - 0x60 )
});
}
ひらがな/カタカナ マルチカーソル対応版 (トグル変換未対応) by Kuro
Mery Ver 3.0.0 のマルチカーソルに対応する例として sukemaru さんのソースコードをもとにカスタマイズしてみました。
変換処理の部分は手を加えずメソッド化しただけです。
マクロからマルチカーソルの位置を取得することはできるのですが、マルチカーソルを設置する機能がないので複数選択の状態を復元することができないためトグル変換に対応できていません。
複数の選択範囲に対して変換処理を行うときに、ひらがな・カタカナ変換のように文字数・行数が変化しないものはこのようにシンプルに書けますが、変換前と変換後で文字数・行数が変わる場合は複数選択の位置を再計算してやる必要があるのでもう少し大変だと思います。
追記: よく見ると「わ゛」あたりの変換は文字数が変わっているので、このままだと位置がずれそうです。 → とりあえず暫定で文字数が変化したときに再計算するようにしてみましたが、少々強引な気もします。(2020/03/15)
#title = "ひらがな/カタカナ変換"
#tooltip = "ひらがな/全角カタカナ のトグル変換"
#icon = "文字_あア[1].ico"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl", 324
// ---------- ▼ 設定項目 ▼ ----------
// ■ 選択範囲がないとき
var autoSelection = 1;
/**
* 0: なにもしない
* 1: カーソル位置の単語を自動選択
* 2: カーソル位置の行全体(表示行)を自動選択
* 3: カーソル位置の行全体(論理行)を自動選択
* 4: 文書全体を自動選択
*/
// ---------- ▲ 設定項目 ▲ ----------
var d = editor.ActiveDocument, s = d.selection;
var isEmpty = s.IsEmpty;
if ( d.ReadOnly ) {
Status = " このドキュメントは書き換え禁止です。";
}
else if ( isEmpty && autoSelection == 0 ) {
Status = " 選択範囲がありません。";
}
else {
Redraw = false;
var sx = ScrollX, sy = ScrollY;
// 以下、変更した箇所
// ---------------------------------ここから---------------------------------
// もともとここにあった処理は下部の Convert 関数にそのまま移動
// 複数選択を保持しておくための配列 (SetActivePoint を使うと複数選択が解除されるため、事前に選択箇所を格納しておく必要がある)
var selections = [];
// マルチカーソルの場合、document.selection.Count は 0 より大きい値が返る
if (document.selection.Count > 0) {
for (var i = 0; i < document.selection.Count; i++) {
// GetTopPointX、GetTopPointY、GetBottomPointX、GetBottomPointY のみ、第二引数に 0 以上の値を指定すれば複数選択の箇所が取得できる
selections.push({
tx: s.GetTopPointX( mePosLogical, i ),
ty: s.GetTopPointY( mePosLogical, i ),
bx: s.GetBottomPointX( mePosLogical, i ),
by: s.GetBottomPointY( mePosLogical, i )
});
}
// マルチカーソルではない場合
} else {
// GetTopPointX、GetTopPointY、GetBottomPointX、GetBottomPointY は第二引数を省略するか -1 を指定すれば現在のカーソル位置が取得できる
selections.push({
tx: s.GetTopPointX( mePosLogical ),
ty: s.GetTopPointY( mePosLogical ),
bx: s.GetBottomPointX( mePosLogical ),
by: s.GetBottomPointY( mePosLogical )
});
}
BeginUndoGroup();
try {
var cnt = 0;
var len = 0;
for (var i = 0; i < selections.length; i++) {
// 複数選択の箇所に現在のカーソルを設定する (選択範囲の開始と終了が逆になることがあるけど気にしない方向で…)
s.SetActivePoint( mePosLogical, selections[i].bx, selections[i].by, false );
s.SetActivePos( s.GetActivePos() + cnt, false );
s.SetActivePoint( mePosLogical, selections[i].tx, selections[i].ty, true );
s.SetActivePos( s.GetActivePos() + cnt, true );
len = d.Text.length;
Convert(s.IsEmpty, s.GetActivePointY( mePosLogical ), ( isEmpty ) ? s.GetActivePos() : -1);
cnt += d.Text.length - len;
}
} finally {
EndUndoGroup();
}
// 今のところマクロから複数選択を設定する仕組みがないので複数の選択範囲を復元することはできません
// ---------------------------------ここまで---------------------------------
ScrollX = sx; ScrollY = sy;
Redraw = true;
}
// Convert メソッドの中身はもとのソースから変更なし
// isEmpty、ay、pos は選択範囲に応じて更新する必要があるため引数で渡す
function Convert(isEmpty, ay, pos) {
// 非選択時には自動選択
if ( isEmpty ) {
if ( autoSelection == 1 ) {
s.SelectWord();
if ( s.GetActivePointY( mePosLogical ) != ay ) {
s.SetActivePos( pos );
}
}
else if ( autoSelection == 2 || autoSelection == 3 ) {
var posMode = autoSelection - 1;
s.SetAnchorPoint( posMode, 1, s.GetActivePointY ( posMode ) );
s.EndOfLine( true, posMode );
}
else if ( autoSelection == 4 ) { s.SelectAll(); }
}
var st = s.Text;
if ( st ) {
var anc = s.GetAnchorPos(), act = s.GetActivePos();
var tp = Math.min( anc, act );
var tmp;
// ひらがな → 全角カタカナ変換 「ゔ ゕ ゖ → ヴ ヵ ヶ」含む
tmp = st.replace( /う[゛゙u\3099]/g, "ヴ" )
.replace( /[\u3041-\u3096\u309D\u309E]/g, function( chr ) {
return String.fromCharCode( chr.charCodeAt( 0 ) + 0x60 );
} );
// ※ unicode 文字に対応できるときは「ヷ ヸ ヹ ヺ」に変換
if ( d.Encoding >= 65000 ) {
tmp = tmp.replace( /ワ[゛゙u\3099]/g, "ヷ" ).replace( /ヰ[゛゙u\3099]/g, "ヸ" )
.replace( /ヱ[゛゙u\3099]/g, "ヹ" ).replace( /ヲ[゛゙u\3099]/g, "ヺ" );
}
if ( st == tmp ) {
// 全角カタカナ → ひらがな変換
// ※ 「ヷ ヸ ヹ ヺ」は「かな+濁点」に分解する
tmp = st.replace( /\u30F7/g, "わ゛" ).replace( /\u30F8/g, "ゐ゛" )
.replace( /\u30F9/g, "ゑ゛" ).replace( /\u30FA/g, "を゛" )
.replace( /[\u30A1-\u30F3\u30FD\u30FE]/g, function( chr ) {
return String.fromCharCode( chr.charCodeAt( 0 ) - 0x60 );
} );
// ※ unicode 文字に対応できるときは「ヴ ヵ ヶ → ゔ ゕ ゖ」に変換
if ( d.Encoding >= 65000 ) {
tmp = tmp.replace( /[\u30F4-\u30F6]/g, function( chr ) {
return String.fromCharCode( chr.charCodeAt( 0 ) - 0x60 );
} );
}
// ※ Shift_JIS などでは「ヴ ヵ ヶ → う゛ ヵ ヶ」
else {
tmp = tmp.replace( /\u30F4/g, "う゛" );
}
}
if ( st != tmp ) {
// ブックマークを保存
var bmArray = [];
s.SetActivePoint( mePosLogical, 1, 2 );
if ( s.PreviousBookmark() ) {
bmArray.push( s.GetActivePointY( mePosLogical ) );
}
s.SetActivePos( 0 );
while ( s.NextBookmark() ) {
bmArray.push( s.GetActivePointY( mePosLogical ) );
}
s.SetActivePos( anc ); s.SetActivePos( act, true );
ScrollX = sx; ScrollY = sy;
// 選択範囲を変換
s.Text = tmp;
act = s.GetActivePos();
// ブックマークを復元
var bmCount = bmArray.length;
if ( bmCount ) {
editor.ExecuteCommandByID( 2129 ); // ブックマークをクリア
for ( var i = 0; i < bmCount; i ++ ) {
s.SetActivePoint( mePosLogical, 1, bmArray[i], false );
editor.ExecuteCommandByID( 2126 ); // ブックマークを設定/解除(設定)
}
}
s.SetActivePos( tp ); s.SetActivePos( act, true );
}
else {
Status = " ひらがな/カタカナ がありません。";
if ( pos >= 0 ) { s.SetActivePos( pos ); }
}
}
}
スポンサーリンク