Initial commit
This commit is contained in:
73
Lib/DefaultJSON.ahk
Normal file
73
Lib/DefaultJSON.ahk
Normal file
@@ -0,0 +1,73 @@
|
||||
default_JSON := "
|
||||
(
|
||||
{
|
||||
"global_Settings": {
|
||||
"Suspend_Hotkeys_Hotkey": "",
|
||||
"Global_Hotkeys": 1,
|
||||
"LastUsedProfile": "Default",
|
||||
"Minimize_Delay": 100,
|
||||
"ThumbnailStartLocation": {
|
||||
"x": 20,
|
||||
"y": 20,
|
||||
"width": 250,
|
||||
"height": 140
|
||||
},
|
||||
"ThumbnailBackgroundColor":"#57504E",
|
||||
"ThumbnailSnap": true,
|
||||
"ThumbnailSnap_Distance": 20,
|
||||
"ThumbnailMinimumSize": {
|
||||
"width": 50,
|
||||
"height": 50
|
||||
}
|
||||
},
|
||||
"_Profiles": {
|
||||
"Default": {
|
||||
"Client Settings": {
|
||||
"MinimizeInactiveClients": false,
|
||||
"AlwaysMaximize": false,
|
||||
"TrackClientPossitions": false,
|
||||
"Dont_Minimize_Clients": [
|
||||
"Example Name1",
|
||||
"Example Name2",
|
||||
"Example Name3"
|
||||
]
|
||||
},
|
||||
"Thumbnail Settings": {
|
||||
"ShowThumbnailTextOverlay": true,
|
||||
"ThumbnailTextColor":"#FAC57A",
|
||||
"ThumbnailTextSize": 12,
|
||||
"ThumbnailTextFont": "Gill Sans MT",
|
||||
"ThumbnailTextMargins": {
|
||||
"x": 15,
|
||||
"y": 5
|
||||
},
|
||||
"ShowClientHighlightBorder": true,
|
||||
"ClientHighligtColor": "#E36A0D",
|
||||
"ClientHighligtBorderthickness": 4,
|
||||
"HideThumbnailsOnLostFocus": false,
|
||||
"ThumbnailOpacity": 80,
|
||||
"ShowThumbnailsAlwaysOnTop": true,
|
||||
"ShowAllColoredBorders":0
|
||||
},
|
||||
"Hotkeys":[
|
||||
{"Example Name1":"1"},
|
||||
{"Example Name2":"ctrl & 1"},
|
||||
{"Example Name3":"Xbutton1 & 1"},
|
||||
{"Example Name4":"^XButton1 & 1"}
|
||||
],
|
||||
"Thumbnail Positions": {},
|
||||
"Client Possitions": {},
|
||||
"Thumbnail Visibility":{},
|
||||
"Hotkey Groups":{},
|
||||
"Custom Colors":{
|
||||
"cColorActive": "0",
|
||||
"cColors": {
|
||||
"CharNames": ["Example Char"],
|
||||
"TextColor": ["FFFFFF"],
|
||||
"Bordercolor":["FFFFFF"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)"
|
||||
330
Lib/LiveThumb.ahk
Normal file
330
Lib/LiveThumb.ahk
Normal file
@@ -0,0 +1,330 @@
|
||||
; ----------------------------------------------------------------------------------------------------------------------
|
||||
; Name .........: LiveThumb class library
|
||||
; Description ..: Windows live thumbnails implementation (requires AERO to be enabled).
|
||||
; AHK Version ..: AHK v2 2.0.3
|
||||
; Author .......: cyruz - http://ciroprincipe.info
|
||||
; v2 Convertion : Gonz0
|
||||
; Forum .......: Ahk V1: https://www.autohotkey.com/boards/viewtopic.php?t=66585
|
||||
; Thanks .......: maul-esel - https://github.com/maul-esel/AeroThumbnail
|
||||
; License ......: WTFPL - http://www.wtfpl.net/txt/copying/
|
||||
; Changelog ....: Feb. 21, 2019 - v0.1.0 - First version.
|
||||
; ..............: Mar. 04, 2019 - v0.1.1 - Added active properties management and propertes getters.
|
||||
; ..............: Jul. 28, 2019 - v0.1.2 - Added "Discard" method. Fixed LoadLibrary return type and a wrong behavior
|
||||
; ..............: when returning false from the constructor (thanks Helgef).
|
||||
; ..............: Sep. 21, 2019 - v0.1.3 - Fixed potential issue with HRESULT return code. Used internal memory
|
||||
; ..............: management instead of LocalAlloc.
|
||||
; ..............: Sep. 21, 2019 - v0.1.4 - Fixed Object.SetCapacity not zero-filling allocated memory.
|
||||
; ..............: Nov. 15, 2022 - v0.1.5 - Fixed DWM_THUMB_PROPERTIES structure offsets (thanks swagfag).
|
||||
; ..............: Jun. 26, 2023 - v0.1.5 - Conerverted to Autohotkey version 2
|
||||
; Remarks ......: The class registers a thumbnail and waits for properties update. When all the desired properties have
|
||||
; ..............: been updated, the "Update()" method should be called to submit the properties. Getting a property
|
||||
; ..............: when an update has not been performed before, will result in the string "NOT UPDATED" to be returned.
|
||||
; ..............: Due to some internal unknown reason, the instantiated object must be in the global namespace to work.
|
||||
; Info .........: Implements the following functions and structures from Win32 API.
|
||||
; ..............: "DwmRegisterThumbnail" Win32 function:
|
||||
; ..............: https://docs.microsoft.com/en-us/windows/desktop/api/dwmapi/nf-dwmapi-dwmregisterthumbnail
|
||||
; ..............: "SIZE" Win32 structure:
|
||||
; ..............: https://docs.microsoft.com/en-us/previous-versions//dd145106(v=vs.85)
|
||||
; ..............: "DwmQueryThumbnailSourceSize" Win32 function:
|
||||
; ..............: https://docs.microsoft.com/en-us/windows/desktop/api/dwmapi/nf-dwmapi-dwmquerythumbnailsourcesize
|
||||
; ..............: "DWM_THUMB_PROPERTIES" Win32 structure:
|
||||
; ..............: https://docs.microsoft.com/en-us/windows/desktop/api/dwmapi/ns-dwmapi-_dwm_thumbnail_properties
|
||||
; ..............: "DWM_TNP" Constants for the dwFlags field:
|
||||
; ..............: https://docs.microsoft.com/en-us/windows/desktop/dwm/dwm-tnp-constants
|
||||
; ..............: "DwmUpdateThumbnailProperties" Win32 function:
|
||||
; ..............: https://docs.microsoft.com/en-us/windows/desktop/api/dwmapi/nf-dwmapi-dwmupdatethumbnailproperties
|
||||
; ..............: "DwmUnregisterThumbnail" Win32 function:
|
||||
; ..............: https://docs.microsoft.com/en-us/windows/desktop/api/dwmapi/nf-dwmapi-dwmunregisterthumbnail
|
||||
; ----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
; * How to use:
|
||||
; -------------
|
||||
|
||||
; Instantiate the object:
|
||||
|
||||
; thumb := LiveThumb(HWND Source Window, HWND Destination Window)
|
||||
|
||||
; Modify its properties:
|
||||
|
||||
; thumb.Source := [x, y, w, h] ;Size of the Source Window Thumbnail. Should be the same Size of the Source Window or it shows free space
|
||||
; thumb.Destination := [x, y, w, h] ;Size of the Destination Window Thumbnail. Shrinks or streches the Thumbnail to the given size. To show the full area its should be the same size like the Destination Window
|
||||
; thumb.Visible := True ;True or False Set the Thumbnail Visible
|
||||
; hLT.SourceClientAreaOnly := True ;Optional: True or False Set Show Client Area Only.
|
||||
; hLT.Opacity := 255 ;Optional: value between 0 and 255
|
||||
|
||||
; Update the properties:
|
||||
|
||||
; thumb.Update() ;Updates the given Propertys. This should be called everytime if some value is changed.
|
||||
|
||||
; Get a property:
|
||||
|
||||
; aProp := thumb.Visible ; Shows 1 or 0
|
||||
|
||||
|
||||
; * Example:
|
||||
; ----------
|
||||
|
||||
; #SingleInstance Force
|
||||
; #Include <LiveThumb>
|
||||
|
||||
; Run("notepad", , , &PID := 0)
|
||||
; WinWait("ahk_pid " PID)
|
||||
; hwndNotepad := WinExist("ahk_pid " PID)
|
||||
|
||||
; WinGetPos( &X, &Y, &W, &H, "ahk_pid " PID)
|
||||
|
||||
; Mygui := Gui()
|
||||
|
||||
; hLT := LiveThumb(hwndNotepad, Mygui.Hwnd)
|
||||
; hLT.Source := [0, 0, W, H]
|
||||
; hLT.Destination := [0, 0, W, H]
|
||||
; hLT.SourceClientAreaOnly := False
|
||||
; hLT.Visible := True
|
||||
; hLT.Opacity := 255
|
||||
; hLT.Update()
|
||||
|
||||
; Mygui.Show("w" W "h" H)
|
||||
|
||||
|
||||
; Name .........: LiveThumb - PUBLIC CLASS
|
||||
; Description ..: Manages thumbnails creation and destruction.
|
||||
Class LiveThumb
|
||||
{
|
||||
Static Dll_Module := 0,
|
||||
OBJ_COUNTER := 0,
|
||||
DTP_SIZE := 48,
|
||||
DTP_DWFLAGS := { Destination: 0x0001,
|
||||
Source: 0x0002,
|
||||
Opacity: 0x0004,
|
||||
Visible: 0x0008,
|
||||
SourceClientAreaOnly: 0x0010 },
|
||||
DTP_OFFSETS := { dwFlags: 0,
|
||||
Destination: 4,
|
||||
Source: 20,
|
||||
Opacity: 36,
|
||||
Visible: 37,
|
||||
SourceClientAreaOnly: 41 }
|
||||
|
||||
|
||||
; Name .........: __New - PRIVATE CONSTRUCTOR
|
||||
; Description ..: Initialize the object, registering a new thumbnail and allocating the memory.
|
||||
; Parameters ...: hSource = Handle to the window to be previewed.
|
||||
; ..............: hDest = Handle to the window containing the live preview.
|
||||
; Return .......: LiveThumb object on success - False on error.
|
||||
__New( hSource, hDest )
|
||||
{
|
||||
; Load the library on first run.
|
||||
If ( !LiveThumb.DLL_MODULE )
|
||||
LiveThumb.DLL_MODULE := DllCall("LoadLibrary", "Str","dwmapi.dll", "Ptr")
|
||||
|
||||
LiveThumb.OBJ_COUNTER += 1
|
||||
|
||||
; Register a thumbnail to get an ID.
|
||||
If ( DllCall( "dwmapi.dll\DwmRegisterThumbnail"
|
||||
, "Ptr", hDest
|
||||
, "Ptr", hSource
|
||||
, "Ptr*", &phThumb := 0
|
||||
, "UPtr" ) )
|
||||
Return False
|
||||
|
||||
this.THUMB_ID := phThumb
|
||||
this.THUMB_UPDATED := False
|
||||
this.THUMB_PENDING_UPDATE := True
|
||||
|
||||
; We define 2 portions of memory used for properties update and active properties tracking.
|
||||
this.THUMB_UPD_PROP_PTR := Buffer(LiveThumb.DTP_SIZE,0)
|
||||
this.THUMB_ACT_PROP_PTR := Buffer(LiveThumb.DTP_SIZE,0)
|
||||
|
||||
; Object.SetCapacity doesn't zero-fill the allocated memory so we call the Discard method.
|
||||
this.Discard( )
|
||||
Return this
|
||||
}
|
||||
|
||||
; Name .........: __Delete - PRIVATE DESTRUCTOR
|
||||
; Description ..: Unregister the thumbnail and deallocate memory.
|
||||
__Delete( )
|
||||
{
|
||||
; Unregister thumbnail ID.
|
||||
If ( this.THUMB_ID )
|
||||
DllCall( "dwmapi.dll\DwmUnregisterThumbnail"
|
||||
, "Ptr", this.THUMB_ID )
|
||||
|
||||
; If it's last instantiated object, free the library.
|
||||
If ( LiveThumb.DLL_MODULE && !(LiveThumb.OBJ_COUNTER -= 1) )
|
||||
{
|
||||
DllCall("FreeLibrary", "Ptr",LiveThumb.DLL_MODULE)
|
||||
LiveThumb.DLL_MODULE := 0
|
||||
}
|
||||
}
|
||||
|
||||
__Get(aName, Params) {
|
||||
If ( LiveThumb.HasOwnProp(aName))
|
||||
return LiveThumb.%aName%
|
||||
|
||||
}
|
||||
; Name .........: QuerySourceSize - PUBLIC METHOD
|
||||
; Description ..: Return the size (width/height) of the source thumbnail.
|
||||
; Return .......: Array with width and height values - False on error.
|
||||
QuerySourceSize( )
|
||||
{
|
||||
SIZE := Buffer(8,0)
|
||||
If ( DllCall( "dwmapi.dll\DwmQueryThumbnailSourceSize"
|
||||
, "Ptr", this.THUMB_ID
|
||||
, "Ptr", SIZE
|
||||
, "UPtr" ) ) {
|
||||
SIZE := Buffer(0)
|
||||
Return False
|
||||
}
|
||||
|
||||
SourceSize := [NumGet(SIZE, 0, "Int"), NumGet(SIZE, 4, "Int")]
|
||||
SIZE := Buffer(0)
|
||||
|
||||
Return SourceSize
|
||||
}
|
||||
|
||||
; Name .........: Update - PUBLIC METHOD
|
||||
; Description ..: Update thumbnail properties and zero fill the dwFlags memory to be ready for next update.
|
||||
; Return .......: True on success - False on error.
|
||||
Update( )
|
||||
{
|
||||
; If no update is pending, return false.
|
||||
; If ( !this.THUMB_PENDING_UPDATE )
|
||||
; Return False
|
||||
|
||||
; Update properties.
|
||||
If ( DllCall( "dwmapi.dll\DwmUpdateThumbnailProperties"
|
||||
, "Ptr", this.THUMB_ID
|
||||
, "Ptr", this.THUMB_UPD_PROP_PTR
|
||||
, "UPtr" ) )
|
||||
Return False
|
||||
|
||||
; Flag as updated and copy memory so that we can use this portion to track active properties with getters.
|
||||
this.THUMB_UPDATED := True
|
||||
DllCall( "NtDll.dll\RtlCopyMemory"
|
||||
, "Ptr", this.THUMB_ACT_PROP_PTR
|
||||
, "Ptr", this.THUMB_UPD_PROP_PTR
|
||||
, "UInt", LiveThumb.DTP_SIZE )
|
||||
|
||||
; Use the "Discard" method to reset dwFlags and return.
|
||||
this.Discard( )
|
||||
Return True
|
||||
}
|
||||
|
||||
; Name .........: Discard - PUBLIC METHOD
|
||||
; Description ..: Discard set properties, resetting dwFlags memory.
|
||||
Discard( )
|
||||
{
|
||||
; Zero-fill dwFlags memory in the properties update memory portion.
|
||||
NumPut("UInt", 0, this.THUMB_UPD_PROP_PTR, LiveThumb.DTP_OFFSETS.dwFlags)
|
||||
this.THUMB_PENDING_UPDATE := False
|
||||
}
|
||||
|
||||
; Name .........: Destination - PUBLIC PROPERTY
|
||||
; Description ..: The area in the destination window where the thumbnail will be rendered.
|
||||
; Value ........: Array with 4 client related coordinates [ left, top, right, bottom ].
|
||||
; Remarks ......: "Destination" property is of "RECT" type (16 bytes structure) and starts from offset 4.
|
||||
Destination {
|
||||
Get {
|
||||
If (!this.THUMB_UPDATED)
|
||||
Return "NOT UPDATED"
|
||||
|
||||
arrRet := []
|
||||
Loop 4
|
||||
arrRet.Push(NumGet(this.THUMB_ACT_PROP_PTR, LiveThumb.DTP_OFFSETS.Destination * A_Index, "Int"))
|
||||
Return arrRet
|
||||
}
|
||||
Set {
|
||||
This.SetDwFlags("Destination")
|
||||
Loop 4
|
||||
NumPut("Int", value[A_Index], this.THUMB_UPD_PROP_PTR, LiveThumb.DTP_OFFSETS.Destination * A_Index)
|
||||
}
|
||||
}
|
||||
|
||||
; Name .........: Source - PUBLIC PROPERTY
|
||||
; Description ..: The region of the source window to use as the thumbnail. Default is the entire window.
|
||||
; Value ........: Array with 4 client related coordinates [ left, top, right, bottom ].
|
||||
; Remarks ......: "Source" property is of "RECT" type (16 bytes structure) and starts from offset 20.
|
||||
Source {
|
||||
Get {
|
||||
If (!this.THUMB_UPDATED)
|
||||
Return "NOT UPDATED"
|
||||
|
||||
arrRet := []
|
||||
Loop 4
|
||||
arrRet.Push(NumGet(this.THUMB_ACT_PROP_PTR, LiveThumb.DTP_OFFSETS.Source + 4*(A_Index-1), "Int"))
|
||||
Return arrRet
|
||||
}
|
||||
Set {
|
||||
This.SetDwFlags("Source")
|
||||
Loop 4
|
||||
NumPut("Int", value[A_Index], this.THUMB_UPD_PROP_PTR, LiveThumb.DTP_OFFSETS.Source + 4*(A_Index-1))
|
||||
}
|
||||
}
|
||||
|
||||
; Name .........: Opacity - PUBLIC PROPERTY
|
||||
; Description ..: The opacity with which to render the thumbnail. 0: transparent - 255: opaque. Default is 255.
|
||||
; Value ........: Integer value from 0 to 255.
|
||||
; Remarks ......: "Opacity" property is of "BYTE" type (1 byte + 3 padding) and starts from offset 36.
|
||||
Opacity {
|
||||
Get {
|
||||
If (!this.THUMB_UPDATED)
|
||||
Return "NOT UPDATED"
|
||||
|
||||
Return NumGet(this.THUMB_ACT_PROP_PTR, LiveThumb.DTP_OFFSETS.Opacity, "UChar")
|
||||
}
|
||||
Set {
|
||||
This.SetDwFlags("Opacity")
|
||||
NumPut("UChar", value, this.THUMB_UPD_PROP_PTR, LiveThumb.DTP_OFFSETS.Opacity)
|
||||
}
|
||||
}
|
||||
|
||||
; Name .........: Visible - PUBLIC PROPERTY
|
||||
; Description ..: True to make the thumbnail visible, otherwise False. Default is False.
|
||||
; Value ........: Boolean True/False or integer 1/0 value.
|
||||
; Remarks ......: "Visible" property is of "BOOL" type (4 bytes) and starts from offset 40.
|
||||
Visible {
|
||||
Get {
|
||||
If (!this.THUMB_UPDATED)
|
||||
Return "NOT UPDATED"
|
||||
|
||||
Return NumGet(this.THUMB_ACT_PROP_PTR, LiveThumb.DTP_OFFSETS.Visible, "Int")
|
||||
}
|
||||
Set {
|
||||
This.SetDwFlags("Visible")
|
||||
NumPut("Int", value, this.THUMB_UPD_PROP_PTR, LiveThumb.DTP_OFFSETS.Visible)
|
||||
}
|
||||
}
|
||||
|
||||
; Name .........: SourceClientAreaOnly - PUBLIC PROPERTY
|
||||
; Description ..: True to use only the thumbnail source's client area, otherwise False. Default is False.
|
||||
; Value ........: Boolean True/False or integer 1/0 value.
|
||||
; Remarks ......: "SourceClientAreaOnly" property is of "BOOL" type (4 bytes) and starts from offset 44.
|
||||
SourceClientAreaOnly {
|
||||
Get {
|
||||
If (!this.THUMB_UPDATED)
|
||||
Return "NOT UPDATED"
|
||||
|
||||
Return NumGet(this.THUMB_ACT_PROP_PTR, LiveThumb.DTP_OFFSETS.SourceClientAreaOnly, "Int")
|
||||
}
|
||||
Set {
|
||||
This.SetDwFlags("SourceClientAreaOnly")
|
||||
NumPut("Uint", value, this.THUMB_UPD_PROP_PTR, LiveThumb.DTP_OFFSETS.SourceClientAreaOnly)
|
||||
}
|
||||
}
|
||||
|
||||
;Writes the DWFlags from the given Property into Memory.
|
||||
SetDwFlags(aName)
|
||||
{
|
||||
If (LiveThumb.DTP_DWFLAGS.HasOwnProp(aName)) {
|
||||
NumPut( "UInt", NumGet( this.THUMB_UPD_PROP_PTR,
|
||||
LiveThumb.DTP_OFFSETS.dwFlags, "UInt" ) | LiveThumb.DTP_DWFLAGS.%aName%,
|
||||
this.THUMB_UPD_PROP_PTR,
|
||||
LiveThumb.DTP_OFFSETS.dwFlags)
|
||||
|
||||
this.THUMB_PENDING_UPDATE := true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
158
Lib/json.ahk
Normal file
158
Lib/json.ahk
Normal file
@@ -0,0 +1,158 @@
|
||||
/************************************************************************
|
||||
* @Mdodified by G0nzo
|
||||
* @description: JSON格式字符串序列化和反序列化, 修改自[HotKeyIt/Yaml](https://github.com/HotKeyIt/Yaml)
|
||||
* 增加了对true/false/null类型的支持, 保留了数值的类型
|
||||
* @author thqby, HotKeyIt
|
||||
* @date 2023/05/12
|
||||
* @version 1.0.5
|
||||
***********************************************************************/
|
||||
|
||||
class JSON {
|
||||
static null := ComValue(1, 0), true := ComValue(0xB, 1), false := ComValue(0xB, 0)
|
||||
|
||||
/**
|
||||
* Converts a AutoHotkey Object Notation JSON string into an object.
|
||||
* @param text A valid JSON string.
|
||||
* @param keepbooltype convert true/false/null to JSON.true / JSON.false / JSON.null where it's true, otherwise 1 / 0 / ''
|
||||
* @param as_map object literals are converted to map, otherwise to object
|
||||
*/
|
||||
static Load(text, keepbooltype := false, as_map := true) {
|
||||
keepbooltype ? (_true := JSON.true, _false := JSON.false, _null := JSON.null) : (_true := true, _false := false, _null := "")
|
||||
as_map ? (map_set := (maptype := Map).Prototype.Set) : (map_set := (obj, key, val) => obj.%key% := val, maptype := Object)
|
||||
NQ := "", LF := "", LP := 0, P := "", R := ""
|
||||
D := [C := (A := InStr(text := LTrim(text, " `t`r`n"), "[") = 1) ? [] : maptype()], text := LTrim(SubStr(text, 2), " `t`r`n"), L := 1, N := 0, V := K := "", J := C, !(Q := InStr(text, '"') != 1) ? text := LTrim(text, '"') : ""
|
||||
Loop Parse text, '"' {
|
||||
Q := NQ ? 1 : !Q
|
||||
NQ := Q && (SubStr(A_LoopField, -3) = "\\\" || (SubStr(A_LoopField, -1) = "\" && SubStr(A_LoopField, -2) != "\\"))
|
||||
if !Q {
|
||||
if (t := Trim(A_LoopField, " `t`r`n")) = "," || (t = ":" && V := 1)
|
||||
continue
|
||||
else if t && (InStr("{[]},:", SubStr(t, 1, 1)) || RegExMatch(t, "^-?\d*(\.\d*)?\s*[,\]\}]")) {
|
||||
Loop Parse t {
|
||||
if N && N--
|
||||
continue
|
||||
if InStr("`n`r `t", A_LoopField)
|
||||
continue
|
||||
else if InStr("{[", A_LoopField) {
|
||||
if !A && !V
|
||||
throw Error("Malformed JSON - missing key.", 0, t)
|
||||
C := A_LoopField = "[" ? [] : maptype(), A ? D[L].Push(C) : map_set(D[L], K, C), D.Has(++L) ? D[L] := C : D.Push(C), V := "", A := Type(C) = "Array"
|
||||
continue
|
||||
} else if InStr("]}", A_LoopField) {
|
||||
if !A && V
|
||||
throw Error("Malformed JSON - missing value.", 0, t)
|
||||
else if L = 0
|
||||
throw Error("Malformed JSON - to many closing brackets.", 0, t)
|
||||
else C := --L = 0 ? "" : D[L], A := Type(C) = "Array"
|
||||
} else if !(InStr(" `t`r,", A_LoopField) || (A_LoopField = ":" && V := 1)) {
|
||||
if RegExMatch(SubStr(t, A_Index), "m)^(null|false|true|-?\d+\.?\d*)\s*[,}\]\r\n]", &R) && (N := R.Len(0) - 2, R := R.1, 1) {
|
||||
if A
|
||||
C.Push(R = "null" ? _null : R = "true" ? _true : R = "false" ? _false : IsNumber(R) ? R + 0 : R)
|
||||
else if V
|
||||
map_set(C, K, R = "null" ? _null : R = "true" ? _true : R = "false" ? _false : IsNumber(R) ? R + 0 : R), K := V := ""
|
||||
else throw Error("Malformed JSON - missing key.", 0, t)
|
||||
} else {
|
||||
; Added support for comments without '"'
|
||||
if A_LoopField == '/' {
|
||||
nt := SubStr(t, A_Index + 1, 1), N := 0
|
||||
if nt == '/' {
|
||||
if nt := InStr(t, '`n', , A_Index + 2)
|
||||
N := nt - A_Index - 1
|
||||
} else if nt == '*' {
|
||||
if nt := InStr(t, '*/', , A_Index + 2)
|
||||
N := nt + 1 - A_Index
|
||||
} else nt := 0
|
||||
if N
|
||||
continue
|
||||
}
|
||||
throw Error("Malformed JSON - unrecognized character-", 0, A_LoopField " in " t)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if InStr(t, ':') > 1
|
||||
throw Error("Malformed JSON - unrecognized character-", 0, SubStr(t, 1, 1) " in " t)
|
||||
} else if NQ && (P .= A_LoopField '"', 1)
|
||||
continue
|
||||
else if A
|
||||
LF := P A_LoopField, C.Push(InStr(LF, "\") ? UC(LF) : LF), P := ""
|
||||
else if V
|
||||
LF := P A_LoopField, map_set(C, K, InStr(LF, "\") ? UC(LF) : LF), K := V := P := ""
|
||||
else
|
||||
LF := P A_LoopField, K := InStr(LF, "\") ? UC(LF) : LF, P := ""
|
||||
}
|
||||
return J
|
||||
UC(S, e := 1) {
|
||||
static m := Map(Ord('"'), '"', Ord("a"), "`a", Ord("b"), "`b", Ord("t"), "`t", Ord("n"), "`n", Ord("v"), "`v", Ord("f"), "`f", Ord("r"), "`r")
|
||||
local v := ""
|
||||
Loop Parse S, "\"
|
||||
if !((e := !e) && A_LoopField = "" ? v .= "\" : !e ? (v .= A_LoopField, 1) : 0)
|
||||
v .= (t := InStr("ux", SubStr(A_LoopField, 1, 1)) ? SubStr(A_LoopField, 1, RegExMatch(A_LoopField, "i)^[ux]?([\dA-F]{4})?([\dA-F]{2})?\K") - 1) : "") && RegexMatch(t, "i)^[ux][\da-f]+$") ? Chr(Abs("0x" SubStr(t, 2))) SubStr(A_LoopField, RegExMatch(A_LoopField, "i)^[ux]?([\dA-F]{4})?([\dA-F]{2})?\K")) : m.has(Ord(A_LoopField)) ? m[Ord(A_LoopField)] SubStr(A_LoopField, 2) : "\" A_LoopField, e := A_LoopField = "" ? e : !e
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a AutoHotkey Array/Map/Object to a Object Notation JSON string.
|
||||
* @param obj A AutoHotkey value, usually an object or array or map, to be converted.
|
||||
* @param expandlevel The level of JSON string need to expand, by default expand all.
|
||||
* @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
|
||||
*/
|
||||
static Dump(obj, expandlevel := unset, space := " ") {
|
||||
expandlevel := IsSet(expandlevel) ? Abs(expandlevel) : 10000000
|
||||
return Trim(CO(obj, expandlevel))
|
||||
CO(O, J := 0, R := 0, Q := 0) {
|
||||
static M1 := "{", M2 := "}", S1 := "[", S2 := "]", N := "`n", C := ",", S := "- ", E := "", K := ":"
|
||||
if (OT := Type(O)) = "Array" {
|
||||
D := !R ? S1 : ""
|
||||
for key, value in O {
|
||||
F := (VT := Type(value)) = "Array" ? "S" : InStr("Map,Object", VT) ? "M" : E
|
||||
Z := VT = "Array" && value.Length = 0 ? "[]" : ((VT = "Map" && value.count = 0) || (VT = "Object" && ObjOwnPropCount(value) = 0)) ? "{}" : ""
|
||||
D .= (J > R ? "`n" CL(R + 2) : "") (F ? (%F%1 (Z ? "" : CO(value, J, R + 1, F)) %F%2) : ES(value)) (OT = "Array" && O.Length = A_Index ? E : C)
|
||||
}
|
||||
} else {
|
||||
D := !R ? M1 : ""
|
||||
for key, value in (OT := Type(O)) = "Map" ? (Y := 1, O) : (Y := 0, O.OwnProps()) {
|
||||
F := (VT := Type(value)) = "Array" ? "S" : InStr("Map,Object", VT) ? "M" : E
|
||||
Z := VT = "Array" && value.Length = 0 ? "[]" : ((VT = "Map" && value.count = 0) || (VT = "Object" && ObjOwnPropCount(value) = 0)) ? "{}" : ""
|
||||
D .= (J > R ? "`n" CL(R + 2) : "") (Q = "S" && A_Index = 1 ? M1 : E) ES(key) K (F ? (%F%1 (Z ? "" : CO(value, J, R + 1, F)) %F%2) : ES(value)) (Q = "S" && A_Index = (Y ? O.count : ObjOwnPropCount(O)) ? M2 : E) (J != 0 || R ? (A_Index = (Y ? O.count : ObjOwnPropCount(O)) ? E : C) : E)
|
||||
if J = 0 && !R
|
||||
D .= (A_Index < (Y ? O.count : ObjOwnPropCount(O)) ? C : E)
|
||||
}
|
||||
}
|
||||
if J > R
|
||||
D .= "`n" CL(R + 1)
|
||||
if R = 0
|
||||
D := RegExReplace(D, "^\R+") (OT = "Array" ? S2 : M2)
|
||||
return D
|
||||
}
|
||||
ES(S) {
|
||||
switch Type(S) {
|
||||
case "Float":
|
||||
if (v := '', d := InStr(S, 'e'))
|
||||
v := SubStr(S, d), S := SubStr(S, 1, d - 1)
|
||||
if ((StrLen(S) > 17) && (d := RegExMatch(S, "(99999+|00000+)\d{0,3}$")))
|
||||
S := Round(S, Max(1, d - InStr(S, ".") - 1))
|
||||
return S v
|
||||
case "Integer":
|
||||
return S
|
||||
case "String":
|
||||
S := StrReplace(S, "\", "\\")
|
||||
S := StrReplace(S, "`t", "\t")
|
||||
S := StrReplace(S, "`r", "\r")
|
||||
S := StrReplace(S, "`n", "\n")
|
||||
S := StrReplace(S, "`b", "\b")
|
||||
S := StrReplace(S, "`f", "\f")
|
||||
S := StrReplace(S, "`v", "\v")
|
||||
S := StrReplace(S, '"', '\"')
|
||||
return '"' S '"'
|
||||
default:
|
||||
return S == JSON.true ? "true" : S == JSON.false ? "false" : "null"
|
||||
}
|
||||
}
|
||||
CL(i) {
|
||||
Loop (s := "", space ? i - 1 : 0)
|
||||
s .= space
|
||||
return s
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user