V9.19β9No.11010
秀丸担当 さん 22/09/07 14:47
 
V9.19β9を公開しました。
hidemaruオブジェクトにいろいろ追加しています。

以下のページの「先行開発バージョンはこちら」からダウンロードできます。
https://hide.maruo.co.jp/software/hidemaru.html

32bit版:
https://hide.maruo.co.jp/software/bin3/hm919b9_signed.exe

64bit版:
https://hide.maruo.co.jp/software/bin3/hm919b9_x64_signed.exe

[ ]
RE:11010 V9.19β9No.11011
こみやんま さん 22/09/07 17:25
 
hidemaru.getCursorPosUnicode();と
hidemaru.getCursorLinenoFromMousePos(); ですが、
さすがに、文字列ではなく、オブジェクト返した方がよいのでは...

function getCursorPosUnicode(): { lineno: number, column: number };

もしくは、column_wcsと完全一致なのであれば、ちょっと名前としてはあれですが思
い切って

function getCursorPosUnicode(): { lineno: number, column_wcs: number };


function getMousePosUnicode(): { lineno: number, column_wcs: number, x: numb
er, y: number }


var pos = getCursorPosUnicode();
console.log([pos.lineno, pos.column]);

[ ]
RE:11011 V9.19β9No.11012
こみやんま さん 22/09/07 17:28
 
あと、自分が実装している範囲だと、SendMessageがあった方がいいように思えました。

秀丸のOutputPaneやExplorerPaneで、SendMessageを使ってしまっているため、
非同期中にSendMessageを奪われてしまうと、そこら辺で頓挫するかなと。

(まぁ実際には、数分しかかからないのでCOMとして生やせばいいんですが、ある程
度知識がないと1時間あってもできないでしょうし...)

[ ]
RE:11011 V9.19β9No.11013
こみやんま さん 22/09/07 17:42
 
オブジェクトを返すのはラベルのcolumn_wcsが美しくないー、
ということであれば、単純に配列で返せばよいかと。

function getCursorPosUnicode(): [number, number]

基本的に、マクロ実行中であれば、マクロ関数が使えるため、
これら非同期でも使える関数の使用は長い目ではWebView2へと偏ってくるかと思いま
す。

配列にしておけば、WebView2(というかES6以降のエンジンならば)

let [pos_lineno, pos_column] = getCursorPosUnicode();

というように分割代入が使えるので。

・個人的にはオブジェクトにしておいた方が将来的には楽です
 (定義ファイルとかが出揃ってきたに入力補完が強く効くので)
・次が、ES6以降の特性を考えて配列にする。
  不自然ではないですが、本当に情報の順序(配列の順序)付けて将来困らないのか考
えたほうがいいですね。

・文字列…文字列と数値の世界の秀丸マクロならわからなくはないですが、JS様の関
数としてはかなり不適切な実装かと思います。




[ ]
RE:11013 V9.19β9No.11014
秀丸担当 さん 22/09/08 09:17
 
getCursorLinenoFromMousePosは例を間違えていました。(そういうメソッドもある
のですがボツにしていた)
getCursorPosUnicodeFromMousePosでした。

返り値をオブジェクトや配列にしたいのはやまやまだったのですが、ネイティブの都
合と、JScriptとWebView2の両立で難しくて、挫折しました。

もしオブジェクトにするとしたら、JavaScriptが備える汎用のオブジェクトではなく
て、ネイティブのオブジェクトになってしまいます。
そうなると一見JSON化もできそうな単純なオブジェクトに見えて、そうではないもの
になってしまいます。
そこまで作るのであれば、2値だけのために存在するのも何だし、単位もよくわから
ないので、hmPosition=getCursorPos();のように単位なしで、HmPositionにはx,y,li
neno,column,column_wcs等が全部あって、入れたり出したり変換できる機能も備えた
ようなものだったらいいかもしれないです。

今の文字列でも、JSONで簡単に配列にできるので、これが一番問題が無く自由にでき
て、合理的なんじゃないかと思います。

頻繁に使うなら、いまこそexecjsかrequireを使って
xxxx=function(){return JSON.parse(hidemaru.getCursorPosUnicode());};
としておいて
let [a,b]=xxxx();
みたにしておくといいのではないかと思います。

sendMessageはあったらいいかもしれません。追加を検討します。


[ ]
RE:11014 V9.19β9No.11015
こみやんま さん 22/09/08 10:53
 
今ある、hidemaru.getCursorPosUnicodeやGetMousePosUnicode***はあくまで、hidea
mru._getCursorPosやhidemaru._getMousePosなどのprivate相当の(非公開な)メソ
ッドにして、
HidemacJSGloba.js の層で、hidemaru.getCursorPosUnicode() { return ネイティブ
からオブジェクトなり配列なり }
にするのがよいかと思います。

