古いマクロが動かなくなりましたNo.09938
小野雅弘 さん 22/08/18 11:42
 
こちらで紹介いただき、20年近く便利に使っていた
計算マクロ

15+19
と秀丸上で書き、実行すると
15+19=34
と答えが出てくる

が最近使用できなくなりました。
実行すると「他のエディタでマクロを使用中です」
というメッセージが出て、マクロ全般が使えなくなり、
再起動するまで直りません。

マクロを作られた方にお聞きするのもはばかられますので、
少しみて助言を頂けませんか。無理なようでしたら、
同様のマクロを紹介して下さると助かります。
よろしくお願いします。

マクロからマクロを呼び出す2段式ですが、2段目だけを実行しても
エラーが出ます。

1段目は

beginsel;
golinetop;


//--------------------------------------------------------------------------
----

 // 現在情報の所得
 #TopX = seltopx;   //選択開始位置
 #TopY = seltopy;   //選択開始位置
 #EndX = selendx;   //選択終了位置
 #EndY = selendy;   //選択終了位置

moveto #EndX,#EndY;
delete;
delete;
beginsel;

 moveto #TopX,#TopY;   //選択位置頭に移動

tohankaku;

execmacro "calc.mac";

golineend;
replaceup " = ","=";
golineend;
beginsel;
golinetop;
tozenkakuhira;
golineend;

endmacro;

2段目は

//--------------------------------------------------------------------------
----
//    「計算式」 ver 1.00
//     Calc.mac
//
//                                                         つくった人 xx xx
//                                             E-mail: xxxx@muh.biglobe.ne.jp
//                                            http://www2s.biglobe.ne.jp/xxxx/
//                                                       ver 1.00完成 2000.0
1.21
//--------------------------------------------------------------------------
----

 // 範囲選択中か確認
 if( !selecting ){
  golinetop2;    //論理行頭に移動
  beginsel;    //範囲選択開始
  golineend2;    //論理行末に移動
 }

//--------------------------------------------------------------------------
----

 // 現在情報の所得
 #TopX = seltopx;   //選択開始位置
 #TopY = seltopy;   //選択開始位置
 #EndX = selendx;   //選択終了位置
 #EndY = selendy;   //選択終了位置

 moveto #TopX,#TopY;   //選択位置頭に移動
 #NowLineno = lineno;   //現在論理行数

 #handleNow = hidemaruhandle(0);  //現在のウィンドウを捕捉
 disableinvert;    //囲選択のときの反転表示を禁止
 disabledraw;    //画面の書き換えを禁止

