えー、本当は今日は別にブログ更新するつもりじゃなかったんだけど、はてなの編集画面で入力ルールチェックしててうっかり「登録ボタン」押してしまったので、まぁ修正がてら。

10/14にタイトルバーにフルパス表記しないアプリについてグチったところ、http://www.h3.dion.ne.jp/~tokky/にアドバイスが。

・非常駐のバッチっぽいアプリ起動スクリプト組んでパラメータで編集ファイルのフルパスを貰う
・WinSetTitleでタイトルバーにフルパスで置換える。

なかなかにダイナミックな方法ですな。自分とこではQuickDirは使ってない(というかNTで動かない)のですが、%FileDir%のオプションとかあったんですね。知らんかったです。
編集ファイルをバッチスプリクト経由で開いてフルパスを得るってのも。しかしヘルプファイルなんかの場合は秀丸の外部ヘルプ機能で飛ばすことが多いので仕組みがわかってないんだよね。DDEとかなんかなぁ、よく知らんけど。

パス取得関数

AutoHotkeyでもプロセスIDを指定して実行ファイルパスを得ることが可能になったため、QuickDirもどきみたいなメニューは楽に作れるようになった。これはこれで便利なんだけどエディタなどの場合アプリパスじゃなくて編集中ファイルのフォルダを開きたいんだよってことも結構ある。
タイトルにフルパス表示してれるアプリだったらそれを利用すればいいだけなんだけど、余計な文字列(「 - 秀丸」とか)を除去しないといけない。単純にStringSplitでスペース分断してパスっぽい部分抽出で良さそうに思えるんだが、C:\Program Files\Hoge Soft\hoge.txt みたいなので上手くいかないわけで。結局関数化して一文字ずつIfExistで実パスチェックする羽目に。厄介なことです。

タイトルにフルパス前提なので、Officeアプリやヘルプなんかは当然ダメですが。特にヘルプはむかつくな。hh.exeにゃ用はねぇんだよ、みたいな。

GetPath(str="")
有効パスを抽出して返す(ダメ文字非考慮)
#p::
    filepath := GetPath()   ; アクティブウィンドウからパスを抜き出す

    ;ファイルのあるディレクトリを開く
    if (filepath)
    {
        FileGetAttrib,a,%filepath%
        ifNotInstring,a,D
            SplitPath, filepath, , filepath
         run,%filepath%
    }