ネイティブの都合でこうなりました、では、今後hidemaru.***で単純なオブジェクト
型すら返せないというJSとしてかなりのハンデを背負うので...

(hidemaruが書き換えられないということなのであれば、hidemaru は __hidemaru__
などにして、JavaScript層でラップしたほうがいいかと)

Positionを得る関数が、文字列で返ってきて、JSON.parse するのが
使い方です、なんてのは、「明らかにかなりおかしい」です。
(これを合理的とするのは、かなり無理があります)

[ ]
RE:11014 V9.19β9No.11016
こみやんま さん 22/09/08 11:26
 
>> JavaScriptが備える汎用のオブジェクトではなくて、ネイティブのオブジェクト
>になってしまいます。

担当さんがやってる実装の仕方が不透明なのでなんとも言えないですが、

linenoやcolumnといったプロパティをもたせられるが、toStringするとネイティブ("
function () { native code }"みたいな)なんだよーといったことであれば、

該当のオブジェクトに toString() メソッドと toJSON() メソッドを独自もたせられ
ませんか?

「この2つのメソッド」を偽装できるのであれば、外からみれば、
一般のオブジェクトとほとんど区分けが付かなくなります。


[ ]
RE:11016 V9.19β9No.11017
秀丸担当 さん 22/09/08 13:54
 
うーん、いい方法が思いつかないというか、いったんの区切りをつけたいところがま
た延長してしまいそうなので、とりあえずこのメソッドは無かったことにというか、
ヘルプからは消しておこうかと思います。
非同期関係は旧V9.18正式後のつもりだったのですが、バグ修正でV9.18を正式にして
しまったので、いま既に延長しているような状況です。

汎用のobj={}とかary=[]をネイティブ上で作って返すだけでいいのですが、難しいこ
とをせずに簡単にする方法があって知らないだけかもしれないので、もし知っていた
ら教えてもらえると助かります。

hidemaruGlobalのようにラップするのは、1つのメソッドだけであれば、hidemaru.X
XXX()メソッドをhidemaru.XXXXプロパティということにして、hidemaru.XXXX=functi
on(){};としてラップすると、hidemaru.XXXX()だけを別関数にラップできますが、そ
れができるのはWebView2だけのようです。JScriptだとできないです。
そうなると、hidemaruオブジェクトを全部引っ越しということになり、まるごとラッ
プすれば一応何でも可能です。
でもその場合、hidemaru.XXXX=__hidemaru__.XXXXといった単純置き換えはできなくて、
hidemaru.XXXX=function(){argなんとか...__hidemaru__.XXXX(...argなんとか...)};
のように引数を1つずつ処理していくことになります。
というそれは、hidemaruGlobalのそれとだいたい同じ話になるのですが、()を書かず
にそのままだとエラーにならない、そこそこ長い文字列としてfunctionが見える、ブ
ロックするのかしないのか、ブロックするのだったらJScriptとWebView2で別だし、J
Scriptはブロックのためにまたネイティブ(つまりネイティブ→ラップ→ネイティブ)、
とかなんとか、またその話になってきます。

他には、従来のHidemaru_GetCursorPosUnicodeの書き方に準じるとして、getlinecou
ntのように参照渡し返しに模した、オブジェクトを渡ししてそのプロパティに書き込
むというのだとしたら、
obj={}; getCursorPosUnicode(obj); lineno=obj.lineno; column=obj.column;
という感じだとして、これはJScriptだと可能です。しかし、WebView2ではできない
です。
obj.lineno=0; obj.column=0; getCursorPosUnicode(obj); lineno=obj.lineno; col
umn=obj.column;
というようにあらかじめメンバを作っておくとWebView2でもできるみたいです。なぜ
かは知らないですが。

ただ2つの値を返したいだけの話なのに、連鎖的に面倒なことが増えて、このことを
説明していること自体もアレなのですが……
文字列化を容認するだけでそれがあっさり超簡単になります。
文字列化とは書きましたが、ようはJSON配列返しなので、複数の情報をJSONで受け渡
しすることはわりと普通なんじゃないかと思います。
同じ言語内ならちょっとあれなのはわかりますが、これはネイティブとJavaScriptの
垣根を超える操作なので、垣根を超えるのにJSON文字列はありのような気がします。

WebView2がけっこうデリケートで、もっと簡単なはずの普通にメソッドを呼ぶことに
もクセがあって、周りが合わせないといけないです。(こみやんまさんが.net 4.xで
問題があって回避されたように)
なのでもし汎用オブジェクトや汎用配列ができるとして、それははたして安全だろう
かとも思います。

もう1つの、独自オブジェクトを作るとしたらの話では、独自オブジェクトに.toStr
ing()を作るのは、かなり簡単な部類だと思います。
それはそれで先に話があったように、...Unicode()なのにcolumnなのか、それともco
lumn_wcsなのか、それが美しいのかどうのかってこともあるので、それじゃあ単位無
くすかっていう話に伸びてきます。

[ ]
RE:11017 V9.19β9No.11018
こみやんま さん 22/09/08 14:30
 
>うーん、いい方法が思いつかないというか、いったんの区切りをつけたいところが
>また延長してしまいそうなので、とりあえずこのメソッドは無かったことにという
>か、ヘルプからは消しておこうかと思います。
>非同期関係は旧V9.18正式後のつもりだったのですが、バグ修正でV9.18を正式にし
>てしまったので、いま既に延長しているような状況です。

そうですね、ちょっと考えたほうがいい「2つのGetPos系」だけ抜いて、
他は今の状態で一度リリースに向けて動いた方がよいかと思います。

JavaScript系でいきなり非同期系をバキバキ使っていくなんてひとは
ほとんど居ないでしょうから
まずは、新しいjsmodeをいろいろ触ってもらって意見が欲しいところですかね。

(私的にはやはり「エラーがーわかりにくいー」とか「入力補完がー」)みたいな方
がもっとマスな人の意見になるかと思いますw)





