「
利用者:Sukemaru
」を編集中
2019年11月21日 (木) 08:50時点における
Sukemaru
(
トーク
|
投稿記録
)
による版
(
差分
)
← 古い版
|
最新版
(
差分
) |
新しい版 →
(
差分
)
ナビゲーションに移動
検索に移動
警告: このページの古い版を編集しています。
公開すると、この版以降になされた変更がすべて失われます。
警告:
ログインしていません。編集を行うと、あなたの IP アドレスが公開されます。
ログイン
または
アカウントを作成
すれば、あなたの編集はその利用者名とともに表示されるほか、さまざまなメリットもあります。
スパム攻撃防止用のチェックです。 決して、ここには、値の入力は
しない
でください!
<div id="TOP"> [[#END|>> ページ末尾へ]] </div> __toc__ <br><br> == マクロライブラリに投稿したマクロ == === 「テキスト操作補助」 カテゴリ === * [[行頭か行末 または 選択範囲の始点か終点|行頭か行末 または 選択範囲の始点か終点 に移動]] (last modified: 2019/03/29) * [[文書の先頭か末尾|文書の 先頭か末尾 に移動]] (last modified: 2019/03/29) * [[対応する括弧に移動#範囲選択の拡張|「対応する括弧に移動」の追加コード]] (last modified: 2019/05/12) * [[バイト数#バイト数と文字数・行数|バイト数と文字数・行数]] ※イベントマクロ (last modified: 2018/11/18) * [[日付と時刻を挿入#sukemaru 版|日付と時刻を挿入]] (last modified: 2018/12/09) * [[行を上下に移動(Mery 2.7 用)]] (uploaded: 2019/05/07) ※ ブックマーク対応 * [[行を複製 (複数行可)]] (last modified: 2019/05/07) ※ ブックマーク対応 * [[字下げ・字上げ#sukemaru 版|字下げ・字上げ(スペース×2 追加・削除)]] (last modified: 2019/11/18) ※ ブックマークを保持 : [[字下げ・字上げ#インデント|インデント/逆インデント]] (last modified: 2019/11/17) ※ ブックマークを保持 * [[貼付け実行後のカーソル位置を貼付け文字列の先頭にする#sukemaru 版|貼付け実行後のカーソル位置を貼付け文字列の先頭にする]] (added: 2018/11/14) * [[行の先頭に貼り付け]] (uploaded: 2018/08/24) <div id="引用符/コメント"></div> * [[引用符/コメント]] ※ポップアップメニュー (last modified: 2019/04/07) ※行頭の文字列操作マクロ「引用の追加」の増補改訂版 * [[カッコで囲う]] ※ポップアップメニュー (last modified: 2019/04/07) : [[カッコで囲う#カッコで囲う (ポップアップメニューなし)|カッコで囲う (簡易版 ポップアップメニューなし)]] : [[カッコで囲う#引用符を追加/削除|引用符を追加/削除]] ※"二重引用符" の追加/削除トグル * [[定型文を挿入|定型文を挿入 マクロ集]] (uploaded: 2018/12/03) <br> <gallery heights=192px> ファイル:引用符/コメント_ポップアップメニュー.png|heights=240px|引用符/コメント ファイル:カッコで囲う_ポップアップメニュー.png|heights=240px|カッコで囲う </gallery> <br clear=all> === 「ファイル操作補助」 カテゴリ === * [[ファイルのプロパティ]] (uploaded: 2018/12/18) * [[選択範囲のURL・パスを開く|ひらけゴマ!]] (last modified: 2019/04/07) ※選択範囲のURL・パスを開く * [[ブックマーク一覧ジャンプ#sukemaru 版|ブックマーク一覧ジャンプ]] (通常版/include版) ※ポップアップメニュー (last modified: 2019/04/16) * [[編集モードの自動選択]] (通常版/include版) ※イベントマクロ (last modified: 2019/04/24) ※書き換え禁止で開く * [[特定のフォルダで「ファイルを開く」ダイアログ]] (last modified: 2018/12/19) * [[すべて閉じる|すべて閉じる マクロ集]] (通常版/include版) (last modified: 2019/05/03) : 「他(右側/左側)のタブを閉じる」 などを追加 ※ポップアップメニュー版あり * [[ファイルを読み直す・開きなおす]] (通常版/include版) ※ポップアップメニュー (last modified: 2019/05/30) : エンコード指定で読み直し・読み取り専用属性の変更・編集モードの変更・プロパティを開く・さいごに閉じたファイルを開く・etc. * [[さいごに閉じたファイルを開く]] ※ポップアップメニュー (uploaded: 2019/04/30) <br> <gallery widths=200px> ファイル:Mery_ブックマークジャンプ_SS(1).png|ブックマークジャンプ 【include版】 ファイル:Mery_すべて閉じる(入力).png|すべて閉じる: 入力ダイアログ ファイル:Mery_すべて閉じる(メニュー).png|すべて閉じる: ポップアップメニュー </gallery> <gallery widths=200px> ファイル:ファイルを読み直す・開きなおす.png|ファイルを読み直す 【通常版】 ファイル:ファイルを読み直す・開きなおす【自家用版】.png|ファイルを読み直す 【include版】 </gallery><br clear=all> === 「変換・ソート・整形」 カテゴリ === * [[昇順で並び替え/降順で並び替え]] トグル変換 (uploaded: 2019/06/03) * [[TrueとFalse_を切り替える|YES/NO マクロ]] (last modified: 2018/11/27) ※「<span style="color:#0000c0;">True</span>」 ⇔ 「<span style="color:#c00;">False</span>」 トグル変換 : + 改造版「'''ToDoリストモード'''[https://www.haijin-boys.com/software/mery/mery-2-7-0#comment=2240]」 (added: 2019/05/06) * [[全角/半角 トグル変換]] (last modified: 2019/05/20) ※「ABCアイウエオ」 ⇔ 「ABCアイウエオ」 * [[大文字/小文字/頭文字 トグル変換]] (last modified: 2019/08/29) ※「Abc」 → 「ABC」 → 「abc」 ... * [[ひらがな/カタカナ変換]] (uploaded: 2019/07/06) ※「あいうえお」 → 「アイウエオ」 / 「カキクケコ」 → 「かきくけこ」 * [[文字列の順番を逆に書き出す]] (uploaded: 2019/07/06) ※「あいうえお」 → 「おえういあ」 <br><br> [[#TOP|>> 目次へ]] <br><br> === 「検索・置換」 カテゴリ === * [[ポップアップメニューで検索先にジャンプ#sukemaru 版|ポップアップメニューで検索先にジャンプ]] (通常版/include版) (last modified: 2019/04/16) : + おまけマクロ「[[マテリアルデザインっぽいアイコンと『小マクロ集』#次の文字列を検索|次の文字列を検索]]/[[マテリアルデザインっぽいアイコンと『小マクロ集』#前の文字列を検索|前の文字列を検索]] (検索オプションをリセット&強調なし)」他 * [[検索ヒット数表示(選択文字列)]] ※イベントマクロ (last modified: 2019/07/20) : + 機能強化版「[[検索ヒット数表示(選択文字列)#機能強化バージョン|文字数・行数・ヒット件数(選択文字列)]]」 ※イベントマクロ (last modified: 2019/08/28) * [[次/前の文字列を検索・改]] (last modified: 2019/09/09) ※複数行選択から『次/前の文字列を検索』 <br> [[ファイル:Mery_ジャンプ_SS_2.png|240px|thumb|left|検索ジャンプ 【include版】]] <br clear=all><br> === 「プログラミング補助」 カテゴリ === * [[コメントマーク付け外し#sukemaru 版|行コメント]] (last modified: 2019/11/10) ※コメントマーク付け外し ブックマークを保持 <br> === 「実験的マクロ・練習マクロなど」 カテゴリ === * 【自家用】 [[カッコをはずす]] & [[カッコをはずす#カッコを削除/追加|カッコを削除/追加 トグル]] & [[カッコをはずす#カッコを追加/削除|カッコを追加/削除]] (通常版/include版) (last modified: 2019/05/03) * 【自家用】 [[ファイルのフルパスをコピーして閉じる]] ※イベントマクロ (last modified: 2019/04/14) * 【自家用】 [[全角/半角変換]] (last modified: 2019/05/11) * 【実験】 [[位置情報を保存してから「次の文字列を検索」]]+ 復帰 (include版) (uploaded: 2019/05/28) * 【実験】 [[タブが「縦書き」モードかチェックする]] ※組み込み用関数 (uploaded: 2019/04/29) : サンプルコード: 「特定の条件で縦書きモードに切りかえる」(※ ver 2.6.5 - 2.7.5 用) * 【実験】 [[「クリップボード履歴」メニューのマクロ化]] (include版) ※ポップアップメニュー (last modified: 2019/11/09) <br> ※「スニペット」の機能を統合 / ※ ver 2.8.1 以降用 * 【自家用】[[行の表示方法を切り替える]] (last modified: 2019/08/24) ※論理行/表示行 トグル切り替え * 【自家用】[[位置情報を保存してから「すべて選択/選択解除」(非スクロール)]] (include版) (last modified: 2019/11/13) : +「[[位置情報を保存してから「すべて選択/選択解除」(非スクロール)#【include 版】位置を復帰/保存|位置を復帰/保存]]」 (include版) * 【実験】 [[コンパクトメニュー]] ※ポップアップメニュー (last modified: 2019/11/21) <br> * 【実験】 [[ファイルへ移動(物理座標ジャンプ)]] (uploaded: 2019/05/15 → '''2019/10/27 隠蔽''') * 【実験】 [[ブックマークを復元(Mery 2.7用)]] (last modified: 2019/04/07 → '''2019/04/12 削除''') <br> [[ファイル:ブックマークを復元D.png|link=|240px|thumb|left|ブックマークを復元]] <br clear=all><br> === 「その他」 カテゴリ === * [[折り返しトグル切り替え#3つの折り返しモードを順々にトグルする|折り返しトグル切り替え]] (include版) (added: 2019/02/19 ※w/ Bleat氏) * [[Mery.iniのオプション値を取得]] ※組み込み用関数 (last modified: 2019/11/15) * [[Mery本体のバージョンチェック]] ※組み込み用関数 (uploaded: 2019/04/17) : サンプルコード: 「Begin/EndUndoGroup() メソッドを使えるのは ver 2.7.0 以降」 * [[IO.Serialize() の JSON を参照する]] ※組み込み用関数 (uploaded: 2019/04/17) * [[ポップアップメニューを「n*十件ずつ」のサブメニューに自動分割する]] ※組み込み用関数 (uploaded: 2019/04/20) : サンプルコード: 「すべての論理行をポップアップメニューに表示する」 * [[アクティブなタブのマクロを実行する]] (uploaded: 2019/08/12) * [[マクロメニュー]] ※ポップアップメニュー (uploaded: 2019/11/02) <br> * [[GetKeyState.exe(キー状態取得実行ファイル)]] の [[GetKeyState.exe(キー状態取得実行ファイル)#実装例|サンプルコード2, 3]] (2019/03/23 - 2019/11/13) <br> <gallery widths=192px> ファイル:Mery_関数_JsonContents.png|JSON ファイルを開く ファイル:Mery_分割サブメニュー_SS(1).png|分割サブメニュー 1 ファイル:Mery_分割サブメニュー_SS(2).png|分割サブメニュー 2 </gallery><br clear=all> * [[キーアサイン集]] (last modified: 2018/10/19 ※w/ ks氏, masme氏, 有志) * [[マテリアルデザインっぽいアイコンと『小マクロ集』]] (last modified: 2019/05/01) ※アイコン収録数'''300'''コ <gallery heights=320px> ファイル:Mery用_マテリアルデザインっぽいアイコン.icl.png| アイコン 一覧画像 ファイル:Mery_小マクロ集_アウトライン.png|小マクロ集 アウトラインイメージ </gallery><br clear=all> == 外部サイトに投稿したマクロ == * [https://pastebin.com/5rUw36qM StrConvテキスト変換メニュー] (uploaded: 2018/08/25) <br> 山本隆 氏作成の [http://gesource.jp/soft/strconv/strconvdll.html 文字変換ライブラリ StrConvDLL] の機能をポップアップメニューにまとめたマクロ * [https://pastebin.com/Bci0eEx2 gPad用 文字数・行数・ヒット数] (uploaded: 2019/08/26) <br> Mery 用マクロ「[[検索ヒット数表示(選択文字列)#機能強化バージョン|文字数・行数・ヒット件数(選択文字列)]]」を [https://mfactory.me/ gPad] 用に改編したもの <br><br> [[#TOP|>> 目次へ]] <br><br> == 組み込み用コード・小関数 == メインコードの途中に短い [https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/function 関数] を置く場合は、最初の呼び出しコードより前に変数([https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/function 関数式])として定義しておいてもよい。 <source lang="javascript"> { var hoge = "hogehoge"; // function 宣言で定義された関数は、宣言された位置より前からでも呼び出せる document.selection.Text = HogeFuga( hoge ); // 関数宣言は参照可能なスコープ内のどの位置に置いてもよい function HogeFuga( str ) { return str.replace( /hoge/ig, "fuga" ); } } </source> ならば、以下のような記述でも同じ意味 (ただし、関数式の場合は、最初に呼び出す文よりも前に定義しておくこと)。 <source lang="javascript"> // 関数式は最初に呼び出されるよりも前に定義すること var HogeFuga = function( str ) { return str.replace( /hoge/ig, "fuga" ); }; var hoge = "hogehoge"; document.selection.Text = HogeFuga( hoge ); </source> <br> === メタ記号をエスケープする === 任意の文字列を正規表現変数 <source lang="javascript" inline>RegExp()</source> におさめる前などにエスケープ(退避修飾)する。 <br><br> * '''正規表現のメタ記号のみ''' をエスケープする方法。<br> : ※ ref. 『[https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping 正規表現 - JavaScript | MDN]』 <source lang="javascript"> /** * 関数 RegQuote( str ) * * 正規表現のメタ記号をすべてエスケープ(退避修飾)する */ function RegQuote( str ) { return str.replace( /[.*+?^=!:${}()|[\]\/\\]/g, "\\$&" ); } </source> <br> * または、記述の簡単な方法。<br> : ※ ref. 『[https://ja.wikibooks.org/wiki/JavaScript/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE#RegExp JavaScript/正規表現 - Wikibooks]』 <source lang="javascript"> /** * 関数 Quote( str ) * * 半角アルファベットと半角数字以外の文字を * すべてエスケープして返す */ function Quote( str ) { return str.replace( /\W/g, "\\$&" ); } // function Quote( str ) { // return str.replace( /\W/g, function( $0 ) { // return "\\" + $0; // } ); // } </source> : ※ JavaScript において <b style="color:#c00;"> $& </b> は "マッチした部分文字列全体" を意味する JavaScript ネイティブの [https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_string_as_a_parameter 特殊変数]。<br> 置換関数 function() の引数がひとつの場合、その引数は <b style="color:#c00;"> $& </b> と同じ意味になるので、上の関数で '''$0''' と記述していることに特別な意味はない('''tmp''' や '''str'''、'''chr''' など任意の文字列でもよい)。 : ※ 後述、[[#関数の「呼び出しコスト」|関数の「呼び出しコスト」]] の項に書いているように、上出のふたつの <source lang="javascript" inline>Quote( str )</source> 関数の処理速度にはちがいが生じる。 <br><br> === 数値を3ケタ区切り(カンマ区切り)にする === <source lang="javascript"> /** * 関数 SeparateNum( num ) * * 数値を3ケタごとにカンマ区切りした文字列にして返す * 引数(推奨):整数値 * ※ 小数点以下が4ケタ以上の場合、小数点以下もケタ区切りされてしまう */ function SeparateNum( num ) { return num.toString().replace( /(\d)(?=(?:\d{3})+(?!\d))/g, "$1," ); } </source> <br> 小数、または半角数字を含む文字列の場合は <source lang="javascript"> /** * 関数 SeparateNum2( num ) * * 数値を3ケタごとにカンマ区切りした文字列にして返す * 引数:任意の数値(を含む文字列) * ※ 小数点以下はケタ区切りしない */ function SeparateNum2( num ) { var num = ( num === 0 || ! num ) ? "0" : num; var a = num.toString().split( /\b/ ); for ( var i = 0, len = a.length; i < len; i ++ ) { if ( a[i] == "." ) { i ++; continue; } a[i] = a[i].replace( /(\d)(?=(?:\d{3})+(?!\d))/g, "$1," ); } return a.join( "" ); } </source> <br> === 数値を小数点以下3ケタの固定長にする === <source lang="javascript"> /** * 関数 NumFix( num ) * * 数値を小数点以下3ケタの固定長小数(文字列)にして返す * 引数(推奨):任意の数値(または数字のみの文字列) */ function NumFix( num ) { if ( typeof num == "number" ) { return num.toFixed( 3 ); } else if ( /^-?\d+(?:\.\d+)?$/.test( num.toString() ) ) { return Number( num ).toFixed( 3 ); } else { return num; } } // 対象が数値( Number 型)であれば toFixed() だけでよい // num = num.toFixed( 3 ); </source> <br> [[#TOP|>> 目次へ]] <br><br> === 数値をケタ埋め(ゼロ埋め)する === ※ 引数の型に応じた関数を使用する。 <source lang="javascript"> /** * 関数 Pad( num ) * * 半角1ケタの数値を0埋めして2ケタの文字列で返す * ※ 引数は「正の整数値」のみ */ function Pad( num ) { return num < 10 ? "0" + num : num; } </source> <source lang="javascript"> /** * 関数 Pad2( str ) * * 文字列中に含まれる半角1ケタの数値を0埋めして2ケタにした文字列で返す * ※ 引数は「文字列値」のみ */ function Pad2( str ) { return str.replace( /[0-9]+/g , function( num ) { return num.length < 2 ? "0" + num : num } ); } </source> <source lang="javascript"> /** * 関数 NumPad2( val ) * * 半角1ケタの数字を0埋めして2ケタにした文字列で返す */ function NumPad2( val ) { return val.toString().replace( /[0-9]+/g, function( num ) { return num.length < 2 ? "0" + num : num; } ); } </source> <br> === 任意の文字列のくりかえしで埋める === ※ Windows XP 用 <source lang="javascript"> /** * 関数 Repeat( str, count ) * * String.prototype.repeat( count ) の代用 */ function Repeat( str, count ) { var ret = ""; for ( var i = 0; i < count; i ++ ) { ret += str; } return ret; } </source> <br> === ストップウォッチ・タイマー === <source lang="javascript"> // 計測開始 ※ ソースコードの先頭付近におくこと var start = new Date(); // 任意のコードを実行 { ; } // ステータスバーに処理時間を表示 Status = ( ( new Date() - start ) / 1000 ).toFixed( 3 ) + " 秒"; </source> <br> === Mery のバージョン情報 === <source lang="javascript"> /** * Mery のバージョン情報 */ var meryVersion = /([^\\]+$)/.exec( editor.FullName )[1] + " " + editor.Version; Status = meryVersion; </source> <br> === JavaScript (JScript) エンジンのバージョン情報 === ※ ref. 『[https://docs.microsoft.com/ja-jp/previous-versions/windows/scripting/cc392005%28v=msdn.10%29 ScriptEngine 関数 (JScript) | Microsoft Docs]』 <source lang="javascript"> /** * JavaScript (JScript) エンジンのバージョン情報 */ var engine = ScriptEngine() + " "; + ScriptEngineMajorVersion() + "."; + ScriptEngineMinorVersion() + "."; + ScriptEngineBuildVersion(); Status = engine; </source> <br> [[#TOP|>> 目次へ]] <br><br> == マクロ覚え書き == === リンク集 === <br> '''[[メインページ|MeryWiki]] / [https://www.haijin-boys.com/ Haijin Boys Online]''' 内 * [[マクロライブラリ#その他|マクロライブラリ]] にある ks 氏らの「[[マクロ覚え書き(開発者向け)|マクロ覚え書き]]」 * 黄身氏の「[[利用者:黄身#覚え書き|覚え書き]]」<br> * MeryWiki の [[マクロリファレンス]] * MeryWiki の [[よくある質問|FAQ (よくある質問)]] * [https://www.haijin-boys.com/discussions Mery 公式フォーラム] <br> ; 外部サイト * MDN web docus(mozzila)の「[https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference JavaScript リファレンス]」<br> * MSDN(Microsoft Docs)の「[https://docs.microsoft.com/ja-jp/previous-versions/windows/scripting/cc392483%28v=msdn.10%29 Microsoft Windows スクリプト テクノロジ]」 * MSDN(Microsoft Docs)の「[https://docs.microsoft.com/ja-jp/previous-versions/windows/scripting/cc409859%28v%3dmsdn.10%29 JScript ランゲージ リファレンス]」 * MSDN(Microsoft Docs)の「[https://docs.microsoft.com/ja-jp/previous-versions/windows/scripting/cc364460%28v=msdn.10%29 WSH リファレンス]」 * MSDN(Microsoft Docs)の「[https://docs.microsoft.com/ja-jp/previous-versions/windows/scripting/cc427968%28v%3dmsdn.10%29 FileSystemObject リファレンス]」<br> * MDN web docus(mozzila)の「[https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions JavaScript ガイド >> 正規表現]」 * MSDN(Microsoft Docs)の「[https://docs.microsoft.com/ja-jp/previous-versions/windows/scripting/cc427946%28v=msdn.10%29 JScript 正規表現の概説]」 * onigmo(鬼雲 / 鬼車・改)の「[https://github.com/k-takata/Onigmo/blob/master/doc/RE.ja 正規表現 ReadMe]」 <br><br> ---- 拙作マクロはポップアップメニューを利用するものが多いので、Tips はその方面の内容に偏ってしまいますが、以下、個人的に注意していることや気付いたことなど。 === アイコン化したマクロ === 通常、フォーカスがアウトプットバーやアウトラインペイン、検索/置換ダイアログにあると、ポップアップメニューやショートカットキーからマクロを起動することはできない。<br> しかし、[[マクロリファレンス:Document インターフェイス|Document]] オブジェクトのかわりに [[マクロリファレンス:Editor インターフェイス#ActiveDocument プロパティ|Editor.ActiveDocument]] で記述したマクロであれば、エディタ領域にフォーカスがない場合でもツールバーアイコンやマクロメニューからマクロを起動できる。 <br><br> ※ ただし、アクティブなタブ以外を操作・編集するマクロにおいては <source lang="javascript" inline>Editor.Documents.Item( dd )</source> などのような記述が必要。 <br><br> マクロをツールバー/マクロバーから使用するために [[マテリアルデザインっぽいアイコンと『小マクロ集』|アイコン]] を作ったり、マクロバーにアイコンを詰め込むために [[#スクショ|試行錯誤]] したりも…。 <br><br> === イベントマクロ === ; [[ヘルプ:マクロ#カスタマイズ|イベントマクロ]] を実行できる "イベント" の種類 : <b style="color:#c00;">赤字</b> は遅延時間を設定できるイベント {|class="wikitable" !フォーカスを受け取った時 | エディタのウインドウがアクティブになったとき。<br> ・「オプション」 などモーダルなダイアログからの復帰時には発動しない<br> ・<source lang="javascript" inline>Editor.ActiveDocument == Document</source> |- !フォーカスを失った時 | エディタのウインドウがアクティブでなくなったとき。<br> ・「検索」 「置換」 ダイアログを開いたときにも発動する…<br> ・<source lang="javascript" inline>Editor.ActiveDocument != Document</source> |- !ファイルを開いた時 | 複数ファイルをまとめて開いたときは、すべて開いたあとに1回だけ。<br> ・複数ファイルをまとめて開いたときには、さいごのタブにしか作用しない |- !ファイルを保存した時 | 複数ファイルをまとめて保存したときは、すべて保存したあとに1回だけ。 |- !更新状態が変更された時 | 「保存済み」 状態から 「未保存*」 状態になったときに発動した。 |- !<span style="color:#c00;">カーソルが移動した時</span> | キャレット位置が動いたとき。<br> ・<span style="color:#c00;">'''遅延''' を大きく設定しないと、すごくジャマ</span> |- !<span style="color:#c00;">スクロールした時</span> | エディタウインドウをスクロールしたとき。<br> ・マウスホイール操作やスクロールバーの操作、<br> PgUp / PgDn / Home / End キーなどでスクロールさせたとき <br> ・文字入力中や、矢印キーなどでのキャレット移動にともなうスクロールでは発動しない |- !<span style="color:#c00;">選択範囲が変更された時</span> | 範囲選択したときと、選択範囲を解除したとき。<br> ・<span style="color:#c00;">'''遅延''' を大きく設定しないと、ドラッグ操作や Shift+矢印キーで範囲選択するときにジャマ</span> |- !<span style="color:#c00;">テキストが変更された時</span> | 入力・削除・置換などの編集操作をしたとき。<br> ・<span style="color:#c00;">'''遅延''' を大きく設定しないと、すごくジャマ</span> |- !<span style="color:#c00;">文字が挿入された時</span> | 文字数が増えたとき?<br> ・選択範囲文字列の [ Ctrl+ドラッグ ] による複製や、 <br> クリップボードからのペースト、<br> マクロの <span style="color:#0000c0;">Document.Write( "hoge" )</span> や <br> <span style="color:#0000c0;">Document.Selection.Text = "hoge"</span> では発動しないようだった <br> ・<span style="color:#c00;">'''遅延''' を大きく設定しないと、すごくジャマ</span> |- !編集モードが変更された時 | 編集モードを変更したとき。<br> ・マクロで編集モードを変更したときも |- !アクティブな文書が変更された時 | 別のタブをアクティブにした後に発動。<br> ・タブを閉じた後や、新規タブを開いたときにも |- !文書を閉じた時 | 複数のタブをまとめて閉じたときは、すべて閉じたあとに1回だけ。<br> ・最後のタブが閉じてエディタウインドウが終了する場合は発動しない |- !タブを移動した時 | タブをドラッグ&ドロップ操作で動かしたとき。<br> ・左側のタブを閉じて右側のタブが動いた場合には発動しない |- !アイドル状態になった時 | (不明) |- !ファイルを保存する前 |ファイルを保存する前。 |} <br> : ※ イベントマクロ であっても、ショートカットキーなどで任意のタイミングに強制的に実行できる。 : ※ イベントマクロでない「マクロA」のコードでファイルを 開く または 閉じる をおこない、それ以降にも「マクロA」のコードが続いている場合は、ファイルを開いた時/閉じた時の「イベントマクロB」は発動しないことがある。 <br> * sukemaru の Mery では、「[[バイト数#バイト数と文字数・行数|バイト数]]」マクロと「[[検索ヒット数表示(選択文字列)#機能強化バージョン|文字数・行数・ヒット件数(選択文字列)]]」マクロの機能を統合したマクロに「ファイルを開いた時」「'''選択範囲が変更された時'''」「'''テキストが変更された時'''」「'''文字が挿入された時'''」「アクティブな文書が変更された時」イベントを設定している('''太字''' のイベントには遅延時間を 1 秒に設定。 ロースペックな PC ゆえ、一定以上の長さのファイル/タブにおいては機能を制限してある)。<br> 遅延時間が短すぎると、"文字列や選択範囲を変更するような他のマクロの実行後に、そのマクロからのステータスメッセージが読めなくなるから"、という意味もある。 * また、「[[編集モードの自動選択#sukemaru 版2(include版)|編集モードの自動選択 (include版)]]」マクロを「ファイルを開いた時」「文書を閉じた時」イベントに、[[編集モードの自動選択#サブマクロ|補助マクロ]] を「ファイルを保存した時」イベントに設定して、それなりに按配よく運用できている。<br> ([[includeライブラリ|include ライブラリ]] を利用して、複数のファイルを開いたときにも、それぞれのタブにたいして編集モードの変更や書き換え禁止を適用できるようにしてある) <br><br> [[#TOP|>> 目次へ]] <br><br> === ポップアップメニュー === sukemaru の環境では、メニューに表示するアイテムが 5000 件とか 10000 件とかを超えるとポップアップメニューが表示されず(エラーメッセージも表示されず)にマクロが終了してしまうことがある…。<br> 「[[ポップアップメニューで検索先にジャンプ#sukemaru 版|検索ジャンプ]]」マクロの include 版で発生するのだが、ポップアップメニューを表示する直前にステータスバーに表示すべき情報を <source lang="javascript" inline>ClipboardData.SetData( Status );</source> でコピーしておくと、<br> ヒット数: 21,525 件 ( 4 件目 ) ・ 21,525 行 ( 4 行目 ) / 全体の行数: 61,001 行 [ 12. 906 秒 ] のようにデータが残ったので、前処理段階でコケたのではなくポップアップメニューの描画のさいにコケていたようだ。<br> また、11 万行の文書から空行を検索したとき、ステータスバーに以下のメッセージを表示して 一致: 27,814 行 / 空白行数: 27,849 行 / 全体の行数: 111,186 行 [ 6. 485 秒 ] ポップアップメニューも表示されたが、実際に表示されていたアイテム数は 6000 件台で、20000 件以上のアイテムは表示されずにスポイルされてしまっていたということもあった。<br><br> 以下の単純なコードでアイテム 10000 件のポップアップメニューを表示させようとしても、4000 件ぐらい(4000 前後で不定)までしか表示されない…。 <source lang="javascript"> var m = CreatePopupMenu(); for ( var i = 1; i <= 10000; i ++ ) { m.Add( "" + i, i ); } var r = m.Track( mePosMouse ); </source> <br> 環境依存の不具合かもしれないが、はて…? <br><br> ==== オプションフラグ ==== [[マクロリファレンス:PopupMenu インターフェイス#Add メソッド|PopupMenu.Add() メソッド]] の第三引数 '''Flags''' : int を数値化すると <source lang="javascript"> meMenuChecked = 1 meMenuGrayed = 2 meMenuChecked + meMenuGrayed = 3 meMenuSeparator = 4 </source> となるので、真偽値が <source lang="javascript" inline>true=1</source> / <source lang="javascript" inline>false=0</source> で評価されることを利用して、真偽値を返す変数や条件式を代入することができる(ただし Number 型に変換する必要がある → 算術演算子「+」をつけるなど)。 <source lang="javascript"> var menu = CreatePopupMenu(); var hoge = true; var fuga = false; menu.Add( "Hoge", 1, + hoge ); // "+" を付けて数値化すると meMenuChecked menu.Add( "Fuga", 2, !fuga * 2 ); // (!fuga = 1) *2 なので meMenuGrayed var num = menu.Track( mePosMouse ); </source> : ※ オプションフラグ ''meMenuGrayed'' を使用して条件付きで特定の項目をグレーアウトするだけでなく、<source lang="javascript" inline>menu.Add( ... );</source> の行を [https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#if...else_statement if() 文] で囲むなどすれば、状況に応じたメニュー項目だけを表示させることもできる。 <br><br> ==== アクセラレータ ==== ポップアップメニューのラベルの文字列に「半角アンパサンド記号 '''<q>&</q>''' + 半角英数字 (またはアスキー記号)」を付記することで、アクセラレータ(アクセスキー)を設定することができる。<br> ラベルの先頭に連番数字などがある場合は、アンパサンド記号を付加することで、数字をアクセラレータにするとよい。<br> そのさい、Shift キー付きでの入力が必要な記号は Shift キーなしで入力可能なキーのラベルと同一視される (e.g. 「'''&#'''」で '''<q>#</q>''' 記号をアクセラレータに指定した場合、JIS 配列のキーボードでは <kbd>3</kbd> キーがアクセラレータになる)。 * <span style="color:#0000c0;">'''<q>&</q>''' 記号でアクセラレータ化する文字の位置は限定されないが、<u>最初の '''<q>&</q>''' 記号のうしろの文字がアクセラレータになる</u></span>( … とおもわれる ← ポップアップメニュー内で「下線つきで表示される文字」と一致しないことがある)。 * <span style="color:#c00;">全角文字はアクセラレータにできない。</span> * <span style="color:#c00;">ラベル文字列に含まれる '''<q>&</q>''' 記号はすべてエスケープされてしまい、ポップアップメニューには表示されなくなるので、ラベルに '''<q>&</q>''' 記号を表示させたいときは、'''<q>&&</q>''' のように二重に記述する必要がある。</span><br> → 不特定の文字列をラベルにする場合は、あらかじめ <source lang="javascript" inline>String.replace( /&/g, "&&" )</source> と記述するとよい。 : ※ '''<q>&&</q>''' で表示される '''<q>&</q>''' 記号は、アクセラレータにならない。 * <span style="color:#0000c0;">同じキーが重複してアクセラレータに指定されていると、そのキーを押した場合、アイテム間をトグル移動する(その場合は <kbd>Enter</kbd> キーで決定する)。</span><br> → アイテム数が多くなるメニューの場合、<source lang="javascript" inline>menu.Add( "キャンセル & ", 0 );</source> という行を 10 件とか 20 件ごとに挿入すると、スペースキーでポップアップメニュー内をスクロールさせることができる。 : ※「'''&<span style="background:#bfdfff;"> </span>'''」(半角アンパサンド+半角空白) で半角スペースをアクセラレータに指定したアイテムは、<kbd>Space</kbd> キーがアクセスキーになる。 <source lang="javascript"> /* アクセラレータを付加する */ var menu = CreatePopupMenu(); var piyo = "LOVE & PEACE & ..."; menu.Add( "アイテム1(&1)", 1 ); // [1] キーがアクセラレータ menu.Add( "アイテム&2", 2 ); // [2] キーがアクセラレータ menu.Add( "0&3 アイテム3", 3 ); // [3] キーがアクセラレータ menu.Add( "&Hello &World &4", 4 ); // [H] キーがアクセラレータ menu.Add( piyo.replace( /&/g, "&&" ) + "(&5)", 5 ); // [5] キーがアクセラレータ menu.Add( piyo + "(&6)", 6 ); // スペースキーがアクセラレータ menu.Add( "※※※※", 0, meMenuSeparator ); // meMenuSeparator があると第一引数の文字列は無視される menu.Add( "キャンセル & ", 0 ); // スペースキーがアクセラレータ // 5つめのアイテムは "LOVE & PEACE & ..." と表示されるが // 6つめのアイテムは "LOVE PEACE ..." と表示される // ※ 6つめのアイテムと最後のアイテムでアクセラレータが重複している var ret = menu.Track( 0 ); </source> <source lang="javascript"> /* 10 行ごとに「キャンセル」項目を挿入し、スペースキーでスクロール可能にする */ var arr = document.Text.split( "\n" ); var menu = CreatePopupMenu(); for ( var i = 0; i < arr.length; i ++ ) { if ( i > 0 && i % 10 == 0 ) { menu.Add( "", 0, meMenuSeparator ); menu.Add( "キャンセル & ", 0 ); menu.Add( "", 0, meMenuSeparator ); } menu.Add( arr[i].slice( 0, 30 ), i + 1 ); } var y = menu.Track( 0 ); if ( y ) { document.selection.SetActivePoint( mePosLogical, 1, y ); } </source> <br> ==== ラベルの整形 ==== * 基本的にポップアップメニュー(警告・確認ダイアログなどもだが)は UI フォントで表示されるので、文字列が英数字の羅列の場合には読みづらい ( …と個人的に感じている)。<br> : 文書内の文字列など不特定の文字列をラベル化する「[[ポップアップメニューで検索先にジャンプ#sukemaru 版|検索ジャンプ]]」や「[[ブックマーク一覧ジャンプ#sukemaru 版|ブックマークジャンプ]]」、「[[「クリップボード履歴」メニューのマクロ化|クリップボード履歴メニュー]]」マクロでは、読みづらい半角アルファベットや記号を全角化させるなどしている。 <source lang="javascript"> /** * ポップアップメニューに表示するラベルを整形する * * ※ 不要な置換については .replace( ... ) の行を 削除/コメントアウト してよい * * ・行頭空白を除去 * ・空白文字を圧縮: →「›」(U+203A) に置換 * ・文字数を切り詰め( String.slice メソッド ) * ・改行記号を可視化: →「↲」(U+21B2) または「⏎」(U+23CE) に置換 * ・削られてしまう「&」を補完 * ・「¥」(U+005C) を「∖」(U+2216) に置換 * ・特殊な空白文字を豆腐に置換: →「⊠」(U+22A0) または「▯」(U+25AF) * ・判読しづらい ascii 記号 !"%'(),.:;@[]`{|} を全角に置換 * ・「a-z」を全角に置換 */ var y = document.selection.GetActivePointY( mePosLogical ) // 行番号 var str = document.GetLine( y, 0 ); // 行の文字列 var menuWidth = 55; // 切り捨ての閾値 var reg = /[\u00A0\u1680\u180e\u2000-\u200A\u2028\u2029\u202F\u205F\uFEFF]/g; var menuKey = str.replace( /^[\t ]+/, "" ) .replace( /(?:\t|[ ]{3,}|[ ]{2,})+/g, " › " ) .slice( 0, menuWidth + 1 ) .replace( /\r?\n/g, " ↲ " ) .replace( /[&]/g, "&&" ) .replace( /[\\]/g, "∖" ) .replace( reg, "▯" ) .replace( /[!"%'(),.:;@\[\]`a-z{|}]/g, function( tmp ) { return String.fromCharCode( tmp.charCodeAt( 0 ) + 0xFEE0 ) } ); // 文字数を切り詰めた場合は「 ...」を付加 menuKey += ( str.length > menuWidth ) ? " ..." : ""; // 文字列の先頭に行番号(連番)を付加する // パターン➀: アクセラレータつきの番号(左端揃え)を付加 var num = "&" + y; menuKey = num + ": " + menuKey; // パターン➁: 番号(左端揃え)の 末尾1桁 をアクセラレータにするなら var num = String( y ).replace( /\d$/, "&$&" ); menuKey = num + ": " + menuKey; // パターン➂: 連番が多いときは「空白文字でケタ埋め (右端揃え)」するとよい // 例: EN SPACE「 」(U+2002) でケタ埋めして、末尾1桁 をアクセラレータにする var numWidth = String( d.GetLines( 0 ) ).length; var num = ( " " + y ).slice( - numWidth ).replace( /\d$/, "&$&" ); menuKey = num + ": " + menuKey; </source> : ※ このコードでは色々と unicode 文字を使用しているので、マクロの JS ファイルは UTF-8 などの形式で保存しなければならない。 <!-- : ※ Mery のダイアログのフォントは Mery.ini の「[[よくある質問#ダイアログのフォントを変更したい|隠しオプション]]」により任意のフォントに変更できるらしいので、個人的にしか使わない非公開マクロであれば、ラベルの整形についてはあまり気にする必要はないかも。 → ポップアップメニューにはカスタムフォントは適用されない --> <br> * また、「[[#マクロライブラリに投稿したマクロ|マクロライブラリに投稿したマクロ]]」の節の画像リンク(サムネイル)のように、タブインデントや連番のケタ埋め、サブメニューの活用などの工夫で、ポップアップメニューの体裁はある程度自分好みにカスタマイズできる。 <br><br> ==== ステータスバーの表示 ==== ポップアップメニュー表示のさいにステータスバーに任意の文字列を表示する場合は、 [[マクロリファレンス:PopupMenu インターフェイス#Track メソッド|PopupMenu.Track()]] の行の直前に ''[[マクロリファレンス:Window インターフェイス#Status プロパティ|Status]] = "hoge";'' を記述する。<br> ※ <syntaxhighlight lang="javascript" inline>PopupMenu.Track()</syntaxhighlight> が発動した時点でエディタウインドウ本体は停止するので、直後に <syntaxhighlight lang="javascript" inline>Status = "hoge";</syntaxhighlight> を記述しても、ポップアップメニューの項目を選択するかメニューをキャンセルするまで表示されない。 <source lang="javascript"> // e.g. ポップアップメニュー表示までのマクロの処理時間をステータス表示させる // 計測開始 ※ ソースコードの先頭付近におくこと var start = new Date(); // 文書の各論理行を配列におさめ、ポップアップメニュー項目に var ay = document.selection.GetActivePointY( mePosLogical ); var lineArray = document.Text.split( "\n" ); var menu = CreatePopupMenu(); for ( var i = 0, y, flag; i < lineArray.length; i ++ ) { y = i + 1; flag = ( y == ay ) ? meMenuChecked : 0; menu.Add( y + ": " + lineArray[i].slice( 0, 50 ), y, flag ); } // ステータスバーに処理時間を表示 Status = ( ( new Date() - start ) / 1000 ).toFixed( 3 ) + " 秒"; // ポップアップメニューを表示 var yy = menu.Track( mePosMouse ); // 選択した行に移動する if ( yy ) { document.selection.SetActivePoint( mePosLogical, 1, yy, false ); } </source> <br> : ※ 順番が逆になると、ステータスはポップアップメニュー項目を選択(またはキャンセル)するまで表示されない。 : ※ ポップアップメニューにかぎらず、[[マクロリファレンス:Window インターフェイス#Alert メソッド|警告 (Alert)]] や [[マクロリファレンス:Window インターフェイス#Confirm メソッド|確認 (Confirm)]]、 [[マクロリファレンス:Window インターフェイス#Prompt メソッド|入力 (Prompt)]] ダイアログなどモーダルなポップアップウインドウを表示させる場合も、同様に <syntaxhighlight lang="javascript" inline>Status = "hoge";</syntaxhighlight> を先に記述する必要がある。 : ※ Mery メインウインドウのメニューバー項目のような、マウスホバーで動的にステータス表示を変更させる制御はできない。 <br><br> [[#TOP|>> 目次へ]] <br><br> ==== 配列からポップアップメニューを生成 ==== [https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Loop_Statements/for_Statement for 文] などの [https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Loop_Statements/ ループ処理] によって配列からポップアップメニューのアイテムを生成する場合に、[[マクロリファレンス:PopupMenu インターフェイス#Add メソッド|PopupMenu.Add() メソッド]] の第二引数 '''Id''' (※通常は 1 ~ )と配列のアイテムのインデックス '''[ i ]''' の値(※通常は 0 ~ )を一致させたいときは、配列の先頭にダミーまたは空の要素を置いておき、ループ処理の開始インデックスを 1 にする。 <source lang="javascript"> var a = new Array( "" ); // 先頭に空のダミー要素を入れておく a.push( "あああ" ); a.push( "いいい" ); a.push( "ううう" ); // a = [ "", "あああ", "いいい", "ううう" ] となる var menuA = CreatePopupMenu(); for ( var i = 1; i < a.length; i ++ ) { // 開始値を 1 にすると menuA.Add( a[i], i ); // Id を ( i + 1 ) にする必要がない } var num = menuA.Track( mePosMouse ); // c.f. 空要素なしの配列 [ "あああ", "いいい", "ううう" ] をループ処理する場合 var b = [ "あああ", "いいい", "ううう" ]; var menuB = CreatePopupMenu(); for ( var i = 0; i < b.length; i ++ ) { menuB.Add( b[i], i + 1 ); // Id を 1 ~ にするには ( i + 1 ) } </source> ==== サブメニュー ==== サブメニューを組みこむ場合、通常はそれぞれの PopupMenu オブジェクトをあらかじめ宣言しておくものだが、[[マクロリファレンス:PopupMenu インターフェイス#AddPopup メソッド|PopupMenu.AddPopup() メソッド]] 内の第二引数で定義することもできる。<br> [[マクロリファレンス:PopupMenu インターフェイス#Add メソッド|PopupMenu.Add() メソッド]] が大量に並んでいる項目群の一部をサブメニュー化して整理したくなったときなどに、サブメニューオブジェクトの宣言行を用意しなくて済むので便利である。<br> サブメニューを多重に含むコードの場合、字下げ(インデント)を活用することで、メニューの階層構造を把握しやすくできる。 <source lang="javascript"> var mainMenu = CreatePopupMenu(); mainMenu.Add( "アイテム1", 1 ); mainMenu.AddPopup( "サブメニュー1", subMenu1 = CreatePopupMenu() ); subMenu1.Add( "アイテム2", 2 ); subMenu1.AddPopup( "サブメニュー2", subMenu2 = CreatePopupMenu() ); subMenu2.Add( "アイテム3", 3 ); var r = mainMenu.Track( 0 ); Alert( ret > 0 ? mainMenu.GetText( r ) : "キャンセル" ); </source> <br> * 配列やオブジェクトからポップアップメニューの生成をするときにサブメニューを利用する場合、あらかじめサブメニューのラベルや各要素の振り分け方が決まっていれば難しいことはないが、<span style="color:#c00;">要素が不定数の配列やオブジェクトを複数のサブメニューに振り分けるのは簡単ではない…。</span> : → 組み込み関数「[[ポップアップメニューを手軽に扱う]]」や「[[階層化マクロメニュー]]」マクロなどのソースコードを参考にして自力でコードを組むか、組み込み関数「[[ポップアップメニューを「n*十件ずつ」のサブメニューに自動分割する]]」で一定数ごとにサブメニュー項目を自動生成して要素を放り込むしかない。 <br> 以下は、自動分割サブメニューのサンプルコード。 <source lang="javascript"> // ポップアップメニューの項目にする任意の配列を用意する var itemArray = []; // ※ アイテムとして 1 ~ 100 の数値を放り込んでおく for ( var i = 0; i < 100; i ++ ) { itemArray.push( i + 1 ); } var len = itemArray.length; var mainMenu = CreatePopupMenu(); var subMenu, id; // 配列からポップアップメニューを生成する for ( var i = 0, j = 1; i < len; i ++ ) { // アイテムを 20 件ずつ分割収容するサブメニューを自動生成する if ( i % 20 == 0 ) { // ※ ループ処理 20 回ごとに subMenu を新しいサブメニュー項目として更新する subMenu = CreatePopupMenu(); // 「サブメニュー 1」からの連番つき定型文字列 mainMenu.AddPopup( "サブメニュー " + ( j ++ ), subMenu ); } // アイテムをサブメニューに収容する id = i + 1; // 「アイテム 1」からの連番つき定型文字列 subMenu.Add( "アイテム " + id, id ); } // ポップアップメニューを表示 var r = mainMenu.Track( 0 ); Alert( r > 0 ? mainMenu.GetText( r ) : "キャンセル" ); </source> ※ 組み込み関数「[[ポップアップメニューを「n*十件ずつ」のサブメニューに自動分割する]]」のソースコードでは、サブメニューオブジェクト専用の配列 smArray を用意して <source lang="javascript" inline>smArray.push( CreatePopupMenu() );</source> → <source lang="javascript" inline>menu.AddPopup( label, smArray[ smId ] );</source> としているが、上のサンプルコードのようにループ処理内で <source lang="javascript" inline>subMenu = CreatePopupMenu();</source> を使いまわしするだけでも新規のサブメニューアイテムを生成できるようだ。 <br><br> * [[マクロリファレンス:PopupMenu インターフェイス#AddPopup メソッド|PopupMenu.AddPopup() メソッド]] では [[マクロリファレンス:PopupMenu インターフェイス#Add メソッド|Add() メソッド]] の第三引数(''meMenuChecked, meMenuGrayed, meMenuSeparator'')は使用できない。 : サブメニュー内のすべてのアイテムが無効(グレーアウト)になる条件でも、サブメニュー見出しを無効化することはできないので、サブメニュー見出しが表示されなくなるように(またはグレーアウトされるように) <source lang="javascript" inline>PopupMenu.AddPopup()</source> 周りを [https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#if...else_statement if() 文] で囲うしかない(※ メニューの階層構造が複雑な場合に、ソースコードが見づらくなってしまうが…)。 <source lang="javascript"> // e.g. 編集モードが Text ならサブメニューを表示する // ※ Text 以外ならグレーアウトさせた "サブメニュー" アイテムを表示 var menu1 = CreatePopupMenu(); var menu2 = CreatePopupMenu(); if ( document.Mode == "Text" ) { menu1.AddPopup( "サブメニュー", menu2 ); menu2.Add( "アイテム2", 2 ); } else { menu1.Add( "サブメニュー", 0, meMenuGrayed ); } menu1.Add( "アイテム1", 1 ); var r = menu1.Track( mePosMouse ); </source> <br> : また、上出の「自動分割サブメニュー」の組み込み関数を制作するさい、チェックつきアイテムを含むサブメニュー見出しにもチェックを付けられるようにしたかったが、これも無理だった。<br> → サブメニューオブジェクトを <syntaxhighlight lang="javascript" inline>AddPopup()</syntaxhighlight> する前に孫アイテムを <syntaxhighlight lang="javascript" inline>Add()</syntaxhighlight> しておき、チェックつきアイテムを含むかどうかの条件文でサブメニューオブジェクトのラベルを生成(サブメニューラベルの先頭に "'''*'''\t" や "'''✔'''" などを付加)してから <syntaxhighlight lang="javascript" inline>AddPopup()</syntaxhighlight> することはできるが、 ''meMenuChecked'' とおなじチェックマークをつけられるわけではないので、コードが煩雑になるわりにあまり報われない努力となる…。 <br><br> ==== マクロの動作設定を変更可能にする ==== 拙作マクロは、ポップアップメニューを使うものにかぎらず動作設定用の項目が多い。<br> ポップアップメニューマクロでないものは、通常、頻繁に動作設定を弄る必要はないが、sukemaru 好みの動作方式は一般的嗜好と合致しないであろうことから公開用のマクロにするにあたってカスタマイズ可能な「設定項目 (変数)」ににして調整しなおすことが多い…。 <br><br> <span style="color:#0000c0;"> ポップアップメニューマクロであれば、メニュー項目から動作設定をカスタマイズできるようにコーディングすることができる。</span> <br> * まず、[[利用者:Masme|masme]] 氏の「[[行並べ替え]]」や「[[連番を挿入]]」マクロのように、[https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/do...while do ... while() 文] によるループを利用して、動作設定の既定値を何度も書き換えながらポップアップメニューを再描画する方法がある。 : 動作設定の変更内容はマクロの完了時に破棄されてしまうので、同じマクロを連続して利用することが多いならば、マクロメニューの [[ヘルプ:マクロ#編集|編集]] コマンドからソースコードを開いて、初期設定項目(変数)の既定値を書き換えておくとよい。 * sukemaru の場合は、「[[ポップアップメニューで検索先にジャンプ#include版|検索ジャンプ]]」「[[ブックマーク一覧ジャンプ#include版|ブックマークジャンプ]]」や「[[ファイルを読み直す・開きなおす#include版|読みなおし]]」マクロなどで、【include 版】と称するものを作っている。 : これらにおいては、[[includeライブラリ|include ライブラリ]] の IO クラス(IO.js)の関数メソッド <syntaxhighlight lang="javascript" inline>Serialize() / Deserialize()</syntaxhighlight> を利用して、ポップアップメニュー内の「設定変更」サブメニューから変更した [[#外部ファイルにマクロの設定などを書き出す|設定値を外部ファイル(JSON ファイル)に保持]] できるようにしている。 : カスタマイズしながら実行するのも、カスタマイズした動作設定を維持したままでままで再実行するのも容易にはなったが、コードが煩雑になって他のマクロに流用しづらくなってしまっている…。 : ※ 非 include 版では、「設定変更」サブメニューや masme 氏のマクロのような処理コードは入れず、動作設定の変更方法はソースコードの変数の値の書き換えのみとしている。 <br><br> ==== GetKeyState.exe の活用 ==== pizz 氏作成の「[[GetKeyState.exe(キー状態取得実行ファイル)]]」を使うと、マクロ実行(開始)時の修飾キーの押し下げ状態でポップアップメニューに表示する項目を変化させたり、メニュー内のアイテムを選択(クリック)するときの修飾キーの押し下げ状態で実行するコマンドを変化させることができる。<br> マクロ開始時に仕込むとショートカットキーの割りあて方が制限されたり、メニュー表示までにタイムラグが生じてしまうこともあるが、アイテム選択後のコマンド実行時に仕込めばあまり問題にならない。<br> ※ ただし、Mery のポップアップメニューは <kbd>Alt</kbd> キーでキャンセルされてしまうので、コマンド実行時に仕込めるのは <kbd>Ctrl</kbd>/<kbd>Shift</kbd> キーにかぎられる。 <br><br> : ref. [[GetKeyState.exe(キー状態取得実行ファイル)#実装例|GetKeyState.exe の実装例: サンプルコード3]] <br><br> [[#TOP|>> 目次へ]] <br><br> === 配列 === <source lang="javascript"> var arr1 = []; arr1[arr1.length] = "hoge"; arr1[arr1.length] = "fuga"; arr1[arr1.length] = "piyo"; ... ; </source> 個人的な所感であるが、配列の要素を羅列して定義するさいに、上のような書き方は好きではない。以下のような書き方のほうが、スッキリしていてよい。 <source lang="javascript"> var arr2 = []; arr2.push( "Hoge" ); arr2.push( "Fuga" ); arr2.push( "Piyo" ); ... ; </source> <source lang="javascript"> var arr3 = [ "HogeHoge", "FugaFuga", "PiyoPiyo", ... ]; // ※ カンマの位置は、前でも後ろでも </source> <br> === 複数行の論理行を範囲選択(末尾改行を含まない) === 文字列操作のマクロでしばしば必要になる処理。<br> ※ 行番号のクリックやドラッグによる行単位の範囲選択をしたときや [[マクロリファレンス:Selection インターフェイス#SelectLine メソッド|Selection.SelectLine()]] のあとなど、選択範囲末尾の改行(次行の先頭)を除外するときに必要。 <br><br> ※ 以下のふたつのコードは、左下(行頭位置)から右上に矩形選択した状態から実行したときの結果が異なる。 <source lang="javascript"> var s = document.selection; // もとの選択範囲の座標を取得 var ty = s.GetTopPointY( mePosLogical ); var by = s.GetBottomPointY( mePosLogical ); var bx = s.GetBottomPointX( mePosLogical ); // 選択範囲の末尾が行頭 x = 1 にあるときの調整 if ( bx == 1 && ty != by ) { by -= 1; } // 論理行全体を範囲選択(さいごの末尾改行 \n をふくめない) s.SetActivePoint( mePosLogical, 1, by ); s.EndOfLine( false, mePosLogical ); s.SetAnchorPoint( mePosLogical, 1, ty ); </source> <source lang="javascript"> // または masme 氏作成の「コメントマーク付け外し」マクロより // ※ 左下(行頭位置)から右上に矩形選択した場合も考慮したコード var s = document.selection; var ty = s.GetTopPointY( mePosLogical ); var by = s.GetBottomPointY( mePosLogical ); var bx = s.GetBottomPointX( mePosLogical ); var br = ( s.Text.match( /\n/g ) || [] ).length; if ( bx === 1 && by - ty === br && br ) { by --; } s.SetActivePoint( mePosLogical, 1, by ); s.EndOfLine( false, mePosLogical ); s.SetAnchorPoint( mePosLogical, 1, ty ); </source> : ref. Mery 公式フォーラム 『[https://www.haijin-boys.com/discussions/4431 マクロについてアドバイスお願いします]』 <br><br> === 選択範囲の 先頭位置/末尾位置 === 選択範囲の 開始(キャレットなし)/終了(キャレットあり) の位置は [[マクロリファレンス:Selection インターフェイス#GetAnchorPos メソッド|Selection.GetAnchorPos()]] と [[マクロリファレンス:Selection インターフェイス#GetActivePos メソッド|Selection.GetActivePos()]] とで取得できるが、先頭/末尾 の位置はそれらをもとにして前後関係を割りだす必要がある。 <br> <span style="color:#c00;">※ '''GetTopPos()''' や '''GetBottomPos()''' というメソッドはない。 </span><br> <source lang="javascript"> var ancPos, actPos, topPos, endPos; ancPos = document.selection.GetAnchorPos(); // 選択開始位置 actPos = document.selection.GetActivePos(); // 選択終了位置(キャレット位置) topPos = Math.min( ancPos, actPos ); // 選択範囲の先頭位置(左・上) endPos = Math.max( ancPos, actPos ); // 選択範囲の末尾位置(右・下) // topPos と endPos の取得は以下のような記述方法でも可 topPos = ( ancPos < actPos ) ? ancPos : actPos; endPos = ( ancPos < actPos ) ? actPos : ancPos; </source> <br> === 変換・挿入した文字列を範囲選択するとき === <source lang="javascript"> var str = "hoge"; document.Write( str ); // または document.selection.text = str; </source> のあとで文字列 '''hoge''' を範囲選択したい場合は、<source lang="javascript" inline>document.selection.CharLeft( str.length, true );</source> ではなく <source lang="javascript"> // キャレットは選択範囲の末尾位置 document.selection.SetAnchorPos( document.selection.GetActivePos() - str.length ); // または(キャレットは選択範囲の先頭位置) document.selectionSetActivePos( document.selection.GetActivePos() - str.length, true ); </source> と記述すること。 <br><br> ※ ''[[マクロリファレンス:Selection インターフェイス#CharLeft メソッド|Selection.CharLeft]]( str.length, true )'' の場合、文字列 ''str'' が「折り返し」にかかってしまったときに想定どおりの選択範囲にならない。 : ref. Mery 公式フォーラム 『[https://www.haijin-boys.com/discussions/3740 "折り返し表示" での CharRight( document.selection.Text.length - 1 ) について]』 <br><br> [[#TOP|>> 目次へ]] <br><br> === Collapse() メソッド とキャレット位置 === [[マクロリファレンス:Selection インターフェイス#Collapse メソッド|Selection.Collapse() メソッド]] で引数 '''''meCollapseEnd''''' を指定した場合は Selection.SetActivePos( Selection.GetActivePos() ) '''''meCollapseStart''''' を指定した場合は Selection.SetActivePos( Selection.SetAnchorPos() ) と意味的には同じである。 <br><br> ※ 引数を省略した場合は ''meCollapseStart'' として動作する。<br> ※ ''meCollapseStart / meCollapseEnd'' はそれぞれ「選択開始位置」と「選択終了位置 (キャレット位置)」を指し、「選択範囲の 先頭/末尾」ではない。<br> ※ [[マクロリファレンス:Selection インターフェイス#SelectLine メソッド|Selection.SelectLine()]] や [[マクロリファレンス:Selection インターフェイス#SelectWord メソッド|Selection.SelectWord()]] メソッドなどでの範囲選択では「キャレット位置=選択範囲の末尾」となり、[[マクロリファレンス:Selection インターフェイス#Find メソッド|Selection.Find()]] や [[マクロリファレンス:Selection インターフェイス#FindRepeat メソッド|Selection.FindRepeat()]] メソッドでの範囲選択では「キャレット位置=選択範囲の先頭」なので、つづけて Collapse() メソッドを使用するときは注意が必要 (…というほどのことでもないか?)。 <br><br> === Find() メソッド と FindRepeat() メソッド の 定数 === <span style="color:#0000c0;">※ [https://github.com/haijinboys/mery-plugin-sdk/blob/master/SDK/C/Basic/plugin.h 定数] の数値は</span> Alert( <span style="color:#408040;">meFindNext</span> ); <span style="color:#0000c0;">のような1行マクロで調べることができる。</span> <br><br> ; [[マクロリファレンス:Selection インターフェイス#Find メソッド|Find() メソッド]] document.selection.'''Find()''' メソッド 指定のパターンを検索します。  0: meFindPrevious カーソル位置から前を検索します。  1: meFindNext カーソル位置から次を検索します。  2: meFindReplaceCase 検索する単語の大文字と小文字を区別します。  4: meFindReplaceOnlyWord 完全に一致する単語を検索します。  8: meFindAround 文書の末尾まで検索したら先頭から検索を開始します。 16: meFindReplaceRegExp 正規表現で検索します。 <br> : <span style="color:#c00;">「検索/置換」ダイアログのオプションフラグをすべて OFF にする方法</span> として <source lang="javascript"> document.selection.Find( "", 0 ); // 空文字列の検索でオプションフラグを解除する </source> : というコードを挟み込むという手がある(第二引数には 0 または 1 を指定する)。 :: ref. Mery 公式フォーラム 『[https://www.haijin-boys.com/discussions/3398 空検索の動作、など]』 : これは、マクロ実行時に「[[ヘルプ:検索|検索/置換]]」ダイアログが開かれていないときにかぎり、マクロ終了後の「検索/置換」ダイアログのオプション項目のチェック ON/OFF の状態にも引き継がれる(次回の「検索/置換」や「[[ヘルプ:検索#次を検索|次/前を検索]]」「[[ヘルプ:検索#次の文字列を検索|次/前の文字列を検索]]」コマンドなどにも引き継がれる)。 : ※ ただし、「終了したら閉じる」と、[https://www.haijin-boys.com/software/mery/mery-2-6-10#1 ベータ版 2.6.10] で追加された「インクリメンタルサーチ」のオプションフラグはマクロから解除することができない。 : ※ ''meFindReplaceOnlyWord'' と ''meFindReplaceRegExp'' は排他関係なので、<span style="color:#c00;">同時に使用した場合 ''meFindReplaceRegExp'' は適用されるが ''meFindReplaceOnlyWord'' は無視される</span> : (検索ダイアログで「正規表現」オプションを有効化したときに「単語のみ」オプションが無効になるのと同様)。 <br> ; [[マクロリファレンス:Selection インターフェイス#FindRepeat メソッド|FindRepeat() メソッド]] document.selection.'''FindRepeat()''' メソッド 前回検索した文字列を検索します。  0: meFindPrevious カーソル位置から前を検索します。  1: meFindNext カーソル位置から次を検索します。  2: meFindRepeatWord 選択範囲が空の場合はカーソル位置の単語を検索します。 : <source lang="javascript" inline>FindRepeat()</source> メソッドでは定数 ''meFindReplaceCase'' や ''meFindReplaceOnlyWord , meFindAround , meFindReplaceRegExp'' が使用できないが、 <span style="color:#0000c0;">'''直前''' の「検索/置換」コマンドや <source lang="javascript" inline>Find() / Replace()</source> メソッドで使用したこれらのオプションのうち ''meFindReplaceRegExp'' 以外の三つの ON/OFF 状態が '''継承''' される。</span> : よって、<source lang="javascript" inline>FindRepeat()</source> メソッドで ''meFindReplaceCase'' や ''meFindReplaceOnlyWord , meFindAround'' を適用した検索をしたいばあいは、以下のように記述すればよい。 : ※ ''meFindReplaceRegExp'' があっても <source lang="javascript" inline>FindRepeat()</source> の実行時には無視される。 <source lang="javascript"> // 1.空文字列の検索をして、任意のオプションフラグを設定(付加)する document.selection.Find( "", meFindNext + meFindReplaceCase + meFindAround ); // 2.「前回検索した文字列を検索」または キャレット位置の単語で「次の文字列を検索」 document.selection.FindRepeat( meFindNext + meFindRepeatWord ); // -------------------------------------------------- // // 3.最後にオプションフラグを解除しておきたいなら document.selection.Find( "", 0 ); </source> : ※ ➂ のコードを最後に使用した場合、「検索/置換」ダイアログのオプションフラグも解除される。 <br> * ちなみに、sukemaru は検索ダイアログの履歴に残るマクロや、検索ハイライトが残るマクロが好きではないので、なるべく <source lang="javascript" inlineSelection.Find/Replace()</source> を使わずに JavaScript ネイティブの [https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf String.indexOf( searchValue, fromIndex ) メソッド] や [https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace String.replace( regexp ) メソッド] で検索/置換を行なったり、 [[マクロリファレンス:Document インターフェイス#HighlightFind プロパティ|Document.HighlightFind = false]] で検索マーカーを消すなどする自作マクロが多い ([https://www.haijin-boys.com/software/mery/mery-2-6-0#3 自動マーカー] で背景色をハイライトする設定にしているから「検索ハイライト」はいらなくて…)。 : [ [https://www.haijin-boys.com/software/mery/mery-tips#2 Ctrl+Shift+↑ / ↓] ] の機能も「[[次/前の文字列を検索・改]]」マクロに置きかえてしまったので、検索ダイアログを開くのは正規表現で検索するときぐらいかも。 <br><br> === 文字列操作が空振りしたときは undo 履歴に残さない === * 条件付きで文字列操作(挿入・置換など)するマクロが空振りしたときに、 <source lang="javascript"> // e.g. 選択範囲に「hoge」が含まれなければ置換しない var fuga = document.selection.Text.replace( /hoge/g, "fuga" ); document.selection.Text = fuga; </source> : 上のようなコードの場合は '''undo''' 履歴に無駄に残ったり、文書に「'''未保存 *'''」のフラグが付加されたりする。 : 以下のように「文字列操作の前後で "変化なし" なら undo 履歴には残さない」記述にすると、[https://www.haijin-boys.com/software/mery/mery-2-6-9#4 変更行の強調表示] なども無用に付かなくなる。 <source lang="javascript"> // e.g. 選択範囲に「hoge」が含まれなければ置換しない var st = document.selection.Text; var piyo = st.replace( /hoge/g, "piyo" ); if ( st != piyo ) { document.selection.Text = piyo; } </source> <br> * 大文字/小文字変換の [[マクロリファレンス:Selection インターフェイス#ChangeCase メソッド|Selection.ChangeCase() メソッド]] や、全角/半角変換の [[マクロリファレンス:Selection インターフェイス#ChangeWidth メソッド|Selection.ChangeWidth() メソッド]] なども、日本語文などで空振りしたときに undo 履歴に残るが、<syntaxhighlight lang="javascript" inline>var temp = document.selection.ChangeCase( meCaseLowerCase );</syntaxhighlight> のようなかたちで変数に格納することはできない。<br> : [[マクロリファレンス:Selection インターフェイス|Document.Selection クラス]] の文字列操作メソッドの場合は、以下のように記述することで「<span style="color:#0000c0;">変換なしなら undo 履歴を巻き戻し</span>」できる。 <source lang="javascript"> // 変換前の文字列 と 保存済み/未保存 の状態を取得 var st = document.selection.Text; var sv = document.Saved; if ( st && ! document.ReadOnly ) { // 小文字に変換 document.selection.ChangeCase( meCaseLowerCase ); // 変換なしなら undo 履歴を巻き戻す if ( document.selection.Text == st ) { document.Undo(); document.Saved = sv; } } </source> : ※ ただし、厳密にいえば undo 履歴には残っているので、'''redo''' (やり直し: Ctrl+Y) することができる。 <br><br> [[#TOP|>> 目次へ]] <br><br> === スクロール位置の調整 === キャレットをジャンプさせた後のスクロール位置とキャレット位置は、移動先の行(表示座標での行番号)がエディタの表示領域の高さに収まるかどうかとジャンプ方向によるので安定的ではない(スクロールマージンの考慮も必要)。 <br><br> 以下のコードは、ジャンプ後にエディタの表示領域がスクロールした場合に、キャレットが表示領域の 先頭位置([[マクロリファレンス:Window インターフェイス#ScrollY プロパティ|window.ScrollY]]) になるように調整するもの。 <source lang="javascript"> var s = Document.Selection; var ax = s.GetActivePointX( mePosLogical ); // キャレット位置の X var ay = s.GetActivePointY( mePosLogical ); // キャレット位置の Y var sy = ScrollY; // エディタ表示領域の先頭行(物理行番号+スクロールマージン) // 下方向に10行(論理行)ジャンプ s.SetActivePoint( mePosLogical, ax, ay + 10 ); // スクロールしないならそのまま / スクロールするならキャレットは表示領域の先頭に ScrollY = ( ScrollY == sy ) ? sy : s.GetActivePointY( mePosView ); // つねにジャンプ先の行が先頭になるようスクロールさせるなら // ScrollY = s.GetActivePointY( mePosView ); // ※ ScrollY プロパティに値を代入するときは物理座標(表示行)の行番号で </source> ※ スクロールマージンは [https://www.haijin-boys.com/software/mery/mery-2-7-0#2 ベータ版 2.7.0] より「オプション」ダイアログの「スクロール」のページ内で変更できるようになっている。[https://www.haijin-boys.com/weblog/assets/uploads/2019/04/mery-2-7-0-4.png?20190417] <br><br> === Window オブジェクト === 通常はソースコード内で [[マクロリファレンス:Window インターフェイス|Window オブジェクト]] を明示的に記述する必要はないが、[[#動作要件としてのバージョンチェック|バージョンチェック]] の節の「例4」のように <span style="color:#c00;"> 実際に記述する場合には <source lang="javascript" inline>Window</source> ではなく <source lang="javascript" inline>window</source> でないと宣言されていない変数・オブジェクトあつかいのエラーになる。</span> ※ <source lang="javascript" inline>Document</source> や <source lang="javascript" inline>Selection</source>、<source lang="javascript" inline>Alert</source> など他の主要なプロパティは「大文字/小文字/頭文字のみ大文字」の区別なしに同一のプロパティとしてあつかわれる。 <br><br> === カレントディレクトリ === カレントディレクトリ(作業フォルダ)は、Mery を起動したときに決定され、一定ではない。<br> 記述の都合上で相対パスを利用するために特定のカレントディレクトリを指定するマクロもあるが、「あえて流動的なカレントディレクトリを利用する」ようなコードが続く場合は、カレントディレクトリを書きもどす必要がある。 <source lang="javascript"> var fso = new ActiveXObject( "Scripting.FileSystemObject" ); var wshShell = new ActiveXObject( "WScript.Shell" ); var meryIni = Editor.FullName.replace( /exe$/, "ini" ); if ( fso.FileExists( meryIni ) ) { // メモ帳で Mery.ini を開く wshShell.Run( "notepad \"" + meryIni + "\"" ); } else { // マクロ実行前の作業フォルダを保存 var currentDir = wshShell.CurrentDirectory; // 相対パス解決のためにカレントディレクトリを設定 e.g. %AppData%\Mery wshShell.CurrentDirectory = wshShell.SpecialFolders( "APPDATA" ) + "\\Mery"; wshShell.Run( "notepad " + "Mery.ini" ); // マクロ実行前の作業フォルダを復帰 wshShell.CurrentDirectory = currentDir; } </source> <br> ※ マクロでカレントディレクトリを変更すると、実行中の Mery のプロセスの作業フォルダも変更されるため、あとから他のマクロを実行するさいのカレントディレクトリにも影響する。<br> → システムの関連付けを利用してテキストファイルなどのダブルクリックから Mery を起動した場合、そのファイルの親フォルダが Mery のプロセスの作業フォルダとなり、Windows OS の仕様により Mery のプロセスを終了するまでそのフォルダはロックされた状態になる(フォルダの移動や削除ができなくなる)が、マクロでカレントディレクトリを変更するとフォルダのロックを解除できる。 <br><br> === 動作要件としてのバージョンチェック === 公開するマクロに Mery ベータ版で追加されたマクロ用プロパティ・定数を利用する場合は、マクロの動作要件として Mery 本体のバージョンをチェックするコードを入れておくのが無難である。 <br> * JavaScript には特定のプロパティがオブジェクト配下に定義されているかを調べる方法も色々とあるが、親オブジェクトのタイプやプロパティ・定数のタイプ、JavaScript(JScript)のバージョンによる互換性などへの考慮が必要になる。 [https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/typeof][https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/in][https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty] <br> * 拙作の '''組み込み関数''' [[Mery本体のバージョンチェック|VersionCheck()]] を利用すれば、Mery のバージョン番号を指定して動作要件のチェックができる。 : ※ あらかじめ、プロパティや定数が導入された Mery のバージョン番号を調べておく必要がある( ← Mery.txt に記載されているはず)。 <source lang="javascript"> // ▼ ChangeCase() メソッドで定数 meCaseCapitalize を使えるのは ver 2.6.10 以降 if ( document.Selection.IsEmpty ) { document.selection.SelectLine(); // とりあえず行を範囲選択 } // 例1. VersionCheck() 関数を利用する場合 if ( VersionCheck( "2.6.10" ) ) { // 「単語の最初の文字を大文字に変換」 document.selection.ChangeCase( meCaseCapitalize ); } else { // 「小文字に変換」 document.selection.ChangeCase( meCaseLowerCase ); Status = "小文字で許せ。"; } function VersionCheck( versionStr ) { /* 関数のコードをコピペ */ ; } // -------------------------------------------------- // // 例2. 定数が定義されているかを調べる場合 if ( typeof meCaseCapitalize == "number" ) { // または meCaseCapitalize==3 // 「単語の最初の文字を大文字に変換」 document.selection.ChangeCase( meCaseCapitalize ); } else { // ExecuteCommandByID() で「単語の最初の文字を大文字に変換」 editor.ExecuteCommandByID( MEID_EDIT_CAPITALIZE = 2116 ); } </source> <source lang="javascript"> // ▼ BeginUndoGroup() メソッドを使えるのは ver 2.7.0 以降 // 例3. VersionCheck() 関数を利用する場合 if ( VersionCheck( "2.7.0" ) ) { BeginUndoGroup(); } function VersionCheck( versionStr ) { /* 関数のコードをコピペ */ ; } // -------------------------------------------------- // // 例4. メソッドが定義されているかを調べる場合 if ( "BeginUndoGroup" in window ) { BeginUndoGroup(); } </source> <br> === 外部リソースのチェック === 「include ライブラリ」や「GetKeyState.exe」のような外部リソースを必要とする前提のマクロでも、それらのリソースがない場合にもある程度マクロが動くようにコーディングすることができる。 <br><br> * [[includeライブラリ|include ライブラリ]] が必要なマクロの場合、ユーザー側が include ライブラリを正しく導入していることが要求される。 : ユーザー側で include ライブラリが導入されていて、マクロ側で <source lang="javascript" inline>#include "include/IO.js"</source> のようなプリプロセッサがソースコードの先頭で宣言されていれば問題ないのだが、include ライブラリが導入されていなくても、プリプロセッサを削除(コメントアウト)すればマクロがある程度動くようにコーディングすることもできる。 <source lang="javascript"> // #include "include/IO.js" if ( typeof IO == "object" ) { /* IO.js がインクルードされているときの動作 */ ; } else { /* IO.js がインクルードされていないときの動作 */ ; } </source> <br> * また、[[GetKeyState.exe(キー状態取得実行ファイル)]] のあるなしで動作内容を分けるなら、以下のようにコードを記述すればよい。 <source lang="javascript"> // あらかじめ変数 ctrl に 0 を代入しておく var ctrl = 0; // GetKeyState.exe のパスで実行ファイルの実在確認をする var getKeyState = editor.FullName.replace( /[^\\]+$/i , "" ) + "Macros\\GetKeyState.exe"; var fso = new ActiveXObject( "Scripting.FileSystemObject" ); if ( fso.FileExists( getKeyState ) ) { // GetKeyState.exe で Ctrl キーの押し下げ状態を取得する var wshShell = new ActiveXObject( "WScript.Shell" ); ctrl = wshShell.Run( "\"" + getKeyState + "\" control", 0, true ); } if ( ctrl == 1 ) { /* GetKeyState.exe があり、Ctrl キーが押されているとき */ ; } else { /* GetKeyState.exe がない、または Ctrl キーが押されていないとき */ ; } </source> <br> [[#TOP|>> 目次へ]] <br><br> === Mery.ini から設定値を取得する === [[includeライブラリ|include ライブラリ]] の MeryInfo クラス (MeryInfo.js) を利用して Mery.ini からいくつかの設定項目の値や状態を取得することはできるが、制約が非常に多い。 * 取得できる項目がきわめて限定的である * 取得する項目が複数あると、その都度 Mery.ini 全体の読み込みが発生する(キャッシュ可) * Mery.exe のファイル名を変更 (e.g. Mery_hoge.exe) している場合、MeryInfo.js のコードを改変しないと Mery.ini (Mery_hoge.ini) のパスを得られず、設定値を取得できない。 <br> 拙作の '''組み込み関数''' [[Mery.iniのオプション値を取得#関数|GetIniOption()]] と [[Mery.iniのオプション値を取得#GetIniOption2() 関数|GetIniOption2()]] はこれらの制約を受けず、とくに後者は <span style="color:#0000c0;"> Mery.ini のすべての項目にアクセスして値を取得することができる。</span><br> ただし、制約がない代わりに組み込み関数自体のコードが長いことや、引数や戻り値が配列であることでコードが煩雑にならざるをえない( ⇔ 配列を使用することで、複数の項目を取得する場合でも Mery.ini ファイルの読み込みを1回におさえられる)。 <br> ※ [[#Mery.ini を読みこむ|IO.LoadFromFile() 関数で Mery.ini を読みこむ]] という方法もある。 <br><br> また、Mery.ini 側の仕様として、 「オプション」など各種の設定ダイアログを [ '''OK''' ] ボタンで閉じたときか、 エディタウインドウを閉じたときにしか Mery.ini への書き込みがされないため、 メニュー項目/ツールバーアイコン/ショートカットキー で変更した設定内容は Mery.ini に直ちに反映されない という制約がある(Mery.ini の実体ファイルへの書き込み回数を減らすための仕様)。 <br><br> <span style="color:#c00;">エディタの表示状態をトグル切り替えするコマンド(縦書き、色の反転、全画面表示、etc. ...)については、マクロ用の標準メソッド/プロパティから「現在の表示状態」を取得する手段がなく、'''組み込み関数 GetIniOption2() で Mery.ini を読み込んでも、必ずしも「最新の設定状態」を取得できるわけではない'''…。</span> <br><br> ※ 「現在の表示状態」を取得してから ON/OFF を指定しての切り替えを行なうためには、include ライブラリの IO クラスを利用するなどして外部に Mery.ini とは別の設定ファイル (e.g. JSON ファイル) を用意し、切り替え実行のたびに設定ファイルを読み書きする必要がある。<br> ただし、この方法をとる場合は、外部ファイルに設定内容をあずける項目(コマンド)の切り替えについては必ずマクロ経由で行なわなければならず、デフォルトの メニュー項目/ツールバーアイコン/ショートカットキー による通常操作でその項目の状態の変更をすると、最新の設定状態(現在の表示状態)と外部ファイルが保持している設定内容とのあいだに齟齬が生じてしまう。 : → e.g. 「[[折り返しトグル切り替え#3つの折り返しモードを順々にトグルする|折り返しトグル切り替え]]」マクロ <br><br> === 外部ファイルにマクロの設定などを書き出す === マクロの設定情報を保存して次回の実行時にそれを参照して使いたい場合、[[includeライブラリ|include ライブラリ]] の IO クラス (IO.js) の <source lang="javascript" inline>IO.Serialize()</source> と <source lang="javascript" inline>IO.Deserialize()</source> を利用するのがもっとも簡単な方法だとおもわれる。 * [[マクロライブラリ]] では「[[折り返しトグル切り替え]]」マクロ(Bleat 版 / sukemaru 版)や ks 氏の「[[スマートインデント(C 構文)]]」マクロの SwitchSmartIndent.js のコードが、 <source lang="javascript" inline>IO.Serialize() / Deserialize()</source> を利用したマクロの雛形として利用しやすい。 * 複数の設定値を保存/参照する複雑なものとしては、ks 氏の「[[階層化マクロメニュー]]」マクロや、拙作「[[ポップアップメニューで検索先にジャンプ#include版|検索ジャンプ]]」「[[ブックマーク一覧ジャンプ#include版|ブックマークジャンプ]]」や「[[ファイルを読み直す・開きなおす#include版|読みなおし]]」マクロなどもあるが、メイン部分の動作コード自体が長く煩雑なので参考にしづらいとおもわれる…。 * 「マクロA」で書き込んだ外部ファイル(JSON)を別の「マクロB」で読み込んで利用する例として、ks 氏の「[[スマートインデント(C 構文)]]」、拙作「[[位置情報を保存してから「すべて選択/選択解除」(非スクロール)]]」。<br> ※ ただし、マクロの実行ごとに外部ファイル(設定ファイル.JSON と include ライブラリの IO.js および json2.js)を読みこむことになるので、環境によってはマクロの動作のもたつきや [[#エラー処理|エラー]] が生じてしまう可能性がある。 <br><br> 以下、「[[折り返しトグル切り替え#3つの折り返しモードを順々にトグルする|折り返しトグル切り替え]]」マクロを例に <source lang="javascript" inline>IO.Serialize() / Deserialize()</source> の利用方法の簡単な説明。 <source lang="javascript"> #include "include/IO.js" // \Macros\include\IO.js をインクルードする // ※ ソースコードの1行目に記述すること。 /* 【準備】 */ // ■ JSON のファイル名(この場合 折り返し.json) ※定義しなくてもよい var jsonName = "折り返し"; // ➀ 書き出し内容として使う「オブジェクト」を用意する var setting = {}; // ➁ 設定項目として使う「プロパティ」と「初期値」を定義する setting.wrapMode = 0; setting.count = 0; // ※ objectName.propertyName = value; // value には数値以外(文字列、真偽値、配列など)も設定できる。 // または、以下のようにまとめてもよい ( ➀+➁ と意味は同じ) var setting = { wrapMode: 0, count: 0 } // ※ {ブラケット} で囲う場合はコロンで結んで propertyName : value とする。 // 複数のプロパティを列挙する場合はカンマ「,」で区切る。 // 最後にセミコロン「;」をつけないこと。 /* 【JSON 読み込み】 */ // JSON ファイルに保存された設定値で上書きする setting = IO.Deserialize( setting, jsonName ); // ※ 第2引数 jsonName を省略した場合は、自動的に「マクロ.js」のベース名。 // 初回起動で JSON ファイルがないときは初期値のまま。 /* 【動作コード】 */ // 折り返しモード切替 if ( setting.wrapMode == 2 ) { editor.ExecuteCommandByID( 2146 ); // 折り返さない setting.wrapMode = 0; } else if ( setting.wrapMode == 0 ) { editor.ExecuteCommandByID( 2147 ); // 指定文字数で折り返し setting.wrapMode = 1; } else { // else if ( setting.wrapMode == 1 ) editor.ExecuteCommandByID( 2148 ); // ウインドウの右端で折り返し setting.wrapMode = 2; } // 任意のプロパティを追加することもできる setting.dateTime = new Date(); // 最終実行日時の記録 // マクロの実行回数を記録 setting.count += 1; if ( setting.count % 100 == 0 ) { // 100 回ごとにダイアログを表示 var d = setting.dateTime; var dateTime = d.getFullYear() + "/" + ( d.getMonth() + 1 ) + "/" + d.getDate() + " " + d.toLocaleTimeString(); var str = dateTime + "\n\n" + ScriptName + " マクロ実行 " + setting.count + " 回目!!"; Alert( str ); } /* 【JSON 書き込み】 */ // setting オブジェクトの変更内容を保存する IO.Serialize( setting, jsonName ); </source> <br> === 関数の「呼び出しコスト」 === ユーザー関数は、呼び出し元から参照可能な位置に記述すれば、ソースコードの任意の位置に配置することができる。 <br>繰り返し何度も呼び出して使用する関数の場合に「呼び出しコスト」を気にする人もいるらしいが、Mery で使用するマクロ程度のソースコードであればあまり気にする必要はないようにおもわれる。 <br><br> '''e.g. [[#メタ記号をエスケープする|半角英数字以外を「¥」でエスケープ処理する]]''' <br> ※ あえて '''ループ処理''' で1行ずつエスケープしてみる ([[#その他、拙作マクロについて|@ロースペの XP ノート]]) <source lang="javascript"> /* 関数バージョン */ function Quote( str ) { return str.replace( /\W/g, "\\$&" ); } // または // var Quote = function( str ) { // return str.replace( /\W/g, "\\$&" ); // } BeginUndoGroup(); var lines = document.GetLines( 0 ); for ( var i = 1, st, a = []; i <= lines; i ++ ) { st = Quote( document.GetLine( i, 0 ) ); a.push( st ); } document.Text = a.join( "\n" ); </source> <br> <source lang="javascript" inline>function Quote( str )</source> でも <source lang="javascript" inline>var Quote = function( str )</source> でも、約 9500 行の日本語テキスト(約 33 万文字)にたいして 1.1 秒台の処理時間がかかり有意な差はみられなかった。 <br> 関数を使用しない以下のようなベタ書きのコードの場合でも、ほぼ同じ程度の処理時間がかかった (@ロースペの XP ノート)。 <source lang="javascript"> /* 非関数バージョン */ BeginUndoGroup(); var lines = document.GetLines( 0 ); for ( var i = 1, st, a = []; i <= lines; i ++ ) { st = document.GetLine( i, 0 ).replace( /\W/g, "\\$&" ); a.push( st ); } document.Text = a.join( "\n" ); </source> <br> ※ ループ文の中で関数を定義した場合は、やや遅くなって 1.3 秒台。 <source lang="javascript"> BeginUndoGroup(); var lines = document.GetLines( 0 ); for ( var i = 1, st, a = []; i <= lines; i ++ ) { function Quote( str ) { return str.replace( /\W/g, "\\$&" ); } st = Quote( document.GetLine( i, 0 ) ); a.push( st ); } document.Text = a.join( "\n" ); </source> <br> ※ 行ごとのループ処理ではなく、文書全体の '''一括処理''' にすると速くなる。<br> 上とおなじ <source lang="javascript" inline>Quote()</source> 関数を使用しての文書全体の一括処理でも… <source lang="javascript"> function Quote( str ) { return str.replace( /\W/g, "\\$&" ); } document.Text = Quote( document.Text ); </source> 関数を使用しないベタ書きの一括処理でも… <source lang="javascript"> document.Text = document.Text.replace( /\W/g, "\\$&" ); </source> …処理時間はほぼ同じで、約 0.7 ~ 0.8 秒だった。 <br> 現行 OS の [https://ja.wikipedia.org/wiki/Chakra#%E6%AD%B4%E5%8F%B2 Chakra エンジン (jscript9.dll) であれば約 20 倍] の速度が出るらしいので、数メガバイトとか数万行とかのよほど長大な文書の処理をする場合でもなければ、「関数の呼び出しコスト」を気にする必要はあまりなさそう。 <br><br> それよりも、 * 文字列操作や検索/置換にさいして、なるべくキャレットの移動をともなうメソッドを使用しない : ※ できるだけ Mery 独自のメソッドよりも、代替可能な JavaScript の [https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String#Methods_2 String オブジェクトのメソッド] を変数内で使用する (Mery のマクロメソッドは「キー操作の記録と再生が一番の目的」なので、動作速度的に最適化されていないのかも)。 * くりかえし何度も参照されるオブジェクトやプロパティは変数に格納する : e.g. [[マクロリファレンス:Document インターフェイス#Text プロパティ|Document.Text]] や [[マクロリファレンス:Selection インターフェイス#Text プロパティ|Document.Selection.Text]]、 [https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/length#Iterating_over_an_array for 文 での Array.length] など。 * 関数定義文で必要となる引数をすべて与えておき、関数スコープからグローバルスコープに変数の値を参照しに行かないで済むようにしておく などで、ソースコードの最適化をはかるほうが良いはず。<br> <br><br> ※ ちなみに、Quote() 関数を以下のように記述した場合、上出のループ処理コードでの所要時間は 3 倍(3 秒台)。 <source lang="javascript"> function Quote( str ) { return str.replace( /\W/g, function( $0 ) { return "\\" + $0; } ); } </source> 以下のような記述だと、ループ処理した場合の所要時間は 4 倍以上(4 ~ 5 秒台)になる。 <source lang="javascript"> function Quote( str ) { return str.replace( /\W/g, Escape ); } function Escape( matched ) { return "\\" + matched; } </source> …ループ処理から参照する関数のネストや二重参照は、ループ文内で関数を定義する場合以上に鬼門のようだ。 <br> [[#TOP|>> 目次へ]] <br><br> === FileSystemObject と WScript.Shell でファイルパスを引数にするとき === 引数として使用するファイルパス文字列に '''半角空白''' がふくまれている場合、 * [https://docs.microsoft.com/ja-jp/previous-versions/windows/scripting/cc409800(v=msdn.10) FileSystemObject] ではパスをダブルクオートなどの <b style="color:#0000c0;">引用符で囲う必要がない</b> * [https://docs.microsoft.com/ja-jp/previous-versions/windows/scripting/cc364436%28v%3dmsdn.10%29 WScript.Shell] などの WSH コードではパスをダブルクオートなどの <b style="color:#c00;">引用符で囲う必要がある</b> <br> よって、[https://docs.microsoft.com/ja-jp/previous-versions/windows/scripting/cc364421%28v%3dmsdn.10%29 WshShell.Run() コマンド] などで不特定のパス(または任意のパス)を指定するときは <source lang="javascript" inline>WshShell.Run( "\"" + path + "\"" )</source> または <source lang="javascript" inline>'WshShell.Run( '"' + path + '"' )</source> のように記述しておき、パスに半角空白がふくまれていてもエラーにならないように備えておくとよい。 <source lang="javascript"> // 半角空白を含むパス var path = "C:\\Hoge hoge\\Fuga fuga\\Piyo piyo.txt"; var fso = new ActiveXObject( "Scripting.FileSystemObject" ); var wshShell = new ActiveXObject( "WScript.Shell" ); if ( fso.FileExists( path ) ) { // 引用符で囲わないでよい wshShell.Run( "\"" + path + "\"" ); // 引用符で囲う必要がある } </source> === 警告・確認ダイアログとステータスバーの使い分け === マクロからユーザーにメッセージを与える手段として '''警告'''([[マクロリファレンス:Window インターフェイス#Alert メソッド|window.Alert]])・'''確認'''([[マクロリファレンス:Window インターフェイス#Confirm メソッド|window.Confirm]])ダイアログと '''ステータスバー'''([[マクロリファレンス:Window インターフェイス#Status プロパティ|window.Status]])への表示などがある(ほかに '''アウトプットバー'''([[マクロリファレンス:OutputBar インターフェイス#Write メソッド|OutputBar.Write]])や '''ポップアップメニュー''' を使う方法もある)。 <source lang="javascript"> // e.g. ポップアップメニューを「ポップアップヒント」として使用する if ( document.ReadOnly ) { var m = CreatePopupMenu(); m.Add( " このドキュメントは 書き換え禁止 です & ", 0 ); var r = m.Track( 1 ); } </source> <br> 基本的に、Mery のマクロで利用できるポップアップダイアログ(警告、確認)はどちらもサウンドをともない、ボタン操作で閉じるまで作業を中断させてしまうので、あえて作業を一時停止させる必要がある場面以外ではステータス表示を使用するのがよい。 <br> ※ ユーザー側がステータス表示を使用するイベントマクロなどを別途で導入していることを考慮すると、マクロの終了時になんらかのイベントが発生するマクロの場合、重要なメッセージはダイアログで出力させるか、マクロ内の動作設定用の変数で出力方法を選択できるようにしておくとなおよい。 <br><br> また、Mery の Window クラスのメソッド・プロパティを使うほかにも、WSH の [https://docs.microsoft.com/ja-jp/previous-versions/windows/scripting/cc364428(v=msdn.10) WshShell.Popup メソッド] によるメッセージボックス利用することもできる。<br> ダイアログ内の左側のアイコンの種類や <kbd>OK</kbd> <kbd>キャンセル</kbd> <kbd>はい</kbd> <kbd>いいえ</kbd> などのボタンの種類をカスタマイズでき、指定時間の経過後に自動で閉じさせることもできるが、引数の指定や戻り値の処理が煩雑なので、 <kbd>はい</kbd> <kbd>いいえ</kbd> <kbd>キャンセル</kbd> の3ボタンが必要な場合でもなければお勧めはしない…。<br> ※ アイコンなしにすれば、システムのサウンドなしでダイアログを表示できる。 <br><br> <!-- === エラー処理 === Mery のマクロで例外(エラー)が発生した場合、ダイアログのポップアップにより中断される。<br> マクロの開発者側にとってはソースファイル内の例外が発生した行に速やかにアクセスできるので便利ではあるが、コードを読むのに不慣れなユーザーにおいてはソースコードを開いたところで何が解決するわけでもない。<br> エラーダイアログは自家用の自作マクロのメンテナンスのさいには有用であるが、公開用のマクロの場合はユーザーがソースコードに誤った改変を加えてしまう惧れもあるので、基本的に必要性がないといえる。 <br><br> ※ <source lang="javascript" inline>wshShell.Run( "実在しない実行ファイル.exe /間違ったパラメータ" );</source> のようなコードの場合でも、Mery.exe のエラーとして扱われる。 <br><br> 例外が発生することを予期できたり、例外が発生してもそれを無視してマクロの実行を継続したり回避用の処理に移行させられる場合は、JavaScript の [https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Exception_Handling_Statements/try...catch_Statement try...catch 文] を組み込むとよい。 <source lang="javascript"> // e.g. コピーや上書き保存のようなファイルシステムを操作するマクロは // アクセス権限や読取専用ファイルへの書き込み、パスの指定ミスなど // ユーザーの実行環境により例外が発生する可能性がある try { /* * 例外が発生する可能性のあるコード * (例外が発生しなかったときはそのまま処理される) * * ※ このブロック内で例外が発生したとき * 原因箇所より後ろのコードは処理されず * catch や finally ブロックにジャンプする */ ; } catch( e ) { /* * 例外が発生したときにだけ実行されるコードブロック * (例外が発生しなかったときは処理されない) * * ・Alert(), Confirm() や Status= でメッセージを表示させたり * 回避処理用のコードを記述したりしてもよい。 * * ※ エラーの内容を特定して予期できるなら * catch( e if e == hoge ) { ... ; } * catch( e if e == fuga ) { ... ; } * catch( e ) { * if ( e.number == -xxxxxxxxxx ) { ... ; } * else { ... ; } * } * のように列記して処理を分岐させてもよい。 * * ・Alert(e); だけ記述しておいて、エラーダイアログだけは出して * マクロを終了させてもよい(ソースファイルを開かせない)。 * ・Quit(); だけ記述しておいて、エラーダイアログなしで * マクロを終了させてもよい。 * ・セミコロンだけおいて {;} とすれば、エラーを無視して * catch(e) {;} ブロックよりうしろのコードを処理させることもできる。 */ ; } finally { /* * 例外が発生してもしなくても処理されるコード * (例外が発生したときは catch ブロックの後に実行される) * ※ finally { ... } ブロックはまるごと省略可 * * Scripting.FileSystemObject や ADODB.Stream でファイルを開いている場合は * ここでリソースを解放してやるとよい。 * * try ... catch 文を関数ブロック function(){ ... } 内においている場合は * return piyo; * などで、なんらかの戻り値を返してやってもよい。 * * ※ catch ブロックで Quit(); や return ***; を記述している場合は * エラーが発生したときに finally ブロックは処理されない * */ ; } /* * 上で Quit(); や return ***; を記述していない場合は * try ... catch 文のあとのコードも処理される */ ; </source> <source lang="javascript"> // テスト try{ hoge; } catch(e) { Status = e.message; // 「'hoge' は宣言されていません。」 Alert(e); // 「TypeError: 'hoge' は宣言されていません。」 } Status = "Error Test"; </source> <br> --> [[#TOP|>> 目次へ]] <br><br> === その他、拙作マクロについて === Kuro 氏の [[#引用符/コメント|「引用を追加」マクロのカスタマイズ]] をきっかけとしてマクロの改造に手を染め、 [[#アイコン|マクロのアイコン化のためにアイコンを量産]] していくうちにマクロの自作も始めて、マクロ制作のための補助的マクロの自作とか「タマゴ? ニワトリ?」状態になったりしています。<br> '''マウス派''' として Mery を便利に扱えるようにするつもりでマクロを作っていますが、マニアックな個人的要求(欲求)を自己解決していくうちに [[#スクショ|Mery の外観]] が本来の姿からかけ離れてしまっているという…。 * sukemaru の Mery 運用環境はロースペックの '''Windows XP sp3 (32bit), JScript 5.8.20587''' のノート PC (CPU: Atom 1.7GHz, 1 コア, 2 スレッド) です。 : ※ 制作したマクロの動作テストは、この XP 機でしかおこなっていません。 : ※ マクロの動作テストに使用している Mery のバージョンは、"最新のベータ版" (および "最新の正式版" ver. 2.6.7 ) のみです。 基本的に ver 2.6.7 以降のバージョンで動作するように作成していますが、ver 2.6.6 以前のバージョンでの利用を想定していません( ver 2.6.6 以下での動作確認はしていません)。 : ※ とくに「[[マクロライブラリ#実験的マクロ・練習マクロなど|実験的マクロ・練習マクロ]]」カテゴリに投稿した【自家用】/【実験】マクロにおいては、よその環境を考慮した動作テストをしていません。 : ※ マクロの動作速度のテストは [https://www.aozora.gr.jp/ 青空文庫] からダウンロードした『[https://www.aozora.gr.jp/cards/000148/card789.html 吾輩は猫である]』のルビを削除して1文ごとに改行させたテキストファイル(約 33 万文字/約 9500 行)でおこなっています。 1 メガバイト超のファイルでのテストはしていません ( ロースペ PC なので 2000 行を超えるあたりから動作速度が気になりだすのですが… [https://www.haijin-boys.com/discussions/4395])。 : ※ ZIP 版の Mery でマクロを作成・運用しているので、インストーラ版では正しく動作しないマクロがあるかもしれません。 * 開発環境が Windows XP なので、拙作マクロは基本的に JavaScript(JScript)マクロです。 : ※ 変数はすべて <source lang="javascript" inline>var</source> で宣言し、JScript 5.8 の環境で実行できるようにコーディングしています。 * Mery のオプション設定で「行の表示方法=論理座標 (論理行)」の状態で運用する前提でマクロを作っています。 公開しているマクロでは、「表示座標 (表示行)」ベースで Mery を運用している場合でも利用できるように設定項目(変数)を設けるか「行の表示方法」を自動判定するコードを追加していますが、動作が不完全になったり処理がおそくなったりすることがあります。 : <span style="color:#c00;"> ※「表示座標 (表示行)」ベースでの動作テストはほとんどしていません。</span> * ソースコード内ではしばしば unicode 文字を使用していますので、マクロの JS ファイルは UTF-8 形式で保存する前提となっています。 * ソースコード内の変数名の検索などで「[[ポップアップメニューで検索先にジャンプ|検索ジャンプ]]」マクロを利用しやすいように(個人的にタグジャンプ系のマクロに馴染めないので)、マクロのコードには半角空白を多用しています。 * 基本的に、変数名は頭文字が小文字の '''camelCase''' に、関数名は頭文字が大文字の '''TitleCase''' にしてあります。 <br> * 「[[includeライブラリ|include ライブラリ]]」(作成: ks 氏) を利用する【'''include 版'''】と利用しない【'''通常版'''】とがあるマクロでは、include 版を優先的にメンテ・更新しています(←自家用)。 * 外部実行ファイル「[[GetKeyState.exe(キー状態取得実行ファイル)|GetKeyState.exe]]」(作成: pizz 氏) の導入が必要なものもあります。[https://www.haijin-boys.com/wiki/GetKeyState.exe%28%E3%82%AD%E3%83%BC%E7%8A%B6%E6%85%8B%E5%8F%96%E5%BE%97%E5%AE%9F%E8%A1%8C%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%29#.E3.81.9D.E3.81.AE.E4.BB.96] * ポップアップメニューマクロの「設定変更サブメニュー」など、複数のマクロで共通の自作関数を使用しているものがありますが、当面は「include ライブラリ」のような外部ファイルにまとめる予定なしです。 : ∴ すでに公開しているマクロが多いこと、公開用と自家用とでコードの内容がちがうマクロが複数あること、それぞれのマクロごとに自作関数のコードに改変をくわえていることなどの理由で、もはや関数・クラスを統一しなおして更新メンテするのが困難。 : <div id="Mery.ini を読みこむ"></div>∴ 「include ライブラリ」のように独自クラスでまとめたものをインクルードして利用するよりも、必要な関数だけをソースコード内にコピペして使用するほうが、マクロの処理速度的には僅かながらも有利?(な気がする… @ロースペ XP)。 <br> → 念のため確認してみたら、やはり差は僅かだった。 : ※「include ライブラリ」の MeryInfo.js と [[マクロ覚え書き(開発者向け)#include ライブラリの IO クラスを利用する|IO.js をインクルード]] したマクロで Mery.ini ( 31 万文字超/約 5600 行、約 320 kB ) から「行の表示方法 (LineColumnView キー)」を取得すると、平均 0.125 秒。 <source lang="javascript"> #include "include/IO.js" #include "include/MeryInfo.js" var start = new Date(); // Mery.ini のテキストデータを読みこむ var iniText = IO.LoadFromFile( MeryInfo.GetIniPath(), "utf-8" ); // LineColumnView キーの値を検索する var lineColumnView = + /^LineColumnView=(\d)$/m.exec( iniText )[1]; Alert( "行の表示方法: " + ( lineColumnView ? "表示行" : "論理行" ) + "\n\n" + ( ( new Date() - start ) / 1000 ).toFixed( 3 ) + " 秒" ); </source> <br> : ※ [[Mery.iniのオプション値を取得#GetIniOption2() 関数|組み込み関数 GetIniOption2()]] を利用したマクロで「行の表示方法」を取得すると、平均 0.095 秒。 <source lang="javascript"> var start = new Date(); // 関数の戻り値 iniOption[0][2] が LineColumnView キーの値 var iniOption = GetIniOption2( [[ "General", "LineColumnView" ]] ); Alert( "行の表示方法: " + ( iniOption[0][2] ? "表示行" : "論理行" ) + "\n\n" + ( ( new Date() - start ) / 1000 ).toFixed( 3 ) + " 秒" ); // ---------- ▼ 組み込み関数 ココから ▼ ---------- function GetIniOption2( keyArray ) { /* ~ 省略 ~ */ // https://www.haijin-boys.com/wiki/Mery.iniのオプション値を取得#ソースコード_2 } // ---------- ▲ 組み込み関数 ココまで ▲ ---------- </source> : GetIniOption2() 関数は、<source lang="javascript" inline>IO.LoadFromFile()</source> と <source lang="javascript" inline>MeryInfo.GetIniPath()</source> のコードを翻案して作ったものなので、Mery.ini のパスを解決して [[マクロ覚え書き(開発者向け)#ADODB.Stream を利用する|ADODB.Stream で読みこむ]] 処理の部分はほぼ同じ。 Mery.ini のテキストデータから LineColumnView キーの値を検索する方法は異なるが、その部分は「include ライブラリ」を使用したコードの [https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec RegExp.exec( str ) メソッド] のほうが速いはず。<br> ※ GetIniOption2() 関数は [https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/search String.search( regexp ) メソッド] と、[https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf String.indexOf( searchValue, fromIndex ) メソッド] ×3回でキーの値を取得する。<br> : … とはいえど、「include ライブラリ」は多種多様な各クラス同士でのプロパティ(関数)の相互参照により高度に効率化されていて、おいそれとアレンジできない部分がたくさんあるため、素直にインクルードして利用するほうがよいのかも。 <br><br> [[#TOP|>> 目次へ]] <br><br> == 投稿した構文ファイル == <br> * [[JaneStyle (正規表現用)]] (uploaded: 2018/08/31) : ReplaceStr.txt / ImageViewURLReplace.dat / URLExec.dat / command.dat に対応 : ※ [http://k-takata.o.oo7.jp/mysoft/bregonig.html bregonig] の正規表現のハイライト可 (基本的に [https://github.com/k-takata/Onigmo/blob/master/doc/RE.ja onigmo] の正規表現にも利用可) : ※ 収録しなかった正規表現タグ (文字・文字種の変数など) があるので、リンク先ページ末尾の注記を参照のこと * [[ファイル:MediaWiki.MSY.zip]] (uploaded: 2019/11/21) : MediaWiki 用構文ファイル * [[Mery MSY]] (uploaded: 2018/09/05) : Mery の MSY 構文ファイル用 * [[Mery Macro JS]] (last modified: 2018/11/10) : マクロの JS ファイル(JScript)用 : JavaScript 用構文ファイル/入力補完用辞書/スペルチェック用辞書/おまけマクロ を同梱 : <span style="color:#c00;"> ※ Web 開発向けのキーワードは未収録 </span> <br> : ref. Mery 公式フォーラム 『 [https://www.haijin-boys.com/discussions/3655#discussion-3951 デフォルトの構文定義の拡充について]』 <br><br> [[#TOP|>> 目次へ]] <br><br> == スクショ == <br> ; マクロバーのアイコン化 マクロバー (1段目) にアイコンを詰めこむための sukemaru の試行錯誤の遍歴... [https://www.haijin-boys.com/software/mery/mery-2-7-5#comment-2379][https://www.haijin-boys.com/discussions/4643] * '''共通''' : システム環境: Windows XP 32bit SP3 (Classic テーマ) : ウインドウサイズ (幅): 約 970 px : アイコンサイズ: 中 (24px) : アイコン:[[マテリアルデザインっぽいアイコンと『小マクロ集』|マテリアルデザインっぽいアイコン]] : 標準ツールバー (2段目) のアイコン数: 28 コ <br> * [https://www.haijin-boys.com/software/mery/mery-2-8-0#4 Ver. 2.8.0](2019/06/22) : マクロバーのアイコン数 28 コ、ラベルなし、セパレータあり( #begingroup=3 ) : [[ファイル:Mery_2.8.0_SS.png|link=https://www.haijin-boys.com/wiki/images/1/1b/Mery_2.8.0_SS.png|480px|thumb|left|Ver. 2.8.0]]<br clear=all> * [https://www.haijin-boys.com/software/mery/mery-2-7-5#12 Ver. 2.7.8](2019/06/13) : マクロバーのアイコン数 22 コ半、ラベルなし、余白あり( #title="" )<br> ※ 3段目は外部ツールバー (アイコン 30 コ) : [[ファイル:Mery_2.7.8_SS.png|link=https://www.haijin-boys.com/wiki/images/5/54/Mery_2.7.8_SS.png|480px|thumb|left|Ver. 2.7.8]]<br clear=all> * Ver. 2.7.4 まで(2019/05/05) : マクロバーのアイテム数 16 件、ラベルあり(#title="hoge" の文字数を切りつめてやり繰り) : [[ファイル:Mery_2.7.4_SS.png|link=https://www.haijin-boys.com/wiki/images/3/3f/Mery_2.7.4_SS.png|480px|thumb|left|Ver. 2.7.4]]<br clear=all> <br> <div id="アイコン"></div> * 「マテリアルデザインっぽいアイコン」は、sukemaru の自作マクロと、sukemaru がマクロライブラリからダウンロードして利用しているマクロを対象として制作しています。 : ※ [[ヘルプ:目次#コマンドリファレンス|メニューバーの標準コマンド]] や、ショートカット設定/右クリックメニュー用コマンド、[[キーアサイン集]] の小マクロをアイコン化できるように、『小マクロ集』としてまとめました。 <br><br> == おまけ == === マーカー設定 === <br> 正規表現でマーカーに登録するさいは、 ラベル |正規表現 のように並列演算子 <q>|</q> の左側に「題名+全角空白」、右側に正規表現としておくと、マーカーバーが見やすくなる(パフォーマンス的にはよくないかも)。 <br><br> * いわゆる「プログラミング用フォント」を導入していないので、'''ゼロ <q>0</q>''' と オー <q>O</q> や、イチ <q>1</q> と '''アイ <q>I</q>''' と エル <q>l</q> と バー <q>|</q> を区別できるよう、アイ と オー にマーカーを設定。<br> '''円マーク <q>¥</q>''' や '''波ダーシ <q>〜</q>''' 他、見分けづらい文字も追加。 <u> ☑ 大文字小文字を区別 ☑ 正規表現 </u> [OOII]|[¥∖╲〜☓×〇➀-➉] : ※「半角数字」は、 [ オプション ] の [ 表示 ] 設定でカスタム文字色を設定。 : ※ 半角バーチカルバー <q>|</q> は、必要におうじて [ 編集モード ] の強調文字列に設定。 : ※ 小文字エル <q>l</q> は、強調なし。 <br> * 特殊な空白文字用 <br>「MeiryoKe_Gothic」 フォントで通常の全角/半角空白と区別できない <q>特殊な空白文字</q> と、<q>ゼロ幅空白文字</q>。 <u> ☑ 大文字小文字を区別 ☑ 正規表現 </u> 特殊な空白文字 |[\x{00A0}\x{2000}-\x{200A}\x{2028}\x{1680}\x{180E}] ゼロ幅空白文字 |\g<blank>\g<chara>|(?<chara>[\n\s\S])(?<blank>[\x{200B}-\x{200E}\x{2029}\x{202C}\x{202F}\x{205F}\x{2062}\x{2063}\x{FEFF}]) : ※ 「MeiryoKe_Gothic」 フォントで文字化けして中黒 <q>・</q> で表示されるものや、ゼロ幅結合子は含めていない。 <br> * /JavaScript の正規表現リテラル用/ <u> ☑ 大文字小文字を区別 ☑ 正規表現 </u> 正規表現リテラル |(?<=^|[{(\[= \t])\/(?![*+?|/)\]])[^\r\n\t]*\/[gmi]{0,3}(?=\s*(?:[.,:;})\]]|//|/\*|$)) : ※ ある程度の誤爆はやむなし。 <br><br> <div id="END"> [[#TOP|>> 目次へ]] </div> <!-- 【スクショ】 [https://i.imgur.com/tJsZBAF.png https://i.imgur.com/tJsZBAF.png 2.8.0] [https://i.imgur.com/fuu5nFy.png https://i.imgur.com/fuu5nFy.png 2.7.8] [https://i.imgur.com/VizaHVo.png https://i.imgur.com/VizaHVo.png 2.7.4] --> <!-- 【マーカー設定】 [OOII]|[¥∖╲〜☓×〇➀-➉] // [OOII]|[\x{00A5}\x{2216}\x{2572}\x{301C}\x{2613}\x{00D7}\x{3007}\x{2780}-\x{2789}] 正規表現リテラル |(?<=^|[{(\[= \t])\/(?![*+?|/)\]])[^\r\n\t]*\/[gmi]{0,3}(?=\s*(?:[.,:;})\]]|//|/\*|$)) 特殊な空白文字 |[\x{00A0}\x{2000}-\x{200A}\x{2028}\x{1680}\x{180E}] ゼロ幅空白文字 |\g<blank>\g<chara>|(?<chara>[\n\s\S])(?<blank>[\x{200B}-\x{200E}\x{2029}\x{202C}\x{202F}\x{205F}\x{2062}\x{2063}\x{FEFF}]) \[行頭の角カッコ ]|^\[[^\]\r\n]+\] var regBlankLine = /^[\s \u00A0\u1680\u180e\u2000-\u200A\u2028\u2029\u202F\u205F\uFEFF]+$/; var regBlank = /[\u00A0\u1680\u180E\u2000-\u200E\u2028\u2029\u202F\u205F\u2062\u2063\uFEFF]/g -->
編集内容の要約:
MeryWikiへの投稿はすべて、他の投稿者によって編集、変更、除去される場合があります。 自分が書いたものが他の人に容赦なく編集されるのを望まない場合は、ここに投稿しないでください。
また、投稿するのは、自分で書いたものか、パブリック ドメインまたはそれに類するフリーな資料からの複製であることを約束してください(詳細は
MeryWiki:著作権
を参照)。
著作権保護されている作品は、許諾なしに投稿しないでください!
このページを編集するには、下記の数式を計算してその答えを欄に入力してください (
ヘルプ
):
いちたすには =
キャンセル
編集ヘルプ
(新しいウィンドウで開きます)
スポンサーリンク
ナビゲーション メニュー
個人用ツール
ログインしていません
トーク
投稿記録
アカウント作成
ログイン
名前空間
利用者ページ
議論
日本語
表示
閲覧
編集
履歴表示
その他
検索
スポンサーリンク
スポンサーリンク
案内
メインページ
ヘルプ
よくある質問
マクロリファレンス
マクロライブラリ
プラグインライブラリ
構文ファイル
テーマ
寄付・開発支援
練習用ページ
開発室
開発者のブログ
ツール
スポンサーリンク