「Mery.iniのオプション値を取得」の版間の差分

提供:MeryWiki
ナビゲーションに移動 検索に移動
(GetIniOption3() 関数を追加)
編集の要約なし
340行目: 340行目:
* GetIniOption2() 関数では戻り値も '''入れ子状の配列''' だったため、任意のキーの「値」を参照するには <source lang="javascript">
* GetIniOption2() 関数では戻り値も '''入れ子状の配列''' だったため、任意のキーの「値」を参照するには <source lang="javascript">
var iniOption = GetIniOption2([[section1, key1], [section2, key2]]);
var iniOption = GetIniOption2([[section1, key1], [section2, key2]]);
// 配列の index をふたつずつ指定して「値」を参照
var value1 = iniOption[0][2];
var value1 = iniOption[0][2];
var value2 = iniOption[1][2];
var value2 = iniOption[1][2];
</source> のように記述しなければならず、可読性にやや難ありでしたが、GetIniOption3() 関数では戻り値を ''' 連想配列(オブジェクト型)''' <code>{section1 : {key1 : value1}, section2 : {key2 : value2} ... }</code> ''<code>objOptions[section][key] = value</code>'' にしてあります。<br>
</source> のように記述しなければならず、コードの可読性にやや難ありでした。<br> GetIniOption3() 関数では戻り値を '''オブジェクト型(連想配列)''' にしてあります。
: INI から取得する「値」が複数のとき、任意の「値」の参照がしやすくなるかとおもいます。<source lang="javascript">
{section1 : {key1 : value1}, section2 : {key2 : value2} ... }
⇒ ''value = objOptions[section][key]''
: <span style="color:#0000c0;">セクション名とキー名がそのままプロパティ名になる</span>ので、INI から取得する「値」が複数のときに任意の「値」の参照がしやすくなるかとおもいます。<source lang="javascript">
var keyArray = [["General", "LineColumnView"], ["View", "FontName0"]];
var keyArray = [["General", "LineColumnView"], ["View", "FontName0"]];
var iniOption = GetIniOption3(keyArray);
var iniOption = GetIniOption3(keyArray);
 
// プロパティをセクション名とキー名の文字列で記述して「値」を参照
var value1 = iniOption.General.LineColumnView; // ドット記法
var value1 = iniOption.General.LineColumnView; // ドット記法
var value2 = iniOption["View"]["FontName0"]; // ブラケット記法
var value2 = iniOption["View"]["FontName0"]; // ブラケット記法
352行目: 355行目:




* 戻り値の「値」の部分 <code>value</code> は文字列型(String)です。<br> ※ GetIniOption2() 関数ではセクション名やキー名の指定が正しくなかったときに記述ミスした項目名を <span style="color:#c00;"><code>undefined</code></span> にして「値」を <span style="color:#c00;"><code>null</code></span> で返しましたが、<span style="color:#c00;">GetIniOption3() 関数では間違えたままの項目名の「プロパティ」に <code>undefined</code> を「値」としてあたえて返します。</span><br> ''e.g.'' <code>obj.General.HOGE = undefined</code>
* 戻り値の「値」の部分 <code>value</code> は文字列型(String)です。<br> ※ GetIniOption2() 関数ではセクション名やキー名の指定が正しくなかったときに記述ミスした項目名を <span style="color:#c00;"><code>undefined</code></span> にして「値」を <span style="color:#c00;"><code>null</code></span> で返しましたが、<span style="color:#c00;">GetIniOption3() 関数では間違えたままの項目名の「プロパティ」に <code>undefined</code> を「値」としてあたえて返します。</span><br> ''e.g.'' <code>objOptions.General.HOGE = undefined</code>


* GetIniOption() 関数と GetIniOption2() 関数ではセクション名やキー名の指定が正しくなかったとき、つねに警告ダイアログを表示させる仕様にしてありましたが、GetIniOption3() 関数では第2引数(Bool)に <code>true</code> をあたえなかった場合は警告なしで処理を続行します。
* GetIniOption() 関数と GetIniOption2() 関数ではセクション名やキー名の指定が正しくなかったとき、つねに警告ダイアログを表示させる仕様にしてありましたが、GetIniOption3() 関数では第2引数(Bool)に <code>true</code> をあたえなかった場合は警告なしで処理を続行します。
<div class="warningbox">
<span style="color:#c00;">※ セクション名に「'''<code>\</code>'''」をふくむ項目を取得したときは、戻り値のプロパティ名はブラケット記法で記述してください。</span><br>
: ''e.g.'' <code>["Macros\\Macro0", "FileName"]</code>, <code>["Mode\\Text"]["Count"]</code><br>  ⇒  <code>objOptions["Macros\\Macro0"]["FileName"]</code>, <code>objOptions["Mode\\Text"]["Count"]</code>
</div>