[ ]
RE:11017 V9.19β9No.11019
こみやんま さん 22/09/08 14:48
 
>()を書かずにそのままだとエラーにならない、そこそこ長い文字列
>....略

ここ辺は、hidemaruGlobal と hidemaru では事情が全く違うかと思います。

hidemaruGlobalでは、もともと、「関数、キー、文」の3種類の
「秀丸マクロ」⇒「全部関数」へとなってしまいました。

このため、秀丸マクロで「キー」として記述していた「癖」が
残っている人ほど、「キー」と一致するものについては( )が抜けやすいということ
です。

lineno, currentmacrodirectory, x, y などです。

これは、あくまでも「キー」だったものが「関数」になっていることの
戸惑い、不慣れ部分です。

一方、hidemaru については、「関数使うつもりがカッコわれれた」
なんてことはあまり起きないと思います。
(起きたとしても hidemaruGlobalの「元キー組」に比べれば、
 その頻度はぐっと落ちる)

中身が少々みえてしまうことはあまりマイナスに捉えない方がよいかと思います。
(むしろ構造の俯瞰がしやすくなるので、使用者が熟達する速度がかなり速くなります)

[ ]
RE:11017 V9.19β9No.11021
こみやんま さん 22/09/09 00:56
 
>汎用のobj={}とかary=[]をネイティブ上で作って返すだけでいいのですが、難しい
>ことをせずに簡単にする方法があって知らないだけかもしれないので、もし知って
>いたら教えてもらえると助かります。


担当さんは、恐らくは
WebView2の方は、多分 WebView2のAddHostObjectToScript 使って、

chrome.webview.hostObjectsの下に、hidemaru を COMとしてぶらさせて、
hidemaruがCOMクラスで、そのクラスにhidemaru.****のメソッドやプロパティを
生やしてるんだろうなぁと想像しています。

で、あるとするならば、おそらく

```
「通常のJavaScriptのオブジェクト」をこのCOMから生やしたメソッドやプロパティ
の返り値として
返す方法は「提供されていない」
```

のではないかと思います。
(マイクロソフトのWebView2 SDK開発者に聞くぐらいでないと出てこないかもw)

オブジェクト的に扱えるものが、まさに現在担当さんがされている(runProcessとか
で)もので、
このやり方は(返り値自体がCOMの新たな型ProcessInfoだろうと思いますが)どうしても
その実態は JavaScriptから見ると function といったことになってしまうため、
(ようするに、COMオブジェクト自体はことごとく=native functionであるかのように
JavaScriptからは見えてしまう、JScriptの方は結構Objectとして認識するかとは思
いますが)

基本的には最初から返り値を普通のJavaScriptオブジェクト的に扱わせたいなら
「hidemaru COMクラスを、__hidemaru__みたいにして、JavaScript層(HidemaruJSGlo
ba)で改めてラップしないとちょっと無理筋」といったように思えます。

というかラッピングしない限りは、無限に実装時間が取られてしまうかと...
----------------------------------------------------------------------------
-------

ネイティブ系でいくなら上にもあげた、

```
ネイティブであることが問題なのではなく、
返ってきた値を見ようとしたら、
function () { native code; } と表示されることが懸念点
```

なんで躊躇しているのではないかと思うので


---------------------------------------- COM クラスでいうところの ----------
------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace ClassLibrary16
{
    [ClassInterface(ClassInterfaceType.None)]
    [Guid("E212AE0C-89E1-41E7-BFCF-F26EA189CBD1")]
    public class ObjectType : IObjectType
    {
        public int x
        {
            get { return 3; }
        }
        public int y
        {
            get { return 10; }
        }
        public string toString()
        {
            return "{x:3, y:10}";
        }
        public string toJSON()
        {
            return "{x:3, y:10}";
        }
    }

    public interface IObjectType
    {
        int x { get; }
        int y { get; }
        string toString();

        string toJSON();
    }

    public interface IInstanceType
    {
        ObjectType getObjType();
        string toString();
    }

    [ClassInterface(ClassInterfaceType.None)]
    [Guid("E212AE0C-89E1-41E7-BFCF-F26EA189CBD1")]
    public class InstanceType : IInstanceType
    {
        public ObjectType getObjType()
        {
            ObjectType c = new ObjectType();
            return c;
        }


        public string toString()
        {
            return "{元のインスタンスのクラス}";
        }
    }

}

---------------------------------------- JS側で呼び出すと... ---------------
-------------------------

js {
debuginfo(2);

var i = createobject( currentmacrodirectory() + "\\ClassLibrary16.dll", "Cla
ssLibrary16.InstanceType" );
message(i); // "元のインスタンスのクラス" という文字列が出る。 COMメソッドと
しての、「★★toString上書きの効果★★」
var objtype = i.getObjType();
message(objtype);
console.log(objtype); // {x:3, y:10} COMメソッドとしての、「★★toString上書
きの効果★★」
message(objtype.x); // 3
message(objtype.y); // 10
var b = objtype.toString(); // {x:3, y:10}
message(b);  // {x:3, y:10}
message(JSON.stringify(b)); //"{x:3, y:10}"COMメソッドとしての、「★★toJSON
上書きの効果★★」

}


みたいに、toStringとtoJSONを偽装して緩和するしかないかと。

しかしながら、個人的にはこのやり方よりは、
素直にラップした方が実装速度もはるかに速く、柔軟性も高いかと思います。

[ ]
RE:11021 V9.19β9No.11022
秀丸担当 さん 22/09/09 10:46
 
いろいろありがとうございます。
やっぱり普通のオブジェクトや配列を返すのは簡単ではなさそうですね。
ラップすることを見据えた場合、hidemaruオブジェクトをまるごとすればできると思
っていたのですが、プロパティの場合JScriptでは都合が悪かったです。
グローバル展開のごとく、とりあえず全部メソッドに変更しておきます。
hidemaru.updateCount→hidemaru.getUpdateCount()
V9.18β1の最初からそういうあれこれがあって、グローバル展開は全部メソッド表記
にしていた気がしてきました。同じことを繰り返しているような…
いずれhidemaruGlobalはネイティブに置き換えていくという考えがあったのですが、
逆で、JavaScript層に置き換えるという方向になっていきそうです。

返り値ではなく引数ですがmenuarrayはJavaScript層をはさんで[]を変換しています。
秀丸ファイラーClassicでも以前からmenuarray相当があったのですが、vbsとjsの両
立という考えではSAFEARRAYというやつで、Scripting.Dictionaryで作るといったな
んだかちょっと…という方法だったのですが、今はjsを主軸にして[]で渡せるように
しています。
これもJavaScript層をはさんでいます。


[ ]
RE:11022 V9.19β9No.11023
こみやんま さん 22/09/09 14:53
 
> 返り値ではなく引数ですがmenuarrayはJavaScript層をはさんで[]を変換しています。
秀丸ファイラーClassicでも以前からmenuarray相当があったのですが、vbsとjsの両
立という考えではSAFEARRAYというやつで、Scripting

WebView2だけだと、オブジェクトではなく配列については、
返り値であっても、JavaScriptの配列objecとしてマーシャルされるようです。

----------------------------------------------------------
.NET 4

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;

[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
[Guid("C74289CD-95C7-439F-8718-6BE026A8F977")]
public class ObjectEntry
{
    public int[] getIntArr()
    {
        int[] arr = { 1, 2 };
        return arr; // これはJSの配列になる
    }
    public String[] getStrArr()
    {
        String[] arr = { "あ", "い" };
        return arr; // これはJSの配列になる
    }


    public object getObject()
    {
        return new object(); // これはJSからはFunction
    }
}

----------------------------------------------------------

jsmode "WebView2";

js {
debuginfo(2);

var i = createobject( currentmacrodirectory() + "\\ClassLibrary16.dll", "Obj
ectEntry" );
var pos = i.getIntArr();
message(typeof(pos)); // object と出る
message(pos.length); // 2
message(pos[0]); // 1
message(pos[1]); // 2
message(pos); // [1,2]

var pos2 = i.getStrArr();
message(typeof(pos2)); // object と出る
message(pos2.length); // 2
message(pos2[0]); // あ
message(pos2[1]); // い
message(pos2); // ["あ", "い"]

}


[ ]
RE:11023 V9.19β9No.11024
秀丸担当 さん 22/09/09 17:23
 
WebView2と.net4の組み合わせだと配列でできるパターンもあるのですね。
参考になります。

[ ]