[ 新規に投稿する ]

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

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

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

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

もう1つの、独自オブジェクトを作るとしたらの話では、独自オブジェクトに.toString()を作るのは、かなり簡単な部類だと思います。
それはそれで先に話があったように、...Unicode()なのにcolumnなのか、それともcolumn_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層(HidemaruJSGloba)で改めてラップしないとちょっと無理筋」といったように思えます。

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

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

```
ネイティブであることが問題なのではなく、
返ってきた値を見ようとしたら、
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", "ClassLibrary16.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", "ObjectEntry" );
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の組み合わせだと配列でできるパターンもあるのですね。
参考になります。
[ ]

[ 新規に投稿する ]