Seek -- by Phi

시작 메뉴를 항해하는 것은 난삽할 수 있습니다. 특히 시간이 지나면서 많은 프로그램을 설치했다면 더욱 난삽합니다. 'Seek'으로 대소문자를 구분하지 않고 키 단어/문구를 지정하면 시작 메뉴로부터 오직 부합하는 프로그램과 디렉토리만 여과합니다. 그래서 쉽게 목표 프로그램을 몇 개 안 되는 부합 엔트리 중 하나에서 열 수 있습니다. 이렇게 하면 시작 메뉴를 검색하고 순회하는 지겨운 작업을 하지 않아도 됩니다.

이 스크립트 내려받기  |  다른 샘플 스크립트  |  홈으로

;*****************************************************************
;
;  Program : Seek
;  Coder   : Phi
;  Updated : Mon Jan 31 10:08:37 2005
;
;  여러분, 무엇을 찾고 계십니까?
;
;*****************************************************************
;
;  필자는 재미있게 이 코딩을 즐겼습니다. 모쪼록 여러분도
;  재미있게 사용하시기를 바랍니다. 주저하지 마시고 이메일을
;  주십시오. 논평이든 피드백이든 환영합니다: phi1618 (*a.t*) gmail
;  :D0T: com.
;
;  옵션:
;    -cache 가능하면 캐쉬된 디렉토리 리스트를 사용한다
;           (아무 옵션도 지정하지 않으면 이것이 기본값이다)
;    -scan  디렉토리를 스캔해 
              최근의 디렉토리 목록을 열람한다
