パス取得関数

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
}