[Script] CodeQuickTester - Write and run code without saving to a temporary file

Post your working scripts, libraries and tools
GeekDude
Posts: 843
Joined: 02 Oct 2013, 22:13

Re: CodeQuickTester

31 May 2015, 13:34

Whoops, looks like I broke the gist open button from the extension, fixed now. @BGM Check the original post, the greasemonkey script is in a spoiler tag about 2/3 the way down.

I've just updated the code tester as well.
  • Moved config to top of script
  • Added default file option to config (Defaults to ShellNew)
  • Made selected text length more responsive
  • Changed pastebin dropdown to combobox
  • Updated to new pastebin URL
  • Added A_AhkDir to the hashbang decoder
GeekDude
Posts: 843
Joined: 02 Oct 2013, 22:13

Re: CodeQuickTester

01 Jun 2015, 22:55

I'm going to go ahead and push this out. Introducing Auto Indent, modified from @maestrith's amazing AHK Studio!
  • Added menu button for Auto Indent
User avatar
BGM
Posts: 419
Joined: 20 Nov 2013, 20:56
GitHub: bgmCoder
Contact:

Re: CodeQuickTester

02 Jun 2015, 09:59

You should add triple-click to select an entire line
User avatar
maestrith
Posts: 731
Joined: 16 Oct 2013, 13:52

Re: CodeQuickTester

02 Jun 2015, 10:01

aww :) you called Studio amazing :)
AHK Studio OSD GUI Creator
Donations
Discord
All code is done on a Windows 10 PC Running x64 and AutoHotkey x32
GeekDude
Posts: 843
Joined: 02 Oct 2013, 22:13

Re: CodeQuickTester

04 Jun 2015, 18:17

I just updated the code tester! This update brings the use of a RichEdit control. Also, I've added a hotkey for opening the help file. Kudos to @just_me for his help with the RE, and his wonderful RE class I used as a guide. Also thanks to @BGM for his feedback in the IRC.
  • Switched to using a RichEdit control
  • Triple click selects whole line
  • Added options for variable tab width, font, typeface, font color, bgcolor etc.
  • ^h to open help file
GeekDude
Posts: 843
Joined: 02 Oct 2013, 22:13

Re: CodeQuickTester

10 Aug 2015, 16:56

What do you guys think about switching to a more OOP code base? Here's an unfinished example

Code: Select all

#SingleInstance, Off
#NoEnv
SetBatchLines, -1

Menu, Tray, Icon, %A_AhkPath%, 2
FileEncoding, UTF-8

MyTester := new CodeQuickTester()
return

class CodeQuickTester
{
	static Msftedit := DllCall("LoadLibrary", "Str", "Msftedit.dll")
	
	__New()
	{
		this.DefaultPath := "C:\Windows\ShellNew\Template.ahk"
		this.DefaultName := "GeekDude"
		this.DefaultDesc := ""
		this.FGColor := 0xCDEDED
		this.BGColor := 0x3F3F3F
		this.TabSize := 4
		this.Indent := "`t"
		this.TypeFace := "Consolas"
		this.Font := "s9 wBold"
		this.Title := "CodeQuickTester"
		
		this.Shell := ComObjCreate("WScript.Shell")
		
		; TODO: This makes the class never get garbage collected. Oops!
		Buttons := new this.MenuButtons(this)
		Menu := 
		( Join
		[
			["&File", [
				["&Save`tCtrl+S", Buttons.Save.Bind(Buttons)],
				["&Open`tCtrl+O", Buttons.Open.Bind(Buttons)],
				["&Fetch", Buttons.Fetch.Bind(Buttons)]
			]], ["&Tools", [
				["&Paste`tCtrl+P", Buttons.Paste.Bind(Buttons)],
				["Re&indent", Buttons.Indent.Bind(Buttons)],
				["Install", Buttons.Install.Bind(Buttons)],
				["&Help`tF1", Buttons.Help.Bind(Buttons)]
			]]
		]
		)
		
		Gui, New, +Resize +hWndhMainWindow
		this.hMainWindow := hMainWindow
		Gui, Menu, % this.CreateMenuBar(Menu)
		Gui, Margin, 5, 5
		
		Gui, Font, % this.Font, % this.TypeFace
		
		this.InitRichEdit()
		
		Gui, Font, s8 w400 q0, Microsoft Sans Serif
		Gui, Add, Button, hWndhRunButton, &Run
		RunFunc := this.RunButton.Bind(this) ; TODO: This makes the class never get garbage collected. Oops!
		GuiControl, +g, %hRunButton%, %RunFunc%
		this.hRunButton := hRunButton
		Gui, Add, StatusBar
		SB_SetParts(70, 70, 70)
		
		WinEvents.Register(this.hMainWindow, new this.Events(this))		
		Gui, Show, w640 h480, % this.Title
	}
	