;    -scex  스캔 & 종료 (잠재적으로 시간을 소모하는 
              디렉토리 스캔 작업을 배경 작업으로 설정할 경우
;              유용하다)
;    -help  이 도움말을 보여준다
;
;*****************************************************************
;
; HOW TO 'SEEK':
;
; 1. 'Seek'은 오토핫키 스크립트입니다. 
;    Seek.ahk (원본 스크립트) 또는 Seek.exe (컴파일된 실행 파일)
;    로 실행할 수 있습니다.
;
;    Seek.exe를 얻으려면, Seek.zip을 내려받으면 됩니다 
;    (안에 소스 코드와 컴파일된 이진 파일이 모두 들어 있습니다)
;    http://home.ripway.com/2004-10/188589/
;    그렇지 않으면, 스스로 Seek.ahk를 컴파일해도 됩니다
;    오토핫키의 Ahk2Exe.exe 컴파일러를 사용하거나, 아니면
;    필자에게 이메일로 사본을 요청해도 됩니다. 파일 크기는 대략
;    200 킬로바이트 정도록 작습니다. 다음 이메일로 연락 주십시오: phi1618 (*a.t*)
;    gmail :D0T: com.
;
;    Seek.ahk를 사용하려면, 먼저, 여러분의 컴퓨터에
;    AutoHotkey v1.0.25 이상을 설치해야 합니다.
;    (http://www.autohotkey.com에서 내려 받으십시오). 다음 명령어를 실행합니다:
;
;    X:\myTools\AutoHotkey\AutoHotkey.exe Y:\myAHK\Seek.ahk
;
;    잊지 말고 X:\myTools 그리고 Y:\myAHK를 
;    여러분의 컴퓨터에 맞는 적절한 디렉토리 이름으로 교체하십시오.
;
; 2. 실행 파일 Seek.exe는 어디든 마음래도 두셔도 됩니다.
;    설치가 필요 없습니다. 레지스트리에 전혀 쓰지도 않으며
;    인터넷에도 전혀 접근하지 않습니다
;    설치를 제거하려면,
;    그냥 Seek.exe를 삭제하면 끝입니다.
;
;    'Seek'이 생성하는 두 개의 2 파일만 
;    TMP 디렉토리에 배치됩니다:
;
;      a. _Seek.key  (마지막 질의 문자열을 위한 캐쉬 파일)
;      b. _Seek.list (디렉토리 리스트를 위한 캐쉬 파일)
;
;    여러분이 순수 주의자라면, 시스템에서 'Seek'을 제거하기로
;    결정한 순간 손수 지워 버리면 됩니다.
;
; 3. 'Seek'을 실행하는 가장 편리한 방법은 단축키/핫키를
;    이용하는 것입니다. 여러분의 컴퓨터에
;    아직 핫키 관리 프로그램을 사용하고 있지 않다면, 필자는 
;    AutoHotkey를 강력 추천합니다. 지금 당장은
;    핫키 관리 프로그램을 설치하고 싶지 않다면
;    윈도우즈의 단축키를 이용할 수 있습니다.  'Seek'를 기동할
;    단축 키 (예, ALT-F1)를 묶으면 됩니다. 이것은 중요합니다.
;    언제든지 어디서든 'Seek'를
;    실행할 수 있기 때문입니다..
;
; 4. 처음 'Seek'를 실행할 때, 시작 메뉴를 스캔합니다
;    그리고 디렉토리 리스트를 
;    캐쉬 파일에 저장합니다.
;
;    다음 디렉토리가 스캔 대상에 포함됩니다:
;    - %A_StartMenu%
;    - %A_StartMenuCommon%
;
;    기본값으로, 연이은 실행은 캐쉬 파일로부터 읽습니다
;    그래서 적재 시간을 절약합니다. 
;    옵션에 관한 더 자세한 정보는 'Seek.exe -help'를 실행하십시오. 
;    시작 메뉴에 별로 프로그램이 없다면
;    캐쉬 사용을 포기하고 언제나 디렉토리 스캔을
;    사용하라고 'Seek'에게 알릴 수 있습니다 (옵션 -scan).
;    그런 식으로 언제나 최신 목록을 얻을 수 있습니다.
;
; 5. 'Seek'을 실행할 때, 창이 나타나서
;    여러분이 키 단어/문구를 입력하기를 기다립니다.
;    질의 문자열을 입력한 후, 부합하는 레코드 목록을
;    보여줍니다. 다음으로, 엔트리를 강조하고
;    <Enter>를 누르거나 'Open' 버튼을 클릭할 필요가 있습니다.
;    그래야 선택된 프로그램을 실행하거나
;     택된 디렉토리를 열 수 있습니다.
;
;*****************************************************************
;
; 기술적 고지 사항:
;
; - 'Seek'는 크리스 멀릿(Chris Mallett)의 AutoHotkey v1.0.25
;   이상을 요구합니다 (http://www.autohotkey.com).
;   크리스에게 위대한 작업을 해 주신 것에 대하여 감사드립니다:)
;
; - 다음 환경 변수는 항상 유효합니다:
;   a. TMP
;
;*****************************************************************
;
; 알려진 문제:
;
; - 없음
;
;*****************************************************************
;
; 구현 제안:
;
; - 기본으로 첫 번째 부합 레코드를 강조.
;   사용자가 그냥 <Enter>만 치면 실행되도록.
;   (Suggested by Yih Yeong)
;
; - 검색 결과 목록을 더블 클릭하면
;   프로그램을 실행하도록 개선.
;   (Suggested by Yih Yeong & Jack)
;
; - 자동 실-시간 점진적 검색.
;   (Suggested by Rajat)
;
; - 사용자가 스페이스로 구분하여,
;    여러 질의 문자열을 입력알 때 퍼지(Fuzzy) 검색.
;   (Suggested by Rajat)
;
;*****************************************************************
;
; 특징 제안 (구현 미정):
;
; - 기동 이력 기록. 최근에 사용된 프로그램을
;   검색 결과의 상단에 배치.
;   (Suggested by Yih Yeong)
;
; - 리스트 박스 대신, 일련의 어플리케이션 아이콘을 
;   보여줌. 그러면 그 아이콘 위에 커서를 올리면
;   프로그램 정보가 들어 있는 툴팁이
;   나타난다 (경로, 등등).
;   (Suggested by Yih Yeong)
;
; - 텍스트 중간에 부합하는 대신에,
;   질의 문자열로 시작하는
;   프로그램/디렉토리에만 부합.
;   (Suggested by Stefan)
;
; - 즐겨 찾기 관리 추가. 단 번에 
;   프로그램 그룹을 기동.
;   (Suggested by Atomhrt)
;
; - Seek를 윈도우즈 태스크바/툴바에 통합.
;   언제나 가능하고 Seek를 기동하기 위해
;   핫키를 묶을 필요가 없기 때문에.
;   (Suggested by Deniz Akay)
;
; - 만능문자/정규 표현식으로 검색.
;   (Suggested by Steve)
;
;*****************************************************************
;
; 변경 이력:
;
; * v1.1.0
; - 최초 배포.
;
; * v1.1.1
; - 창-최대화 옵션 제거. 
;   잘 작동하지 않은 프로그램이 있기 때문에.
; - 'Open' 기능을 촉발시키기 위해 더블 클릭 탐지 추가.
;
; * v2.0.0
; - 'Seek' 팝업 창을 출력 화면에 통합
;   덕분에 사용자가 질의 문자열을 재입력할 수 있음
;   뭔가를 검색하기 위해 종료했다가 다시 Seek을 실행할 필요가 없음.
; - 'Scan Start-Menu' 버튼 추가.
; - 실시간 점진 검색 추가. 타자하는 동안
;   부합하는 레코드를 자동으로 여과한다,
;   <Enter>를 누르기를 기다리지 않는다.
; - 검색 문자열을 추적할 내부 스위치 추가 (TrackKeyPhrase).
; - 툴팁을 이용하여 파일이름을 보여줄
;   내부 스위치 추가 (ToolTipFilename)
;
; * v2.0.1
; - 수평 스크롤바를 리스트박스에 추가. 이제 아주 긴
;   레코드라도 중간에서 끊어지지 않는다.
;
; * v2.0.2
; - 사용자가 자신의 맞춤 디렉토리 목록을 스캔 대상에 포함할 수 있도록 허용.
;   사용자는 그냥 텍스트 파일 'Seek.dir'을 Seek.exe 또는  Seek.ahk가 있는
;   디렉토리에 만들어, 추가될 디렉토리의 전체 경로를
;   한 줄에 하나씩 지정하기만 하면 된다. 
;   경로는 홑따옴표 또는 겹따옴표로 둘러 싸지 마십시오.
;
; * v2.0.3
; - 이름으로 정렬 /on 옵션을 DIR-명령어에 추가.
; - 사용자가 여러 질의 문자열을 스페이스로 분할해 입력할 때,
;   퍼지 검색. 예, "med pla". 문자열이 모두
;   ("med" & "pla") 발견되면 부합한다.
;   이것은 "Media Player", "Macromedia Flash Player",
;   "Play Medieval King", "medpla", "plamed"에 부합한다.
; - 탭-이동 절차를 교정. 모든 버튼을 시작으로부터 오른쪽으로 추가하고,
;   실제로 사용할 수 있을 때까지
;   불능으로 만들어서.
; - 툴팁=피드백을 교체하기 위해 상태 바를 추가.
; - 폐기된 내부 스위치를 제거 (ToolTipFilename).
; - "dir" 명령어의 사용을 오토핫키의
;   "Loop" 명령어로 교체해 디렉토리 내용을 스캔.
;   "dir"은 확장 문자 세트를 처리할 수 없으므로
;   비-영어 (예, 독일어) 디렉토리와 파일이름은 잘못 얻게 됨
;   (이 변경을 테스트해 주신 볼프강 부가티(Wolfgang Bujatti)와
;   시에스 플리지(Sietse Fliege)에게 감사)
; - 내부 스위치 추가 (ScanMode) 파일이나 디렉토리가
;   스캔 대상에 포함되었는지 확인.
; - 하드코드된 시작 메뉴 경로를 내장 변수
;    A_StartMenu, A_StartMenuCommon으로 교체.
;   이로서, Seek은 이제 시작 메뉴에서
;   다른 이름짓기 관례를 가진 다른 로케일과도 작동.
;   (이 새 변수를 사용하기 전에 또다른 방법을 테스트해 주신
;   볼프강 부가티(Wolfgang Bujatti)와
;   시에스 플리지(Sietse Fliege)에게 감사)
; - 마지막-실행 프로그램 레코드를 미리 선택
;   신속하게-<ENTER>를 두 번 누르면 그것을 실행.
;
;*****************************************************************

;**************************
;<--- BEGIN OF PROGRAM --->
;**************************

;==== 여기는 맞춤 설정 구역================================

; 디렉토리를 열 때 사용할 프로그램을 지정합니다.
; 프로그램을 발견할 수 없거나 지정하지 않으면
; (즉, 변수가 할당되지 않았거나 무효한 값이 할당되어 있으면),
; 기본 익스플로러가 사용됩니다.
dirExplorer = E:\utl\xplorer2_lite\xplorer2.exe

; 스캔 대상에 포함될  사용자의 추가 맞춤 디렉토리 목록 
; 전체 경로는 홑따옴표 또는 겹따옴표로 둘러싸면 안 됩니다
; 이 파일이 없으면
; 기본 디렉토리만 스캔합니다.
SeekMyDir = %A_ScriptDir%\Seek.dir

; 캐쉬 디렉토리/프로그램 목록을 저장할
; 파일이름과 디렉토리 위치를 지정합니다
; 원하지 않으면 이를 바꿀 필요가 없습니다.
dirListing = %A_Temp%\_Seek.list

; 마지막 검색의 캐쉬된 키 단어/문구를 저장할
; 파일이름과 디렉토리 위치를 지정합니다
;  원하지 않으면 이를 바꿀 필요가 없습니다.
keyPhrase = %A_Temp%\_Seek.key

; 검색 문자열 추적 (ON/OFF)
; ON이면, 다음에 Seek을 실행할 때 
; 마지막-사용된 질의 문자열을기본으로 재사용합니다.
; OFF이면, 마지막 사용된 질의 문자열을 추적하지 않습니다
; 그리고 다음번 Seek를 실행할 때
; 질의 문자열이 없습니다.
TrackKeyPhrase = ON

; 스캔 대상에 포함될 것들을 지정합니다.
; 0: 디렉토리 배제 (파일만 포함).
; 1: 모든 파일과 디렉토리 포함.
; 2: 오직 디렉토리만 포함 (파일 제외).
ScanMode = 1

;...........................................................

; INIT
;#NoTrayIcon
StringCaseSense, Off
version = Seek v2.0.3

; DISPLAY HELP INSTRUCTIONS
If 1 in --help,-help,/h,-h,/?,-?
{
    MsgBox,, %version%, 시작 메뉴를 항해하는 것은 난삽할 수 있습니다. 특히 시간이 지나면서 많은 프로그램을 설치했다면 더욱 난삽합니다. 'Seek'으로 대소문자를 구분하지 않고 키 단어/문구를 지정하면 시작 메뉴로부터 오직 부합하는 프로그램과 디렉토리만 여과합니다. 그래서 쉽게 목표 프로그램을 몇 개 안 되는 부합 엔트리 중 하나에서 열 수 있습니다. 이렇게 하면 시작 메뉴를 검색하고 순회하는 지겨운 작업을 하지 않아도 됩니다.`n`n;  필자는 재미있게 이 코딩을 즐겼습니다. 모쪼록 여러분도 재미있게 사용하시기를 바랍니다. 주저하지 마시고 이메일을 주십시오. 논평이든 피드백이든 환영합니다: phi1618 (*a.t*) gmail :D0T: com.`n`nOptions:`n  -cache`t가능하면 캐쉬된 디렉토리 리스트를 사용한다 (아무 옵션도 지정하지 않으면 이것이 기본값이다)`n  -scan`t디렉토리를 스캔해 최근의 디렉토리 목록을 열람한다`n  -scex`tScan & 스캔 & 종료 (잠재적으로 시간을 소모하는 디렉토리 스캔 작업을 배경 작업으로 설정할 경우 유용하다)`n  -help`t이 도움말을 보여준다
    Goto QuitNoSave
}

; 필수 환경 변수가 존재하는지 그리고 유효한지 점검합니다
; *TMP*
IfNotExist, %A_Temp% ; 경로가 존재하지 않습니다
{
    MsgBox 이 필수 환경 변수는 정의되지 않았거나 유효하지 않습니다:`n`n    TMP = %A_Temp%`n`n먼저 수정한 후에 Seek을 실행하십시오.
    Goto QuitNoSave
}

; SCAN-AND-EXIT이 아니면
IfNotEqual 1, -scex
{
    ; 마지막으로 사용된 키-문구를 캐쉬 파일로부터 열람해
    ; 기본 질의 문자열로 사용합니다
    If TrackKeyPhrase = ON
    {
        FileReadLine, PrevKeyPhrase, %keyPhrase%, 1
        FileReadLine, PrevOpenTarget, %keyPhrase%, 2
    }
    NewKeyPhrase = %PrevKeyPhrase%
    NewOpenTarget = %PrevOpenTarget%

    ; 사용자가 질의 문자열을 입력할 텍스트 박스를 추가합니다.
    Gui, 1:Add, Edit, vFilename W600, %NewKeyPhrase%

    ; ADD MY FAV TAGLINE
    Gui, 1:Add, Text, X625 Y10, 무엇을 찾고 계십니까, 여러분?

    ; 사용자에게 피드백을 제공하기 위해 상태 바를 추가합니다
    Gui, 1:Add, Text, vStatusBar X10 Y31 R1 W764

    ; 검색 결과를 보여줄 선택 리스트박스를 추가합니다
    Gui, 1:Add, ListBox, vOpenTarget gTargetSelection X10 Y53 R28 W764 HScroll Disabled, %List%

    ; 다음 버튼을 추가하지만, 지금은 불능으로 만들어 둡니다
    Gui, 1:Add, Button, gButtonOPEN vButtonOPEN Default X10 Y446 Disabled, Open
    Gui, 1:Add, Button, gButtonOPENDIR vButtonOPENDIR X59 Y446 Disabled, Open Directory
    Gui, 1:Add, Button, gButtonSCANSTARTMENU vButtonSCANSTARTMENU X340 Y446 Disabled, Scan Start-Menu

    ; 종료 버튼 추가
    Gui, 1:Add, Button, gButtonEXIT X743 Y446, Exit

    ; 질의 창을 팝업 
    Gui, 1:Show, Center, %version%
}

; 마지막 디렉토리 목록을 다시 스캔
If 1 in -scan,-scex
    rescan = Y
; 디렉토리 캐쉬 파일이 이미 존재하는지 점검합니다. 없다면, 다시 스캔합니다.
Else IfNotExist, %dirListing%
    rescan = Y

If rescan = Y ; 다시 스캔합니다
{
    ; 사용자가 SCAN-AND-EXIT 옵션을 지정하지 않는 한, 상태를 보여줍니다.
    IfNotEqual 1, -scex
        GuiControl,, StatusBar, 디렉토리 목록 스캔 중...

    ; 시작 메뉴를 스캔해 디렉토리/프로그램 목록을 캐쉬 파일에 저장합니다
    Gosub ScanStartMenu

    ; 사용자가 SCAN-AND-EXIT 옵션을 지정했다면 종료합니다
    IfEqual 1, -scex, Goto, QuitNoSave
}

GuiControl,, StatusBar, 마지막 질의 결과를 열람 중...

; 마지막으로 사용된 키 문구에 대하여 부합하는 목록을 열람합니다
Gosub SilentFindMatches

; 상태 텍스트를 제거합니다
GuiControl,, StatusBar,

; 디렉토리 목록이 이제 적재되었습니다. 다른 버튼을 활성화합니다.
; 이 버튼들은 앞에서 불능화 시켜 두었습니다. 왜냐하면 이 스크립트에서
; 이 부분에 도착하기 전까지 작동하면 안 되기 때문입니다.
GuiControl, 1:Enable, ButtonOPEN
GuiControl, 1:Enable, ButtonOPENDIR
GuiControl, 1:Enable, ButtonSCANSTARTMENU

; 점진 검색을 켭니다
SetTimer, tIncrementalSearch, 500

; 구이를 갱신합니다
Gosub EnterQuery

Return

;***********************************************************
;                                                          *
;                 END OF MAIN PROGRAM                      *
;                                                          *
;***********************************************************


;=== BEGIN ButtonSCANSTARTMENU EVENT =======================

ButtonSCANSTARTMENU:

Gui, 1:Submit, NoHide
GuiControl,, StatusBar, 디렉토리 목록 스캔 중...

; 스캔 중인 동안 리스트박스를 불능으로 만듭니다
GuiControl, 1:Disable, OpenTarget
GuiControl, 1:Disable, ButtonEXIT
GuiControl, 1:Disable, ButtonOPEN
GuiControl, 1:Disable, ButtonOPENDIR
GuiControl, 1:Disable, ButtonSCANSTARTMENU

; 스캔합니다
Gosub ScanStartMenu

; 사용자에게 스캔이 완료되었다고 알립니다
If Filename =
{
    ; 질의 문자열이 비어 있다면...
    GuiControl, 1:Enable, ButtonEXIT
    GuiControl, 1:Enable, ButtonOPEN
    GuiControl, 1:Enable, ButtonSCANSTARTMENU
    GuiControl,, StatusBar, Scan completed.
    Gosub EnterQuery
}
Else
{
    ; 질의 문자열이 존재하면...
    ; 새 목록을 검색 문자열에 대하여 여과합니다.
    NewKeyPhrase =
    Gosub FindMatches
}
Return

;... END ButtonSCANSTARTMENU EVENT .........................


;=== BEGIN ScanStartMenu SUBROUTINE ========================
; 시작 메뉴를 스캔하고 캐시 파일에
; 디렉토리/프로그램 목록을 저장합니다
ScanStartMenu:

; 열람할 디렉토리 경로를 정의합니다.
; 경로를 홑따옴표 또는 겹따옴표로 둘러싸면 안 됩니다.
;
; 영어 버전의 창에 대하여
scanPath = %A_StartMenu%|%A_StartMenuCommon%

; 사용자가 정의한 추가 경로를 스캔 대상에 포함합니다
IfExist, %SeekMyDir%
{
    Loop, read, %SeekMyDir%
    {
        IfNotExist, %A_LoopReadLine%
            MsgBox, 8192, %version%, 맞춤 디렉토리 리스트를 처리중
			...`n`n"%A_LoopReadLine%"는 존재하지 않으며
			스캔 대상에서 제외됩니다.`n업데이트 하십시오 [ %SeekMyDir% ].
        Else
            scanPath = %scanPath%|%A_LoopReadLine%
    } 
}

; 새 버전을 만들기 전에 기존의 파일을 삭제합니다
FileDelete, %dirListing%

; 디렉토리 목록을 스캔합니다 (구분자 = |)
; 각 디렉토리마다 재귀해 들어가 그 내용을 열람합니다.
; 숨은 파일은 제외됩니다.
Loop, parse, scanPath, |
{
    Loop, %A_LoopField%\*, %ScanMode%, 1
    {
        FileGetAttrib, fileAttrib, %A_LoopFileFullPath%
        IfNotInString, fileAttrib, H ; 숨은 파일을 제외합니다
            FileAppend, %A_LoopFileFullPath%`n, %dirListing%
    }
}

Return

;... END ScanStartMenu SUBROUTINE ..........................


;=== BEGIN FindMatches SUBROUTINE ==========================
; 부합하는 모든 레코르를 검색해 리스트박스에 보여줍니다
FindMatches:

Gui, 1:Submit, NoHide
CurFilename = %Filename%
GuiControl,, StatusBar, 

; 빈 질의 문자열인지 점검합니다
If CurFilename =
{
    MsgBox, 8192, %version%, 검색할 키 단어/문구를 입력하십시오.
    Goto EnterQuery
}

; tIncrementalSearch는 인터럽트된 상태입니다. 종료시켜 버립니다.
If NewKeyPhrase <> %CurFilename%
{
    ; 사용자에게 참고 기다리라고 알립니다
    GuiControl,, StatusBar, 찾는 중...
    ResumeFindMatches = TRUE
    Return
}

If List = |
{
    ; 부합하는 레코드가 하나도 발견되지 않았습니다
    ; 사용자에게 질의 문자열을 변경하고 다시 시도하도록 요구합니다.
    MsgBox, 8192, %version%, 질의 문자열 "%CurFilename%"는 부합하는 레코드가 없습니다. 다시 시도하십시오.
    GuiControl, 1:Disable, ButtonOPENDIR
    GuiControl, 1:Enable, ButtonSCANSTARTMENU
    Goto EnterQuery
}
Else
{
    ; 다른 레코드가 선택되어 있지 않으면 첫 번째 레코드를 선택합니다
    Gui, 1:Submit, NoHide
    GuiControl, 1:Enable, OpenTarget
    GuiControl, 1:Enable, ButtonOPEN
    GuiControl, 1:Enable, ButtonOPENDIR
    GuiControl, 1:Enable, ButtonSCANSTARTMENU
    GuiControl, Focus, OpenTarget
    If OpenTarget =
        GuiControl, 1:Choose, OpenTarget, |1
}

; REFRESH GUI
Gui, 1:Show, Center, %version%

Return

;... END FindMatches SUBROUTINE ............................


;=== BEGIN SilentFindMatches SUBROUTINE ====================

SilentFindMatches:

Gui, 1:Submit, NoHide
sfmFilename = %Filename%

; 사용자의 질의 문자열에 기반하여 부합하는 레코드를 여과합니다
List = |
If sfmFilename <>
{
    Loop, read, %dirListing%
    {
        Gui, 1:Submit, NoHide
        tFilename = %Filename%
        If sfmFilename <> %tFilename%
        {
            ; 사용자가 검색 문자열을 변경했습니다. 
            ; 예전 문자열을 사용하여 검색을 계속할 이유가 없습니다. 그래서 종료합니다.
            Return
        }
        Else
        {
            ; APPEND MATCHING RECORDS INTO THE LIST
            SplitPath, A_LoopReadLine, name, dir, ext, name_no_ext, drive
            MatchFound = Y
            Loop, parse, sfmFilename, %A_Space%
            {
                IfNotInString, name, %A_LoopField%
                {
                    MatchFound = N
                    Break
                }
            }
            IfEqual, MatchFound, Y
            {
                ; 레코드를 리스트에 추가합니다
                List = %List%%A_LoopReadLine%|

                ; 다음이 마지막-실행 프로그램에 부합하면 미리 선택합니다
                If (A_LoopReadLine = PrevOpenTarget && sfmFilename = PrevKeyPhrase)
                    List = %List%|
            }
        }
    }
}

; 검색 결과로 리스트를 갱신합니다
GuiControl, 1:, OpenTarget, %List%

If List = |
{
    ; 부합하는 레코드를 발견하지 못햇습니다
    ; 리스트박스를 불능으로 만듭니다
    GuiControl, 1:Disable, OpenTarget
    GuiControl, 1:Disable, ButtonOPENDIR
}
Else
{
    ; 부합하는 레코드를 발견했습니다
    ; 리스트박스를 활성화 합니다
    GuiControl, 1:Enable, OpenTarget
    GuiControl, 1:Enable, ButtonOPENDIR
}

; 구이를 갱신합니다
Gui, 1:Show, Center, %version%

Return

;... END SilentFindMatches SUBROUTINE ......................


;=== BEGIN EnterQuery SUBROUTINE ===========================
; 구이를 갱신하고 사용자가 검색 문자열을 입력하도록 허용합니다
EnterQuery:
GuiControl, Focus, Filename
GuiControl, 1:Enable, ButtonOPEN
Gui, 1:Show, Center, %version%
Return
;... END EnterQuery SUBROUTINE .............................


;=== BEGIN TargetSelection EVENT ===========================

TargetSelection:
Gui, 1:Submit, NoHide

; 프로그램을 기동하기 위하여 더블 클릭을 탐지합니다
If A_GuiControlEvent = DoubleClick
{
    Gosub ButtonOPEN
}
Else
{
    ; 미래에 사용할 - 임시 구조물
    If A_GuiControlEvent = Normal
    {
        ; 지금 당장은 아무 것도 하지 않습니다
    }
}

Return

;... END TargetSelection EVENT .............................


;=== BEGIN ButtonOPEN EVENT ================================

; 사용자가 'OPEN' 버튼을 클릭하거나 <ENTER>를 눌렀습니다.
ButtonOPEN:
Gui, 1:Submit, NoHide

; 키보드 초점이 있는 곳을 알아냅니다. 초점이 텍스트 필드에
; 있다면, 질의 문자열을 실행해 부합하는 것을 찾습니다.
; 분명히 리스트 박스 안에 있을 것입니다.
GuiControlGet, focusControl, 1:Focus
If focusControl = Edit1
{
    GuiControl, Focus, OpenTarget
    GuiControl, 1:Disable, OpenTarget
    GuiControl, 1:Disable, ButtonOPENDIR
    GuiControl, 1:Disable, ButtonSCANSTARTMENU
    Goto FindMatches
}

; 리스트박스에 아무 레코드도 선택되어 있지 않습니다
If OpenTarget =
{
    MsgBox, 8192, %version%, 선택을 먼저 한 후에 <Enter>를 누르십시오.`n종료하려면 <Esc>를 누르십시오.
    Goto EnterQuery
}

; 선택된 레코드가 존재하지 않습니다 (파일이나 디렉토리를 발견하지 못함)
IfNotExist, %OpenTarget%
{
    MsgBox, 8192, %version%, %OpenTarget%이 존재하지 않습니다. 이것은 그 디렉토리 캐쉬가 유효기간이 지났다는 뜻입니다. 아래의 'Scan Start-Menu' 버튼을 클릭하면 이제 여러분의 최신 디렉토리 목록으로 디렉토리 캐쉬를 업데이트할 수 있습니다.
    Goto EnterQuery
}

; 선택된 레코드가 파일인지 아니면 디렉토리인지 점검합니다
FileGetAttrib, fileAttrib, %OpenTarget%
IfInString, fileAttrib, D ; IS DIRECTORY
{
    Gosub sOpenDir
}
Else If fileAttrib <> ; IS FILE
{
    Run, %OpenTarget%
}
Else
{
    MsgBox %OpenTarget%는 디렉토리도 아니고 파일도 아닙니다. 이런 일은 일어날 수 없습니다. 더 이상 검색을 진행하지 못합니다. 종료 중...
}

Goto Quit

;... END ButtonOPEN EVENT ..................................


;=== BEGIN ButtonOPENDIR EVENT =============================

; 사용자가 'OPEN DIRECTORY' 버튼을 클릭했습니다
ButtonOPENDIR:
Gui, 1:Submit, NoHide

; 사용자가 레코드를 이미 선택했는지 점검합니다
If OpenTarget =
{
    MsgBox, 8192, %version%, 먼저 선택하십시오.
    Goto EnterQuery
}

; 디렉토리를 열기 위해 서브루틴을 실행합니다
Gosub sOpenDir

Goto Quit

;... END ButtonOPENDIR EVENT ...............................


;=== BEGIN sOpenDir SUBROUTINE =============================

sOpenDir:

; 사용자가 디렉토리-레코드 대신에 파일-레코드를 선택했다면,
; 그 디렉토리 경로를 추출합니다. (필자는 FileGetAttrib 대신에
; DriveGet을 사용합니다. OpenTarget은 유효하지 않지만
; OpenTarget의 디렉토리 경로는 유요한 경우에 대처할 수 있기 때문입니다.
DriveGet, status, status, %OpenTarget%
If status <> Ready ; 디렉토리가 아님
{
    SplitPath, OpenTarget, name, dir, ext, name_no_ext, drive
    OpenTarget = %dir%
}

; 디렉토리가 존재하는지 점검합니다
IfNotExist, %OpenTarget%
{
    MsgBox, 8192, %version%, %OpenTarget%이 존재하지 않습니다. 이것은 디렉토리 캐쉬가 유효 기간이 지났다는 뜻입니다. 'Scan Start-Menu' 버튼을 아래에서 클릭하면 이제 최신 디렉토리 리스트로 디렉토리 캐쉬를 업데이트할 수 있습니다.
    Goto EnterQuery
}

; 디렉토리를 엽니다
IfExist, %dirExplorer%
{
    Run, "%dirExplorer%" "%OpenTarget%", , Max ; OPEN WITH CUSTOMISED FILE EXPLORER
}
Else
{
    Run, %OpenTarget%, , Max ; 기본 창 파일 탐색기를 엽니다
}
Return

;... END sOpenDir SUBROUTINE ...............................


;=== BEGIN tIncrementalSearch EVENT ========================
; 자동으로 실시간 점진 검색을 수행하여
; 부합하는 레코드를 찾습니다.
; 사용자가 <ENTER>를 누르기를 기다리지 않습니다.
tIncrementalSearch:

Loop
; 사용자가 질의 문자열 바꾸기를 멈출 때까지 검색을 반복합니다.
{
    Gui, 1:Submit, NoHide
    CurFilename = %Filename%
    If NewKeyPhrase <> %CurFilename%
    {
        OpenTarget =
        Gosub SilentFindMatches
        NewKeyPhrase = %CurFilename%
        Sleep, 100 ; CPU 독점 금지!
    }
    Else
    {
        ; 질의 문자열이 더 이상 변하지 않습니다
        Break
    }
}

; 사용자가 <ENTER>를 눌러서 부합하는 레코드를 찾습니다.
; RUN FindMatches NOW.
If ResumeFindMatches = TRUE
{
    ResumeFindMatches = FALSE
    Gosub FindMatches
}

; 계속 변화를 관제합니다
SetTimer, tIncrementalSearch, 500

Return

;... END tIncrementalSearch EVENT ..........................


;=== BEGIN Quit SUBROUTINE =================================

Quit:
ButtonEXIT:
GuiClose:
GuiEscape:

Gui, 1:Submit, NoHide

; 만약 변경되었다면 그 키 단어/문구를 다음 실행을 대비해 저장합니다.
If TrackKeyPhrase = ON
{
    If (PrevKeyPhrase <> Filename || PrevOpenTarget <> OpenTarget)
    {
        FileDelete, %keyPhrase%
        FileAppend, %Filename%`n, %keyPhrase%
        FileAppend, %OpenTarget%`n, %keyPhrase%
    }
}

QuitNoSave:
ExitApp ; 이상 끝. 즐거운 하루 되시기를!

;... END Quit SUBROUTINE ...................................


;************************
;<--- END OF PROGRAM --->
;************************

; /* vim: set noexpandtab shiftwidth=4: */
선택 | 내려받기