◀ANSI版開発トップへ
  • 206 TeXにおける問題点に対する考察
    • 208 Re:TeXにおける問題点に対する考察
    • 209 外部コマンドについて
      • 211 Re: 外部コマンドについて
        • 216 文中のURL
        • 220 Re2: 外部コマンドについて
        • 221 Re2: 外部コマンドについて
          • 222 PipeCommandの質問
            • 224 Re:PipeCommandの質問
              • 226 解決策(Re2:PipeCommandの質問)
                • 227 Re:解決策(Re2:PipeCommandの質問)
                • 228 Re: 解決策
                  • 229 Re2: 解決策
                    • 230 新たな質問
                      • 231 Re:新たな質問
                        • 233 評価順序は処理系依存(話がそれてすみません)
                          • 234 Re:評価順序は処理系依存(話がそれてすみません)
                            • 235 Re2:評価順序は処理系依存(話がそれてすみません)
  • [206] TeXにおける問題点に対する考察 げんた 2001年03月29日 00:11

    ▼じぇぷろさんが一般掲示板にて
    >マクロをキーに割り当てられれば便利だが
    現時点では一度に1つのマクロしか扱うことができない上、マクロではエディタでのキー操作しか登録できません。

    キー操作では単一のコマンドコードを送信することしかできないのですが、複数(10個程度)のマクロを登録できる領域を用意してカスタムメニューみたいにMACRO_00~MACRO_09で対応するマクロを呼び出すようにすることは一時期考えました。(その後忘れましたが)。

    もう一つ、現在のマクロではパラメータを伴うコマンドが用意されていませんので、たとえばJUMPを登録してもジャンプのダイアログが開くだけであり、移動先をパラメータ指定することができません。以前も書きましたがこれを提供するには対応する受け皿関数の実装とそれを使うための新規マクロの導入が必要と思われます。

    >外部コマンド
    これ、誰か作り直してくれる人いませんか。Perl用Editor COPALのページに標準出力をうまく取り込む方法が詳しく書かれていたのでそれを利用できると思うのですが。

    > オプションスィッチに使われている'='が set xxx=の'='と見なされる
    Windows 2000では'='も文字として設定できました。

    > 互換性の問題
    実はテキストエディタ自身が新しいエディタを開くときにパラメータ指定を使っています。もっとも顕著な例がGREPですね。

    > ほとんど同じコードがずらーーっと増える
    ここは作り方を工夫すれば回避可能だと思いますよ。ただ、回避しても気合いを入れただけの見返りがあるとは思えないけど。

    > 既に開いているファイルでもユーザが起動オプションを指定している場合はそれに従った動作をするように
    WinMain.cppの280行目にあるとおり、既にウィンドウが開かれているときは単にActiveにするだけです。ここでパラメータを反映させるためには既にある別のプロセスに情報を送らないといけません。

    最も簡単なのはコマンド送付用の共通メッセージを定義してPostMessageで送ることだと思います。幸いWindow Handleは取得できていますし。と思ったら既にありました。MYWM_SETCARETPOSメッセージです。ただ、これは共有メモリのワークエリアを使ってデータを送っているので、複数のエディタを同時に開いたりするとワークエリアが衝突する危険性が高いです。できれば共有メモリを使わないやり方に変えたいところです。

    Window Messageで送れるパラメータ付きコマンドのレパートリーを増やしていけば、それがそのままマクロにも使えそうですしね。でももっと複雑なデータを確実に送るにはどうするのが一番良いのでしょうか?
    • [208] Re:TeXにおける問題点に対する考察 じぇぷろ 2001年03月29日 02:39

      ▼ げんたさん
      いろいろコメントいただき有難うございます。そのいくつかに。。。

      > もう一つ、現在のマクロではパラメータを伴うコマンドが用意されていませんので、たとえばJUMPを登録してもジャンプのダイアログが開くだけであり、移動先をパラメータ指定することができません。以前も書きましたがこれを提供するには対応する受け皿関数の実装とそれを使うための新規マクロの導入が必要と思われます。
      環境変数みたいに必要な内部変数を用意すればいいわけですよね。例えばK2Editorではそうなってます。

      > >外部コマンド
      > これ、誰か作り直してくれる人いませんか。Perl用Editor COPALのページに標準出力をうまく取り込む方法が詳しく書かれていたのでそれを利用できると思うのですが。
      自分には手に余りますが、とりあえず今のダイアログを少し修正しました。無効な[?]を消し、コンテキストヘルプを表示させたり(ただしヘルプ自体はない)、無効な参照ボタンを使えるようにしたり、
      コマンド入力が水平スクロールしなかったのを直したり、など。

      > > オプションスィッチに使われている'='が set xxx=の'='と見なされる
      > Windows 2000では'='も文字として設定できました。
      Win95/98ではダメです。Meは? Y:だけは追加しました。他にメッセージなどの細かい修正も。
      みく氏の修正と私のこの修正(+.rcの修正)でUR1.2.33.1にしてはどうでしょうか?

      > > 互換性の問題
      > 実はテキストエディタ自身が新しいエディタを開くときにパラメータ指定を使っています。もっとも顕著な例がGREPですね。
      内部使用だけなら、どう修正しても整合が取れていれば問題ないわけですが。。。見直すのがメンドくさいね。やっぱり追加が楽か。

      > > ほとんど同じコードがずらーーっと増える
      > ここは作り方を工夫すれば回避可能だと思いますよ。ただ、回避しても気合いを入れただけの見返りがあるとは思えないけど。
      そう思い、やってません。

      > > 既に開いているファイルでもユーザが起動オプションを指定している場合はそれに従った動作をするように
      > WinMain.cppの280行目にあるとおり、既にウィンドウが開かれているときは単にActiveにするだけです。ここでパラメータを反映させるためには既にある別のプロセスに情報を送らないといけません。
      文字コード指定オプションなど、複雑なのはいいから、行ジャンプだけでも何とかしてほしいです。

      例えば、保存しないまま修正していると、エラー行番号がずれてしまいますが、これはユーザがちゃんと保存することで対処できます。未保存の修正ファイルを行番号指定して開こうとしたら、開く前に注意を促す(保存してないよとか、行番号ズレルかも、とか)のが理想ですが、保存・未保存に関係なくいきなり指定行にジャンプするのでも大して問題はないでしょう。たかがジャンプですから。
    • [209] 外部コマンドについて じぇぷろ 2001年03月29日 13:37

      ▼ げんたさん
      > >外部コマンド
      > これ、誰か作り直してくれる人いませんか。Perl用Editor COPALのページに標準出力をうまく取り込む方法が詳しく書かれていたのでそれを利用できると思うのですが。
      COPALはコパルではなくてコーパルと読むんですか。自分では何も出来ませんが、HPにお得な情報がありました。
      COPAL HPのトップ http://homepage1.nifty.com/kaityo/
      COPALの部屋にある「ちょっと愚痴っていいですか?(希望編)」を読みましたか?>げんた氏
      COPALももうじきそうするようですが、それを待つよりこっちのほうを利用できませんか?
      # 今度は得した気分?そうでもないか。。。
      # 色々便利な物があるんですね。COPALもはじめて知りました。こういうツールでしのぐ手も十分ありますね。でもファイルサイズがsakura並なのが。。。
      # sakuraに取り込む分にはもう一つの方のProでないもので十分という気がします。
      • [211] Re: 外部コマンドについて げんた 2001年03月29日 15:31

        ▼じぇぷろさん
        >COPALももうじきそうするようですが、それを待つよりこっちのほうを利用できませんか?
        DosExec.cppが参考になりそうですね。スレッド部分でMFCの機能を使っているのでこのまま使うわけには行きませんが。

        P.S. INCMから投稿すると文中のURLがハイパーリンクにならないんですよね。
        • [216] 文中のURL じぇぷろ 2001年03月30日 00:40

          ▼ げんたさん
          > P.S. INCMから投稿すると文中のURLがハイパーリンクにならないんですよね。
          ごく普通にオンラインで投稿したんですが・・・INCMなるソフトは入れてません。
        • [220] Re2: 外部コマンドについて じぇぷろ 2001年04月02日 03:16

          ▼ げんたさん
          > ▼じぇぷろさん
          > >COPALももうじきそうするようですが、それを待つよりこっちのほうを利用できませんか?
          > DosExec.cppが参考になりそうですね。スレッド部分でMFCの機能を使っているのでこのまま使うわけには行きませんが。
          COPALはレジストリを使いませんが、DosExe(Pro)はレジストリに書き込んじゃいますね。アンインストールの手順が書いてないのもちょっと困るかな。。。
          レジストリエディタで消すしかないですね。
        • [221] Re2: 外部コマンドについて 蛭子屋双六 2001年04月02日 10:25

          ▼ げんたさん
          > ▼じぇぷろさん
          > >COPALももうじきそうするようですが、それを待つよりこっちのほうを利用できませんか?
          > DosExec.cppが参考になりそうですね。スレッド部分でMFCの機能を使っているのでこのまま使うわけには行きませんが。

          こんなのを作ってみたんですが
          http://cgisv.chldren.net/%7Eyebisuya/Pip
          eCommand.lzh
          使えませんでしょうか?
          • [222] PipeCommandの質問 げんた 2001年04月02日 14:33

            ▼蛭子屋双六さん
            >http://cgisv.chldren.net/%7Eyebisuya/Pi
            peCommand.lzh
            拝見させていただきましたが、よくわからないところがありますので教えてください。

            1. PipeCommand::executeでglobal変数paramに関数のアドレスをセットしてAnonymousPipeクラスではそれを使っていますが、クラスオブジェクトのメンバー関数を直接呼び出さないのはどうしてですか?

            2. &PipeCommand::getCommandLine としてメンバー関数のアドレスをセットしていますが、これで派生クラスの関数のポインタが入るんですか?

            3. paramがglobal変数なので、PipeCommandでは2種類の派生クラスを同時には使えないという認識でいいんでしょうか。

            4. その他KEY POINTがありましたら教えてください。
            • [224] Re:PipeCommandの質問 蛭子屋双六 2001年04月02日 21:16

              ▼ げんたさん
              > ▼蛭子屋双六さん
              > >http://cgisv.chldren.net/%7Eyebisuya/Pi
              > peCommand.lzh
              > 拝見させていただきましたが、よくわからないところがありますので教えてください。
              >
              > 1. PipeCommand::executeでglobal変数paramに関数のアドレスをセットしてAnonymousPipeクラスではそれを使っていますが、クラスオブジェクトのメンバー関数を直接呼び出さないのはどうしてですか?

              外部からこれらのプライベートメンバにアクセスできないように、
              また、このソース(PipeCommand.cpp)にある関数からであれば
              アクセスできるように隠蔽しています。

              この方法の他にもfriend等を使って隠蔽する方法がありますが、
              friendに指定したクラス名や関数名がばれてしまうので
              ごく一部のクラスや関数にだけメンバの一部を公開するときに
              私はこの方法を使っています。

              しかし、理解しにくくなってしまってますね。
              Keep It Simple and Smallを守るべきだったと後悔してます。

              > 2. &PipeCommand::getCommandLine としてメンバー関数のアドレスをセットしていますが、これで派生クラスの関数のポインタが入るんですか?

              派生クラスの関数のポインタが入るのではなく
              PipeCommandクラスのメンバ関数へアクセスするための
              ポインタが入ります。

              例えば

              void (SampleClass::*func)(const char*) = &SampleClass::func1;
              SampleClass* object;

              とした場合、次の二つは同じになります。

              object->*func(text);
              object->func1(text);

              つまりfunc1が仮想関数として宣言されていれば、
              派生クラスでオーバーライドしていれば
              オーバーライドしたメンバ関数func1が呼ばれるようになります。
              ですので、

              > 3. paramがglobal変数なので、PipeCommandでは2種類の派生クラスを同時には使えないという認識でいいんでしょうか。

              これは複数派生させたクラスがあれば
              それぞれのメンバ関数が呼ばれるので
              同時に使用しても大丈夫です。

              > 4. その他KEY POINTがありましたら教えてください。

              PipeCommandのprivateメンバをすべてpublicにして
              PipeCommand.cppの「->*param.」をすべて「->」に置換すれば
              もうちょっとわかりやすくなるかも知れません。
              • [226] 解決策(Re2:PipeCommandの質問) げんた 2001年04月03日 11:26

                ▼蛭子屋双六さん
                >外部からこれらのプライベートメンバにアクセスできないように、
                >また、このソース(PipeCommand.cpp)にある関数からであれば
                >アクセスできるように隠蔽しています。
                もっとStandardな方法で実現できないものかと考えていて思ったこと。PipeCommandクラスに、呼び出し側に提供する関数(こちらはoverrideなし)と呼び出し側が提供する関数が混在しているのがそもそもの問題なのだと思います。現在privateとなっているメンバー関数をPipeComandParamInterfaceとかいう名前の別クラスに分離し、PipeCommandにはPipeCommandParamInterfaceへのポインタor参照を渡すようにすれば、Interfaceクラスは呼び出し側がPipeCommand実装部に対して“公開”するのでpublic扱いでもおかしくないですし、PipeCommand本体は継承なしで使うことができます。
                • [227] Re:解決策(Re2:PipeCommandの質問) 蛭子屋双六 2001年04月03日 15:35

                  ▼ げんたさん
                  > ▼蛭子屋双六さん
                  > >外部からこれらのプライベートメンバにアクセスできないように、
                  > >また、このソース(PipeCommand.cpp)にある関数からであれば
                  > >アクセスできるように隠蔽しています。
                  > もっとStandardな方法で実現できないものかと考えていて思ったこと。PipeCommandクラスに、呼び出し側に提供する関数(こちらはoverrideなし)と呼び出し側が提供する関数が混在しているのがそもそもの問題なのだと思います。現在privateとなっているメンバー関数をPipeComandParamInterfaceとかいう名前の別クラスに分離し、PipeCommandにはPipeCommandParamInterfaceへのポインタor参照を渡すようにすれば、Interfaceクラスは呼び出し側がPipeCommand実装部に対して“公開”するのでpublic扱いでもおかしくないですし、PipeCommand本体は継承なしで使うことができます。

                  実は最初、シングルスレッドで実行しているときは
                  げんたさんの書かれているような方法で実装していました。

                  しかし、プロセスの終了を待つ部分を別スレッドに分けた結果
                  //プロセスのハンドルや終了コードを格納する先は
                  //インターフェイスとは別に渡さなければいけないので
                  スレッドに渡す引数の寿命を考えるのが面倒になって
                  私の使い方ではPipeCommandとインターフェイスのスパンはほぼ同じでしたので
                  「ええい、PipeCommandと一緒にしてしまえ」とやってしまいました。

                  しかしインターフェイスで実装した方が
                  確かにわかりやすいですね。
                  書き直したものを同じところに置いておきます。
                  お時間があれば見てください。
                • [228] Re: 解決策 げんた 2001年04月03日 15:43

                  うーん、結局同じことが起こってしまった。CreateThreadで渡すものが2つに分かれてやりにくくなっただけかも。でも始めと違ってPipeCommandのサブクラス化は行わないわけだから、AnonymouosPipeをfriend関数にしても(気分的には)問題ないように思う。
                  • [229] Re2: 解決策 げんた 2001年04月03日 15:49

                    ありゃ、新しいのが...新しいのを見てからまた考えます。
                    • [230] 新たな質問 げんた 2001年04月03日 20:08

                      AnonymousPipe::read()でパイプチェック、サイズチェック、読み出しの3つが&&で接続されていますが、C++ではPerlとは異なり左から評価されるという保証がないのでは?

                      もちろん&&は左結合ですから普通は左から評価するとは思いますが何となく気持ち悪い。

                      あと、availSizeに関係なくbufferSize読み込むようですが、これだとCopalのページで書かれていたようにBLOCKしてしまわないんですか?availSizeとbufferSizeのうち小さい方だけ読むというのが正しいのでは?
                      • [231] Re:新たな質問 蛭子屋双六 2001年04月03日 21:55

                        ▼ げんたさん
                        > AnonymousPipe::read()でパイプチェック、サイズチェック、読み出しの3つが&&で接続されていますが、C++ではPerlとは異なり左から評価されるという保証がないのでは?

                        CやC++でも左から評価されることは保証されてますよ。
                        #というかPerlの&&ってCから来たのではなかっただろうか

                        > もちろん&&は左結合ですから普通は左から評価するとは思いますが何となく気持ち悪い。

                        気持ち悪いっていうのは、まぁ個人の趣味の問題なので…。
                        私はwhile(1)とかの方が気持ち悪いのでこのような書き方をよくします。
                        #while(1)と書くしかないときには書きますが

                        > あと、availSizeに関係なくbufferSize読み込むようですが、これだとCopalのページで書かれていたようにBLOCKしてしまわないんですか?availSizeとbufferSizeのうち小さい方だけ読むというのが正しいのでは?

                        こちらの環境では特に問題なく動いていたんでそのままにしてます。
                        95とNT4でしか試してないので
                        98やらMeやら2000では問題が起こるのかも知れませんね。
                        問題の起こる環境があるなら変更します。
                        • [233] 評価順序は処理系依存(話がそれてすみません) げんた 2001年04月04日 10:04

                          ▼ 蛭子屋双六さん
                          > CやC++でも左から評価されることは保証されてますよ。
                          http://msdn.microsoft.com/library/devpro
                          ds/vs6/visualc/vclang/_clang_precedence_
                          and_order_of_evaluati
                          on.htm
                          を見てください。表の下にあるパラグラフの最後には
                          >> Order of operations is not defined by the language. The compiler is free to evalute such expression in any order, if the compiler can guarantee a consistent result.
                          と書かれています。つまり演算結果は保証されるが評価順序は処理系依存と。

                          A&&BでAがfalseならBをskipするのも最適化の結果であって、AとBを無条件に評価してその後でANDを取って結果を出すという処理系があったとしてもそれは規格違反にはならないということです。私が気にしているのは左からということよりも、左の結果が偽でも残りの項が評価される=関数が呼び出される可能性が残っているのではないかということです。availSizeと無関係にReadFileが呼び出されてしまうと処理が止まってしまうので。

                          > #というかPerlの&&ってCから来たのではなかっただろうか
                          意味はそうかもしれないですが、Perlでは&&や||は左から評価して結果が確定したらその後の処理をうち切ると明確に決まっていたはず。
                          だから、open(FP,file) || die "failed"; って書けます。||の前に全部評価されたら100%ここで止まってしまうので。

                          > while(1)
                          これ何ですか?for(;;)?無限ループ以外に何か面白い技があるんですか?
                          • [234] Re:評価順序は処理系依存(話がそれてすみません) 蛭子屋双六 2001年04月04日 11:12

                            ▼ げんたさん
                            > ▼ 蛭子屋双六さん
                            > > CやC++でも左から評価されることは保証されてますよ。
                            > http://msdn.microsoft.com/library/devpro
                            > ds/vs6/visualc/vclang/_clang_precedence_
                            > and_order_of_evaluati
                            > on.htm
                            > を見てください。表の下にあるパラグラフの最後には
                            > >> Order of operations is not defined by the language. The compiler is free to evalute such expression in any order, if the compiler can guarantee a consistent result.
                            > と書かれています。つまり演算結果は保証されるが評価順序は処理系依存と。

                            その後ろに
                            Only the sequential-evaluation (,), logical-AND (&&), logical-OR (||), conditional-expression (? :), and function-call operators constitute sequence points and therefore guarantee a particular order of evaluation for their operands.
                            とも書かれていますが…

                            > > while(1)
                            > これ何ですか?for(;;)?無限ループ以外に何か面白い技があるんですか?

                            いや別にfor(;;)でもいいですが、

                            DWORD avail;
                            while (1) {
                            if (!::PeekNamedPipe(/*...*/, &avail))
                            break;
                            if (avail == 0)
                            break;
                            if (!::ReadFile(/*...*/))
                            break;
                            output(/*...*/);
                            }
                            // /*...*/の部分は引数調べるのが面倒なので略しましたm(_ _;)m

                            と書くよりは

                            while (::PeekNamedPipe(/*...*/, &avail))
                            && avail > 0
                            && ::ReadFile(/*...*/))
                            output(/*...*/);

                            とかく方が私の趣味にあうってだけの話なので
                            気にしないで下さい
                            • [235] Re2:評価順序は処理系依存(話がそれてすみません) げんた 2001年04月04日 12:31

                              http://www.lysator.liu.se/c/
                              私の認識違いでした。例外規定があったのね。&&で先の評価結果がfalse(0)だとその後は評価されないって書いてありました。