394行目: 403行目:


function GetIniOption3( keyArray, alertEnable ) {
function GetIniOption3( keyArray, alertEnable ) {
  var Fso = new ActiveXObject( "Scripting.FileSystemObject" );
   // Mery.ini を探す
   // Mery.ini を探す
   var iniPath = editor.FullName.replace( /\.exe$/i, ".ini" );
   var iniPath = editor.FullName.replace( /\.exe$/i, ".ini" );
  var Fso = new ActiveXObject( "Scripting.FileSystemObject" );
   if ( ! Fso.FileExists( iniPath ) ) {
   if ( ! Fso.FileExists( iniPath ) ) {
     var iniName = /\\([^\\]+)\.exe$/.exec( editor.FullName )[1];
     var iniName = /\\([^\\]+)\.exe$/.exec( editor.FullName )[1];
413行目: 422行目:


   // 引数の配列をループ処理して ini からオプションの値を取得する
   // 引数の配列をループ処理して ini からオプションの値を取得する
   var section, key, value, options = {};
   var options = {};
   var reg, id1, id2, id3, id4;
   var section, key, value, reg, id1, id2, id3, id4;
   var iniLength = iniText.length;
   var iniLength = iniText.length;
  var Quote = function( str ) { return str.replace( /\W/g, "\\$&" ) };
   for ( var i = 0, len = keyArray.length; i < len; id1 = 0, i ++ ) {
   for ( var i = 0, len = keyArray.length; i < len; i ++ ) {
     section = keyArray[i][0];
     section = keyArray[i][0];
     key    = keyArray[i][1];
     key    = keyArray[i][1];
     options[ section ] = options[ section ] || {};
     options[ section ] = options[ section ] || {};
     reg = new RegExp( "^\\[" + Quote( section ) + "\\]$", "m" );
    // セクション名を検索
     reg = new RegExp( "^\\[" + section.replace( /\W/g, "\\$&" ) + "\\]$", "m" );
     id1 = iniText.search( reg ); // セクションの開始位置
     id1 = iniText.search( reg ); // セクションの開始位置
     if ( id1 != -1 ) { // セクション名が正しいか?
     if ( id1 != -1 ) { // セクション名が正しいか?
       id2 = iniText.indexOf( "\r\n[", id1 + 1 ); // 次のセクションの開始位置
       id2 = iniText.indexOf( "\r\n[", id1 + 1 ); // 次のセクションの開始位置
       id2 = ( id2 > id1 ) ? id2 : iniLength;
       id2 = ( id2 > id1 ) ? id2 : iniLength;
      // キー名を検索
       id3 = iniText.indexOf( "\n" + key + "=", id1 ); // キーの開始位置
       id3 = iniText.indexOf( "\n" + key + "=", id1 ); // キーの開始位置
       if ( id3 != -1 && id2 > id3 ) { // セクション内にキーがあるか?
       if ( id3 != -1 && id2 > id3 ) { // セクション内にキーがあるか?
         id4 = iniText.indexOf( "\r\n", id3 ); // 検索項目の行末位置
         id4 = iniText.indexOf( "\r\n", id3 ); // 検索項目の行末位置
         value = iniText.slice( id3 + key.length + 2, id4 );
         value = iniText.slice( id3 + key.length + 2, id4 ); // ("\n"+"=").length=2
         options[ section ][ key ] = value;
         options[ section ][ key ] = value;
       }
       }
       // キーの指定ミス
       else { // キー名の指定ミス
      else {
         options[ section ][ key ] = undefined;
         options[ section ][ key ] = undefined;
         if ( alertEnable ) {
         if ( alertEnable ) {
442行目: 451行目:
       }
       }
     }
     }
     // セクションの指定ミス
     else { // セクション名の指定ミス
    else {
       options[ section ][ key ] = undefined;
       options[ section ][ key ] = undefined;
       if ( alertEnable ) {
       if ( alertEnable ) {
451行目: 459行目:
       }
       }
     }
     }
    id1 = 0;
   }
   }
   return options;
   return options;
478行目: 485行目:
   * ※ 値はすべて '''"文字列"''' (String)型で返されるので、
   * ※ 値はすべて '''"文字列"''' (String)型で返されるので、
   *    必要に応じて  ''Number( value )''  などのかたちで利用すること
   *    必要に応じて  ''Number( value )''  などのかたちで利用すること
  *
  * <b style="color:#c00;">【注意】</b>
  * <span style="color:#c00;">※ セクション名に「'''<code>\</code>'''」が含まれる場合、</span>
  *    <span style="color:#c00;">戻り値のプロパティ名を指定するさいには '''ブラケット記法''' で記述すること</span>
  *  e.g. ''[ "Themes'''\\'''Theme0", "Caption" ]''
  *  ⇒  ''objOptions['''"Themes\\Theme0"''']["Caption"]''
  *  (ドット記法で ''objOptions.Themes'''\\'''Theme0.Caption'' とすると <b style="color:#c00;">エラー</b> になる)
   */
   */
<source lang="javascript">
<source lang="javascript">
510行目: 524行目:
   section = keyArray[i][0],  key = keyArray[i][1];
   section = keyArray[i][0],  key = keyArray[i][1];
   OutputBar.Writeln( "[" + section + "]\t" + key
   OutputBar.Writeln( "[" + section + "]\t" + key
                   + "=" + iniOptions[ section ][ key ] );
                   + "=" + iniOptions[ section ][ key ] ); // ブラケット記法
  // セクション名に「\」をふくむ項目があるのでブラケット記法を使用
}
}



2020年5月15日 (金) 01:45時点における版

テキストエディタ Mery の設定ファイル Mery.ini を参照して任意の項目の設定値を取得するための マクロ用組み込みコード です。

複数の項目を配列にして関数に渡す仕様につき Mery.ini へのアクセス(読みこみ)が1回で済むため、多様性に富んだ参照を高速に処理できます。

このページのマクロ関数は Mery.ini の内容を編集(書き換え)するものではありません。
※ 標準ツールバーのメニューや右クリックメニューのコマンド、ツールバーアイコン、ショートカットキー、他のマクロなどから変更された設定内容(おもにエディタの表示設定)は直ちに Mery.ini に反映されるわけではないので、この組み込み用コードにより取得されたオプション値がエディタの状態どおりではない場合があります。


GetIniOption() 関数

Mery.ini ファイル内の各行

KeyName=value

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


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


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


  • 基本的に Mery.ini は オプション などの設定ダイアログを閉じたときと Mery を終了したときにしか更新されず、標準メニューバー、ツールバーアイコン、右クリックメニュー、ショートカットキー、マクロ等でエディタの設定状態を変更しているばあい、INI の内容が最新の状態とはなりません。
    よって、かならずしもエディタの表示状態(折り返しや色の反転、記号の表示設定など)どおりの値を取得できるわけではありません。
    ・・・ MeryInfo.js にはない項目として「行の表示方法」の取得ぐらいしか使い道がない?
  • Mery.ini の直接編集でオプションパネルから設定変更できない「隠し機能」項目をカスタマイズしている人なら、現在の設定値の確認などにも使えるかも?
  • メモ に挙げた導入事例のマクロのように、関数コードを改造することで Mery.ini のマクロへの活用法の幅がひろがりますが…。


ソースコード

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

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

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 );
  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 ファイルの読み込み が発生してマクロの処理速度が落ちるので
 * 取得したい項目すべてをひとつの配列にまとめること
 * 
 * ※ 取得したいオプション項目がひとつだけの場合でも引数は
 *    配列 ["KeyName"] のかたちで記述すること
 * 
 *   GetIniOption( [ "KeyName" ] )
 *
 * ※ INI のオプション項目名の記述を間違えても警告ダイアログを表示して
 *    組み込み関数および呼び出し元のコードを続行する
 *   → 誤ったキーの戻り値は undefined
 */
// ➀ 取得したい INI オプション項目を配列 ["KeyName1", "KeyName2" ...] に列挙する

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 );
}	// "LineColumnView = 1 ↲ object type: number" ...


// ➂-2.(例2)個々の「値」の参照には、戻り値の配列の [index] で要素を指定する

var settings = {
  lineColumnView:	iniValue[0],	// 「行の表示方法」
  wrapMode:			iniValue[1],	// 「折り返し方法」
  quoteCharacter:	iniValue[2],	// 「引用マーク」
  tabColumns:		iniValue[3],	// 「タブの桁数」
  autoIndent:		iniValue[4]		// 「自動インデントを有効にする」
};

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


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

Alert( GetIniOption( ["LineColumnView"] ) );


GetIniOption2() 関数

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

[SectionName]
KeyName1=value1
KeyName2=value2

の「段落名・セクション [SectionName]」と「項目名・キー KeyName」の文字列を指定して「値 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 );
  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 );
        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=  の場合は空文字列  ""  を返す
 *
 * ※ 値はすべて "文字列" (String)型で返されるので、
 *    必要に応じて  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( "\nRun > " + ScriptName + " : function 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 );
}


