Last active
August 29, 2015 14:22
-
-
Save TLMcode/e2955e489d46a203f000 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#SingleInstance, Off | |
#NoEnv | |
SetBatchLines, -1 | |
FilePath = C:\Windows\ShellNew\Template.ahk | |
DefaultName = %A_UserName% | |
DefaultDesc = | |
Indent := "`t" | |
Title = CodeQuickTester | |
Param1 = %1% | |
FilePath := Param1 ? RegExReplace(Param1, "^ahk:") : FilePath | |
if FileExist(FilePath) | |
Code := FileOpen(FilePath, "r").Read() | |
else if (FilePath ~= "^https?://") | |
Code := UrlDownloadToVar(FilePath) | |
Menu, Tray, Icon, %A_AhkPath%, 2 | |
Shell := ComObjCreate("WScript.Shell") | |
FileEncoding, UTF-8 | |
Menu, MenuBar, Add, &Save, SaveButton | |
Menu, MenuBar, Add, &Load, LoadButton | |
Menu, MenuBar, Add, &Fetch, FetchButton | |
Menu, MenuBar, Add, &Paste, PasteButton | |
Menu, MenuBar, Add, P&arams, ParamsButton | |
Menu, MenuBar, Add, Re&indent, IndentButton | |
Menu, MenuBar, Add, Install, ServiceHandler | |
Gui, Main:New, +Resize | |
Gui, Menu, MenuBar | |
Gui, Margin, 5, 5 | |
Gui, Color,, 3F3F3F | |
Gui, Font, s10 cEDEDCD, Consolas | |
Gui, Add, Edit, vCodeEditor hWndhCodeEditor WantTab -Wrap HScroll t14 r2 ; t14 sets tab size to 4 characters | |
Gui, Font, s8, Microsoft Sans Serif | |
Gui, Add, Button, gRunButton vRun, &Run | |
Gui, Show, w640 h480, %Title% | |
Gui, Add, StatusBar | |
SB_SetParts(70, 70, 70) | |
LoadCode(Code) | |
OnMessage(0x100, "ProcessEditEvents") ; WM_KEYDOWN | |
OnMessage(0x201, "ProcessEditEvents") ; WM_LBUTTONDOWN | |
OnMessage(0x202, "ProcessEditEvents") ; WM_LBUTTONUP | |
OnMessage(0x204, "ProcessEditEvents") ; WM_RBUTTONDOWN | |
return | |
#If Exec.Status == 0 | |
Escape::Exec.Terminate() ; CheckIfRunning updates the GUI | |
#If | |
ProcessEditEvents(wParam, lParam, Msg, hWnd) | |
{ | |
global hCodeEditor | |
if (hWnd == hCodeEditor) | |
SetTimer, UpdateStatusBar, -0 ; Spawn new pseudo thread that will run after this function terminates | |
} | |
UpdateStatusBar() | |
{ | |
global hCodeEditor | |
Gui, Main:Default | |
GuiControlGet, CodeEditor | |
SB_SetText("Len " StrLen(CodeEditor), 1) | |
ControlGet, Row, CurrentLine,,, ahk_id %hCodeEditor% | |
ControlGet, Col, CurrentCol,,, ahk_id %hCodeEditor% | |
SB_SetText("Line " Row, 2) | |
SB_SetText("Col " Col, 3) | |
ControlGet, Selected, Selected,,, ahk_id %hCodeEditor% | |
Len := StrLen(StrReplace(Selected, "`r`n", "`n")) | |
SB_SetText(Len ? "Selection Length: " Len : "", 4) | |
} | |
MainGuiClose: | |
GuiControlGet, CodeEditor | |
if !CodeEditor | |
ExitApp | |
MsgBox, 308, %Title%, Are you sure you want to exit? | |
IfMsgBox, Yes | |
ExitApp | |
return | |
MainGuiSize: | |
Critical | |
Process, Priority,, R | |
GuiControl, Move, CodeEditor, % "x" 5 "y" 5 "w" A_GuiWidth-10 "h" A_GuiHeight-60 | |
ButtonWidth := (A_GuiWidth-10) | |
GuiControl, Move, Run, % "x" 5 "y" A_GuiHeight-50 "w" ButtonWidth "h" 22 | |
SetTimer, Normal, -100 | |
return | |
Normal: | |
Process, Priority,, N | |
return | |
MainGuiDropFiles: | |
LoadCode(FileOpen(StrSplit(A_GuiEvent, "`n")[1], "r").Read()) | |
return | |
RunButton: | |
if (Exec.Status == 0) ; Running | |
Exec.Terminate() ; CheckIfRunning updates the GUI | |
else ; Not running or doesn't exist | |
{ | |
GuiControlGet, CodeEditor, Main: | |
GuiControlGet, Params, Params: | |
Exec := ExecScript(CodeEditor, Params, DeHashBang(CodeEditor)) | |
GuiControl, Main:, Run, &Kill | |
SetTimer, CheckIfRunning, 100 | |
} | |
return | |
CheckIfRunning: | |
if (Exec.Status == 1) | |
{ | |
SetTimer, CheckIfRunning, Off | |
GuiControl, Main:, Run, &Run | |
} | |
return | |
SaveButton: | |
Gui, +OwnDialogs | |
FileSelectFile, FilePath, S2 | |
if ErrorLevel | |
return | |
GuiControlGet, CodeEditor | |
FileOpen(FilePath, "w").Write(CodeEditor) | |
return | |
LoadButton: | |
Gui, +OwnDialogs | |
FileSelectFile, FilePath, 3 | |
if !ErrorLevel | |
LoadCode(FileOpen(FilePath, "r").Read()) | |
return | |
FetchButton: | |
Gui, +OwnDialogs | |
InputBox, Url, %Title%, Enter a URL to fetch code from. | |
if (Url := Trim(Url)) | |
LoadCode(UrlDownloadToVar(Url)) | |
return | |
PasteButton: | |
Gui, Paste:New, +OwnerMain +ToolWindow | |
Gui, Margin, 5, 5 | |
Gui, Font, s8, Microsoft Sans Serif | |
Gui, Add, Text, xm ym w30 h22 +0x200, Desc: | |
Gui, Add, Edit, x+5 yp w125 h22 vPasteDesc, %DefaultDesc% | |
Gui, Add, Button, x+4 yp-1 w52 h24 Default gPaste, Paste | |
Gui, Add, Text, xm y+5 w30 h22 +0x200, Name: | |
Gui, Add, Edit, x+5 yp w100 h22 vPasteName, %DefaultName% | |
Gui, Add, ComboBox, x+5 yp w75 vPasteChan hWndPasteChan, Announce||#ahk|#ahkscript | |
PostMessage, 0x153, -1, 22-6,, ahk_id %PasteChan% ; Set height of ComboBox | |
Gui, Show,, Paste | |
return | |
PasteGuiEscape: | |
Gui, Destroy | |
return | |
Paste: | |
Gui, Submit | |
Gui, Destroy | |
GuiControlGet, CodeEditor, Main: | |
Link := Ahkbin(CodeEditor, PasteName, PasteDesc, PasteChan) | |
MsgBox, 292, %Title%, Link acquired:`n%Link%`n`nCopy to clipboard? | |
IfMsgBox, Yes | |
Clipboard := Link | |
return | |
ParamsButton: | |
Gui, Params:New, +OwnerMain +ToolWindow | |
Gui, Margin, 5, 5 | |
Gui, Font, s8, Microsoft Sans Serif | |
Gui, Add, Text, xm ym w300 h22 Center +0x200, Params will be cleared on window exit | |
Gui, Add, Edit, w300 h22 vParams | |
Gui, Show,, Command Line Params | |
return | |
ParamsGuiEscape: | |
Gui, Destroy | |
return | |
IndentButton: | |
GuiControlGet, CodeEditor, Main: | |
LoadCode(AutoIndent(CodeEditor, Indent)) | |
return | |
ServiceHandler: | |
Gui, +OwnDialogs | |
if ServiceHandlerInstalled() | |
{ | |
MsgBox, 36, , Are you sure you want to remove CodeQuickTester from being the default service handler for "ahk:" links? | |
IfMsgBox, Yes | |
RemoveServiceHandler() | |
} | |
else | |
{ | |
MsgBox, 36, , Are you sure you want to install CodeQuickTester as the default service handler for "ahk:" links? | |
IfMsgBox, Yes | |
AddServiceHandler() | |
} | |
return | |
LoadCode(Code) | |
{ | |
GuiControlGet, CodeEditor | |
if (CodeEditor && CodeEditor != Code) | |
{ | |
MsgBox, 308, %Title%, Are you sure you want to overwrite your code? | |
IfMsgBox, No | |
return | |
} | |
GuiControl,, CodeEditor, %Code% | |
UpdateStatusBar() | |
} | |
UrlDownloadToVar(Url) | |
{ | |
try | |
{ | |
http := ComObjCreate("WinHttp.WinHttpRequest.5.1") | |
http.Open("GET", Url, false), http.Send() | |
return http.ResponseText | |
} | |
catch | |
throw Exception("Something went wrong with the HTTP Request. Invalid URL?") | |
} | |
; Modified from https://github.com/cocobelgica/AutoHotkey-Util/blob/master/ExecScript.ahk | |
ExecScript(Script, Params="", AhkPath="") | |
{ | |
Name := "AHK_CQT_" A_TickCount | |
Pipe := [] | |
Loop, 2 | |
{ | |
Pipe[A_Index] := DllCall("CreateNamedPipe" | |
, "Str", "\\.\pipe\" name | |
, "UInt", 2, "UInt", 0 | |
, "UInt", 255, "UInt", 0 | |
, "UInt", 0, "UPtr", 0 | |
, "UPtr", 0, "UPtr") | |
} | |
if !FileExist(AhkPath) | |
AhkPath := A_AhkPath | |
Call = "%AhkPath%" /CP65001 "\\.\pipe\%Name%" | |
Shell := ComObjCreate("WScript.Shell") | |
Exec := Shell.Exec(Call " " Params) | |
DllCall("ConnectNamedPipe", "UPtr", Pipe[1], "UPtr", 0) | |
DllCall("CloseHandle", "UPtr", Pipe[1]) | |
DllCall("ConnectNamedPipe", "UPtr", Pipe[2], "UPtr", 0) | |
FileOpen(Pipe[2], "h", "UTF-8").Write(Script) | |
DllCall("CloseHandle", "UPtr", Pipe[2]) | |
return Exec | |
} | |
Ahkbin(Content, Name="", Desc="", Channel="") | |
{ | |
static URL := "http://p.ahkscript.org/" | |
Form := "code=" UriEncode(Content) | |
if Name | |
Form .= "&name=" UriEncode(Name) | |
if Desc | |
Form .= "&desc=" UriEncode(Desc) | |
if Channel | |
Form .= "&announce=on&channel=" UriEncode(Channel) | |
Pbin := ComObjCreate("WinHttp.WinHttpRequest.5.1") | |
Pbin.Open("POST", URL, False) | |
Pbin.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") | |
Pbin.Send(Form) | |
return Pbin.Option(1) | |
} | |
; Modified by GeekDude from http://goo.gl/0a0iJq | |
UriEncode(Uri, RE="[0-9A-Za-z]") { | |
VarSetCapacity(Var, StrPut(Uri, "UTF-8"), 0), StrPut(Uri, &Var, "UTF-8") | |
While Code := NumGet(Var, A_Index - 1, "UChar") | |
Res .= (Chr:=Chr(Code)) ~= RE ? Chr : Format("%{:02X}", Code) | |
Return, Res | |
} | |
DeHashBang(Script) | |
{ | |
AhkPath := A_AhkPath | |
if RegExMatch(Script, "`a)^\s*`;#!\s*(.+)", Match) | |
{ | |
AhkPath := Trim(Match1) | |
Vars := {"%A_ScriptDir%": A_WorkingDir | |
, "%A_WorkingDir%": A_WorkingDir | |
, "%A_AppData%": A_AppData | |
, "%A_AppDataCommon%": A_AppDataCommon | |
, "%A_LineFile%": A_ScriptFullPath | |
, "%A_AhkPath%": A_AhkPath | |
, "%A_AhkDir%": A_AhkPath "\.."} | |
for SearchText, Replacement in Vars | |
StringReplace, AhkPath, AhkPath, %SearchText%, %Replacement%, All | |
} | |
return AhkPath | |
} | |
AddServiceHandler() | |
{ | |
RegWrite, REG_SZ, HKCU, Software\Classes\ahk,, URL:AHK Script Protocol | |
RegWrite, REG_SZ, HKCU, Software\Classes\ahk, URL Protocol | |
RegWrite, REG_SZ, HKCU, Software\Classes\ahk\shell\open\command,, "%A_AhkPath%" "%A_ScriptFullPath%" "`%1" | |
} | |
RemoveServiceHandler() | |
{ | |
RegDelete, HKCU, Software\Classes\ahk | |
} | |
ServiceHandlerInstalled() | |
{ | |
RegRead, Out, HKCU, Software\Classes\ahk | |
return !ErrorLevel | |
} | |
AutoIndent(Code, Indent = "`t", Newline = "`n") | |
{ | |
IndentRegEx = | |
( LTrim Join | |
Catch|else|for|Finally|if|IfEqual|IfExist| | |
IfGreater|IfGreaterOrEqual|IfInString| | |
IfLess|IfLessOrEqual|IfMsgBox|IfNotEqual| | |
IfNotExist|IfNotInString|IfWinActive|IfWinExist| | |
IfWinNotActive|IfWinNotExist|Loop|Try|while | |
) | |
; Lock and Block are modified ByRef by Current | |
Lock := [], Block := [] | |
ParentIndent := Braces := 0 | |
ParentIndentObj := [] | |
for each, Line in StrSplit(Code, "`n", "`r") | |
{ | |
Text := Trim(RegExReplace(Line, "\s;.*")) ; Comment removal | |
First := SubStr(Text, 1, 1), Last := SubStr(Text, 0, 1) | |
FirstTwo := SubStr(Text, 1, 2) | |
IsExpCont := (Text ~= "i)^\s*(&&|OR|AND|\.|\,|\|\||:|\?)") | |
IndentCheck := (Text ~= "iA)}?\s*\b(" IndentRegEx ")\b") | |
if (First == "(" && Last != ")") | |
Skip := True | |
if (Skip) | |
{ | |
if (First == ")") | |
Skip := False | |
Out .= Newline . RTrim(Line) | |
continue | |
} | |
if (FirstTwo == "*/") | |
Block := [], ParentIndent := 0 | |
if Block.MinIndex() | |
Current := Block, Cur := 1 | |
else | |
Current := Lock, Cur := 0 | |
; Round converts "" to 0 | |
Braces := Round(Current[Current.MaxIndex()].Braces) | |
ParentIndent := Round(ParentIndentObj[Cur]) | |
if (First == "}") | |
{ | |
while ((Found := SubStr(Text, A_Index, 1)) ~= "}|\s") | |
{ | |
if (Found ~= "\s") | |
continue | |
if (Cur && Current.MaxIndex() <= 1) | |
break | |
Special := Current.Pop().Ind, Braces-- | |
} | |
} | |
if (First == "{" && ParentIndent) | |
ParentIndent-- | |
Out .= Newline | |
Loop, % Special ? Special-1 : Round(Current[Current.MaxIndex()].Ind) + Round(ParentIndent) | |
Out .= Indent | |
Out .= Trim(Line) | |
if (FirstTwo == "/*") | |
{ | |
if (!Block.MinIndex()) | |
{ | |
Block.Push({ParentIndent: ParentIndent | |
, Ind: Round(Lock[Lock.MaxIndex()].Ind) + 1 | |
, Braces: Round(Lock[Lock.MaxIndex()].Braces) + 1}) | |
} | |
Current := Block, ParentIndent := 0 | |
} | |
if (Last == "{") | |
{ | |
Braces++, ParentIndent := (IsExpCont && Last == "{") ? ParentIndent-1 : ParentIndent | |
Current.Push({Braces: Braces | |
, Ind: ParentIndent + Round(Current[Current.MaxIndex()].ParentIndent) + Braces | |
, ParentIndent: ParentIndent + Round(Current[Current.MaxIndex()].ParentIndent)}) | |
ParentIndent := 0 | |
} | |
if ((ParentIndent || IsExpCont || IndentCheck) && (IndentCheck && Last != "{")) | |
ParentIndent++ | |
if (ParentIndent > 0 && !(IsExpCont || IndentCheck)) | |
ParentIndent := 0 | |
ParentIndentObj[Cur] := ParentIndent | |
Special := 0 | |
} | |
if Braces | |
throw Exception("Segment Open!") | |
return SubStr(Out, StrLen(Newline)+1) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment