最近編集したファイルのパスをメニューで選択して貼付ける。

ChangeLogメモに更新ファイルのパス貼っつけるのが面倒だったので作成。メニューの表示と文字列比較に田楽DLLを使わせてもらったんですが、現行バージョン(Ver.2.80)ではメニューの表示位置がキャレットからズレてしまうようです。これは作者さんの報告したところ次期公開版で対策していただけるとのことです。ありがとうございます。

あと相対パスに変換できれば設定ファイル修正が楽かなぁと思って入れ込んだんだけど、これが結構大変だった。秀のマクロ言語は変数に対して文字列比較で比較開始位置を指定できないとか、大小文字無視での比較ができないとか改めて知ってちょっと愕然としたり。外部DLL使うことで拡張はできるもののWinAPI直接触れないのは痛い。
本当はソートさせたかったんだけど自力でやるのしんどいしのでやめた。つかソート前提だったらテンポラリファイルに書き出してCompleteXに丸投げしたほうが良かったような気がしてきた。インクリメンタルとかもお任せでしてもらえるしそっちのが楽だったかも。

//----------------------------------------------------------------------
//  ファイルパス貼付けマクロ(要 田楽DLL)
//   秀丸で現在開いているファイルの一覧(および履歴ファイル/フォルダ)を
//   メニューから選択して貼り付けるマクロ。
//      FilePathMenu.mac  2005.10.08 eamat.
//----------------------------------------------------------------------
Main:
    //	田楽DLLのロード
    loaddll hidemarudir + "\\DengakuDLL.dll";
    if (!result) { message "DLL をロードできませんでした。"; endmacro; }

    call CreateApath;       // 絶対パスメニュー作成

    //--- メニュー表示 ---
    while(1)
    {
        // 絶対パスメニュー
        $ret = dllfuncstr("MENU","menu0",hidemaruhandle(0));
        if ($ret != "menu0:" + str(#cnt[0]+5))
        {
            insert $file[val(midstr($ret,4,1))][val(midstr($ret,6,2))-1];   //編集位置へ貼付け
            break;
        }

        //相対パスメニュー
        if (#rmenu != 1)
        {
            title "メニュー作成中...";
            call CreateRpath;   //メニュー作成
            #rmenu = 1;
            title 0;
        }
        $ret = dllfuncstr("MENU","rmenu0",hidemaruhandle(0));
        if ($ret != "rmenu0:" + str(#cnt[0]+5))
        {
            insert $rfile[val(midstr($ret,5,1))][val(midstr($ret,7,2))-1];   //編集位置へ貼付け
            break;
        }
    }
freedll;
endmacro;

// ----------------------------------------------------------
//  サブルーチン

CreateApath:
// ===========================================================
//  絶対パスメニュー作成
//      $file[0]  編集中ファイル(ウィンドウ一覧)
//      $file[1]  ファイル履歴
//      $file[2]  フォルダ履歴
//      #cnt[0〜2]  $file[0〜2]の配列数
//      menu0〜2    絶対パスメニュー名(1,2は0のサブメニュー)
// ===========================================================

    //======= パスを取得 =======

    // --- 編集中ファイル(新規、grep等は省く) ---
    ##i = 0;
    ##k = 0;
    while (##i < hidemarucount)
    {
        if (1 < strlen(filename2[##i]))  { $file[0][##k]=filename2[##i];  ##k = ##k+1; }
        ##i = ##i+1;
    }
    #cnt[0] = ##k;

    //--- ファイルヒストリ ---
    ##i = 0;
    ##k = 0;
    while("" != getfilehist(##i))
    {   // 編集中ファイル & 存在しないパスは履歴から省く
        // (ただしネットワークドライブは重いので存在チェックしない)
        ##hit = 0;
        while(##hit < #cnt[0])
        {
            if ($file[0][##hit] == getfilehist(##i))    break;
            ##hit = ##hit+1;
        }
        if (##hit == #cnt[0])
        {
            if ("\\\\" == leftstr(getfilehist(##i),2))  { $file[1][##k]=getfilehist(##i);  ##k=##k+1; }
            else if (existfile(getfilehist(##i)))       { $file[1][##k]=getfilehist(##i);  ##k=##k+1; }
        }
        ##i = ##i+1;
    }
    #cnt[1] = ##k;

    //--- フォルダヒストリ ---
    ##i = 0;
    ##k = 0;
    while("" != getpathhist(##i))
    {
        if ("\\\\" == leftstr(getpathhist(##i),2))  { $file[2][##k]=getpathhist(##i);  ##k=##k+1;  }
        else if (existfile(getpathhist(##i)))       { $file[2][##k]=getpathhist(##i);  ##k=##k+1;  }
        ##i = ##i+1;
    }
    #cnt[2] = ##k;

    // === メニュー作成 ===
    ##i = 0;
    while(##i < 3)
    {
        if(!dllfunc("NEWMENU","menu" + str(##i)))    return false;
        ##k = 0;
        while(##k < #cnt[##i])
        {
            if(!dllfunc("ADDMENUITEM","", "&" + str(##k+1) + " " + $file[##i][##k],""))  return false;
            ##k = ##k+1;
        }
        ##i = ##i+1;
    }
    if(!dllfunc("ADDMENUITEM","menu0","",""))                       return false;
    if(!dllfunc("ADDMENUITEM","menu0","&F ファイル履歴","menu1"))   return false;
    if(!dllfunc("ADDMENUITEM","menu0","&D フォルダ履歴","menu2"))   return false;
    if(!dllfunc("ADDMENUITEM","menu0","",""))                       return false;
    if(!dllfunc("ADDMENUITEM","menu0","&R 相対パス表示",""))        return false;
return true;

CreateRpath:
// ==================================================
//  相対パスメニュー作成
//      $rfile[0]  編集中ファイル(ウィンドウ一覧)
//      $rfile[1]  ファイル履歴
//      $rfile[2]  フォルダ履歴
//      rmenu0〜2    相対パスメニュー名(1,2は0のサブメニュー)
// ==================================================

    // === メニュー作成 ===
    ##i = 0;
    while(##i < 3)
    {
        if(!dllfunc("NEWMENU","rmenu" + str(##i)))    return false;
        ##k = 0;
        while(##k < #cnt[##i])
        {
            if (##i != 2)   call GetRelativePath directory2,$file[##i][##k];
            else            call GetRelativePath directory2,$file[##i][##k] + "\\";
            $rfile[##i][##k] = $$return;

            if(!dllfunc("ADDMENUITEM","",str(##k+1) + " " + $rfile[##i][##k],""))  return false;
            ##k = ##k+1;
        }
        ##i = ##i+1;
    }
    if(!dllfunc("ADDMENUITEM","rmenu0","",""))                      return false;
    if(!dllfunc("ADDMENUITEM","rmenu0","&F ファイル履歴","rmenu1")) return false;
    if(!dllfunc("ADDMENUITEM","rmenu0","&D フォルダ履歴","rmenu2")) return false;
    if(!dllfunc("ADDMENUITEM","rmenu0","",""))                      return false;
    if(!dllfunc("ADDMENUITEM","rmenu0","&A 絶対パス表示",""))       return false;
return true;

GetRelativePath:
//------------------------------------------------
//  相対パスを返す (田楽DLL使用)
//  in  $$1: 基準(カレント)ディレクト絶対パス
//           (末尾に\は含まない)
//      $$2: 相対パスに変換したい絶対パス
//          (フォルダ時の場合は末尾に\を付加)
//  戻り値 : $$2の相対パス
//------------------------------------------------

    // --- 相対にならない場合はフルパスを返す ---
    // ネットワーク名が違う場合は諦める
    if (leftstr($$1,2) == "\\\\")
    {
        // \\PC名\第一階層\ までが同じじゃないものは諦める
        if (leftstr($$2,2) != "\\\\")   return  $$2;                    //ローカル
        $$tmp = rightstr($$1,strlen($$1)-2);
        $$cmp = "\\\\" + leftstr($$tmp,strstr($$tmp,"\\"));             //PC名
        $$tmp = rightstr($$tmp,strlen($$tmp)-strstr($$tmp,"\\")-1);
        $$cmp = $$cmp + "\\" + leftstr($$tmp,strstr($$tmp,"\\")) + "\\"; //第一階層
        if (0 != dllfunc("STRICMP",$$cmp,leftstr($$2,strlen($$cmp))))   return $$2;
    }
    // ドライブが違う場合は諦める。
    if (0 != dllfunc("STRICMP",leftstr($$1,1),leftstr($$2,1)))  return $$2;

    // --- 相対パス作成 ---
    if (rightstr($$2,1) == "\\")    // ディレクトリ時
    {
        if (3 == strlen($$1))   return rightstr($$2,strlen($$2)-3); //ルート
        if (0 == dllfunc("STRICMP",$$1+"\\",$$2))    return ".\\";  //カレント
    }

    $$upper = "";
    while(0 != dllfunc("STRICMP",$$1+"\\",leftstr($$2,strlen($$1)+1)))
    {
        ##i = dllfunc("STRRSTR",$$1,"\\");              //前の\検索
        if (##i == -1)                      break;
        $$1 = leftstr($$1, ##i);
        $$upper = $$upper + "..\\";
    }
    if (rightstr($$2,1) == "\\")    $$2 = leftstr($$2,strlen($$2)-1);
return $$upper + rightstr($$2,strlen($$2)-strlen($$1)-1);