GetIniOption3() 関数

GetIniOption2() 関数 とおなじく、Mery.ini ファイル内の各項目

[SectionName]
KeyName1=value1
KeyName2=value2

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


  • GetIniOption2() 関数では戻り値も 入れ子状の配列 だったため、任意のキーの「値」を参照するには
    var iniOption = GetIniOption2([[section1, key1], [section2, key2]]);
    // 配列の index をふたつずつ指定して「値」を参照
    var value1 = iniOption[0][2];
    var value2 = iniOption[1][2];
    
    のように記述しなければならず、コードの可読性にやや難ありでした。
    GetIniOption3() 関数では戻り値を オブジェクト型(連想配列) にしてあります。
{section1 : {key1 : value1}, section2 : {key2 : value2} ... }
⇒ value = objOptions[section][key]
セクション名とキー名がそのままプロパティ名になるので、INI から取得する「値」が複数のときに任意の「値」の参照がしやすくなるかとおもいます。
var keyArray = [["General", "LineColumnView"], ["View", "FontName0"]];
var iniOption = GetIniOption3(keyArray);
// プロパティをセクション名とキー名の文字列で記述して「値」を参照
var value1 = iniOption.General.LineColumnView;	// ドット記法
var value2 = iniOption["View"]["FontName0"];	// ブラケット記法


  • 戻り値の「値」の部分 value は文字列型(String)です。
    ※ GetIniOption2() 関数ではセクション名やキー名の指定が正しくなかったときに記述ミスした項目名を undefined にして「値」を null で返しましたが、GetIniOption3() 関数では間違えたままの項目名の「プロパティ」に undefined を「値」としてあたえて返します。
    e.g. objOptions.General.HOGE = undefined
  • GetIniOption() 関数と GetIniOption2() 関数ではセクション名やキー名の指定が正しくなかったとき、つねに警告ダイアログを表示させる仕様にしてありましたが、GetIniOption3() 関数では第2引数(Bool)に true をあたえなかった場合は警告なしで処理を続行します。


