[ 新規に投稿する ]

existfile() 関数で期待と違う動作No.09198
yamashita さん 20/04/03 17:25 [ コメントを投稿する ]
  お世話になっております。

以下のようなマクロを動かすと、私の手元では 1 と表示されます。
$ss = "/: hoge";
message(str(existfile($ss)));

実際には、"/: hoge" というファイルは存在しないので、
0 と表示されることを期待しています。

なお、
$ss = "/: ";
とすると、 マクロの実行結果は 0 になります。
"/: " というファイルも存在しません。

何らかの事情による仕様なのでしょうか?
[ ]
RE:09198 existfile() 関数で期待と違う動作No.09201
n'Guin さん 20/04/04 03:02 [ コメントを投稿する ]
  1ユーザーのn'Guinといいます。


>$ss = "/: hoge";
>message(str(existfile($ss)));

秀丸マクロのヘルプ
https://help.maruo.co.jp/hidemac/html/051_FilePath.html
に次のようにあります。


各種の文や関数をフルパスで書く場合、フォルダ(ディレクトリ)の区切り記号は半角\のみが使えます。
半角スラッシュ(/)は使えません。
書くことで使えてしまう文や関数もありますが、そのままWindowsのAPIに渡して結果的に動作している場合があるためで、秀丸エディタとしては想定していないため何が起きるかはわからないです。

----ここまで

よって、仕様だと思いますが、いかがでしょうか。
[ ]
RE:09201 existfile() 関数で期待と違う動作No.09204
秀丸担当 さん 20/04/06 09:57 [ コメントを投稿する ]
 
existfileは、n'Guinさんの言われる通り、ファイル名として成立するかどうかの解釈はWindowsとファイルシステムによります。
existfileはWin32APIのFindFirstFileを呼んでいるだけになり、「/」は自動的に「\」として解釈されるようです。
秀丸エディタとしては「/」の書き方はサポートしていなくて推奨しないですが、WindowsのAPIに渡すとできてしまうものは、結果的に「/」もできてしまいます。

--------

ほぼWindowsとファイルシステムの仕様はどうなっているのかという話になってしまうのですが、「/: hoge」という文字列は、ものすごく特殊なことが起きるようです。
まず、「/」は「\」と解釈され、この場合はC:\とかD:\といったドライブのルートになります。
「:」は、ファイル名の後に書くとNTFSのサブストリーム(副ストリーム・代替データストリーム)となる書き方があります。「C:\Folder\test.txt:hoge」とすると、test.txtの中身とは別のファイル内容になったりします。(秀丸エディタでは開く/名前を付けて保存はできないです。コマンドラインやマクロで直接は一応できます)

次に初めて知ったのですが、サブストリームは、無名のファイル(というかディレクトリ?)に対しても作れてしまうようです。
しかも、ルートにもできてしまうようです。さらに先頭に空白があるサブストリーム名でもいいようです。
でも、existfile(=Win32APIのFindFirstFile)では見つからないようです。エクスプローラやコマンドプロンプトのdirでも普通は現れないです。
「/: hoge」は、ルートにあるファイル名なしのサブストリーム名" hoge"で、存在できるけど、見つからないファイルということになるようです。

ルートにあると探すことも消すこともできず、だいぶん焦ってしまいましたが、見つける裏技を見つけました。
コマンドプロンプトで、「dir /R」とするとサブストリームも見れるのですが、ルートは見れないです。
ダミーのディレクトリFolderを作って「dir D:\Folder /R」といった感じにすると、Folderの親の「<DIR> ..」のサブストリームとして、ルートにあるものを見つけることができました。

でも存在しても普通は見つからないはずなので、結局existfile("/: hoge")がなぜ見つかる判定なのかわからないですが、一度、コマンドプロンプトで「dir C:\Folder /R」とか「dir D:\Folder /R」とかしてみるといいかもしれないです。

[ ]
RE:09204 何か回避方法を考えますNo.09206
yamashita さん 20/04/06 22:03 [ コメントを投稿する ]
  n'Guin 様、秀丸担当様、ありがとうございます。

作りたかったのは「特にフォーマットの決まっていないカレント行に対して、カレント行の中に実在するパス名が含まれていれば、それを開く」というマクロです。
このために、「カレント行の文字列の中に、パス名と判断できる部分文字列があれば(existfile で true が返る部分文字列があれば)、それを openfile する。パス名がなければ何もしない。」という実装をしたかったのです。
例示した "/" は、パス名の区切り子の "/" ではなく、秀丸マクロのコメントの "//" の2文字目の "/" です。

秀丸側ではなく、windows API の問題なのだとすれば、与件とするしかないので何か回避方法を考えます。
ありがとうございました。
[ ]
RE:09206 関連していそうな事項No.09207
yamashita さん 20/04/07 11:43 [ コメントを投稿する ]
  おそらくこの件に関連してるのではと思う別件があったので、質問します。

秀丸 8.91
32bit edition です。