//--------------------------------------------------------------------------
----

 // 選択範囲の情報を所得
 beginsel;    //範囲選択開始
 moveto #EndX,#EndY;   //選択位置後ろに移動
 copy;     //コピー
 escape;     //範囲選択を取り消す
 beginclipboardread;   //クリップボード読取初期化
 #FormulaNo = 0;    //計算式数初期化
 while(1){
  $Formula[#FormulaNo] = getclipboard;  //クリップボード所得
  if( $Formula[#FormulaNo] == "" )break;
  #FormulaNo = #FormulaNo+1;   //計算式数を増やす
 }

//--------------------------------------------------------------------------
----

 // バッファウィンドウ作成
 openfile "/h";    //ファイルの新規作成
 #handleBuf = hidemaruhandle(0);  //バッファウィンドウを捕捉
 showwindow 0;    //ウィンドウ非表示

//--------------------------------------------------------------------------
----

 // 計算式数のループ
 #a = 0;
 while( #a < #FormulaNo ){
  // バッファでの作業
  setactivehidemaru #handleBuf;   //バッファウィンドウに移動
  insertfix "\n"+$Formula[#a];   //計算式一行貼付け
  call AnalysisFormula;    //計算式の分析へ
  call RunFormula;    //計算の実行へ
  selectall;     //すべてを選択
  backspace;     //Backspace
  // 計算結果出力
  setactivehidemaru #handleNow;   //現在のウィンドウに移動
  if( #FormulaNo <= 1 ){
   // 計算式が一行のみの場合の処理
   moveto selendx,selendy;   //選択範囲の最後に移動
   insert $Anser;    //答えの出力
  }else{
   // 計算式が複数行の場合の処理
   movetolineno 0,#NowLineno+#a;  //出力位置の論理行頭へ移動
   golineend2;    //論理行末に移動
   insert $Anser;    //答えの出力
  }
  #a = #a+1;
 }

//--------------------------------------------------------------------------
----

 // ウィンドウの書き換えを許可
 setactivehidemaru #handleNow;  //現在のウィンドウに移動
 enableinvert;    //囲選択のときの反転表示禁止を解除
 enabledraw;    //画面の書き換えを許可

 // バッファウインドウの終了
 closehidemaruforced #handleBuf;  //結果出力ウィンドウを強制終了

 // 終了処理
 endmacro;    //マクロの終了

//--------------------------------------------------------------------------
----
//●● 以下サブルーチン ●●●●●●●●●●●●●●●●●●●●●●●●●
●●
//--------------------------------------------------------------------------
----

//--------------------------------------------------------------------------
----
//
// ● 計算式の分析 ●
 AnalysisFormula:
//
//--------------------------------------------------------------------------
----

 // 計算用変数の初期化
 #SuutiNo = 0;    //数値配列数
 #Suuti[0] = 0;    //数値配列
 #EnzanNo = 0;    //演算子配列数
 #Enzan[0] = 0;    //演算子配列
      //1-^、2-/、3-\、4-*、5-+、6--
 #COpen[0] = 0;    //「(」配列
 #CClose[0] = 0;    //「)」配列

 // 状態変数の初期化
 #CNow = 1;    //「()」状態
      //0-チェック終了後、1-チェック中
 #COpRock = -1;    //「(」ロック位置
 #CClRock = -1;    //「)」ロック位置
 #EnzanNow = 1;    //計算演算子状態
      //1-^、2-/\*、3-+-
 #ResSuutiNo = 0;   //残り数値配列数

 // 戻り値初期化
 $Anser = "";    //戻り文字変数

//--------------------------------------------------------------------------
----

 // 数値配列の所得
 ##a = 0;
 while(1){
  searchdown "[0-9]+",regular,fuzzy;  //数字を下向き検索
  if( !result )break;
  ##HeadX = x;
  ##HeadY = y;
  searchdown "[^0-9]",regular,fuzzy  //数字以外を下向き検索
  if( !result )gofileend;    //ファイルの最後に移動
  ##EndX = x;
  ##EndY = y;
  $$GetTxt = gettext( ##HeadX,##HeadY,##EndX,##EndY ); //文字列取り込み
  #SuutiNo = #SuutiNo+1;    //数値配列数
  #Suuti[##a] = val($$GetTxt);   //数値配列
  ##a = ##a+1;
 }

//--------------------------------------------------------------------------
----

 gofiletop;    //ファイルの先頭に移動

//--------------------------------------------------------------------------
----

 // 演算子配列の所得
 ##a = 0;
 while(1){
  searchdown "(%|[\\(-\\+]|\\-|/|\\\\|\\^)",regular,fuzzy;
        //演算子を下向き検索
  if( !result )break;
  ##HeadX = x;
  ##HeadY = y;
  $$GetTxt = gettext( ##HeadX,##HeadY,##HeadX+1,##HeadY );
        //演算子取り込み
  if( $$GetTxt == "(" ){
   #COpen[##a] = #COpen[##a]+1;  //「(」配列
  }else if( $$GetTxt == ")" ){
   #CClose[##a] = #CClose[##a]+1;  //「)」配列
  }else{
   #EnzanNo = #EnzanNo+1;   //演算子配列数
   // 演算子配列の所得
   if( $$GetTxt == "^" )#Enzan[##a] = 1;
   if( $$GetTxt == "/" )#Enzan[##a] = 2;
   if( $$GetTxt == "\\" )#Enzan[##a] = 3;
   if( $$GetTxt == "%" )#Enzan[##a] = 3;
   if( $$GetTxt == "*" )#Enzan[##a] = 4;
   if( $$GetTxt == "+" )#Enzan[##a] = 5;
   if( $$GetTxt == "-" )#Enzan[##a] = 6;
   #COpen[##a+1] = 0;   //「(」配列
   #CClose[##a+1] = 0;   //「)」配列
   ##a = ##a+1;
  }
 }

//--------------------------------------------------------------------------
----

 return;     //返り値なし

//--------------------------------------------------------------------------
----

//●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
●●

//--------------------------------------------------------------------------
----
//
// ● 計算の実行 ●
 RunFormula:
//
//--------------------------------------------------------------------------
----

 // エラーチェック
 if( #SuutiNo <= 1 )return;  //数字が一つ以下
 if( #SuutiNo-1 != #EnzanNo ){  //計算式が合っていない
  $Anser = " = err! 不正な計算式です。";
  return;
 }

//--------------------------------------------------------------------------
----

 #ResSuutiNo = #SuutiNo;   //残り数値配列数を初期化

//--------------------------------------------------------------------------
----

 // 「()」状態の管理
 ##a = 0;
 while(1){
  if( #CNow == 1 ){
   // 「(」配列を「残り数値配列数」まで走査
   #COpRock = -1;    //「(」ロック位置の初期化
   #CClRock = -1;    //「)」ロック位置の初期化
   ##b = 0;
   while( ##b < #ResSuutiNo ){
    if( #COpen[##b] >= 1 )#COpRock = ##b;
    if( #COpRock >= 0 && #CClose[##b] >= 1 )#CClRock = ##b;
    if( #COpRock >= 0 && #CClRock >= 0 ){
     // 「()」の数の整理
     #COpen[#COpRock] = #COpen[#COpRock]-1;
     #CClose[#CClRock] = #CClose[#CClRock]-1;
     #PrHead = #COpRock; //先頭位置
     #PrEnd = #CClRock; //末端位置
     call PressFormula; //計算配列処理へ
     break;   //処理戻る
    }
    ##b = ##b+1;
   }
   if( #COpRock >= 0 && #CClRock == -1 ){
    $Anser = " = err! 「(」「)」を見直して下さい。";
    return;
   }
   if( #COpRock == -1 )#CNow = 0;  //「()」処理終了
  }else{
   //------------------------------------------------------
   // 「(」なし、数字のみの計算
   #PrHead = 0;    //先頭位置
   #PrEnd = #ResSuutiNo-1;   //末端位置
   call PressFormula;   //計算配列処理へ
  }
  // 終了確認
  if( #ResSuutiNo <= 1 ){
   $Anser = " = "+str(#Suuti[0]);  //解答
   return;
  }
 }

//--------------------------------------------------------------------------
----

 $Anser = " = err! 予測外のエラーです。";
 return;     //返り値なし

//--------------------------------------------------------------------------
----

//●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
●●

//--------------------------------------------------------------------------
----
//
// ● 計算配列処理 ●
 PressFormula:
//
//--------------------------------------------------------------------------
----

 #EnCalcNo = 0;    //演算子による計算回数の初期化
 PressFormula2:    //演算子状態でループ

 // 現在位置の初期化
 ##HeadNow = #PrHead;   //現在先頭位置初期化
 ##EndNow = #PrEnd-#EnCalcNo;  //現在末端位置初期化
 #EnCalcNo = 0;    //演算子による計算回数の初期化

//--------------------------------------------------------------------------
----

 // 計算配列処理
 while( ##HeadNow != ##EndNow ){
  // 計算値算出
  #EnCalcTrue = 0;    //演算子無効
  // 階乗
  if( #Enzan[##HeadNow] == 1 && #EnzanNow == 1 ){
   ##c = 1;
   ##d = #Suuti[##HeadNow];
   while( ##c < #Suuti[##HeadNow+1] ){
    ##d = ##d*#Suuti[##HeadNow];
    ##c = ##c+1;
   }
   if( #Suuti[##HeadNow+1] == 0 )##d = 1;
   if( #Suuti[##HeadNow+1] == 1 )##d = #Suuti[##HeadNow];
   #Suuti[##HeadNow] = ##d;
   #EnCalcTrue = 1;   //演算子有効
  }
  // 除算
  if( #Enzan[##HeadNow] == 2 && #EnzanNow == 2 ){
   if( #Suuti[##HeadNow] == 0 ){
    message "除算エラーです。";
    endmacro;   //マクロ終了
   }
   #Suuti[##HeadNow] = #Suuti[##HeadNow]/#Suuti[##HeadNow+1];
   #EnCalcTrue = 1;   //演算子有効
  }
  // 余り
  if( #Enzan[##HeadNow] == 3 && #EnzanNow == 2 ){
   if( #Suuti[##HeadNow] == 0 ){
    message "除算エラーです。";
    endmacro;   //マクロ終了
   }
   #Suuti[##HeadNow] = #Suuti[##HeadNow]%#Suuti[##HeadNow+1];
   #EnCalcTrue = 1;   //演算子有効
  }
  // 乗算
  if( #Enzan[##HeadNow] == 4 && #EnzanNow == 2 ){
   #Suuti[##HeadNow] = #Suuti[##HeadNow]*#Suuti[##HeadNow+1];
   #EnCalcTrue = 1;   //演算子有効
  }
  // 加算
  if( #Enzan[##HeadNow] == 5 && #EnzanNow == 3 ){
   #Suuti[##HeadNow] = #Suuti[##HeadNow]+#Suuti[##HeadNow+1];
   #EnCalcTrue = 1;   //演算子有効
  }
  // 減算
  if( #Enzan[##HeadNow] == 6 && #EnzanNow == 3 ){
   #Suuti[##HeadNow] = #Suuti[##HeadNow]-#Suuti[##HeadNow+1];
   #EnCalcTrue = 1;   //演算子有効
  }
  //--------------------------------------------------------------
  // 配列圧縮処理
  if( #EnCalcTrue == 1 ){
   ##PressNo = 0;    //圧縮回数の初期化
   // 圧縮位置
   while( #ResSuutiNo-##HeadNow-2 >= ##PressNo ){
    #Suuti[##HeadNow+##PressNo+1] = #Suuti[##HeadNow+##PressNo+2];        //
数値配列の圧縮
    #Enzan[##HeadNow+##PressNo] = #Enzan[##HeadNow+##PressNo+1];        //演
算子配列の圧縮
    if( ##PressNo == 0 ){
     #COpen[##HeadNow+##PressNo] = #COpen[##HeadNow+##PressNo]+#COpen[##Head
Now+##PressNo+1];        //「(」配列の圧縮
     #CClose[##HeadNow+##PressNo] = #CClose[##HeadNow+##PressNo]+#CClose[##H
eadNow+##PressNo+1];        //「)」配列の圧縮
    }else{
     #COpen[##HeadNow+##PressNo] = #COpen[##HeadNow+##PressNo+1];        //
「(」配列の圧縮
     #CClose[##HeadNow+##PressNo] = #CClose[##HeadNow+##PressNo+1];        /
/「)」配列の圧縮
    }
    ##PressNo = ##PressNo+1; //圧縮回数を増やす
   }
   #ResSuutiNo = #ResSuutiNo-1;  //残り数値配列数を減らす
   #EnCalcNo = #EnCalcNo+1;  //計算回数増やす
   ##EndNow = ##EndNow-1;   //現在末端位置の移動
  }else{
   ##HeadNow = ##HeadNow+1;  //現在先頭位置の移動
  }
 }

 if( #EnzanNow != 3 ){
  #EnzanNow = #EnzanNow+1;   //計算演算子状態の更新
  goto PressFormula2;    //計算演算子状態でループ
 }

 #EnzanNow = 1;    //計算演算子状態の初期化

//--------------------------------------------------------------------------
----

 return;     //返り値なし

//--------------------------------------------------------------------------
----
//●● 以上サブルーチン ●●●●●●●●●●●●●●●●●●●●●●●●●
●●
//--------------------------------------------------------------------------
----

//--------------------------------------------------------------------------
----
//                                              copyright (c)2000 Masakazu Y
anai

[ ]
RE:09938 古いマクロが動かなくなりましたNo.09939
igus さん 22/08/18 14:06
 
小野さん、こんにちは。
rubyを使っていいということなら以前(といっても二ヶ月程前ですが)数値計算のマ
クロを作りました。参考になれば良いのですが。
http://pansy.s1010.xrea.com/2022/06/10/%e6%95%b0%e5%80%a4%e8%a8%88%e7%ae%97/


[ ]
RE:09939 古いマクロが動かなくなりましたNo.09940
秀丸担当 さん 22/08/18 17:29
 
小野さんご提示のマクロは、とりあえず普通に動作はしたのですが、一度クリックを
受け付けない状態になって、その状態はまだマクロ実行中と判断されて似た状態にな
ったのですが、その後何十回かやってみても再現していないです。
一度だけ似た状態になったことを調べてみたら、V9.18β4でのJavaScriptのことで、
マクロと関係あったかどうか不明でした。

もしかたらまずい問題が潜んでいるかもしれないので、必ず再現するというような状
況があったら、詳しいことを教えてもらえると助かります。
再現する場合、差し支えなければ再現できるテキストや、[その他]→[設定内容の保
存/復元...]でファイルに設定を保存したものを"taki@maruo.co.jp"まで送ってもら
えると助かります。
バージョン番号も教えてほしいです。

igusさんのマクロようなrubyを使ったevalの方法もあるのですね。
昔から比べると、秀丸エディタ自身でもevalが使えるようになって、四則演算くらい
であれば、数字と記号の文字列でやる方法もできると思います。
V9.18βであれば、suzuさんが最近ライブラリにアップしたようなJavaScriptのeval
の方法もできるようになってきています。

[ ]
RE:09940 ruby様、taki様、再現しなくなりNo.09944
小野雅弘 さん 22/08/19 14:08
 
igus様、taki様
ご返信ありがとうございます。
rubyを入れるか迷い、
確認のため動かしたら問題なく動作しました。
投稿の数日前は駄目だったのに。
以前、マクロが動かなかった別の端末でも同様です。
信じられません。

windowsの問題かもしれません。
win10 64 秀丸は8.67 64です。

お騒がせしました。小野




>
>もしかたらまずい問題が潜んでいるかもしれないので、必ず再現するというような
>状況があったら、詳しいことを教えてもらえると助かります。
>再現する場合、差し支えなければ再現できるテキストや、[その他]→[設定内容の保
>存/復元...]でファイルに設定を保存したものを"taki@maruo.co.jp"まで送ってもら
>えると助かります。
>バージョン番号も教えてほしいです。
>
>igusさんのマクロようなrubyを使ったevalの方法もあるのですね。
>昔から比べると、秀丸エディタ自身でもevalが使えるようになって、四則演算くら
>いであれば、数字と記号の文字列でやる方法もできると思います。
>V9.18βであれば、suzuさんが最近ライブラリにアップしたようなJavaScriptのeval
>の方法もできるようになってきています。

[ ]
RE:09944 ruby様、taki様、再現しなくなりNo.09945
秀丸担当 さん 22/08/19 16:39
 
情報ありがとうございます。
何かしらの条件があって、もしかしたら何か引き金となる理由があるのもしれないで
す。
自分が一度起きた気がするのも、もしかしたら同じ原因が同じ時期に発生する何か
(例えばWindows Update関連とか)だったのかもしれませんが、いまのところ不明で
す。

最近のバージョンで問題ができてしまったのかと思いましたが、V8.67ということで、
それから現在までの間にそういった事例は無かったので、稀なことなのかもしれない
です。

----

関係ないかもしれませんが、Windows11でOS更新になるとタスクバーの端にオレンジ
の丸ポチアイコンが出てきて、数分おきにウィンドウが非アクティブになって入力が
中断されてしまうということがあります。

[ ]