Mery.iniのオプション値を取得

提供: MeryWiki
ナビゲーションに移動 検索に移動

設定ファイル Mery.ini にアクセスして任意の項目の設定値を参照するための 組み込み用コード です。
複数の項目を配列にして関数に渡す仕様につき Mery.ini へのアクセス(読みこみ)を1回で済ませられるため、多様性に富んだ参照を高速に処理できます。

Mery.ini の内容を編集(書き換え)するものではありません。

GetIniOption() 関数[編集]

Mery.ini ファイル内の各行

KeyName=value

の「項目名 Key」の文字列を指定して「値 value」を取得するための 組み込み用関数 です。
Mery.ini の任意の項目名(左辺)で検索をかけて、生の値(右辺)をそのまま取得します。


ペーストする位置は呼び出し元のコードから参照できるスコープ内であれば、ソースコードの末尾でも問題ありません。
使い方は 使用例 を参考にしてください。
  • INI 内に同名の「項目名」がある場合は、さいしょにヒットした項目の「値」のみを返します。これは、引数の配列の要素(項目名)と戻り値の配列の要素(値)を 1 対 1 で対照させるための仕様です。
    → 重複する「項目名」のある項目を参照する場合は GetIniOption2 関数 を使用してください(2019/05/21 追加)。
  • 引数の配列で「オプション項目名」の記述を間違えると、 警告ダイアログを表示し、誤った項目名を指摘します。
    ※ 呼び出し元のコードの処理は継続されます。
  • 「Mery.exe」自体のファイル名をリネームしている場合も、Mery の実行ファイルのベース名を取得して、適切な INI ファイルを読みこみます。


  • このマクロ関数は Mery.ini の内容を編集(書き換え)するものではありません。


  • 基本的に Mery.ini は オプション などの設定ダイアログを [OK] ボタンで閉じたときと Mery を終了したときにしか更新されず、標準メニューバー、ツールバーアイコン、右クリックメニュー、ショートカットキー、マクロ等でエディタの設定状態を変更しているばあい、INI の内容が最新の状態とはなりません。
    よって、かならずしもエディタの表示状態(折り返しや色の反転、記号の表示設定など)どおりの値を取得できるわけではありません。


・・・ MeryInfo.js にはない項目として「行の表示方法」の取得ぐらいしか使い道がない?
  • Mery.ini の直接編集でオプションパネルから設定変更できない「隠し機能」項目をカスタマイズしている人なら、現在の設定値の確認などにも使えるかも?
  • メモ に挙げた導入事例のマクロのように、関数コードを改造することで Mery.ini のマクロへの活用法の幅がひろがります。


ソースコード[編集]

// #title="Mery.ini のオプション値を取得"

/**
 * 組み込み関数 GetIniOption( keyArray )
 *
 * 引数で指定した任意の INI オプション項目の「値」を返す
 * ※ 引数は INI オプション項目名を列挙した配列
 *   記述形式は [ "KeyName1", "KeyName2", "KeyName3" ] 
 * → 戻り値 も INI オプション項目の値を並べた 配列。
 *   (各要素は 数値 または 文字列)
 */
// ---------- ▼ 組み込み関数 ココから ▼ ----------

function GetIniOption( keyArray ) {
  // Mery.ini を探す
  var iniPath = editor.FullName.replace( /\.exe$/i, ".ini" );
  var Fso = new ActiveXObject( "Scripting.FileSystemObject" );
  if ( ! Fso.FileExists( iniPath ) ) {
    var iniName = /\\([^\\]+)\.exe$/.exec( editor.FullName )[1];
    var WshShell = new ActiveXObject( "WScript.Shell" );
    iniPath = WshShell.SpecialFolders( "APPDATA" )
            + "\\Mery\\" + iniName + ".ini";
  }
  // Mery.ini を読みこむ
  var Adodb = new ActiveXObject( "ADODB.Stream" );
  var adTypeText = 2,  adReadAll = -1;
  Adodb.Type = adTypeText, Adodb.Charset = "UTF-8";
  Adodb.Open();
  Adodb.LoadFromFile( iniPath );
  var iniText = Adodb.ReadText( adReadAll );	// .replace( /\r\n?/g, "\n" )
  Adodb.Close();

  // includeライブラリの IO.js と MeryInfo.js を #include しているマクロに組み込むなら
  //   var iniPath  から  Adodb.Close()  までは以下の一行だけでよい
  // var iniText = IO.LoadFromFile( MeryInfo.GetIniPath(), "utf-8" );

  // 引数の配列をループ処理して ini からオプションの値を取得する
  var reg, value, iniOptionArray = [];
  for ( var i = 0, len = keyArray.length; i < len; i ++ ) {
    reg = new RegExp( "^" + keyArray[i] + "=[^\\r\\n]*$", "gm" );
    try {
      // 項目名の記述ミスがあるとこの行でエラーが発生する
      value = iniText.match( reg )[0]
                     .substr( keyArray[i].length + 1 );
      // 10進数なら Number 型で返す
      if ( /^-?[1-9][0-9]*$/.test( value ) ) {
        value = Number( value );
      }
    }
    catch( e ) {
      Alert( keyArray[i] + " という項目はありません。" );
      value = undefined;
    }
    iniOptionArray.push( value );
  }
  return iniOptionArray;
}