return
GetPath(str="") ; As String
;--------------------------------------------------------------------
;   有効パスを抽出して返す(ダメ文字非考慮)
;     対象: AHK v1.0.34以降    2005.10.14
;       in  str : 対象文字列(省略時:アクティブウィンドウタイトル)
;       戻り値  パス情報 (0:なし)
;--------------------------------------------------------------------
{
    ifEqual str,,   WinGetTitle,str,A
    TrimMode := A_AutoTrim
    AutoTrim,ON
    str = %str%                 ; trim

    ;右端を削っていきパスとして有効なら終了。無かったら逆(左端)もチェック
    ; 例) c:\hoge.txt - 秀丸
    Loop,2
    {
        mode := A_index
        work := str
        loop, % strlen(work)
        {
            IfExist,%work%
            {
                AutoTrim,%TrimMode%
                return work
            }
            IfEqual mode,1,  StringTrimRight,work,work,1
            IfEqual mode,2,  StringTrimLeft, work,work,1
        }
    }

    ;パスとして無効な文字列で分割してチェック
    ;※ 半角スペースはパスとして有効なので誤パスが返る可能性も有
    SplitList := """,|;<>/*?" . A_Tab . A_Space
    Loop,Parse,SplitList
    {
        Loop,parse,str,%A_LoopField%,%A_Space% %A_Tab%
        {
            IfExist,%A_LoopField%
            {
                AutoTrim,%TrimMode%
                return A_LoopField
            }
        }
    }

    ;対応する括弧でチェック
    ;※ <>以外はパスとして有効なので誤パスが返る可能性も有
    SplitList := "<>,(),[],{},''"
    Loop,Parse,SplitList,`,
    {
        StringLeft, schar,A_LoopField,1
        StringRight,echar,A_LoopField,1
        spos := Instr(str,schar)
        if (spos) && (spos < Instr(str,echar,"",spos+1))
        {
            StringTrimLeft,work,str,  % spos
            StringLeft,    work,work, % Instr(work,echar)-1
            work = %work%                                       ; Trim
            IfExist,%work%
            {
                AutoTrim,%TrimMode%
                return work
            }
        }
    }

    AutoTrim,%TrimMode%
    return 0
}

ファイラー

FDの作者の方が亡くなったそうで。自分98後期の世代なんでFILMTN、HFあたりをメインに使ってたけど、会社の出張用PCや納品用WS,人ん家のPCなんかには大概FDが入っててそれでファイル操作をしたもんでした。友人宅でファイルソートしたままうっかりMSDOS.SYSを下のほうに配置して起動できなくさせちゃったりとかしてたなぁ。(いやちゃんと復旧させましたけど)


そんなわけで何となくあふだいな落としてきて試してみた。せっかくなんでフォントもQハチゴシックで。普段フォントは 9〜10ptで使ってるのだけど白基調だと12ptなんて馬鹿デカくてやってらんねぇよって感じなのに、黒背景だと問題なく馴染んでる。むしろ9ptなんて小さすぎて正気の沙汰には思えないってくらい見づらい。なんでだろな、確かに右上の秀丸は行間 1/8空ける設定にしてるけど文字間は0だし同じサイズのはずなんだが。

ちなみに現在の常用ファイラはX-Finder 全然使いこなしてないけど。エクスプローラに慣れちゃうとツリーないと不安でしょうがないんだよね。マウス主体の操作が効率低下やドロップミスを招いているのはわかってはいるんだけど。

Amazonでの商品発送体系

Amazonで本を24冊ほど購入した。
24時間以内発送可能が16冊、2〜3日以内に発送可能が5冊、4〜5日、1〜2週間、4〜6週間がそれぞれ 1冊ずつ
流石にこれだけ一度に買うと納期にバラツキがでるが、発送方法は一括(全商品が入手可能になってから発送)と分割(入手可能になった商品から随時発送)のどちらかしか選択できない。別に急いでいるわけじゃないし一週間以内で入手可能なものとそれ以上かかるものの2分割発送が良かったんでコメント欄にでも書いとこうと思ったんだけど、そもそも注文フォームにコメント欄が存在してなかった。まぁ送料はAmazonもち*1だし、最遅のものに合わせて6週間も待たされるのも嫌なので分割発送を選択した。注文内容確認メールによると5回に分けて発送されるそうだ。

半日後に来た発送完了のメール

なんちゅーか恩着せがましい内容で始まる発送完了メールがきましたよ。

Amazon.co.jpからのお知らせ
ご注文いただいた商品をできるだけ早くお客様にお届けするため、以下の商品をお客様のご希望どおり分割して発送させていただきます。残りの商品も、準備でき次第発送いたします。

今回発送する商品は以下のとおりです。

                                                                                                                                        • -

数量 商品 価格 発送済み 小計

                                                                                                                                        • -

1 BECK (Volume17) ¥530 1 ¥530
販売元: Amazon.com Int'l Sales, Inc. - 税込価格

                                                                                                                                        • -

小計: ¥530
配送料: ¥0
合計: ¥530

                                                                                                                                      • -

お客様へのご請求は、発送済みの商品についてのみ行いました。
Amazon.co.jpの規約により、お客様に発送した商品についてのみお支払いいただいております)
以下の商品は、準備ができ次第分割して発送いたします。
(以下略)

って、一冊だけかよ!! どうやら2〜3日以内だった品が早めに手配できたらしく、24時間以内発送より先に発送されたらしい。いやしかし、そこまで小出しで発送してくれなくてもいいんですが。つかもBECKは 16〜23巻まで頼んでるので17巻だけ先に送られてもむしろ困るんですが。
うーんこういう場合ってどうすりゃいいんですかね。納期別に注文分ければ良かったのか? でも面倒だしなぁ。

その後

上のメールは昨日来たもので、そこに書かれている本は今日すでに届きました。
そして今日新たに3通の発送完了メールが。どうやら明日は3梱包で18冊来るらしいです。まぁ発送元が違うとかあるのかも知れんけど、同日に出るものは同一梱包にしたほうがいいんじゃないですかね、とか思ったり。

*1:購入金額1500円超で送料無料、Amazonの超有名ルールですな

最近編集したファイルのパスをメニューで選択して貼付ける。

ChangeLogメモに更新ファイルのパス貼っつけるのが面倒だったので作成。メニューの表示と文字列比較に田楽DLLを使わせてもらったんですが、現行バージョン(Ver.2.80)ではメニューの表示位置がキャレットからズレてしまうようです。これは作者さんの報告したところ次期公開版で対策していただけるとのことです。ありがとうございます。

あと相対パスに変換できれば設定ファイル修正が楽かなぁと思って入れ込んだんだけど、これが結構大変だった。秀のマクロ言語は変数に対して文字列比較で比較開始位置を指定できないとか、大小文字無視での比較ができないとか改めて知ってちょっと愕然としたり。外部DLL使うことで拡張はできるもののWinAPI直接触れないのは痛い。
本当はソートさせたかったんだけど自力でやるのしんどいしのでやめた。つかソート前提だったらテンポラリファイルに書き出してCompleteXに丸投げしたほうが良かったような気がしてきた。インクリメンタルとかもお任せでしてもらえるしそっちのが楽だったかも。

//----------------------------------------------------------------------
//  ファイルパス貼付けマクロ(要 田楽DLL)
//   秀丸で現在開いているファイルの一覧(および履歴ファイル/フォルダ)を
//   メニューから選択して貼り付けるマクロ。
//      FilePathMenu.mac  2005.10.08 eamat.
//----------------------------------------------------------------------
Main:
    //	田楽DLLのロード
    loaddll hidemarudir + "\\DengakuDLL.dll";
    if (!result) { message "DLL をロードできませんでした。"; endmacro; }

    call CreateApath;       // 絶対パスメニュー作成

    //--- メニュー表示 ---
    while(1)
    {
        // 絶対パスメニュー
        $ret = dllfuncstr("MENU","menu0",hidemaruhandle(0));
        if ($ret != "menu0:" + str(#cnt[0]+5))
        {
            insert $file[val(midstr($ret,4,1))][val(midstr($ret,6,2))-1];   //編集位置へ貼付け
            break;
        }

        //相対パスメニュー
        if (#rmenu != 1)
        {
            title "メニュー作成中...";
            call CreateRpath;   //メニュー作成
            #rmenu = 1;
            title 0;
        }
        $ret = dllfuncstr("MENU","rmenu0",hidemaruhandle(0));
        if ($ret != "rmenu0:" + str(#cnt[0]+5))
        {
            insert $rfile[val(midstr($ret,5,1))][val(midstr($ret,7,2))-1];   //編集位置へ貼付け
            break;
        }
    }
freedll;
endmacro;

// ----------------------------------------------------------
//  サブルーチン

CreateApath:
// ===========================================================
//  絶対パスメニュー作成
//      $file[0]  編集中ファイル(ウィンドウ一覧)
//      $file[1]  ファイル履歴
//      $file[2]  フォルダ履歴
//      #cnt[0〜2]  $file[0〜2]の配列数
//      menu0〜2    絶対パスメニュー名(1,2は0のサブメニュー)
// ===========================================================

    //======= パスを取得 =======

    // --- 編集中ファイル(新規、grep等は省く) ---
    ##i = 0;
    ##k = 0;
    while (##i < hidemarucount)
    {
        if (1 < strlen(filename2[##i]))  { $file[0][##k]=filename2[##i];  ##k = ##k+1; }
        ##i = ##i+1;
    }
    #cnt[0] = ##k;

    //--- ファイルヒストリ ---
    ##i = 0;
    ##k = 0;
    while("" != getfilehist(##i))
    {   // 編集中ファイル & 存在しないパスは履歴から省く
        // (ただしネットワークドライブは重いので存在チェックしない)
        ##hit = 0;
        while(##hit < #cnt[0])
        {
            if ($file[0][##hit] == getfilehist(##i))    break;
            ##hit = ##hit+1;
        }
        if (##hit == #cnt[0])
        {
            if ("\\\\" == leftstr(getfilehist(##i),2))  { $file[1][##k]=getfilehist(##i);  ##k=##k+1; }
            else if (existfile(getfilehist(##i)))       { $file[1][##k]=getfilehist(##i);  ##k=##k+1; }
        }
        ##i = ##i+1;
    }
    #cnt[1] = ##k;

    //--- フォルダヒストリ ---
    ##i = 0;
    ##k = 0;
    while("" != getpathhist(##i))
    {
        if ("\\\\" == leftstr(getpathhist(##i),2))  { $file[2][##k]=getpathhist(##i);  ##k=##k+1;  }
        else if (existfile(getpathhist(##i)))       { $file[2][##k]=getpathhist(##i);  ##k=##k+1;  }
        ##i = ##i+1;
    }
    #cnt[2] = ##k;

    // === メニュー作成 ===
    ##i = 0;
    while(##i < 3)
    {
        if(!dllfunc("NEWMENU","menu" + str(##i)))    return false;
        ##k = 0;
        while(##k < #cnt[##i])
        {
            if(!dllfunc("ADDMENUITEM","", "&" + str(##k+1) + " " + $file[##i][##k],""))  return false;
            ##k = ##k+1;
        }
        ##i = ##i+1;
    }
    if(!dllfunc("ADDMENUITEM","menu0","",""))                       return false;
    if(!dllfunc("ADDMENUITEM","menu0","&F ファイル履歴","menu1"))   return false;
    if(!dllfunc("ADDMENUITEM","menu0","&D フォルダ履歴","menu2"))   return false;
    if(!dllfunc("ADDMENUITEM","menu0","",""))                       return false;
    if(!dllfunc("ADDMENUITEM","menu0","&R 相対パス表示",""))        return false;
return true;

CreateRpath:
// ==================================================
//  相対パスメニュー作成
//      $rfile[0]  編集中ファイル(ウィンドウ一覧)
//      $rfile[1]  ファイル履歴
//      $rfile[2]  フォルダ履歴
//      rmenu0〜2    相対パスメニュー名(1,2は0のサブメニュー)
// ==================================================

    // === メニュー作成 ===
    ##i = 0;
    while(##i < 3)
    {
        if(!dllfunc("NEWMENU","rmenu" + str(##i)))    return false;
        ##k = 0;
        while(##k < #cnt[##i])
        {
            if (##i != 2)   call GetRelativePath directory2,$file[##i][##k];
            else            call GetRelativePath directory2,$file[##i][##k] + "\\";
            $rfile[##i][##k] = $$return;

            if(!dllfunc("ADDMENUITEM","",str(##k+1) + " " + $rfile[##i][##k],""))  return false;
            ##k = ##k+1;
        }
        ##i = ##i+1;
    }
    if(!dllfunc("ADDMENUITEM","rmenu0","",""))                      return false;
    if(!dllfunc("ADDMENUITEM","rmenu0","&F ファイル履歴","rmenu1")) return false;
    if(!dllfunc("ADDMENUITEM","rmenu0","&D フォルダ履歴","rmenu2")) return false;
    if(!dllfunc("ADDMENUITEM","rmenu0","",""))                      return false;
    if(!dllfunc("ADDMENUITEM","rmenu0","&A 絶対パス表示",""))       return false;
return true;

GetRelativePath:
//------------------------------------------------
//  相対パスを返す (田楽DLL使用)
//  in  $$1: 基準(カレント)ディレクト絶対パス
//           (末尾に\は含まない)
//      $$2: 相対パスに変換したい絶対パス
//          (フォルダ時の場合は末尾に\を付加)
//  戻り値 : $$2の相対パス
//------------------------------------------------

    // --- 相対にならない場合はフルパスを返す ---
    // ネットワーク名が違う場合は諦める
    if (leftstr($$1,2) == "\\\\")
    {
        // \\PC名\第一階層\ までが同じじゃないものは諦める
        if (leftstr($$2,2) != "\\\\")   return  $$2;                    //ローカル
        $$tmp = rightstr($$1,strlen($$1)-2);
        $$cmp = "\\\\" + leftstr($$tmp,strstr($$tmp,"\\"));             //PC名
        $$tmp = rightstr($$tmp,strlen($$tmp)-strstr($$tmp,"\\")-1);
        $$cmp = $$cmp + "\\" + leftstr($$tmp,strstr($$tmp,"\\")) + "\\"; //第一階層
        if (0 != dllfunc("STRICMP",$$cmp,leftstr($$2,strlen($$cmp))))   return $$2;
    }
    // ドライブが違う場合は諦める。
    if (0 != dllfunc("STRICMP",leftstr($$1,1),leftstr($$2,1)))  return $$2;

    // --- 相対パス作成 ---
    if (rightstr($$2,1) == "\\")    // ディレクトリ時
    {
        if (3 == strlen($$1))   return rightstr($$2,strlen($$2)-3); //ルート
        if (0 == dllfunc("STRICMP",$$1+"\\",$$2))    return ".\\";  //カレント
    }

    $$upper = "";
    while(0 != dllfunc("STRICMP",$$1+"\\",leftstr($$2,strlen($$1)+1)))
    {
        ##i = dllfunc("STRRSTR",$$1,"\\");              //前の\検索
        if (##i == -1)                      break;
        $$1 = leftstr($$1, ##i);
        $$upper = $$upper + "..\\";
    }
    if (rightstr($$2,1) == "\\")    $$2 = leftstr($$2,strlen($$2)-1);
return $$upper + rightstr($$2,strlen($$2)-strlen($$1)-1);

マウスクリック関数

作りっぱでほかしてあったやつ。ちょっと前に AutoHotKey Threadでダブルクリック検知についてのレスがあったので出してみる。
トリプルとかクワクトブル(でいいのか?)クリックとかも検知したくて作ってみたやつです。

MultiClickCheck(button,MaxCount=2,timout=0)
割と厳密な多重クリックチェック
;てきとうなダブルクリックチェック例
;Rbutton Up::
WClick_test:    
    WClickTime := DllCall("User32.dll\GetDoubleClickTime",Int)
    if (A_PriorHotkey = A_ThisHotkey) && (A_TimeSincePriorHotkey < WClickTime)
    {
        ;ダブルクリック時処理
    }
    else
    {
        ;シングルクリック時処理
    }
return
続きを読む

週末のこととか

ネットで家具を買うのはバクチかも

ネット通販で家具を2点、近場のホームセンターで2点ほど買った。前者の2つはメーカーも購入ショップも別だったのだが何故か揃って製品不良。両方とも返品交換せなならない。鬱だ。

慢性週末病

頭痛:日〜火曜で3日間、今週はバファリンもあんま効かんかった。つらい。
腰痛:週末はそうでもなかったのだが、昨夜頭が痛くてもんどり打ってたので寝違えた。

TVアンテナ工事(デジタル対応に向けて)

ノ○マでTVアンテナ工事を依頼しようと思い、週末に見積もりに来てしてもらった。天井裏への進出がやばそうだったのでその旨は伝えたが、見積もりに来た工事の人の話だと室外引き込みだと工事費も高くデメリットが多いので、何とか天井入って従来線利用する方向でいったほうが良いと言われる。
説明聞いてその気になってたのに、店番のお兄ちゃんからの後日の電話では従来線がデジタル向きではないので新規で室外引き込みするしかないとか言うことになってた。
工エエェェ(´д`)ェェエエ工工 話が違うじゃないですかノ○マさん。
んでもって値段は13万円だそうだ。いや相場とか知らんですけどね、2,3万〜多くても5万くらいだと考えてたので思わず電話口で思わず仰け反る。
あーなんか別に今無理にアンテナ工事しなくてもいいか。とりあえずアナログが見れればいいかな、みたいな。