秀丸マクロディレクトリが x:\macro だとします。
x:\macro\hoge.mac というファイルが存在するとします。
なお、x:\macro\<hoge.mac> というファイルは存在しません。

また、以下の設定を行っています。
[その他] メニュー [動作環境] [ファイル] [開く] [ファイル検索パス] に、
x:\macro
を加えています。

以下のマクロ x:\macro\gege.mac を作成します。
ここから >>>>
openfile "\"gege\" \\<hoge.mac>";
endmacro;
<<<< ここまで

これを実行すると、以下のように動作します。
(a) x:\macro\<hoge.mac> が見つかりました。開きますか?
  yes/no/cancel
  のダイアログが開きます。
(b) yes を選択すると、hoge.mac を開きます。
(c) no か cancel を選択すると、2つの秀丸が起動し、
  "x:\<hoge.mac>" と "x:\macro\gege" を「新規」の秀丸で開きます。

どこから突っ込んだら良いのかしばらく悩みましたが、以下のように整理してみました。

まず、(a) のメッセージが変ですが、これは既出の Windows API の問題と類似していて、秀丸の論点ではなく、Windows API の論点かなと思いますが、どうでしょうか。(-> 質問1)
そうであれば、これは仕方がありません。

次に、(a) で "<hoge.mac>" という存在しないファイルについてメッセージを出したのに、(b) で しれっと "hoge.mac" を開いていますが、まぁこれも小さいことのように思うので、気にしないことにします。

(c) において、no という返事の応答として、そのファイルを開くべきではないことは確かですが、その他にどういう応答をするべき(しないべき)と考えるのが合理的なのか、私はよくわかりません。なので no の後の動作については、現時点では特に質問も要望もありません。

しかし (c) において、cancel を選択した場合には、ユーザの意図は、「この先の動作はやめてくれ」だと考えるのが合理的ではないかと思います。
したがって cencel が選択された場合には、
(p) openfile の動作は中断し、次のマクロに移る。
(q) openfile の動作を中断すると共に、マクロの動作も中断する。
のどちらかになって欲しいように思いますが、どうでしょうか。(-> 質問2)
この辺の動作にも Windows API 的な制約があるのなら、それをどうにかして欲しいとまでは思いません。

なお (p) の場合には openfile の動作が「中断」したことを result の値などで知りたいように思います。

気のせいかも知れませんが、大昔に似たような質問をしたような気がします。
重複してたら恐縮ですが、OS もかなり変わっているはずなのでお許しください。
[ ]
RE:09207 関連していそうな事項No.09208
秀丸担当 さん 20/04/07 17:19 [ コメントを投稿する ]
 
"<hoge.mac>"のようなファイルは、なぜか"<" ">"を無視して見つかってしまい、開けてもしまうようで、Windowsがそのように判断しているようです。
そういう文字を事前に秀丸エディタ側でエラー扱いにできなくもないですが、下手に触らないでおこうと思います。
"/"や":"もそうですが、Windows標準のアプリやコマンドプロンプトでも通るものと通らないものがまちまちのようです。

ファイル検索パスのキャンセルは、開くダイアログの入力欄でEnterしたときにキャンセルして、また入力に戻るためのものでした。
openfileでは意味が無かったです。
「いいえ」は、ファイル検索パスが複数あれば次の検索をし、なければファイルが無いときの処理として続行するものでした。
問い合わせのメッセージで、
[はい]:このパスで開く
[いいえ]:見つからない場合の処理として続行
[キャンセル]:マクロ中断
といった感じでボタンを押したら何が起きるのかわかるようにしようと思います。

openfileでの詳細なエラーなどはgetresultexで知ることができますが、ファイルが見つからなくて新規になるときは、ファイル検索パスで選んだときはわかりませんでした。getresultex(20)や(21)くらいで取得できるようにしようと思います。
書き方によって複数のファイルが開けてしまいますが、1つの場合だけの想定にしようと思います。
[ ]
RE:09208 関連していそうな事項No.09209
Iranoan さん 20/04/07 22:09 [ コメントを投稿する ]
  秀丸担当さんこんにちは Iranoan です
> "<hoge.mac>"のようなファイルは、なぜか"<" ">"を無視して見つかってしまい、開けてもしまうようで、Windowsがそのように判断しているようです。
> そういう文字を事前に秀丸エディタ側でエラー扱いにできなくもないですが、下手に触らないでおこうと思います。
<, > はおそらくリダイレクションとして処理されるんでしょうね
少なくとも <hoge.mac> が無いときは

> [はい]:このパスで開く
> [いいえ]:見つからない場合の処理として続行
> [キャンセル]:マクロ中断
> といった感じでボタンを押したら何が起きるのかわかるようにしようと思います。
基本はこれで良いと思いますが
openfile "\"gege\" \\<hoge.mac>HOGEHOGE.txt";
とした時に、gege に加えて
・<hoge.mac>HOGEHOGE.txt の一つ
・hoge.mac と HOGEHOGE.txt の二つ
を開くといった使用を決めておいたほうが良いでしょうね
「Windows API でどう扱われるか?」に任せてしまってよいのでしょうが
[ ]
RE:09209 関連していそうな事項No.09210
秀丸担当 さん 20/04/08 10:25 [ コメントを投稿する ]
 
どうも"<"は"*"、">"は"?"と似たような振る舞いをするようです。
でも全く同じというわけではないようです。
コマンドプロンプトでdir "test<.txt"はdir "test*.txt"のようになるけど、copyやtypeは似ているけど微妙に違っていたり、mspaintはそのまま1つのファイルで開けたり、とても奇妙な動作です。
秀丸エディタで何かするとしたら、複数ファイルとしての区切りとかではなくエラーにしたほうがよさそうですが、あまりいじらないでおこうと思います。
[ ]
RE:09210 関連していそうな事項No.09211
yamashita さん 20/04/08 17:20 [ コメントを投稿する ]
  > copyやtypeは似ているけど微妙に違っていたり、mspaintは
色々とお手数をお掛けして恐縮です。全然ちゃんとしてないんですね。

windows API の奇妙な仕様は、ご示唆の通り「触るな危険」だと思います。

念のためですが、
・[はい]:このパスで開く。次のファイルがあれば次へ。
・[いいえ]:このパスは開かない。次のファイルがあれば次へ。
・[キャンセル]:openfile() の処理を終了して返る。
・いずれの場合も、openfile() から返った後、マクロの次行の実行を継続し、
 getresultex() で openfile が「cancel されたかどうか」
 あるいは「yes/no/cancel のどれだったか」が取得できる。
という動作ならば、私は便利です。

> 書き方によって複数のファイルが開けてしまいますが、1つの場合
> だけの想定に

getresultex() で取得できるのは「最後に処理したファイルでの結果」
ということならば、簡易でベターな対案は思いつきません。

2つのファイルの openfile() で、
・1つ目のファイルは yes
・2つ目のファイルは cencel
ならば、将来を含めて私が便利なのは「2つ目のファイルの cencel」
ではないかと予想します。
[ ]
RE:09211 関連していそうな事項No.09212
秀丸担当 さん 20/04/08 17:56 [ コメントを投稿する ]
 
複数ファイルが開く場合はマクロでは1つ1つについて制御しきれず、1つのみがマクロの続行対象になります。

よく考えたら、ファイル検索パスが複数ファイルの書き方で出てしまうこと自体が問題でした。
現状でも、ファイル検索パスとして働くのは複数のファイルにはならず、最後の1つのファイルだけでした。
フルパスではないけど\の直後にあるようなファイルを検出してしまっていて、このこと自体が問題だと思うので、こういう書き方では働かないようにしようと思います。

「はい」は、ファイル検索パスで見つかったファイルで開きます。複数ファイル指定では動作しないようにします。
「いいえ」は、ファイル検索パスで見つかったファイルでは開かず、動作環境のファイル検索パスを複数指定している場合は、次の検索パスを探します。全部検索パスで見つからなかったときは、検索パスが無いときと同じように、新規ファイルのような扱いになります。
「キャンセル」は、マクロ中断するようにします。
getresultex(20)で見つからなかったかどうか、getresultex(21)でyesかnoか、をわかるようにしようと思います。
[ ]
RE:09212 関連していそうな事項No.09213
yamashita さん 20/04/10 00:45 [ コメントを投稿する ]
  > 1つ1つについて制御しきれず、1つのみがマクロの続行対象になります。
> こういう書き方では働かないようにしようと思います。
私は問題構造をきちんと把握できてないかも知れませんが、
私がどうこう言う問題ではなさそうなので異論はありません。

> 「キャンセル」は、マクロ中断するようにします。
くどくてすいませんが、getresultex(20), getresultex(21) の値の話しを
なさっているので本来は確認不要ながら、「マクロ中断」というのは、
(a) マクロ自体の実行を終了する。
ではなく、
(b) openfile() の処理を中断して返り、マクロの次行以下を続行する。
のであれば異論はありません。
(今回の私の事例においては、(a) でも困らないですが、(b) の方が多くの
事例において使いやすいと予想します。)
[ ]
RE:09213 関連していそうな事項No.09214
秀丸担当 さん 20/04/10 10:30 [ コメントを投稿する ]
 
もともとキャンセルボタンがあるのは開くダイアログのためのもので、マクロのほうのキャンセルは、開くダイアログのように再び入力状態に戻るということはできないです。
異論はあるかもしれまんが、マクロでは3つも選択肢があるのがよくわからないので、とりあえずキャンセルは無くしてみます。(V8.92β11で)
そうすると、問い合わせは、あくまでファイル検索パスを適用するかどうかということになります。

キャンセルでファイルを開かず続行という選択肢を設けるとしたら、ファイル検索パスのときだけでなく、通常のファイルが見つからないときにも問い合わせがあったほうがいいと思います。
そうなると仕様変更になるので、問い合わせを出すかどうかという指定をできるように何らかの方法(例えばseterrormode文で)を検討しようと思います。
[ ]

[ 新規に投稿する ]