// ---------- ▲ 組み込み関数 ココまで ▲ ----------


使い方[編集]

/**
 * 【使い方】
 *
 * GetIniOptions() 関数の使用は1回で済ませないと
 * その都度 INI ファイルの読み込みが発生してマクロの処理速度が落ちるので
 * 取得したい項目すべてをひとつの配列にまとめること
 * 
 * ※ 取得したいオプション項目がひとつだけの場合でも引数は ["配列"] のかたちで記述すること
 *   GetIniOption( [ "KeyName" ] )
 *
 * ※ INI のオプション項目名の記述を間違えても警告ダイアログを表示して続行する
 *   → 誤ったキーの戻り値は undefined
 */
// ➀ 取得したい INI オプション項目を ["配列"] に列挙する
var iniItem = [ "LineColumnView", "WrapMode", "QuoteCharacter", "TabColumns", "AutoIndent" ];

// または
var iniItem = new Array( "LineColumnView", "WrapMode", "QuoteCharacter", "TabColumns", "AutoIndent" );


// ➁ GetIniOption() の引数に配列を指定して変数に代入 (※返り値も配列)
var iniValue = GetIniOption( iniItem );


// ➂-1.(例1)取得したオプションをダイアログで順々に表示する
for ( var i = 0, type; i < iniItem.length; i ++ ) {
  type = Object.prototype.toString.call( iniValue[i] ).slice( 8, -1 );
  Alert( iniItem[i] + " = " + iniValue[i] + "\nobject type: " + type );
}


// ➂-2.(例2)個々の値の参照には、戻り値の配列の [インデックス] で要素を指定する
var settings = {
  lineColumnView:	iniValue[0],	// 「行の表示方法」
  wrapMode:			iniValue[1],	// 「折り返し方法」
  quoteCharacter:	iniValue[2],	// 「引用マーク」
  tabColumns:		iniValue[3],	// 「タブの桁数」
  autoIndent:		iniValue[4]		// 「自動インデントを有効にする」
};

Alert( "行の表示方法: "
     + ( settings.lineColumnView == 1 ? "表示行" : "論理行" )
);


// ➂-3.(注)取得したいオプション項目がひとつの場合も、["配列"] のかたちで記述すること
Alert( GetIniOption( ["LineColumnView"] ) );


GetIniOption2() 関数[編集]

Mery.ini ファイル内の各項目

[SectionName]
KeyName1=value1
KeyName2=value2

の「段落名・セクション [Section]」と「項目名・キー Key」の文字列を指定して「値 value」を取得するための 組み込み用関数 です。
ことなるセクションに同じキー名の項目が重複して存在することを考慮してありますので、Mery.ini のすべての項目の参照が可能になります。


使い方は 使用例 を参考にしてください。


  • このマクロ関数は Mery.ini の内容を編集(書き換え)するものではありません。


ソースコード[編集]

// #title="Mery.ini のオプション値を取得"

/**
 * 組み込み関数 GetIniOption2( keyArray )
 *
 * 引数で指定した任意の INI オプション項目の配列に
 * 「値」をくわえた配列 で返す
 *
 * ※ 引数: INI オプション項目(セクション名とキー名)を指定する配列
 *   記述形式は [ [section1, key1], [section2, key2] ... ] (※入れ子にする)
 *
 * → 戻り値: INI オプション項目の「値」を追加した配列
 *   配列の形式は [ [section1, key1, value1], [section2, key2, value2] ... ]
 * ※ value はすべて文字列値(String)で返す
 *  (数字の場合も "1" として返す  "1" !== 1  )
 */
// ---------- ▼ 組み込み関数 ココから ▼ ----------

function GetIniOption2( keyArray ) {
  // Mery.ini を探す
  var iniPath = editor.FullName.replace( /\.exe$/i, ".ini" );
  var Fso = new ActiveXObject( "Scripting.FileSystemObject" );
  if ( ! Fso.FileExists( iniPath ) ) {
    var iniName = /\\([^\\]+)\.exe$/.exec( editor.FullName )[1];
    var WshShell = new ActiveXObject( "WScript.Shell" );
    iniPath = WshShell.SpecialFolders( "APPDATA" )
            + "\\Mery\\" + iniName + ".ini";
  }
  // Mery.ini を読みこむ
  var Adodb = new ActiveXObject( "ADODB.Stream" );
  var adTypeText = 2,  adReadAll = -1;
  Adodb.Type = adTypeText, Adodb.Charset = "UTF-8";
  Adodb.Open();
  Adodb.LoadFromFile( iniPath );
  var iniText = Adodb.ReadText( adReadAll );	// .replace( /\r\n?/g, "\n" )
  Adodb.Close();

  // includeライブラリの IO.js と MeryInfo.js を #include しているマクロに組み込むなら
  //   var iniPath  から  Adodb.Close()  までは以下の一行だけでよい
  // var iniText = IO.LoadFromFile( MeryInfo.GetIniPath(), "utf-8" );

  // 引数の配列をループ処理して ini からオプションの値を取得する
  var section, key, value, iniOptionArray = [];
  var reg, id1, id2, id3, id4;
  var iniLength = iniText.length;
  var Quote = function( str ) { return str.replace( /\W/g, "\\$&" ) };
  for ( var i = 0, len = keyArray.length; i < len; i ++ ) {
    section = keyArray[i][0];
    key     = keyArray[i][1];
    reg = new RegExp( "^\\[" + Quote( section ) + "\\]$", "m" );
    id1 = iniText.search( reg );				// セクションの開始位置
    if ( id1 != -1 ) {							// セクション名が正しいか?
      id2 = iniText.indexOf( "\r\n[", id1 + 1 );// 次のセクションの開始位置
      id2 = ( id2 > id1 ) ? id2 : iniLength;
      id3 = iniText.indexOf( "\n" + key, id1 );	// キーの開始位置
      if ( id3 != -1 && id2 > id3 ) {			// セクション内にキーがあるか?
        id4 = iniText.indexOf( "\r\n", id3 );	// 検索項目の行末位置
        value = iniText.slice( id3 + key.length + 2, id4 );	// ("\n"+"=").length=2
        iniOptionArray.push( [ section, key, value ] );
      }
      else {	// キーの指定ミスがあった場合
        Alert( "\"" + key + "\" key is NOT found in [" + section + "] section." );
        iniOptionArray.push( [ section, undefined, null ] );
      }
    }
    else {	// セクションの指定ミスがあった場合
      Alert( "[" + section + "] section is NOT found in \"Mery.ini\" file." );
      iniOptionArray.push( [ undefined, key, null ] );
    }
    id1 = 0;
  }
  return iniOptionArray;
}

// ---------- ▲ 組み込み関数 ココまで ▲ ----------


使い方[編集]

/**
 * 【使い方】
 *
 * GetIniOptions2() 関数の使用は1回で済ませないと
 * その都度 INI ファイルの読み込みが発生してマクロの処理速度が落ちるので
 * 取得したい項目すべてをひとつの配列にまとめること
 * 
 * ※ 取得したいオプション項目がひとつだけの場合でも引数の配列は入れ子にすること
 *   GetIniOption2( [ [ "SectionName", "KeyName" ] ] )
 *
 * ※ INI のオプション項目名の記述を間違えても警告ダイアログを表示して続行する
 *   記述ミスをした項目は  undefined  に置き換え、要求された値は  null  で返す
 * ※ オプションの値が空  KeyName=  の場合は空文字列  ""  を返す
 *
 * ※ 値はすべて "文字列" 型で返されるので、
 *   必要に応じて  Number( value )  などのかたちで利用する
 */
// ➀ セクション名とキー名をセットにした配列 [ [section1, key1], [section2, key2] ... ]
// セクション名にバックスラッシュ・¥ 記号「\」がある場合は、ふたつ重ね「\\」で記述すること

var keyArray = new Array(
  [ "General", "LineColumnView" ], 		// 0 or 1
  [ "General", "FileFilter" ], 			// "*.txt;*ini;*.htm; …"
  [ "General", "Untitled" ], 			// 「無題」の代替文字列 or ""
  [ "View", "FontName0" ], 				// フォント名(履歴) or ""
  [ "Macros\\Macro1", "FileName" ], 	// Macros\マクロ名.js or ""
  [ "Outline\\JavaScript", "Match1" ],	// 文字列値 or 正規表現 or "..."
  [ "Themes\\Theme29", "Caption" ], 	// テーマ名 or ""
  [ "Display", "FallbackFonts" ], 		// フォント名 or ""
  // ※ ~ver 2.7.4 では FallbackFonts キーがないので [Display] undefined = null

  // ※ 無効な セクション名 や キー名 を指定した場合
  [ "HOGE", "FUGA" ],  				// [undefined]	FUGA  =  null
  [ "Themes", "PIYO" ]				// [Themes]		undefined  =  null
);