※ セクション名に「\」をふくむ項目を取得したときは、戻り値のプロパティ名はブラケット記法で記述してください。

e.g. ["Macros\\Macro0", "FileName"], ["Mode\\Text"]["Count"]
objOptions["Macros\\Macro0"]["FileName"], objOptions["Mode\\Text"]["Count"]


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


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


ソースコード

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

/**
 * 組み込み関数 GetIniOption3( keyArray, boolAlertEnable )
 * 
 * 引数で指定した INI オプション項目名と「値」をプロパティ値として持つ
 * 入れ子型のオブジェクトを返す
 * 
 * 引数: INI オプション項目(セクション名とキー名)を指定する入れ子型の配列
 * ※ 配列の記述形式は [ [ section1, key2 ], [ section2, key2 ] ... ]
 * 
 * 戻り値: INI オプション項目の「値」を String 型のプロパティ値として持つオブジェクト
 *     { section1 : { key1 : value1 }, section2 : { key2 : value2 } ... }
 *     objOptions[ section ][ key ] = value
 * 
 * ※ 有効な value はすべて 文字列型 (String)で返す
 *  (数字の場合も "1" として返す  "1" !== 1  )
 * ※ 無効な section, key が指定されたものにたいしては value = undefined で返す
 * 
 * ※ 各「値」への参照方法は
 *   var iniOptions = GetIniOption3( keyArray );
 *   var value1 = iniOptions[ "section1" ][ "key1" ];	// ブラケット記法
 *   var value2 = iniOptions.section2.key2;		// ドット記法
 */
// ---------- ▼ 組み込み関数 ココから ▼ ----------

function GetIniOption3( keyArray, alertEnable ) {
  var Fso = new ActiveXObject( "Scripting.FileSystemObject" );
  // Mery.ini を探す
  var iniPath = editor.FullName.replace( /\.exe$/i, ".ini" );
  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 );
  Adodb.Close();

  // 引数の配列をループ処理して ini からオプションの値を取得する
  var options = {};
  var section, key, value, reg, id1, id2, id3, id4;
  var iniLength = iniText.length;
  for ( var i = 0, len = keyArray.length; i < len; id1 = 0, i ++ ) {
    section = keyArray[i][0];
    key     = keyArray[i][1];
    options[ section ] = options[ section ] || {};
    // セクション名を検索
    reg = new RegExp( "^\\[" + section.replace( /\W/g, "\\$&" ) + "\\]$", "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
        options[ section ][ key ] = value;
      }
      else {	// キー名の指定ミス
        options[ section ][ key ] = undefined;
        if ( alertEnable ) {
          Alert( "\"" + key + "\" key is NOT found in [" + section + "] section.\n\n"
               + "The function will return ... \n"
               + "{ \"" + section + "\" : { \"" + key + "\" : undefined } }" );
        }
      }
    }
    else {		// セクション名の指定ミス
      options[ section ][ key ] = undefined;
      if ( alertEnable ) {
        Alert( "[" + section + "] section is NOT found in \"Mery.ini\" file.\n\n"
             + "The function will return ... \n"
             + "{ \"" + section + "\" : { \"" + key + "\" : undefined } }" );
      }
    }
  }
  return options;
}

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


