sakura
sakura copied to clipboard
マクロ関数 TagJump() に戻り値1と0の追加を要望します
(必須) やりたいこと(=実現したいこと)
ティラノスクリプトを編集している際、「[call storage="foo.ks" target="*bar"]」といった行で、 foo.ksに ジャンプしたいですが、タグジャンプではジャンプできません。
ここで「[call storage= "foo.ks" target="*bar"]」 のように、"foo.ks"の前に半角スペースを追記すればタグジャンプできますが、可読性が落ちるため解決手段とならないと考えました。
そこでマクロを書いて運用しています。 当初は「TagJump() し、それが失敗したら、マクロでユーザー定義ジャンプを行う」というものを想定しました。 ですが問題が発生しました。 TagJump()の成功/失敗が識別できないのです。成功しても失敗してもundefinedが返却されます。 このためタグジャンプとユーザー定義ジャンプが同時発動することがあり不便です。 そこで TagJump() の成功/失敗を戻り値で得られれば問題解決となると考えました。
※以降、目的 -> 手段(目的2) -> 手段2(目的3) -> のように階層が深くなり、記述の重複が発生することをご容赦ください
目的
既存のタグジャンプとダイレクトタグジャンプが対応していない行でも、 ジャンプを行いたいです。 どんな行かの仕様は、変化が想定されますし、既存のタグジャンプとの衝突もありえます。
そのため、マクロでユーザー定義ジャンプを行いたいです。 そのとき、既存のタグジャンプとダイレクトタグジャンプの失敗時のみ、ユーザー定義ジャンプを行いたいです。 そのため、既存のタグジャンプとダイレクトタグジャンプの成功/失敗を識別する方法がほしいです。 そのため、既存のタグジャンプとダイレクトタグジャンプの戻り値で1:成功、0:失敗がほしいです。
用途の具体例です。 ケース1 : タグジャンプ機能が対応していない「[call storage="foo.ks" target="*bar"]」という行にて、 foo.ks にジャンプしたいです。 ケース2 : 「foo.ks 2: "bar.ks"」という行では、foo.ks の2行目にタグジャンプしたいです。
(省略可) 解決手段の提案
マクロ関数 TagJump() に、戻り値を追加するのはいかがでしょうか。 これにより、マクロでタグジャンプまたはダイレクトタグジャンプの成功や失敗が検知可能となります。
今までの「タグジャンプが失敗したらダイレクトタグジャンプ」にくわえ、 マクロにて「タグジャンプもダイレクトタグジャンプも失敗したら、さらに別のジャンプを試みる」 という機能拡張が可能となります。
「現在行や現在カーソルがファイル名を表現している」 (がタグジャンプやダイレクトタグジャンプのフォーマットを満たしていない)とき、 直感的にそのファイルにジャンプできることは、 ファイル編集をスムーズにし、ユーザーの生産性を高めるメリットがあると考えます。
なお解決手段として「タグジャンプ機能の字句解析仕様の変更」も考えましたが、 影響範囲が大きく困難であると考えるため、 ユーザーごとにマクロで個別対応するのが適切と考えました。
機能
マクロ関数 TagJump() に、 機能「成功か失敗かを戻り値として返却する」を追加するのはいかがでしょうか。
手段
具体的な手段は、以下となると考えます。
マクロ関数 TagJump() 以下の機能を追加する タグジャンプ成功時、1を返却する タグジャンプ失敗かつダイレクトタグジャンプ成功時、1を返却する タグジャンプ失敗かつダイレクトタグジャンプ失敗時、0を返却する
なお、成功とは、タグジャンプまたはダイレクトタグジャンプが成立し当該ファイルを開いたことをさします。 失敗とは、それ以外をさします。
そして、DirectTagJump() は変更不要と考えます。 本件の用途から、「DirectTagJump()を個別で使い、その戻り値を必要とするケース」はないと考えるためです。 類似するタグジャンプ系マクロ関数についても同様に、変更不要と考えます。
また、この戻り値仕様変更による、 既存マクロファイルへの悪影響としては、ないと考えます。 戻り値がundefinedであることを積極的に利用するような既存マクロファイルの存在はないと考えるためです。
終わりに、ソースを取り急ぎ確認したところでは、
https://github.com/sakura-editor/sakura/blob/8588683cbc79d395c17002f9c570898c8510d3cb/sakura_core/cmd/CViewCommander.cpp#L453
で戻り値を捨てているようですので、
case F_TAGJUMP: Command_TAGJUMP(lparam1 != 0);break; /* タグジャンプ機能 */ // Apr. 03, 2003 genta 引数追加
から
case F_TAGJUMP: bRet = Command_TAGJUMP(lparam1 != 0);break; /* タグジャンプ機能 */ // Apr. 03, 2003 genta 引数追加
のようにし、
また、
https://github.com/sakura-editor/sakura/blob/8588683cbc79d395c17002f9c570898c8510d3cb/sakura_core/macro/CSMacroMgr.cpp#L275
で戻り値 m_varResult が VT_EMPTY と定義されていますので、
{F_TAGJUMP, LTEXT("TagJump"), {VT_EMPTY, VT_EMPTY, VT_EMPTY, VT_EMPTY}, VT_EMPTY, NULL}, //タグジャンプ機能
から
{F_TAGJUMP, LTEXT("TagJump"), {VT_EMPTY, VT_EMPTY, VT_EMPTY, VT_EMPTY}, VT_I4, NULL}, //タグジャンプ機能
のようにすることで、
目的を達成できるようにも見えました。
ですが問題があります。 m_MacroFuncInfoCommandArr に定義されているものは、いずれも戻り値が VT_EMPTY です。 設計思想としてそこをみだりに変更できない、という可能性があるのか、 あるいは今までたまたますべて戻り値が VT_EMPTY なだけで、VT_I4 に変更してよいのか、 判断がつきませんでした。
また、ビルドもできていないため、上記が誤りの可能性もあります。
以上です。ご検討よろしくお願いいたします。
(省略可) スクリーンショット
issue立てありがとうございます。
※以降、目的 -> 手段(目的2) -> 手段2(目的3) -> のように階層が深くなり、記述の重複が発生することをご容赦ください
ぶっちゃけると、書きづらければ書きやすいように組み立てて頂いて大丈夫です。 プロジェクト側としても「どうしたら分かりやすく提案できるか」を手探りしている過程です。
要望内容は タグジャンプコマンドの操作結果が欲しい。 ですよね。
なんで操作結果が欲しいか?って、 タグジャンプに失敗しても「それっぽく動く」ようにカスタムしたい。 ということなわけです。
で、可能かどうかというと、おそらく可能だと思います。 根拠はこの関数のシグニチャです。 https://github.com/sakura-editor/sakura/blob/8588683cbc79d395c17002f9c570898c8510d3cb/sakura_core/cmd/CViewCommander_TagJump.cpp#L74 戻り値boolで宣言されていますし既存コードに利用箇所もありますから、ほぼそのまま使えるでしょう。
ここまで来たらほぼ実装できるじゃないですか!と思ったんですが、 サクラエディタ特有の文化に引っ掛かってしまったようで・・・。
m_MacroFuncInfoCommandArr に定義されているものは、いずれも戻り値が VT_EMPTY です。 設計思想としてそこをみだりに変更できない、という可能性があるのか、 あるいは今までたまたますべて戻り値が VT_EMPTY なだけで、VT_I4 に変更してよいのか、 判断がつきませんでした。
ご希望の変更を行うには、宣言位置を変更する必要があります。
これ、コマンドアレーとファンクションアレーの二種類が用意されていて、 コマンド側の配列に宣言された関数は戻り値を無視する実装になっています。
いま TagJump は「戻り値なしのプロシージャ(=コマンド)」になってるので、 変更を実現するには「戻り値ありのプロシージャ(=関数)」にしてやる必要があります。
なお、趣味の問題かと思いますが、 「失敗時に0を返す」という仕様を作る場合、 「成功時」の戻り値は「0以外」が良いです。
そしてそういう値域を取る数値型のバリアントタイプは VT_I4(4byte符号付整数型)ではなく VT_BOOL(真偽型)だと思います。 これは呼出元スクリプト言語がbooleanをサポートしていなくても「そうすべき」という設計ネタです。
既存コードで使われとらんですけどね(マテ
整理ありがとうございます。 もろもろ異論ありません。
変更を実現するには「戻り値ありのプロシージャ(=関数)」にしてやる必要があります。
おお、そこは見落としていました。ありがとうございます。
VT_BOOL(真偽型)だと思います。
こちらもご指摘ありがとうございます。VARIANT型の存在の理解不足でした。 自分は、(VTが接頭辞のこの型に見覚えがないけど、 付近のソースに寄せてVT_I4が適切だろう…)、くらいに思っていましたが(危険)、 できればまずVT_I4を追って、VARIANT型と、VT_BOOLについてまで認識を深めておくとよかった感じです。
腹案があります。 サクラエディタのCookieについて某所で記事を書いたので思いついたのですが、 Cookieに新しいスコープを導入して、Cookieに結果を書き込んでおけば、
Editor.TagJump():
var jump_result = Editor.GetCookieDefault('sysytem', 'LastResult', '-1');
if(jump_result == '1'){
// Jump成功
}else{
// Jump失敗
}
みたいに手軽に実装できるんじゃないかな、と思った次第です。どうでしょう? errorlevelみたいな感じで。 Functionをプロシージャにしてしまうと、VBScriptの書き方によっては、既存のマクロがエラーになってしまうような気がしています。
デメリットは、クッキーは文字列型なので、結果の0や1だけもしくは-1とかも、文字列になってしまいます。 あとは10万回とかループする場合には、文字列の解釈とコピーでちょっと遅いかもしれないです。
ご提案ありがとうございます。 賛成です。 やりたいことを実現できるのでOKと考えます。
Functionをプロシージャにしてしまうと、VBScriptの書き方によっては、既存のマクロがエラーになってしまうような気がしています。
なるほど、そういうことがありうるんですね。そこは考えが及びませんでした。
デメリットについても問題なさそうに見えます。 今後、もし同様にプロシージャやFunctionの処理結果をクッキーで受け取る機能追加をするケースがあるとして、 そこで処理速度の差で困るかどうか?というと困らないように思えます。