hmLJ 秀丸マクロ用 500倍速スクリプト via LuaJIT with FFI

概要

秀丸マクロに「超高速スクリプトLuaJIT」を組み込むためのdllとなります。

ダウンロード

動作環境

  • 秀丸

    秀丸エディタ 32bit版 ver7.00以上

インストール

  • hmLJ.zipを解凍する。
  • 「hmLJ.dll」を秀丸エディタのディレクトリ内(hidemaru.exeと同じ場所)へと コピーする。
    (実際には置き場所場所はどこでも良いですが、loaddll時にdllの場所をご自身で指定してください。
    当サイトの説明は全てhidemaru.exeと同じ場所へとコピーしたものとして解説しています。)
  • 秀丸エディタ ストアアプリ版について

    hmLJはストアアプリ版でも利用することが出来ます。詳細は左メニューのストアアプリ版での利用などを参照してください。

特徴

  • 基本言語はLua

    アプリケーション等への「組み込み言語」としては最も実績のある言語となります。

  • 非常にポータブル。たった1つのdllで全て完結!!

    たった1つのhmLJ.dllのファイルだけで、

    • コンパクトにしてエレガントな文法
    • 簡易的な正規表現
    • 基本的なライブラリ

    が使えるようになります。
    他のランタイムへの依存などもないため、配布物マクロに含めてしまうのにも向いています。

  • 秀丸エディタ 8.66 以降では、Luaをそのままマクロ内に記述出来る!!

    秀丸エディタ 8.66にて、「ヒアドキュメント」が実装されたため、
    Luaをそのままマクロ内に記述出来るようになりました。(エスケープ等の必要性がなくなりました!)
    詳細は後述されています。

    超高速

    スクリプト言語中、1・2位の高速さを誇るLuaJITを採用。
    特に小さな範囲で回転数が多いシチュエーションでは「秀丸マクロの1000倍以上のスピード」であり、
    この場合の実行速度はC言語すら凌ぎます。

  • win32 apiの呼び出し

    秀丸マクロでは、その仕様上、win32apiがまともに呼び出せないといった問題がありますが、
    このhmJTでは、LuaJITのFFIがそのまま組み込まれています。
    よって、Windowsのwin32apiをはじめ、C/C++等で作成したネイティブなdllを呼び出すことが可能です。

    LuaJITでは、luapowerといったサイト等で、このFFIを利用した有力なライブラリが多数配布されています。

  • cp932(sjis)にフォーカスした特別なカスタム

    秀丸マクロは基本的にはcp932(sjis)で記述するのが通例となっていますので、hmLJもcp932で記述されたスクリプトが良好に動作するよう特別にカスタムされています。

  • 秀丸用の組み込み言語を自作する際のミニマムな例

    hmLJは非常にスケールが小さいですので、「秀丸用マクロへの組み込み言語を作成する」際の良い例となるでしょう。

秀丸マクロとLuaの連携

  • HTMLにJavaScriptを埋め込むような感覚で、秀丸マクロにLuaを文字列として埋め込むことが出来ます。
    複数個所に埋め込んでも、記述の内容は持続性を持っています。
    又、HTMLに対するJavaScript同様に、中に埋め込むのではなく、ファイルの外に記述してもかまいません。

一番簡単なソース例