使い方

/**
 * 【使い方】
 *
 * GetIniOption3() 関数の使用は1回で済ませないと
 * その都度 INI ファイルの読み込み が発生してマクロの処理速度が落ちるので
 * 取得したい項目すべてをひとつの配列にまとめること
 *
 * ※ 要求する項目が1セットの場合も配列を 入れ子 にすること
 *   GetIniOption3( [ [ "SectionName", "KeyName" ] ] );
 *
 * ※ INI のオプション項目名の記述を間違えても警告ダイアログを表示して続行する
 *    記述ミスをした項目の値 value undefined で返される
 * ※ INI 内でオプションの値が空  KeyName=  の場合は空文字列  ""  を返す
 *
 * ※ 値はすべて "文字列" (String)型で返されるので、
 *    必要に応じて  Number( value )  などのかたちで利用すること
 * 
 * 【注意】
 * ※ セクション名に「\」が含まれる場合、
 *    戻り値のプロパティ名を指定するさいには ブラケット記法 で記述すること
 *  e.g. [ "Themes\\Theme0", "Caption" ]
 *   ⇒  objOptions["Themes\\Theme0"]["Caption"]
 *  (ドット記法で objOptions.Themes\\Theme0.Caption とすると エラー になる)
 */
// ➀ セクション名とキー名をセットにした配列 [ [section1, key2], [section2, key2] ... ]
//    セクション名に「\」がある場合は、ふたつ重ね「\\」で記述すること
var keyArray = new Array(
  [ "General", "LineColumnView" ], 		// 0 or 1
  [ "General", "FileFilter" ], 			// "*.txt;*ini;*.htm; …"
  [ "General", "Untitled" ], 			// 「無題」の代替値 or ""
  [ "Display", "FallbackFonts" ], 		// フォント名 or "" (~ver2.7.4 では undefined)
  [ "View", "FontName0" ], 				// フォント名(履歴) or ""
  [ "Macros\\Macro1", "FileName" ], 	// Macros\マクロ名.js or ""
  [ "Outline\\JavaScript", "Match1" ],	// 文字列値 or 正規表現 or "..."
  [ "Themes\\Theme29", "Caption" ], 	// テーマ名 or ""
  [ "Themes", "HOGE" ],				 	// [Themes] HOGE  =  null
  [ "FUGA", "PIYO" ] 					// [FUGA] PIYO = null
);

// ➁ 関数の引数に配列をあたえて、変数 iniOption に代入する
//    関数の戻り値は入れ子状のオブジェクト
//    { section1 : { key1 : value1 }, section2 : { key2 : value2 } ... }
// ※ value は文字列値(String)で返される(数字の場合も "1"  ※ "1" !== 1 )

var iniOptions = GetIniOption3( keyArray, true );	// 戻り値は Object 型


// ➂-1.(例1)戻り値で取得した内容をアウトプットバーに出力する

OutputBar.Writeln( "\nRun > " + ScriptName + " : function GetIniOption3()" );
var section, key;
for ( var i = 0; i < keyArray.length; i ++ ) {
  section = keyArray[i][0],  key = keyArray[i][1];
  OutputBar.Writeln( "[" + section + "]\t" + key
                   + "=" + iniOptions[ section ][ key ] );	// ブラケット記法
  // セクション名に「\」をふくむ項目があるのでブラケット記法を使用
}


// ➂-2.(例2)特定の key の値を参照して変数に格納する場合

var ff = iniOptions.General.FileFilter;			// ドット記法
var fn = iniOptions[ "View" ][ "FontName0" ];	// ブラケット記法
Alert( "[General]\nFileFilter=" + ff + "\n"
     + "[View]\nFontName0=" + fn );


更新履歴

  • 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)
関数コードの軽微な修正。
説明などの文面を変更。
  • 2020/05/14 (sukemaru)
セクション指定可能で、戻り値をオブジェクト型にした GetIniOption3() 関数 を追加。


メモ

  • 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進数になっていて「マクロ名」などで検索できないため)。
スポンサーリンク