	InitRichEdit()
	{
		Gui, Add, Custom, ClassRichEdit50W hWndhWnd +0x5031b1c4 +E0x20000
		this.hCodeEditor := hWnd
		
		; Set background color
		SendMessage, 0x443, 0, this.BGColor,, ahk_id %hWnd% ; EM_SETBKGNDCOLOR
		
		; Set FG color
		VarSetCapacity(CharFormat, 116, 0)
		NumPut(116, CharFormat, 0, "UInt") ; cbSize := sizeOf(CHARFORMAT2)
		NumPut(0x40000000, CharFormat, 4, "UInt") ; dwMask := CFM_COLOR
		NumPut(this.FGColor, CharFormat, 20, "UInt") ; crTextColor := 0xBBGGRR
		SendMessage, 0x444, 0, &CharFormat,, ahk_id %hWnd% ; EM_SETCHARFORMAT
		
		; Set tab size to 4
		VarSetCapacity(TabStops, 4, 0), NumPut(this.TabSize*4, TabStops, "UInt")
		SendMessage, 0x0CB, 1, &TabStops,, ahk_id %hWnd% ; EM_SETTABSTOPS
		
		; Change text limit from 32,767 to max
		SendMessage, 0x435, 0, -1,, ahk_id %hWnd% ; EM_EXLIMITTEXT
		
		; Disable inconsistent formatting
		SendMessage, 0x4CC, 1, 1,, ahk_id %hWnd% ; EM_SETEDITSTYLE SES_EMULATESYSEDIT
	}
	
	CreateMenuBar(Menu)
	{
		static MenuName := 0
		MyMenuName := "CQT_" MenuName, MenuName++
		for each, Item in Menu
		{
			Ref := Item[2]
			if IsObject(Ref) && Ref._NewEnum()
				Ref := ":" this.CreateMenuBar(Ref)
			Menu, %MyMenuName%, Add, % Item[1], %Ref%
		}
		return MyMenuName
	}
	
	RunButton()
	{
		if (this.Exec.Status == 0) ; Running
			this.Exec.Terminate() ; CheckIfRunning updates the GUI
		else ; Not running or doesn't exist
		{
			GuiControlGet, CodeEditor,, % this.hCodeEditor
;			GuiControlGet, Params, Params:
			this.Exec := ExecScript(CodeEditor, "", DeHashBang(CodeEditor)) ; TODO: Implement Params
			GuiControl,, % this.hRunButton, &Kill
			
			BoundFunc := this.CheckIfRunning.Bind(this, Context := {})
			Context.BoundFunc := BoundFunc
			SetTimer, %BoundFunc%, 100
		}
	}
	
	CheckIfRunning(Context)
	{
		if (this.Exec.Status == 1)
		{
			BoundFunc := Context.BoundFunc
			SetTimer, %BoundFunc%, Delete
			GuiControl,, % this.hRunButton, &Run ; TODO: Make sure I don't have to specify default gui
		}
	}
	
	class MenuButtons
	{
		__New(Parent)
		{
			this.Parent := Parent
		}
		
