UWSCでCUI(コンソールウインドウ)を扱う(その3)
UWSCでCUI(コンソールウインドウ)を扱う(その2) - じゅんじゅんのきまぐれ
この、その2から、クリップボード依存を排除しました!
までも、お勧めなのは、stuncloudさんのモジュールですが。
UWSCのコマンドラインインタプリタ | たっぷす庵
優位なのは、補完ができること。もっさりしてるけど。
スクリプト
Asmモジュールに依存しています。
http://d.hatena.ne.jp/junjun777/20120616/uwsc_function_pointer
CUI.uws
OPTION EXPLICIT CALL Asm IFB GET_UWSC_NAME = "CUI.uws" THEN STOPFORM(FALSE) CUI.Create() THREAD CuiCompSample() DIM loop = TRUE, cmd WHILE loop CUI.Output("> ", FALSE) cmd = CUI.Input() loop = (cmd <> "exit") AND (cmd <> "quit") WEND CUI.Destroy() STOPFORM(TRUE) ENDIF PROCEDURE CuiCompSample() DIM buf, id = CUI.ID() WHILE TRUE IFB GETKEYSTATE(VK_TAB) AND GETID(GET_ACTIVE_WIN) = id THEN buf = CUI.GetBuffer(2) // 「> 」分飛ばす IFB buf = COPY("exit", 1, LENGTH(buf)) THEN CUI.PushSckey(COPY("eXit", LENGTH(buf) + 1), 1) ELSE CUI.PushSckey("", 1) ENDIF ELSE SLEEP(0.01) ENDIF WEND FEND module CUI public hThInput = NULL dim hInput, hOutput, hError dim orgTextAttr = 0 dim FOREGROUND_ORIGINAL, BACKGROUND_ORIGINAL dim id = -1, _addr = 0, _para = 0 hashtbl _keyConv function Create(title = GET_UWSC_NAME, BufferSize = 1024) result = AllocConsole() if result then SetConsoleTitleA(title) hInput = GetStdHandle(STD_INPUT_HANDLE) hOutput = GetStdHandle(STD_OUTPUT_HANDLE) hError = GetStdHandle(STD_ERROR_HANDLE) orgTextAttr = getOriginalTextAttribute() BACKGROUND_ORIGINAL = orgTextAttr and $F0 FOREGROUND_ORIGINAL = orgTextAttr and $F id = getid(title, "ConsoleWindowClass") _addr = Asm.Set("VYvsUYtFCIlF/GoAi038g8EMUYtV/ItCCFCLTfyLUQRSi0X8iwhRi1X8i0IQ/9CL5V3CBADM") DIM paraSize = 20, i = 0 _para = Asm.Alloc(paraSize) IFB _addr > 0 AND _para > 0 THEN i = i + Asm.SetDword(_para + i, hInput) i = i + Asm.SetDword(_para + i, Asm.Alloc(BufferSize)) i = i + Asm.SetDword(_para + i, BufferSize) i = i + Asm.SetDword(_para + i, 0) i = i + Asm.SetDword(_para + i, Asm.GetProcAddress(Asm.hK32, "ReadConsoleA")) ENDIF _keyConv = HASH_REMOVEALL _keyConv[" "] = " VK_SPACE" _keyConv["<#TAB>"] = " VK_TAB" _keyConv["-"] = " 189" _keyConv["^"] = " 222" _keyConv["\"] = " 220" _keyConv["@"] = " 192" _keyConv["["] = " 219" _keyConv[";"] = " 187" _keyConv[":"] = " 186" _keyConv["]"] = " 221" _keyConv[","] = " 188" _keyConv["."] = " 190" _keyConv["/"] = " 191" _keyConv["\"] = " 226" _keyConv["="] = "+189" _keyConv["~"] = "+222" _keyConv["|"] = "+220" _keyConv["`"] = "+192" _keyConv["{"] = "+219" _keyConv["+"] = "+187" _keyConv["*"] = "+186" _keyConv["}"] = "+221" _keyConv["<"] = "+188" _keyConv[">"] = "+190" _keyConv["?"] = "+191" _keyConv["_"] = "+226" _keyConv["!"] = "+VK_1" _keyConv["<#DBL>"] = "+VK_2" _keyConv["#"] = "+VK_3" _keyConv["$"] = "+VK_4" _keyConv["%"] = "+VK_5" _keyConv["&"] = "+VK_6" _keyConv["'"] = "+VK_7" _keyConv["("] = "+VK_8" _keyConv[")"] = "+VK_9" fend function ID() result = id fend function GetColor(fgcolor = "", bgcolor = "") DIM f = _color(fgcolor) if f < 0 then f = FOREGROUND_ORIGINAL DIM b = _color(bgcolor) if b < 0 then b = BACKGROUND_ORIGINAL else b = b * $10 result = f or b fend function _color(color = "", def = -1) select color case "blue", "b" result = FOREGROUND_BLUE or FOREGROUND_INTENSITY case "green", "g" result = FOREGROUND_GREEN or FOREGROUND_INTENSITY case "red", "r" result = FOREGROUND_RED or FOREGROUND_INTENSITY case "yellow", "y" result = FOREGROUND_GREEN or FOREGROUND_RED or FOREGROUND_INTENSITY case "yellow-", "y-" result = FOREGROUND_GREEN or FOREGROUND_RED case "pink", "p" result = FOREGROUND_BLUE or FOREGROUND_RED or FOREGROUND_INTENSITY case "lightblue", "lb" result = FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_INTENSITY case "white", "w" result = FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_RED or FOREGROUND_INTENSITY case "black", "bl", "bk" result = 0 case "gray", "gy" result = FOREGROUND_INTENSITY default result = def selend fend function Destroy() IFB _para THEN Asm.Free(Asm.GetDword(_para + 4)) Asm.Free(_para) ENDIF IF _addr THEN Asm.Free(_addr) result = FreeConsole() fend procedure Clear(row = -1, col = -1, len = -1) DIM cbi = getConsoleScreenBufferInfoArray() if row = -1 then row = cbi[3] if col = -1 then col = cbi[2] if len = -1 then len = cbi[0] - col SetConsoleCursorPosition(hOutput, col + row * $10000) Output(FORMAT(" ", len), FALSE) SetConsoleCursorPosition(hOutput, cbi[2] + cbi[3] * $10000) fend function Output(Text = "", Cr = TRUE, color = -1, hOut = -1) if hOut = -1 THEN hOut = hOutput if Cr then Text = Text + "<#CR>" color = _color(color, color) if length(Text) then dim size if color > -1 then SetConsoleTextAttribute(hOutput, color) result = WriteConsoleA(hOutput, Text, lengthb(Text), size, 0) if color > -1 then SetConsoleTextAttribute(hOutput, orgTextAttr) endif fend function Input() DIM i = 1, timeout = $7fffffff IF _addr AND _para THEN hThInput = Asm.Run(_addr, _para, i, 0) WHILE i = 258 AND timeout > 0 i = Asm.WaitForSingleObject(hThInput, 100) timeout = timeout - 100 WEND Asm.CloseHandle(hThInput) hThInput = NULL ifb i = 0 then i = Asm.GetDword(_para + 12) result = FORMAT(CHR(0), i) RtlMoveMemory(result, Asm.GetDword(_para + 4), i) result = replace(result, "<#cr>", "") endif fend function GetBuffer(col = 0, row = -1) dim cbi = getConsoleScreenBufferInfoArray(), l = 1 if row = -1 then row = cbi[3] if row < 0 then row = 0 l = cbi[1] endif dim buf = format(chr(0), cbi[0] * l - col), num = 0 result = empty if ReadConsoleOutputCharacterW(hOutput, buf, cbi[0] * l - col, col + row * $10000, num) then result = trim(buf) fend function PushSckey(cmd, backNum=0, ignoreCase=FALSE) result = "" dim i, n, nn, b = GetKeyState(TGL_CAPSLOCK), nb = false for i = 1 to backNum result = result + ",VK_BACK" next for i = 1 to length(cmd) n = copy(cmd, i, 1) if _keyConv[n, HASH_EXISTS] then n = _keyConv[n] nn = (copy(n, 1, 1) = "+") if nn xor nb then nb = !nn else nn = nb endif n = copy(n, 2) else nn = asc(n) nn = ((nn >= 65 and nn <= 90) xor b) and !ignoreCase endif if nn xor nb then if length(result) then eval("sckey(id" + result + ")") result = "" if nn then result = ",vk_shift" nb = nn endif result = result + "," + n next if length(result) then eval("sckey(id" + result + ")") fend function Error(Text, Cr = TRUE, color = -2) if color = -2 then color = GetColor("r") result = Output(Text, Cr, color, hError) fend function getConsoleScreenBufferInfoArray() result = safearray(0, 10) GetConsoleScreenBufferInfo(hOutput, result) fend function getOriginalTextAttribute() DIM CONSOLE_SCREEN_BUFFER_INFO = getConsoleScreenBufferInfoArray() result = CONSOLE_SCREEN_BUFFER_INFO[4] fend function GetConsoleWidth() DIM CONSOLE_SCREEN_BUFFER_INFO = getConsoleScreenBufferInfoArray() result = CONSOLE_SCREEN_BUFFER_INFO[0] fend def_dll AllocConsole():bool:kernel32 def_dll FreeConsole():bool:kernel32 def_dll GetStdHandle(dword):dword:kernel32 def_dll ReadConsoleA(dword, var string, dword, var dword, dword):bool:kernel32 def_dll WriteConsoleA(dword, string, dword, var dword, dword):bool:kernel32 def_dll SetConsoleTitleA(string):bool:kernel32 def_dll SetConsoleTextAttribute(dword, int):bool:kernel32 def_dll GetConsoleScreenBufferInfo(hwnd, word[]):bool:kernel32 def_dll SetConsoleCursorPosition(dword, dword): bool: kernel32 def_dll RtlMoveMemory(var string, dword, dword): kernel32 def_dll ReadConsoleOutputCharacterW(dword, var wstring, dword, dword, var dword): bool: kernel32 const STD_INPUT_HANDLE = -10 //標準入力ハンドルを取得 const STD_OUTPUT_HANDLE = -11 //標準出力ハンドルを取得 const STD_ERROR_HANDLE = -12 //標準エラーハンドルを取得 const FOREGROUND_BLUE = $1 //文字色に青を加える const FOREGROUND_GREEN = $2 //文字色に緑を加える const FOREGROUND_RED = $4 //文字色に赤を加える const FOREGROUND_INTENSITY = $8 //文字色を高輝度にする const BACKGROUND_BLUE = $10 //背景色に青を加える const BACKGROUND_GREEN = $20 //背景色に緑を加える const BACKGROUND_RED = $40 //背景色に赤を加える const BACKGROUND_INTENSITY = $80 //背景色を高輝度にする endmodule
修正ポイント
取得側は、ReadConsoleOutputCharacter Win32APIで可能なことがわかったので、これで取得することにしました。
設定側は、UWSCのSCKEYを使いました。
記号は小細工して送れるようにしていますが、日本語は送れません。
UWSC4.9a以降なら、KBDが使えるかな、、、?
いずれにしても、少々もっさりしてしまうのは否めない、、、。
AttachConsole Win32APIを使えば、http://d.hatena.ne.jp/junjun777/20110529/uwsc_cmdもクリップボード非依存にできますね。
ついでにインタープリターも更新しました。
上のCUIモジュールに依存しています。
OPTION EXPLICIT CALL cui STOPFORM(FALSE) Interpreter.Run() STOPFORM(TRUE) module Interpreter // 予約済み変数 hashtbl hash, hash2 hashtbl __threads CONST VAR_HASH = VAR_ARRAY * 2 // 勝手定義 CONST SEC_SETTINGS = "settings" procedure Run() thread Proc() sleep(0.1) while length(__threads) sleep(0.01) wend fend procedure Proc(__cmd=EMPTY) hashtbl __cmdN dim __ret="", __i, __id, __cmds, __exit=false, __if=0, __while=0, __cui=(__cmd=EMPTY) dim __display=TRUE, __key, __val, __mode, __offset, __c, __ck, __cp dim __r1=NULL, __r2=NULL, __r3=NULL, __threadId=GetCurrentThreadId() __threads[__threadId] = __cmd if __cui then CUI.Create() THREAD Complete() __cmd = trim(readini(SEC_SETTINGS, "startup")) endif if length(__cmd) = 0 then __cmd = "" while __cmd <> EMPTY __cmds = split(__cmd, " ", TRUE) if length(__cmds) = 0 then __cmds = safearray(0, 0) select __cmds[0] case "exit", "quit" __cmd = EMPTY __exit = length(__cmds) > 1 or !__cui if !__exit then CUI.Output("終了しますか? (y/n): ", FALSE) __exit = (copy(trim(CUI.Input()), 1, 1) = "y") endif if __exit and __cui then __cmd = trim(readini(SEC_SETTINGS, "exit")) if length(__cmd) then continue case "window" __cmd = EMPTY if length(__cmds) > 1 then __ret = val(__cmds[1], 1) else __ret = FALSE endif CUI.Output("ID Title / Class", TRUE) CUI.Output(format("-", CUI.GetConsoleWidth() - 1), TRUE) for __i = 0 to getallwin() - 1 __id = ALL_WIN_ID[__i] if !__ret and ! status(__id, ST_VISIBLE) then continue CUI.Output(format(__id, 4), FALSE) CUI.Output(format(" ", 2) + status(__id, ST_TITLE), TRUE) CUI.Output(format(" ", 6) + status(__id, ST_CLASS), TRUE) next case "enum" if length(__cmds) > 1 then __cmdN[length(__cmdN)] = __cmd try if __mode = 0 then __display = false try __id = eval("VarTypeEx(" + __cmds[1] + ")") except __id = eval("vartype(" + __cmds[1] + ")") endtry __mode = eval("length(" + __cmds[1] + ")") __i = 0 if __id <> VAR_HASH AND __id >= VAR_ARRAY then try __offset = eval(__cmds[1]) __offset = resize(__offset) - __mode + 1 except __offset = eval("resize(" + __cmds[1] + ")") - __mode + 1 endtry endif else if VarTypeEx(__val) >= VAR_ARRAY then CUI.Output(__cmds[1] + "[" + __key + "] = var_array:" + length(__val) + " " + __ret) else CUI.Output(__cmds[1] + "[" + __key + "] = " + __val + " " + __ret) endif endif if __i < __mode and __id >= VAR_ARRAY then if __id = VAR_HASH then __key = eval(__cmds[1] + "[" + __i + ",HASH_KEY]") __val = eval(__cmds[1] + "[" + __i + ",HASH_VAL]") else __key = __i + __offset __val = eval(__cmds[1] + "[" + __key + "]") endif if length(__cmds) > 2 then __cmd = trim(join(slice(__cmds, 2))) else __cmd = "" __ret = "" __i = __i + 1 else __mode = 0 endif except CUI.Error(" " + TRY_ERRMSG) __mode = 0 endtry if __mode = 0 then __display = true __cmd = EMPTY if length(__cmdN) then __i = __cmdN[length(__cmdN) - 1, HASH_REMOVE] endif endif case "thread" if length(__cmds) > 1 then thread Proc(trim(copy(__cmd, 7))) __cmd = EMPTY case "help", "?" __cmd = EMPTY if length(__cmds) > 1 then doscmd(GET_UWSC_DIR + "\uwsc.chm", TRUE) else Help() endif default if pos("#", __cmds[0]) = 1 then __ck = trim(readini(SEC_SETTINGS, __cmds[0])) if length(__ck) then __cmd = __ck continue endif endif selend if length(__cmd) then __c = Conv(__r1, __r2, __r3, __cmd, __ck, __cp) try if __ck = "if" and length(__cp) > 0 then if length(__cp[0]) then __if = __if + 1 if length(__cmd) then __cmdN[length(__cmdN)] = __cmd if length(__cp) < 3 then resize(__cp, 2) __cmdN[length(__cmdN)] = __cp[2] __cmdN[length(__cmdN)] = __cp[1] __cmd = __cp[0] elseif length(__cp) > 2 then for __ck = length(__cp) - 1 to 2 step - 1 __cmdN[length(__cmdN)] = __cp[__ck] next __cmd = __cp[1] endif __ret = "" elseif __ck = "while" and length(__cp) > 0 then __while = (__while * 4) or 1 if length(__cmd) then __cmdN[length(__cmdN)] = __cmd if length(__cp) < 2 then resize(__cp, 1) __cmdN[length(__cmdN)] = __cp[0] __cmdN[length(__cmdN)] = __cp[1] __cmd = __cp[0] __ret = "" else if length(__c) then __ret = eval(__c) else __ret = "" if __while and 2 then if length(__cmd) = 0 then __while = (__while - 2) or 1 elseif __while and 1 then if length(__cmd) = 0 then try __ret = vartype(__ret, var_boolean) except __ret = false endtry __while = __while - 1 if __ret then __while = __while or 2 __cmd = __cmdN[length(__cmdN) - 1] __cmdN[length(__cmdN)] = __cmdN[length(__cmdN) - 2] else __ck = __cmdN[length(__cmdN) - 1, hash_remove] __ck = __cmdN[length(__cmdN) - 1, hash_remove] __while = int(__while / 4) endif __ret = "" endif elseif __if > 0 and length(__cmd) = 0 then __if = __if - 1 try __ret = vartype(__ret, var_boolean) except __ret = false endtry if __ret then __cmd = __cmdN[length(__cmdN)-1] else __cmd = __cmdN[length(__cmdN)-2] endif __ret = __cmdN[length(__cmdN)-1, hash_remove] __ret = __cmdN[length(__cmdN)-1, hash_remove] __ret = "" endif endif if __display then select __ret case EMPTY CUI.Output(" EMPTY", TRUE, "lb") case NULL CUI.Output(" NULL", TRUE, "lb") case NOTHING CUI.Output(" NOTHING", TRUE, "lb") case "" // do nothing default CUI.Output( " " + __ret, TRUE, "w") selend endif except CUI.Error(" " + TRY_ERRMSG) endtry endif if length(__cmd) = 0 and length(__cmdN) > 0 then __cmd = __cmdN[length(__cmdN) - 1] __ck = __cmdN[length(__cmdN) - 1, hash_remove] endif if length(__cmd) = 0 then if __exit then __cmd = EMPTY elseif __cui then ctrlwin(CUI.ID(), ACTIVATE) CUI.Output("> ", FALSE) __cmd = trim(CUI.Input()) endif endif wend if __cui then CUI.Destroy() __threadId = __threads[__threadId, HASH_REMOVE] fend def_dll GetCurrentThreadId(): dword: kernel32 function Conv(var __r1, var __r2, var __r3, var cmd, var kind, var p) ifb __r1 = NULL then __r1 = CreateOleObj("VBScript.RegExp") __r1.Pattern = "^((?:[^=()<#DBL>]|<#DBL>[^<#DBL>]*<#DBL>|\([^)]*\))+)=(?!=)" endif ifb __r2 = NULL then __r2 = CreateOleObj("VBScript.RegExp") __r2.Pattern = "^((?:[^=()<#DBL>]|<#DBL>[^<#DBL>]*<#DBL>|\([^)]*\))+)=(?==)" endif ifb __r3 = NULL then __r3 = CreateOleObj("VBScript.RegExp") __r3.Pattern = "((?:[^,();<#DBL>]|<#DBL>[^<#DBL>]*<#DBL>)*)([,();])?" __r3.Global = TRUE endif // 関数解析 dim ms = __r3.Execute(cmd), i, step=0, s=0, wk="", res=EMPTY kind = EMPTY result = EMPTY p = safearray(0, -1) ifb ms.Count > 0 then kind = ms.Item(0).SubMatches(0) for i = 0 to ms.Count - 1 res = res + ms.Item(i).Value if s = 0 then if ms.Item(i).SubMatches(1) = ";" and result = EMPTY then result = copy(res, 1, length(res) - 1) res = "" endif elseif s = 1 and result = EMPTY then wk = wk + ms.Item(i).Value if ms.Item(i).SubMatches(1) = "," or ms.Item(i).SubMatches(1) = ")" then if length(p) <= step then resize(p, step) p[step] = trim(copy(wk, 1, length(wk) - 1)) wk = "" step = step + 1 endif else wk = wk + ms.Item(i).Value endif if ms.Item(i).SubMatches(1) = "(" then s = s + 1 if ms.Item(i).SubMatches(1) = ")" and s > 0 then s = s - 1 next endif if result = EMPTY then if res = EMPTY then res = cmd result = res cmd = EMPTY else cmd = trim(res) if length(cmd) = 0 then cmd = EMPTY endif // =を:=に result = __r1.Replace(trim(result), "$1:=") // ==を=に result = __r2.Replace(result, "$1") fend FUNCTION VarTypeEx(val[]) TRY RESULT = VarType(val) EXCEPT IFB POS("が定義されていません", TRY_ERRMSG) THEN RESULT = VAR_HASH ELSE RESULT = VAR_VARIANT + VAR_ARRAY ENDIF ENDTRY FEND CONST SEC_TYPE = "types" CONST SEC_VAL = "vals" FUNCTION GetName(name, i) RESULT = name + "[" IF CHKNUM(i) THEN RESULT = RESULT + i + "]" ELSE RESULT = RESULT + "<#DBL>" + i + "<#DBL>]" FEND PROCEDURE SaveP(name, data) DIM type=VARTYPE(data), i, l, u // safearrayはこっちで処理 IFB type >= VAR_ARRAY THEN WRITEINI(SEC_TYPE, name, type) u = RESIZE(data) l = u - LENGTH(data) + 1 WRITEINI(SEC_VAL, name, l + "," + u) FOR i = l TO u type = VARTYPE(data[i]) IFB type >= VAR_ARRAY THEN SaveP(GetName(name, i), data[i]) ELSE WRITEINI(SEC_TYPE, GetName(name, i), type) WRITEINI(SEC_VAL, GetName(name, i), data[i]) ENDIF NEXT ELSE WRITEINI(SEC_TYPE, name, type) WRITEINI(SEC_VAL, name, data) ENDIF FEND PROCEDURE Save(name, data[]) DIM type, i TRY type = VarTypeEx(data) EXCEPT type = VARTYPE(data) ENDTRY // 通常配列がある場合は、それもここで処理 IFB type = VAR_HASH THEN WRITEINI(SEC_TYPE, name, type) WRITEINI(SEC_VAL, name, LENGTH(data)) FOR i = 0 TO LENGTH(data) - 1 type = VARTYPE(data[i, HASH_VAL]) IFB type >= VAR_ARRAY THEN SaveP(GetName(name, data[i, HASH_KEY]), data[i, HASH_VAL]) ELSE WRITEINI(SEC_TYPE, GetName(name, data[i, HASH_KEY]), type) WRITEINI(SEC_VAL, GetName(name, data[i, HASH_KEY]), data[i, HASH_VAL]) ENDIF NEXT ELSE SaveP(name, data) ENDIF FEND DEF_DLL GetPrivateProfileStringA(string,string,string,DWORD,DWORD,string): DWORD: kernel32 DEF_DLL RtlMoveMemory(var string,DWORD,DWORD): kernel32 DEF_DLL lstrlenA(DWORD): int: kernel32 FUNCTION ReadSections(sec, ini=EMPTY) DIM size=2048, ptr = 0, i = size, len, val IF LENGTH(ini) = 0 THEN ini = ".\" + REPLACE(GET_UWSC_NAME, ".uws", ".ini") WHILE i >= size - 2 IF ptr THEN Asm.Free(ptr) size = size * 2 ptr = Asm.Alloc(size) IF ptr THEN i = GetPrivateProfileStringA(sec, NULL, NULL, ptr, size, ini) WEND HASHTBL buf IFB ptr THEN i = ptr len = lstrlenA(i) WHILE len > 0 val = FORMAT(CHR(0), len) RtlMoveMemory(val, i, len) buf[LENGTH(buf)] = val i = i + len + 1 len = lstrlenA(i) WEND Asm.Free(ptr) ENDIF len = LENGTH(buf) - 1 RESULT = SAFEARRAY(0, len) FOR i = 0 TO len RESULT[i] = buf[i] NEXT FEND FUNCTION Load(name) RESULT = NULL DIM type = READINI(SEC_TYPE, name), val = READINI(SEC_VAL, name), i, secs TRY IFB type >= VAR_ARRAY THEN IFB type = VAR_HASH THEN EVAL(name + ":=HASH_REMOVEALL") secs = ReadSections(SEC_TYPE) FOR i = 0 TO LENGTH(secs) - 1 IFB POS(name + "[", secs[i]) = 1 AND POS("[", COPY(secs[i], LENGTH(name) + 2)) = 0 THEN type = READINI(SEC_TYPE, secs[i]) IFB type >= VAR_ARRAY THEN val = Load(secs[i]) EVAL(secs[i] + ":=val") ELSE EVAL(secs[i] + ":=VARTYPE(<#DBL>" + READINI(SEC_VAL, secs[i]) + "<#DBL>," + type + ")") ENDIF ENDIF NEXT RESULT = VAR_HASH ELSE secs = VAL(COPY(val, 1, POS(",", val) - 1)) val = VAL(COPY(val, POS(",", val) + 1)) RESULT = SAFEARRAY(secs, val) FOR i = secs TO val type = READINI(SEC_TYPE, GetName(name, i)) IFB type >= VAR_ARRAY THEN RESULT[i] = Load(GetName(name, i)) ELSE RESULT[i] = VARTYPE(READINI(SEC_VAL, GetName(name, i)), type) ENDIF NEXT ENDIF ELSE RESULT = VARTYPE(val, type) ENDIF EXCEPT // nop ENDTRY FEND PROCEDURE Delete(name) DIM type = READINI(SEC_TYPE, name), val = READINI(SEC_VAL, name), i, secs IFB type >= VAR_ARRAY THEN IFB type = VAR_HASH THEN secs = ReadSections(SEC_TYPE) FOR i = 0 TO LENGTH(secs) - 1 IFB POS(name + "[", secs[i]) = 1 THEN DELETEINI(SEC_TYPE, secs[i]) DELETEINI(SEC_VAL, secs[i]) ENDIF NEXT ELSE secs = VAL(COPY(val, 1, POS(",", val) - 1)) val = VAL(COPY(val, POS(",", val) + 1)) FOR i = secs TO val type = READINI(SEC_TYPE, GetName(name, i)) IFB type >= VAR_ARRAY THEN Delete(GetName(name, i)) ELSE DELETEINI(SEC_TYPE, GetName(name, i)) DELETEINI(SEC_VAL, GetName(name, i)) ENDIF NEXT ENDIF ENDIF DELETEINI(SEC_TYPE, name) DELETEINI(SEC_VAL, name) FEND PROCEDURE Complete() DIM __r = CREATEOLEOBJ("VBScript.RegExp"), id = CUI.ID(), buf, ret, n, k __r.Pattern = "[^ !<#DBL>$%&'()\-=^\\|@`[\]{}+*;:<>,./?]+.?$" WHILE TRUE IFB GETKEYSTATE(VK_TAB) AND GETID(GET_ACTIVE_WIN) = id THEN buf = CUI.GetBuffer() ret = __r.Execute(CUI.GetBuffer()) IF ret.Count > 0 THEN buf = ret.Item(0).Value IFB buf <> TRIM(_comp_code) THEN _comp_base = buf _comp_sels = HASH_REMOVEALL FOR k = 0 TO LENGTH(_comps) - 1 FOR n = 0 TO LENGTH(_comps[k]) - 1 IF POS(buf, _comps[k][n]) = 1 THEN _comp_sels[n] = _comps[k][n] NEXT NEXT _comp_n = 0 ELSE buf = _comp_code ENDIF IF LENGTH(_comp_sels) THEN _comp_code = _comp_sels[_comp_n, HASH_VAL] ELSE _comp_code = buf _comp_n = _comp_n + 1 IF LENGTH(_comp_sels) <= _comp_n THEN _comp_n = 0 CUI.PushSckey(COPY(_comp_code, LENGTH(_comp_base) + 1), LENGTH(buf) - LENGTH(_comp_base) + 1, true) ENDIF SLEEP(0.1) GETKEYSTATE(VK_TAB) WEND FEND HASHTBL _comp_sels DIM _comp_base = EMPTY, _comp_code = EMPTY, _comp_n = 0 DIM _comps[] = SPLIT("help window enum Load( Save( Delete( DIM PUBLIC CONST IF( THEN ELSE IFB ELSEIF ENDIF SELECT CASE DEFAULT SELEND FOR NEXT TO STEP WHILE( WEND REPEAT UNTIL CALL BREAK CONTINUE EXIT PRINT AND OR XOR MOD PROCEDURE FUNCTION FEND RESULT VAR DEF_DLL OPTION THREAD CLASS ENDCLASS THIS. GLOBAL WITH ENDWITH TEXTBLOCK ENDTEXTBLOCK HASHTBL TRY ENDTRY EXCEPT FINALLY GETID( CLKITEM( CHKBTN( CTRLWIN( SENDSTR( GETSTR( GETITEM( GETSLCTLST( SETSLIDER( GETSLIDER( SCKEY( GETALLWIN( STATUS( MOUSEORG( PEEKCOLOR( CHKIMG( SAVEIMG( MUSCUR( POSACC( INPUT( MSGBOX( SLCTBOX( POPUPMENU( BALLOON( FUKIDASI( STOPFORM( LOGPRINT( MONITOR( EXEC( SLEEP( DOSCMD( POWERSHELL( SOUND( GETTIME( POFF( KINDOFOS( CPUUSERATE( GETKEYSTATE( SETHOTKEY( LOCKHARD( EVAL( GETCTLHND( IDTOHND( HNDTOID( VARTYPE( MMV( BTN( KBD( ACW( COPY( POS( LENGTH( CHKNUM( VAL( REPLACE( TRIM( FORMAT( CHR( ASC( ISUNICODE( STRCONV( TOKEN( BETWEENSTR( COPYB( LENGTHB( POSB( CHRB( ASCB( RESIZE( SETCLEAR( SHIFTARRAY( CALCARRAY( SPLIT( JOIN( SLICE( QSORT( FOPEN( FGET( FPUT( FDELLINE( FCLOSE( GETDIR( DROPFILE( READINI( WRITEINI( DELETEINI( CREATEOLEOBJ( GETACTIVEOLEOBJ( GETOLEITEM( OLEEVENT( COM_ERR_IGN COM_ERR_RET SAFEARRAY( SPEAK( RECOSTATE( DICTATE( IEGETDATA( IESETDATA( IEGETSRC( IESETSRC( IELINK( ENCODE( DECODE( CREATEFORM( GETFORMDATA( SETFORMDATA( XLOPEN( XLCLOSE( XLACTIVATE( XLSHEET( XLGETDATA( XLSETDATA( RANDOM( ABS( ZCUT( INT( CEIL( ROUND( SQRT( POWER( EXP( LN( LOGN( SIN( COS( TAN( ARCSIN( ARCCOS( ARCTAN( PARAM_STR[ ALL_WIN_ID[ ALL_ITEM_LIST[ GETDIR_FILES[ ALL_OLE_ITEM[ EVENT_PRM[ GET_WIN_DIR GET_SYS_DIR GET_CUR_DIR GET_APPDATA_DIR GET_UWSC_DIR GET_UWSC_VER GET_UWSC_NAME COM_ERR_FLG G_IMG_X G_IMG_Y G_SCREEN_W G_SCREEN_H G_SCREEN_C G_MOUSE_X G_MOUSE_Y TRY_ERRMSG TRY_ERRLINE HOTKEY_VK HOTKEY_MOD G_TIME_YY G_TIME_MM G_TIME_DD G_TIME_HH G_TIME_NN G_TIME_SS G_TIME_ZZ G_TIME_WW G_TIME_YY2 G_TIME_MM2 G_TIME_DD2 G_TIME_HH2 G_TIME_NN2 G_TIME_SS2 G_TIME_ZZ2 G_TIME_YY4 TRUE FALSE NULL EMPTY NOTHING ERR_VALUE GET_SLIDER GET_MENU_HND GET_SYSMENU_HND ACTIVATE CLOSE CLOSE2 HIDE SHOW MIN MAX NORMAL TOPMOST NOTOPMOST TOPNOACTV CLICK DOWN UP LEFT RIGHT MIDDLE WHEEL F_READ F_WRITE F_EXISTS F_EXCLUSIVE F_TAB F_NOCR F_WRITE8 F_WRITE8B F_WRITE16 F_WRITE1 F_LINECOUNT F_ALLTEXT F_INSERT CLK_BTN CLK_LIST CLK_TAB CLK_MENU CLK_TREEVIEW CLK_LISTVIEW CLK_TOOLBAR CLK_ACC CLK_SHORT CLK_BACK CLK_MOUSEMOVE CLK_RIGHTCLK CLK_LEFTCLK CLK_DBLCLK<e3><80><80>CLK_FROMLAST CLK_CONTINUE STR_EDIT STR_STATIC STR_STATUS STR_ACC_EDIT STR_ACC_STATIC BTN_YES BTN_NO BTN_OK BTN_CANCEL BTN_ABORT BTN_RETRY BTN_IGNORE SLCT_BTN SLCT_CHK SLCT_RDO SLCT_CMB SLCT_LST SLCT_STR SLCT_NUM SLCT_1~31 ITM_BTN ITM_LIST ITM_TAB ITM_MENU ITM_TREEVIEW ITM_LISTVIEW ITM_EDIT ITM_STATIC ITM_STATUSBAR ITM_TOOLBAR ITM_ACCCLK ITM_ACCCLK2 ITM_ACCTXT ITM_BACK ST_TITLE ST_CLASS ST_X ST_Y ST_WIDTH ST_HEIGHT ST_CLX ST_CLY ST_CLWIDTH ST_CLHEIGHT ST_PARENT ST_ICON ST_MAXIMIZED ST_VISIBLE ST_ACTIVE ST_BUSY ST_PATH ST_PROCESS ST_WIN64 ST_MONITOR CUR_APPSTARTING CUR_ARROW CUR_CROSS CUR_HAND CUR_HELP CUR_IBEAM CUR_NO CUR_SIZEALL CUR_SIZENESW CUR_SIZENS CUR_SIZENWSE CUR_SIZEWE CUR_UPARROW CUR_WAIT ACC_ACC ACC_API ACC_NAME ACC_VALUE ACC_ROLE ACC_STATE ACC_DESCRIPTION ACC_LOCATION ACC_BACK P_POWEROFF P_LOGOFF P_REBOOT P_SUSPEND P_SUSPEND2 P_MONIPOWER P_MONIPOWER2 P_MONIPOWER3 P_SCREENSAVE P_UWSC_REEXEC P_FORCE TGL_IME TGL_NUMLOCK TGL_CAPSLOCK TGL_SCROLLLOCK TGL_KANALOCK GET_ACTIVE_WIN GET_FROMPOINT_WIN GET_FROMPOINT_OBJ GET_THISUWSC_WIN GET_LOGPRINT_WIN GET_FUKIDASI_WIN GET_FORM_WIN GET_SCHEDULE_WIN SC_LOWERCASE SC_UPPERCASE SC_HIRAGANA SC_KATAKANA SC_HALFWIDTH SC_FULLWIDTH FOM_NOICON FOM_MINIMIZE FOM_MAXIMIZE FOM_NOHIDE FOM_NOSUBMIT FOM_NORESIZE FOM_NOLUNA FOM_BROWSER CODE_URL CODE_UTF8 CODE_BYTEARRAY CODE_BYTEARRAYW CALC_ADD CALC_MIN CALC_MAX CALC_AVR IMG_MSK_BGR1~4 IMG_MSK_B1~4 IMG_MSK_G1~4 IMG_MSK_R1~4 MOD_ALT MOD_CONTROL MOD_SHIFT MOD_WIN SLD_POS SLD_MIN SLD_MAX SLD_PAGE SLD_BAR SLD_X SLD_Y MON_X MON_Y MON_WIDTH MON_HEIGHT COL_RGB COL_R COL_G COL_B MORG_CLIENT MORG_DIRECT MORG_FORE MORG_BACK VK_START VK_WIN VK_ALT VK_CTRL VK_RCTRL VK_ESC VK_BACK VK_TAB VK_CLEAR VK_RETURN VK_RRETURN VK_SHIFT VK_RSHIFT VK_CONTROL VK_MENU VK_PAUSE VK_CAPITAL VK_KANA VK_FINAL VK_KANJI VK_CONVERT VK_NONCONVERT VK_ACCEPT VK_MODECHANGE VK_ESCAPE VK_SPACE VK_PRIOR VK_NEXT VK_END VK_HOME VK_LEFT VK_UP VK_RIGHT VK_DOWN VK_SELECT VK_PRINT VK_EXECUTE VK_SNAPSHOT VK_INSERT VK_DELETE VK_HELP VK_APPS VK_MULTIPLY VK_ADD VK_SEPARATOR VK_SUBTRACT VK_DECIMAL VK_DIVIDE VK_NUMPAD0~9 VK_F1~12 VK_NUMLOCK VK_SCROLL VK_SLEEP VK_BROWSER_BACK VK_BROWSER_FORWARD VK_BROWSER_REFRESH VK_BROWSER_STOP VK_BROWSER_SEARCH VK_BROWSER_FAVORITES VK_BROWSER_HOME VK_VOLUME_MUTE VK_VOLUME_DOWN VK_VOLUME_UP VK_MEDIA_NEXT_TRACK VK_MEDIA_PREV_TRACK VK_MEDIA_STOP VK_MEDIA_PLAY_PAUSE VK_LAUNCH_MEDIA_SELECT VK_LAUNCH_MAIL VK_LAUNCH_APP1 VK_LAUNCH_APP2 VK_OEM_PLUS VK_OEM_COMMA VK_OEM_MINUS VK_OEM_PERIOD VK_OEM_1~8 VK_OEM_RESET VK_OEM_JUMP VK_OEM_PA1~3 HASH_CASECARE HASH_SORT HASH_EXISTS HASH_REMOVE HASH_KEY HASH_VAL HASH_REMOVEALL VAR_EMPTY VAR_NULL VAR_SMALLINT VAR_INTEGER VAR_SINGLE VAR_DOUBLE VAR_CURRENCY VAR_DATE VAR_BSTR VAR_DISPATCH VAR_ERROR VAR_BOOLEAN VAR_VARIANT VAR_UNKNOWN VAR_SBYTE VAR_BYTE VAR_WORD VAR_DWORD VAR_INT64 VAR_ARRAY", " "), SAFEARRAY(0,-1) procedure Help() CUI.Output() CUI.Output("※使い方", TRUE, "lb") CUI.Output(" 式を入力すると実行します") CUI.Output(" 式の戻り値はコンソールに表示されます") CUI.Output() CUI.Output("※変数について", TRUE, "lb") CUI.Output(" 連想配列は ", FALSE) CUI.Output("hash hash2", FALSE, "y") CUI.Output(" を使ってください") CUI.Output(" 配列は SAFEARRAY関数で作成してください") CUI.Output(" 先頭の比較演算子は ", FALSE) CUI.Output("==", FALSE, "y") CUI.Output(" を使用してください(先頭の=は代入文と認識されます)") CUI.Output() CUI.Output("※特殊コマンド一覧", TRUE, "lb") CUI.Output("help [uwsc]", TRUE, "y") CUI.Output(" このヘルプを表示します", TRUE) CUI.Output(" オプション指定でuwscのヘルプを表示します", TRUE) CUI.Output("window [all]", TRUE, "y") CUI.Output(" ウィンドウIDを列挙、オプション指定で非表示ウィンドウも列挙します", TRUE) CUI.Output("enum 配列名", TRUE, "y") CUI.Output(" 配列の内容を列挙します", TRUE) CUI.Output("exit [silent]", TRUE, "y") CUI.Output(" " + GET_UWSC_NAME + "を終了します、オプション指定で確認なしで終了", TRUE) CUI.Output() fend endmodule
対応内容
特殊コマンドの#はずし
#が押しにくいので外しました。
既存コマンドとはかぶってないしね。
戻したければ、Run関数のselect文を修正してください。
補完
クリップボード依存じゃなくなりました!
少々もっさりしてるので、タブ連打は許してくらはい。
補完の順番に不満がある場合は、がーっと書いてある文字列の順番を直してください。
ポインターが指している目障りなTopMostウインドウのTopMost解除をしたい場合、
ct<#TAB>ge<#TAB>get_f<#TAB>),no<#TAB><#TAB><#TAB>)<#CR>
で入力が可能!23タイプの節約!52%OFFですよ!
複文
tokenによる;区切りの複文を入れました。
それに伴い、#waitコマンドを廃止しました。
stuncloudさんのモジュールで、
#wait 1 msgbox("ok?")
は
sleep(1);msgbox("ok?")
となります。
特殊コマンドの後の複文は上手くいかないケースが多いです。
enum拡張
getallwinとかした時に、all_win_idをenumしたいじゃないですか。
やむなく、関数を統合して、巨大なRun関数にしました。
これで、enumの制限がなくなります。
ついでに、enumによる列挙処理をできるようにしました。
「window all」は
getallwin() enum all_win_id status(__val,st_title)+" : "+status(__val,st_class)
とかでも似たような感じですね。
また、ハッシュテーブルを二つ用意しましたが、ハッシュテーブルのコピーは、
enum hash hash2[__key]=__val
でOKです。
「enum」便利!
thread起動
指定したコマンドをスレッドで実行します。
thread sleep(3);msgbox("proc?")
スレッド側から出力があると、画面表示がおかしくなりますが、まあ気にしない。
ほとんどの変数は渡せませんが、hash/hash2だけはスレッドからも参照できます。
参照できる変数を増やしたければ、モジュール変数を増やしてください。
if分岐
if関数がなんとなく実装されています。
いろいろ不完全ですが、、、。
if(a==1,msgbox("OK"),msgbox("NG"))
が可能となっています。
が、この場合aが存在しないと、おかしなことになります。
また、条件のないif文は、両方を実行するので、複文として機能します。
whileループ
while関数によるループを実装しました
i=0;while(i<10,j=cui.output(i);i=i+1)
jで受けているのは、cui.outputの結果を表示させないため。
一応ネスト可能だけど、if関数とは仲が悪そう(バグりそう)、、、。
代入演算子と等号
先頭の「=」を「:=」にしたり、先頭の「==」を「=」にしたりしてます。
if/while関数内はそれぞれが文とみなされるので、それぞれ先頭だったりします。
複文も分割後が先頭。
先頭以外は置換されないので、留意願います。
変数の保存
Save/Load/Delete関数で変数の保存/復元/削除ができます。
保存先は、スクリプト名.ini。
Save関数の第一引数は、保存する名前。
ただし、ハッシュテーブルは変数名と同じでないと使えません。
第二引数が、保存する変数自身。
Save("hash", hash)
Load関数の引数は、名前だけ。
ハッシュテーブルは、同名のテーブルにセット(RESULTは、Interpreter.VAR_HASH)
それ以外はRESULTで返す。
a = Load("a")
iniに保存された変数が不要になったら、Delete関数に名前を渡して削除してください。
Delete("a")
Startup
iniファイルの[settings] startupキーにコマンドを定義します。
想定としては、Load関数を呼ぶかなー、と思っています。
補完用の配列_compsは、二次元配列になっています。
(_comps[0]以外は現在空ですが)
これを利用して_comps[1]等追加しても良いかと思います。
Exit
iniファイルの[settings] exitキーにコマンドを定義すると、「exit」の際に実行します。
想定としては、、、Save関数を呼ぶかなー、と。
マクロ
iniファイルの[settings]セクションに「#」で始まるキーに設定すると、その名前で呼べます。
よくやる複文を登録すると便利かもしれません。
登録は、iniファイルに直接書くか、「WRITEINI(SEC_SETTINGS, "#キー名", "コマンド")」