// ➁ 関数の引数に配列をあたえて、変数 iniOption に代入する
// 関数の戻り値も配列 [ [section1, key1, value1], [section2, key2, value2] ... ]
// ※ value は文字列値(String)で返される(数字の場合も "1"、※ "1" !== 1 )

var iniOption = GetIniOption2( keyArray );


// ➂ 戻り値で得た配列の内容をアウトプットバーに出力する

OutputBar.Writeln( "\n> GetIniOption2()" );
var section, key, value;
for ( var i = 0; i < iniOption.length; i ++ ) {

  section = iniOption[i][0];	// セクション名に記述ミスがあると undefined
  key     = iniOption[i][1];	// キー名に記述ミスがあると undefined

  // 上の二つのいずれかにミスがあると値は null、値が空のときは ""
  value   = iniOption[i][2];

  OutputBar.Writeln( "\n[" + section + "]\n"
                   + key + "  =  " + value );
}

更新履歴[編集]

  • 2019/03/10 (sukemaru)
GetIniOption 関数 の初版
  • 2019/04/28 (sukemaru)
「文字列値」が2バイト文字を含むときに正常に読みこめなかったので、"ADODB.Stream" / UTF-8 での読みこみに変更した。
  • 2019/04/29 (sukemaru)
値がハイフン-マイナス「-」1文字のときに戻り値が NaN になっていたのを文字列 "-" で返すように修正(値が空のときは長さ 0 の文字列 "" のまま)。
  • 2019/05/21 (sukemaru)
セクション指定可能な GetIniOption2() 関数 を追加し、Mery.ini の完全な参照ができるようにした。
一応、従来の GetIniOption() 関数も簡易版として残しておく(誤った参照キー名に対するエラー処理を変更)。
  • 2019/06/02 (sukemaru)
GetIniOption2() 関数の変数 id2 周りのコードで、引数のキー名にエラーがあった場合の処理が正しく行われなかった不具合を修正。
  • 2019/08/27 (sukemaru)
GetIniOption2() 関数の変数 id2 周りのコードで、同一セクション内で に角カッコ「[」を含む キー が上にあると次の セクション の開始位置を正しく取得できなかった不具合を修正。
  • 2019/11/15 (sukemaru)
関数コードの軽微な修正。
説明などの文面を変更。


メモ[編集]

  • 2019/03/10 (sukemaru)
将来的に INI を最新の状態に強制更新したり INI の設定項目を取得できる専用メソッドが実装されるかもしれませんし、現状でも includeライブラリMeryInfo.js)によりある程度 INI へのアクセスはできますが…。
一応、includeライブラリ(IO.js)の使用のみでエディタの表示状態を変更するマクロの例として「折り返しトグル切り替え」などもあります。


INI アクセスのための専用メソッド については フォーラム 内のトピック『マクロコマンドから「表示」の「色の反転」を取得したい』で検討・議論されていますので、ご参考までに(セキュリティ上の 懸念 により実装は見送りとなっています)。


  • 導入事例
  • 検索ジャンプ」「ブックマークジャンプ」マクロでは「行の表示方法」(論理座標/表示座標) の取得に GetIniOption 関数を利用しています。
  • 読みなおし」マクロでは「自動保存」「バックアップ」関連の設定内容とすべての「編集モード名」を取得しています (※「読みなおし」マクロでは、GetIniOption 関数を大幅に魔改造して使用しています)。
  • コンパクトメニュー」マクロでは GetIniOption 関数をさらに魔改造して、「最近のファイルの表示数」 「無題タブ用のラベル」 などの値や、「編集モード」 「マクロ」 「プラグイン」 「外部ツール」 の一覧などを取得しています。


  • 読みこみたい値が「数値」や「Ascii だけの文字列」であれば、記述が煩雑になる ADODB.Stream や拙作の関数を使わずに、FileSystemObject の OpenTextFile と ReadAll メソッドでも問題ありません(値が2バイト文字の場合、文字化けするので FileSystemObject は不適)。
なお、Mery.ini の改行コードは CR+LF なので、検索で改行位置を利用する場合は "\r\n" を用います。


  • 基本的に、「編集モード」 「マクロ」 「プラグイン」 「外部ツール」 のショートカットキーは取得できません (キー名が32桁の16進数になっていて「マクロ名」などで検索できないため)。
スポンサーリンク