		Save()
		{
			Gui, +OwnDialogs
			FileSelectFile, FilePath, S2
			if ErrorLevel
				return
			GuiControlGet, CodeEditor,, % this.Parent.hCodeEditor
			
			; TODO: Confirm before overwrite
			FileOpen(FilePath, "w").Write(CodeEditor)
		}
		
		Open()
		{
			; TODO
		}
		
		Fetch()
		{
			; TODO
		}
		
		Paste()
		{
			; TODO
		}
		
		Indent()
		{
			; TODO
		}
		
		Help()
		{
			Run, %A_AhkPath%\..\AutoHotkey.chm
		}
		
		Install()
		{
			; TODO
		}
	}
	
	class Events
	{
		__New(Parent)
		{
			this.Parent := Parent
		}
		
		Size()
		{
			ToolTip, hi
			GuiControl, Move, % this.Parent.hCodeEditor, % "x" 5 "y" 5 "w" A_GuiWidth-10 "h" A_GuiHeight-60
			ButtonWidth := (A_GuiWidth-10)
			GuiControl, Move, % this.Parent.hRunButton, % "x" 5 "y" A_GuiHeight-50 "w" ButtonWidth "h" 22
		}
		
		Close()
		{
			; TODO: Allow multiple instances?
			ExitApp
		}
	}
}

; TODO: Decide if I should keep a separate class for
; event dispatching or if I should handle it all inline.
class WinEvents ; static class
{
	static Table := {}
	
	Register(hWnd, Class)
	{
		Gui, +LabelWinEvents.
		this.Table[hWnd] := Class
	}
	
	Unregister(hWnd)
	{
		this.Table.Delete(hWnd)
	}
	
	Dispatch(hWnd, Type)
	{
		Class := this.Table[hWnd]
		
		; TODO: Decide if it should use a prefix for the method name
		Class[Type].Call(Class)
	}
	
	; These *CANNOT* be added dynamically or handled dynamically via __Call
	Close()
	{
		WinEvents.Dispatch(this, "Close")
	}
	
	Escape()
	{
		WinEvents.Dispatch(this, "Escape")
	}
	
	Size()
	{
		WinEvents.Dispatch(this, "Size")
	}
	
	ContextMenu()
	{
		WinEvents.Dispatch(this, "ContextMenu")
	}
	
	DropFiles()
	{
		WinEvents.Dispatch(this, "DropFiles")
	}
}

; 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
}

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
}
dd900
Posts: 76
Joined: 27 Oct 2013, 16:03

Re: CodeQuickTester

10 Aug 2015, 23:46

Looks good. I just tested this with CodeQuickTester then I used the new instance to load another instance of CodeQuickTester.

CodeQuickTesterCeption
User avatar
joedf
Posts: 6498
Joined: 29 Sep 2013, 17:08
Facebook: J0EDF
Google: +joedf
GitHub: joedf
Location: Canada, Quebec
Contact:

Re: CodeQuickTester

11 Aug 2015, 10:43

dd900 wrote:Looks good. I just tested this with CodeQuickTester then I used the new instance to load another instance of CodeQuickTester.

CodeQuickTesterCeption
:D
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500 @ 3.00 GHz, 16GB DDR4 3200 MHz, NVIDIA GTX 1060 6GB | [About Me] | [ASPDM - StdLib Distribution]
[Populate the AHK MiniCity!] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library] | [About the AHK Foundation]
dd900
Posts: 76
Joined: 27 Oct 2013, 16:03

Re: CodeQuickTester

11 Aug 2015, 11:22

GeekDude wrote:What effect do you think this new approach has on code readability?
I think that would depend on the user. I myself find it easier to read the newer version, but that's only because I am familiar with how classes work in ahk (thank you lexikos). Someone with no experience using objects or classes in ahk or any other language might not understand what is going on in the code.

I say continue with the new OOP aproach
GeekDude
Posts: 843
Joined: 02 Oct 2013, 22:13