「a」に「3」、「b」に「10」を定義し、足しこんで表示。

    #L = loaddll( hidemarudir + "\\" + "hmLJ.dll" );
    
    // 以下の文字列を「luajitの環境スコープへと追加書き込みし、追加分だけ実行する」
    #_ = dllfunc(#L, "DoString", "                  \n"+
        "a = 3                                       \n"+
        "b = 10                                      \n"
    );
    
    #a = dllfunc(#L, "GetNumVar", "a"); // luajit側のグローバル変数「a」を秀丸マクロ側へと得る
    #b = dllfunc(#L, "GetNumVar", "b"); // …〃…「b」を…〃…
    
    message(str(#a));
    message(str(#b));
    
    // 以下の文字列を「luajitの環境スコープへと追加書き込みし、追加分だけ実行する」
    #_ = dllfunc(#L, "DoString", "                  \n"+
        "c = a + b                                   \n"+ // 上で書き込んだaやbの変数は持続されている。
        "hm.debuginfo(c)                             \n"  // DebugMonitorに表示。
    );
    
    #c = dllfunc(#L, "GetNumVar", "c"); // …〃…「c」を…〃…
    message(str(#c));
    
    freedll(#L);
    
    PICTURE

Win32 API を使った簡単なソース例

Win32 APIを使って、実行中のモジュール(通常秀丸本体)のフルパスを得る

    
    
    #L = loaddll( hidemarudir + "\\hmLJ.dll");
    
    // ffiを利用することで、typedefで基本型名にwin32の名前に沿ったエイリアスを付ける
    // win32で良くあるパターンのように受け口のパッファーを確保する必要がある。
    // win32の文字列⇒luaの文字列への変換としては、ffi.stringが用いられる。
    #_ = dllfunc(#L, "DoString", ""+
    "ffi.cdef[[                                                                \n" +
    "typedef void *			HMODULE;                                \n" +
    "typedef char *			LPTSTR;                                 \n" +
    "typedef unsigned short	DWORD;	                                        \n" +
    "DWORD GetModuleFileNameA(HMODULE hModule, LPTSTR lpFilename, DWORD nSize);\n" +
    "]]                                                                        \n" +
    "kernel32 = ffi.load('kernel32');                                          \n" +
    "szPathBuf = ffi.new('char[?]', 256);                                      \n" +
    "ret = kernel32.GetModuleFileNameA( nil, szPathBuf, 256 );\n" +
    "szPathBuf = ffi.string(szPathBuf)"
    );
    
    // luajitのffi経由のwin32api で得た情報を、秀丸マクロへと持ってくる
    $strBufFileName = dllfuncstr(#L, "GetStrVar", "szPathBuf");
    
    message($strBufFileName);
    
    
    freedll(#L)
    
    PICTURE

秀丸エディタ 8.66以降

秀丸エディタ8.66以降では、ヒアドキュメントのようなものを利用することが出来ますので、
以下のようにもマクロ内にLuaをそのまま記述できます。

    #L = loaddll( hidemarudir + "\\hmLJ.dll");
    
    // ffiを利用することで、typedefで基本型名にwin32の名前に沿ったエイリアスを付ける
    // win32で良くあるパターンのように受け口のパッファーを確保する必要がある。
    // win32の文字列⇒luaの文字列への変換としては、ffi.stringが用いられる。
    #_ = dllfunc(#L, "DoString", R"LUA(
    ffi.cdef[[
    typedef void *  HMODULE;
    typedef char *  LPTSTR;
    typedef unsigned short DWORD;
    DWORD GetModuleFileNameA(HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
    ]]
    kernel32 = ffi.load("kernel32")
    szPathBuf = ffi.new("char[?]", 256)
    ret = kernel32.GetModuleFileNameA( nil, szPathBuf, 256 )
    szPathBuf = ffi.string(szPathBuf)
    )LUA"
    );
    
    // luajitのffi経由のwin32api で得た情報を、秀丸マクロへと持ってくる
    $strBufFileName = dllfuncstr(#L, "GetStrVar", "szPathBuf");
    
    message($strBufFileName);
    
    freedll(#L)
    

その他解説

  • 左メニューに各解説を用意しました。

ライセンス

  • hmLJ

    hmLJは、MITライセンスとなります。
    ソースはgithubにあります。

  • LuaJIT

    LuaJITについても、MITライセンスです。
    詳細は、http://luajit.org/を見てください。

  • Lua

    Luaについても、MITライセンスです。
    詳細は、http://www.lua.org/を見てください。

  • その他

    その他の追加修正ソースファイル等も、全てMITライセンスです。
    詳細は、http://www.lua.org/を見てください。