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を呼んでいるだけになり、「/」は自動的に
「\」として解釈されるようです。
秀丸エディタとしては「/」の書き方はサポートしていなくて推奨しないですが、Win
dowsのAPIに渡すとできてしまうものは、結果的に「/」もできてしまいます。

--------

ほぼWindowsとファイルシステムの仕様はどうなっているのかという話になってしま
うのですが、「/: hoge」という文字列は、ものすごく特殊なことが起きるようです。
まず、「/」は「\」と解釈され、この場合はC:\とかD:\といったドライブのルートに
なります。
「:」は、ファイル名の後に書くとNTFSのサブストリーム(副ストリーム・代替デー
タストリーム)となる書き方があります。「C:\Folder\test.txt:hoge」とすると、t
est.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文で)を検討しようと思います。

[ ]