Re: CodeQuickTester

11 Aug 2015, 11:45

A fun side effect is that you can create multiple instances of the code editor from one script. That could make it easier for me to add a "open new instance" button that works while the script is being run dynamically.
User avatar
joedf
Posts: 6498
Joined: 29 Sep 2013, 17:08
Facebook: J0EDF
Google: +joedf
GitHub: joedf
Location: Canada, Quebec
Contact:

Re: CodeQuickTester

11 Aug 2015, 12:51

+1
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500 @ 3.00 GHz, 16GB DDR4 3200 MHz, NVIDIA GTX 1060 6GB | [About Me] | [ASPDM - StdLib Distribution]
[Populate the AHK MiniCity!] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library] | [About the AHK Foundation]
GeekDude
Posts: 843
Joined: 02 Oct 2013, 22:13

Re: CodeQuickTester

17 Aug 2015, 11:18

Run this, and click the run button a few times. Works fine, right? Click the edit box, then click the run button a few more times. It gets stuck on "Kill". Now kill the script, and uncomment the two lines in the UpdateStatusBar method, and try again. Everything works fine. My question is why does that fix a seemingly unrelated problem? I'm baffled.

Code: Select all

#NoEnv
MyTester := new CodeQuickTester()

class CodeQuickTester
{
	__New()
	{
		this.Bound := []
		this.Bound.RunButton := this.RunButton.Bind(this)
		this.Bound.OnMessage := this.OnMessage.Bind(this)
		this.Bound.UpdateStatusBar := this.UpdateStatusBar.Bind(this)
		this.Bound.CheckIfRunning := this.CheckIfRunning.Bind(this)
		
		Gui, New, +Resize +hWndhMainWindow
		this.hMainWindow := hMainWindow
		
		Gui, Add, Edit, hWndhCodeEditor
		this.hCodeEditor := hCodeEditor
		
		Gui, Add, Button, hWndhRunButton, &Run
		this.hRunButton := hRunButton
		
		BoundFunc := this.Bound.RunButton
		GuiControl, +g, %hRunButton%, %BoundFunc%
		
		OnMessage(0x201, this.Bound.OnMessage)
		Gui, Show
	}
	
	RunButton()
	{
		GuiControl,, % this.hRunButton, &Kill
		
		BoundFunc := this.Bound.CheckIfRunning
		SetTimer, %BoundFunc%, 100
	}
	
	CheckIfRunning()
	{
		BoundFunc := this.Bound.CheckIfRunning
		SetTimer, %BoundFunc%, Delete
		GuiControl,, % this.hRunButton, &Run ; TODO: Make sure I don't have to specify default GUI
	}
	
	OnMessage(wParam, lParam, Msg, hWnd)
	{
		if (hWnd == this.hCodeEditor)
		{
			; Call BoundFunc after we return and the key press propagates downwards into the edit
			BoundFunc := this.Bound.UpdateStatusBar
			SetTimer, %BoundFunc%, -0
		}
	}
	
	UpdateStatusBar()
	{
		; BoundFunc := this.Bound.UpdateStatusBar
		; SetTimer, %BoundFunc%, Delete
		return
	}
}
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

Re: CodeQuickTester

01 Sep 2015, 04:12

Nice, the app deserves a dedicated repo :D
ABCza on the old forum.
My GitHub.
User avatar
TLM
Posts: 1323
Joined: 01 Oct 2013, 07:52

Re: CodeQuickTester

10 Sep 2015, 13:20

FR: 1 click code commenting plz :D
User avatar
maestrith
Posts: 731
Joined: 16 Oct 2013, 13:52

Re: CodeQuickTester

04 Aug 2017, 10:35

Scintilla or RichEdit?
AHK Studio OSD GUI Creator
Donations
Discord
All code is done on a Windows 10 PC Running x64 and AutoHotkey x32

Return to “Scripts and Functions”

Who is online

Users browsing this forum: Bing [Bot] and 30 guests