ioa747 Posted May 11 Posted May 11 (edited) I divide the project into parts for easier management. The project is in early beta stage, for research and development. 🚀 AI_Assistant.au3 which is included in SciTE_AI_Assistant.au3, but can also be used as a standalone UDF in which I #include "StringSize.au3" ; "https://www.autoitscript.com/forum/topic/114034-stringsize-m23-bugfix-version-27-dec-23" by Melba23 - thanks for that So that it folds the console output, and is visible within its boundaries (especially when it is on the side and is slim) for more comfortable reading works directly with the ollama. I use a small models qwen2.5-coder:3b as default, llama3.2:3b , phi4-mini:3.8b so that I don't have to wait too long for a response. However, I have set as a parameter which model it calls, so that it changes the model per job if necessary I added a new function: _AI_Request which asynchronously sends a request to _AI_Call() and waits for the response. I also added a new parameter $iThink - Enable or disable thinking if Model supporting (0=none, 1=yes/not visible, 2=yes/visible). (Default is 0) to conform with the new ability to enable or disable thinking. (feature since version 0.9.0) Ollama now has the ability to enable or disable thinking. This gives users the flexibility to choose the model’s thinking behavior for different applications and use cases. When thinking is enabled, the output will separate the model’s thinking from the model’s output. When thinking is disabled, the model will not think and directly output the content. Models that support thinking: DeepSeek R1 Qwen 3 more will be added under thinking models. AI_Assistant\Example\Example2.au3 - thinking example #include "..\AI_Assistant.au3" _AI_DebugInfo(True) Example2() Func Example2() Local $sPrompt = "how many r's are in strawberry?" Local $sModel = "qwen3:4b" ; _AI_Request with thinking Enable (0=none, 1=yes/not visible, 2=yes/visible) Local $sResponse = _AI_Request($sPrompt, $sModel, Default, 1, 2) ConsoleWrite($sResponse & @CRLF & @CRLF) EndFunc Output: Thinking... Okay, so the user is asking how many R's are in the word "strawberry". Let me think. First, I need to write out the word and check each letter. Let me spell it out: S-T-R-A-W-B-E-R-R-Y. Wait, let me make sure I have that right. Strawberry is S-T-R-A-W-B-E-R-R-Y. Let me break it down letter by letter. S, T, R, A, W, B, E, R, R, Y. So that's 10 letters in total. Now, I need to count the number of R's. Let's go through each letter one by one. The first letter is S, not R. Second is T, no. Third is R—that's one. Fourth is A, no. Fifth is W, no. Sixth is B, no. Seventh is E, no. Eighth is R—that's two. Ninth is R—that's three. Tenth is Y, no. So that's three R's. Wait, let me check again to make sure I didn't miss any. S-T-R-A-W-B-E-R-R-Y. Yes, positions 3, 8, and 9 are R. So three R's in total. I think that's correct. Maybe I should write it out again to confirm. Strawberry: S T R A W B E R R Y. Yep, three R's. So the answer is 3. ...done thinking. The word **"strawberry"** contains **3 R's**. Breaking it down: **S-T-R-A-W-B-E-R-R-Y** R's are in positions 3, 8, and 9. **Answer: 3** 🍓 SciTE_AI_Assistant.au3 I changed the approach, and made it as SciTE tool. This way, the selection process, and console writing, is handled internally by SciTE. To do this you need to add the following to SciTEUser.properties (Adding_utilities_to_the_SciTE_Tools_menu) #------------------------------------------------------------------------------ # 41 SciTE_AI_Assistant command.41.$(au3)="$(SciteDefaultHome)\..\AutoIt3.exe" "D:\i\Pro\.AutoIT\SciTE_AI_Assistant\SciTE_AI_Assistant.au3" command.subsystem.41.$(au3)=0 command.name.41.$(au3)=SciTE AI Assistant command.shortcut.41.*.au3=F10 command.save.before.41.$(au3)=2 # command.replace.selection.41.$(au3)=1 # command.quiet.41.$(au3)=0 # command.input.41.$(au3)=$(CurrentSelection) #------------------------------------------------------------------------------ #---------------------- Contex Menu ------------------------------------------- user.context.menu=\ ||\ >>> SciTE AI Assistant <<< |1141|\ ||\ Execute Selected Path|IDM_OPENSELECTED|\ #------------------------------------------------------------------------------ and make the necessary adjustments e.g. in command.41.$(au3)="$(SciteDefaultHome)\..\AutoIt3.exe" "D:\i\Pro\.AutoIT\SciTE_AI_Assistant\SciTE_AI_Assistant.au3" your path for the d:\your\location\SciTE_AI_Assistant\SciTE_AI_Assistant.au3 You may need to adjust the 41 to the first tool number available to you. in this case, change the >>> SciTE AI Assistant <<< |1141|\ as well in the Context Menu After that, select the text in the SciTE, right-click and select 'instruction' from the context menu '>>> SciTE AI Assistant <<<' output: ; #FUNCTION# ==================================================================================================================== ; Name...........: IsMouseOverWin ; Description....: Determines if the mouse pointer is positioned over a specified window. ; Syntax.........: IsMouseOverWin($hWnd) ; Parameters.....: $hWnd - The handle of the window to check for mouse position. ; Return values .: Success: Returns True if the mouse is over the window, False otherwise. ; @error = 0: No error occurred. ; Author ........: ioa747 ; Modified ......: ; Remarks .......: This function uses MouseGetPos() to retrieve the current mouse position and WinGetPos($hWnd) to obtain ; the dimensions of the specified window. It checks if the mouse position falls within the boundaries of the window. ; Related .......: ; Link ..........: ; Example .......: ; =============================================================================================================================== FIM (Fill-in-the-Middle <??> ) when it comes to FIM (Fill-in-the-Middle <??> ), the '<??>' tag is to specify the-Middle e.g. as in the example below, highlight the text , right click , and select, >>> SciTE AI Assistant <<< , FIM (Fill-in-the-Middle <??> ) Func SumNumbers($aNumbers) Local $iTotal = 0 For $i = 0 To UBound($aNumbers) - 1 <??> Next Return $iTotal EndFunc Prompt Builder GUI The script described is an advanced AI prompt builder tool The tool provides a user-friendly interface that allows users to create, manage, and execute AI prompts based on predefined templates or customizable settings from .ini file. macros in the Prompt Builder GUI @Selection@ = the Selection of SciTE @ScriptName@ = the Script Name (useful as title) @ScriptFullPath@ = all the content of Script @ClipGet@ = the content of Clipboard @FileRead(FilePath)@ = the content of FilePath self-introduction - ReadMe Reveal hidden contents Exploring SciTE AI Assistant: A Script for Enhanced Coding Experience Introduction The SciTE AI Assistant is a powerful script designed to enhance the coding experience within the SciTE editor. By leveraging AI capabilities, it provides developers with suggestions, code optimizations, and explanations, streamlining their workflow. This presentation explores the key functionalities of the SciTE AI Assistant and its integration with the AI Prompt Builder Script, which further enhances its capabilities. Key Features of SciTE AI Assistant Contextual Assistance: The assistant creates a context menu when right-clicking on any text in the SciTE editor, offering various AI-based options such as code comments, optimizations, and explanations. Debugging Support: The _AI_DebugInfo(True) function enables debugging information, aiding developers during the debugging process. Dynamic Content Handling: It retrieves the current selection or the entire file content, allowing for tailored suggestions based on the developer’s needs. Functionality Overview The SciTE AI Assistant operates through several key functions: - Code Optimization: It analyzes the selected code or entire file and provides suggestions for improvements. - Code Explanation: The assistant can explain complex code logic, making it easier for developers to understand and maintain their code. - Function Header Generation: It automatically generates function headers based on the selected code, saving time and ensuring consistency. - Filling-in-the-Middle (FIM) Comments: The assistant can insert comments in the code, enhancing readability and documentation. Integration with AI Prompt Builder Script The AI Prompt Builder Script complements the SciTE AI Assistant by providing a user-friendly interface for managing and executing AI prompts. Key features include: User-Friendly GUI: The script offers a graphical interface for defining, saving, loading, and executing AI prompts tailored to various tasks. Macro Processing: It processes special placeholders in prompts, ensuring that the AI model receives contextually relevant inputs. Persistent Storage: The script manages INI files for storing saved prompts, allowing users to easily retrieve and utilize them. Use Cases The combined capabilities of the SciTE AI Assistant and the AI Prompt Builder Script can be applied in various scenarios: - Code Development: Developers can optimize their code and receive explanations, improving overall productivity. - Technical Support: Support teams can utilize the AI Prompt Builder to manage troubleshooting prompts efficiently. - Educational Tools: Educators can create interactive learning experiences, allowing students to engage with AI models in practical scenarios. Conclusion The SciTE AI Assistant, enhanced by the AI Prompt Builder Script, is an invaluable tool for developers. Its ability to provide AI-based assistance, optimize code, and manage prompts makes it a powerful addition to any developer’s toolkit. As technology evolves, these tools will continue to improve, further automating repetitive tasks and enhancing productivity in coding environments. I will update the thread as soon as anything new comes up. SciTE_AI_Assistant_0.12.zipFetching info... Please, every comment is appreciated! leave your comments and experiences here! Thank you very much Edited Tuesday at 04:03 AM by ioa747 update to Version: 0.12 mLipok and argumentum 2 I know that I know nothing
argumentum Posted May 11 Posted May 11 (edited) ... ... Global $__g_OllamaAssistant_DefaultURL = "http://localhost:11434" Func OllamaAssistant_DefaultURL($sStr = Default) If $sStr <> Default Then $__g_OllamaAssistant_DefaultURL = $sStr Return $__g_OllamaAssistant_DefaultURL EndFunc ConsoleWrite(Ollama_IsModelAvailable() & @CRLF) If @error Then Exit 5 Func Ollama_IsModelAvailable($sStr = "qwen2.5-coder") Local $sRet = OllamaAPI() ; default is get models at default URL If @error Then ConsoleWrite("! Ollama is not running there =(" & @CRLF) Return SetError(1, 0, "") EndIf If StringInStr($sRet, $sStr) Then Return $sRet ConsoleWrite(@CRLF & $sRet & @CRLF & "! the model was not found. Pull it ! =)" & @CRLF ) Return SetError(2, 0, $sRet) EndFunc ; "/api/tags" ; List models that are available locally. ; "/api/ps" ; List models that are currently loaded into memory. ; "/api/pull" '{"model": "qwen2.5-coder:3b"}' ; well, pull the model Func OllamaAPI($sAPI = "/api/tags", $sURL = $__g_OllamaAssistant_DefaultURL) Local $sStr = BinaryToString(InetRead($sURL & $sAPI)) ; this is not the function I should use, but it works to present the idea Return SetError(@error, @extended, $sStr) EndFunc ; ..you may need to retry at times ?, ..I don't have much experience with it to know much ConsoleWrite('HotKeySet = ' & HotKeySet("{END}", "GenerateFunctionHeader") & @CRLF) ; * <-- ... ... Nice !. I was thinking yesterday that "I don't wanna leave SciTE" in a child tantrum kind of childish voice So, I highlighted a function, pressed the end key and got me a "1" in the console. But I don't know if is all that is so, add a start and end line, like: ---- 8< ---- start 1 ---- >8 ---- end so I get some feedback. Again, thanks for working on my wish Edited May 11 by argumentum fixed OllamaAPI() default ioa747 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
argumentum Posted May 11 Posted May 11 (edited) ... ... If $oHttp.Status <> 200 Then ;~ MsgBox(0, "Error", "WinHttp request failed with status code: " & $oHttp.Status) FileWriteLine(StringTrimRight(@ScriptFullPath, 4) & ".log", 'Error: $oHttp.Status:' & $oHttp.Status & @CRLF) ... ... Error: $oHttp.Status:400 What does it mean ? I pasted the question in open-webui ( ..not quite like that but I forgot what I did ) Reveal hidden contents You are an AutoIt documentation assistant. Your task is to generate precise header comments for AutoIt functions, using the standard UDF format. Now generate a header comment for the following function: Func Ollama_IsModelAvailable($sStr = "qwen2.5-coder") Local $sRet = OllamaAPI() ; default is get models at default URL If @error Then ConsoleWrite("! Ollama is not running there =(" & @CRLF) Return SetError(1, 0, "") EndIf If StringInStr($sRet, $sStr) Then Return $sRet ConsoleWrite(@CRLF & $sRet & @CRLF & "! the model was not found. Pull it ! =)" & @CRLF ) Return SetError(2, 0, $sRet) EndFunc and returned it's answer: Reveal hidden contents qwen2.5-coder:latest Today at 1:45 PM Certainly! Below is a header comment for the Ollama_IsModelAvailable function in AutoIt using the standard UDF format: ; #FUNCTION# =================================================================================================================== ; ; Name...........: Ollama_IsModelAvailable ; Description....: Checks if an AI model specified by name is available. ; Syntax.........: $sStr = "qwen2.5-coder" (optional) - The name of the model to check. ; Parameters.....: ; $sStr - [optional] The name of the model to check. Default is "qwen2.5-coder". ; ; Return values : ; Success: Returns the available models if the specified model is found. ; Failure: Sets @error and returns an empty string with a custom message. ; @error = 1: Ollama is not running at the default URL. ; @error = 2: The specified model was not found. ; ; Author.........: [Your Name] ; Remarks........: This function assumes that there is an API endpoint for checking available models. ; It uses the default URL if no other is provided. ; ; Related........: ; Link...........: ; Example........: ; ; #FUNCTION# =================================================================================================================== Func Ollama_IsModelAvailable($sStr = "qwen2.5-coder") Local $sRet = OllamaAPI() ; default is get models at default URL If @error Then ConsoleWrite("! Ollama is not running there =(" & @CRLF) Return SetError(1, 0, "") EndIf If StringInStr($sRet, $sStr) Then Return $sRet ConsoleWrite(@CRLF & $sRet & @CRLF & "! the model was not found. Pull it ! =)" & @CRLF ) Return SetError(2, 0, $sRet) EndFunc This header comment follows the standard UDF format and includes: The function name and its description. Parameters and their descriptions. Return values with error codes and custom messages. Author and remarks (indicating that it assumes an API endpoint for checking available models). Related functions, links, and examples if applicable. so, maybe sending the $sSystem and $sPrompt as a single string is better ? ( am just talking out of my ... imagination here ) Edited May 11 by argumentum more Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
argumentum Posted May 11 Posted May 11 (edited) edited my 1st post and added OllamaAssistant_DefaultURL() It'll be much better if helper functions are used for default values. I guess the same should be done for the model to be used and any other default. Edited May 11 by argumentum English ioa747 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
argumentum Posted May 11 Posted May 11 ... ... $sRequest &= '"system": "' & $sSystem & '", ' $sPrompt = StringReplace($sPrompt, @CRLF, "\r\n") $sPrompt = StringReplace($sPrompt, @TAB, "\t") $sPrompt = StringReplace($sPrompt, '"', "\""") $sRequest &= '"prompt": "' & $sPrompt & '", ' ... ... ..it needed to escape stuff. All good Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
argumentum Posted May 11 Posted May 11 On 5/11/2025 at 8:57 PM, ioa747 said: __JSON_FormatString($sPrompt) Expand I understand you answer. But it only worked for me when I "man handle" the string 🤷♂️ Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
argumentum Posted May 11 Posted May 11 On 5/11/2025 at 9:00 PM, argumentum said: I understand you answer. But it only worked for me when I "man handle" the string 🤷♂️ Expand Quote #include "JSON.au3" ;" https://www.autoitscript.com/forum/topic/209502-json-udf-in-pure-autoit/#comment-1511873 " Expand I went to the git and pulled the file from there. Maybe the version there is bad ? Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
ioa747 Posted May 11 Author Posted May 11 (edited) i have this Reveal hidden contents ; https://github.com/Sylvan86/autoit-json-udf #include-once ; #INDEX# ======================================================================================================================= ; Title .........: JSON-UDF ; Version .......: 0.10 ; AutoIt Version : 3.3.16.1 ; Language ......: english (german maybe by accident) ; Description ...: Function for interacting with JSON data in AutoIt. ; This includes import, export as well as helper functions for handling nested AutoIt data structures. ; Author(s) .....: AspirinJunkie, Sven Seyfert (SOLVE-SMART) ; Last changed ..: 2023-02-20 ; Link ..........: https://autoit.de/thread/85435-json-udf/ ; License .......: This work is free. ; You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2, ; as published by Sam Hocevar. ; See http://www.wtfpl.net/ for more details. ; =============================================================================================================================== ; #Function list# ======================================================================================================================= ; ---- import and export from or to json ------ ; _JSON_Parse - converts a JSON-structured string into a nested AutoIt data structure ; _JSON_Generate - converts a nested AutoIt data structure into a JSON structured string ; _JSON_GenerateCompact - shorthand for _JSON_Generate() to create JSON structured strings as compact as possible ; _JSON_Unminify - reads minified (compact) JSON file or string and converts to well readable JSON string ; _JSON_Minify - reads unminified (readable) JSON file or string and converts to minified (compact) JSON string ; ; ---- extraction and manipulation of nested AutoIt data structures ---- ; _JSON_Get - extract query nested AutoIt-datastructure with a simple selector string ; _JSON_addChangeDelete - create a nested AutoIt data structure, change values within existing structures or delete elements from a nested AutoIt data structure ; ; ---- helper functions ---- ; __JSON_FormatString - converts a string into a json string by escaping the special symbols ; __JSON_ParseString - converts a json formatted string into an AutoIt-string by unescaping the json-escapes ; __JSON_A2DToAinA - converts a 2D array into a Arrays in Array ; __JSON_AinAToA2d - converts a Arrays in Array into a 2D array ; __JSON_Base64Decode - decode data which is coded as a base64-string into binary variable ; __JSON_Base64Encode - converts a binary- or string-Input into BASE64 (or optional base64url) format ; =============================================================================================================================== #include <String.au3> ; #FUNCTION# ====================================================================================== ; Name ..........: _JSON_Parse ; Description ...: convert a JSON-formatted string into a nested structure of AutoIt-datatypes ; Syntax ........: _JSON_Parse(ByRef $s_String, $i_Os = 1) ; Parameters ....: $s_String - a string formatted as JSON ; [$i_Os] - search position where to start (normally don't touch!) ; Return values .: Success - Return a nested structure of AutoIt-datatypes ; @extended = next string offset ; Failure - Return "" and set @error to: ; @error = 1 - part is not json-syntax ; = 2 - key name in object part is not json-syntax ; = 3 - value in object is not correct json ; = 4 - delimiter or object end expected but not gained ; Author ........: AspirinJunkie ; ================================================================================================= Func _JSON_Parse(ByRef $s_String, $i_Os = 1) Local $i_OsC = $i_Os, $o_Current, $o_Value ; Inside a character class, \R is treated as an unrecognized escape sequence, and so matches the letter "R" by default, but causes an error if Local Static _ ; '\s' = [\x20\x09\x0A\x0D] $s_RE_G_String = '\G\s*"([^"\\]*+(?>\\.[^"\\]*+)*+)"', _ ; old variant: '\G\s*"((?>[^\\"]+|\\.)*+)"' - new one is more efficient coz it searches firstly for non quotes and bs - these are more unlikely $s_RE_G_Number = '\G\s*(-?(?>0|[1-9]\d*)(?>\.\d+)?(?>[eE][-+]?\d+)?)', _ $s_RE_G_KeyWord = '\G\s*\b(null|true|false)\b', _ $s_RE_G_Object_Begin = '\G\s*\{', _ $s_RE_G_Object_Key = '\G\s*"((?>[^\\"]+|\\.)*+)"\s*:', _ $s_RE_G_Object_Further = '\G\s*,', _ $s_RE_G_Object_End = '\G\s*\}', _ $s_RE_G_Array_Begin = '\G\s*\[', _ $s_RE_G_Array_End = '\G\s*\]' $o_Current = StringRegExp($s_String, $s_RE_G_String, 1, $i_Os) ; String If Not @error Then Return SetExtended(@extended, __JSON_ParseString($o_Current[0])) StringRegExp($s_String, $s_RE_G_Object_Begin, 1, $i_Os) ; Object If Not @error Then $i_OsC = @extended Local $s_Key, $a_T Local $o_Current[] StringRegExp($s_String, $s_RE_G_Object_End, 1, $i_OsC) ; check for empty object If Not @error Then ; empty object $i_OsC = @extended Else Do $a_T = StringRegExp($s_String, $s_RE_G_Object_Key, 1, $i_OsC) ; key of element If @error Then Return SetError(2, $i_OsC, "") $i_OsC = @extended $s_Key = __JSON_ParseString($a_T[0]) $o_Value = _JSON_Parse($s_String, $i_OsC) If @error Then Return SetError(3, $i_OsC, "") $i_OsC = @extended $o_Current[$s_Key] = $o_Value ; add key:value to map StringRegExp($s_String, $s_RE_G_Object_Further, 1, $i_OsC) ; more elements If Not @error Then $i_OsC = @extended ContinueLoop Else StringRegExp($s_String, $s_RE_G_Object_End, 1, $i_OsC) ; end of array If Not @error Then $i_OsC = @extended ExitLoop Else Return SetError(4, $i_OsC, "") EndIf EndIf Until False EndIf Return SetExtended($i_OsC, $o_Current) EndIf StringRegExp($s_String, $s_RE_G_Array_Begin, 1, $i_Os) ; Array If Not @error Then $i_OsC = @extended Local $o_Current[1], $d_N = 1, $i_C = 0 StringRegExp($s_String, $s_RE_G_Array_End, 1, $i_OsC) ; check for empty array If Not @error Then ; empty array ReDim $o_Current[0] $i_OsC = @extended Return SetExtended($i_OsC, $o_Current) EndIf Do $o_Value = _JSON_Parse($s_String, $i_OsC) If @error Then Return SetError(3, $i_OsC, "") $i_OsC = @extended If $i_C = $d_N - 1 Then $d_N += $d_N ; or *= 2 ReDim $o_Current[$d_N] EndIf $o_Current[$i_C] = $o_Value $i_C += 1 StringRegExp($s_String, $s_RE_G_Object_Further, 1, $i_OsC) ; more elements If Not @error Then $i_OsC = @extended ContinueLoop Else StringRegExp($s_String, $s_RE_G_Array_End, 1, $i_OsC) ; end of array If Not @error Then $i_OsC = @extended ExitLoop Else Return SetError(5, $i_OsC, "") EndIf EndIf Until False If UBound($o_Current) <> $i_C Then ReDim $o_Current[$i_C] Return SetExtended($i_OsC, $o_Current) EndIf $o_Current = StringRegExp($s_String, $s_RE_G_Number, 1, $i_Os) ; Number If Not @error Then Return SetExtended(@extended, Number($o_Current[0])) $o_Current = StringRegExp($s_String, $s_RE_G_KeyWord, 1, $i_Os) ; KeyWord If Not @error Then Return SetExtended(@extended, Execute($o_Current[0])) ; $o_Current[0] = "null" ? Null : $o_Current[0] = "true" ? True : False) Return SetError(1, $i_OsC, "") EndFunc ;==>_JSON_Parse ; #FUNCTION# ====================================================================================== ; Name ..........: _JSON_Generate ; Description ...: converts a nested AutoIt data structure into a JSON structured string ; Syntax ........: _JSON_Generate($o_Object, $s_ObjIndent = @TAB, $s_ObjDelEl = @CRLF, $s_ObjDelKey = " ", $s_ObjDelVal = "", $s_ArrIndent = @TAB, $s_ArrDelEl = @CRLF, $i_Level = 0) ; Parameters ....: $o_Object - [nested] AutoIt data structure ; [$s_ObjIndent] - indent for object elements (only reasonable if $s_ObjDelEl contains a line skip ; [$s_ObjDelEl] - delimiter between object elements ; [$s_ObjDelKey] - delimiter between keyname and ":" in object ; [$s_ObjDelVal] - delimiter between ":" and value in object ; [$s_ArrIndent] - indent for array elements (only reasonable if $s_ArrDelEl contains a line skip) ; [$s_ArrDelEl] - delimiter between array elements ; [$i_Level] - search position where to start (normally don't touch!) ; Return values .: Success - Return a JSON formatted string ; Failure - Return "" ; Author ........: AspirinJunkie ; ================================================================================================= Func _JSON_Generate($o_Object, $s_ObjIndent = @TAB, $s_ObjDelEl = @CRLF, $s_ObjDelKey = "", $s_ObjDelVal = " ", $s_ArrIndent = @TAB, $s_ArrDelEl = @CRLF, $i_Level = 0) Local Static $s_JSON_String If $i_Level = 0 Then $s_JSON_String = "" Switch VarGetType($o_Object) Case "String" __JSON_FormatString($o_Object) $s_JSON_String &= '"' & $o_Object & '"' Case "Int32", "Int64", "Float", "Double" $s_JSON_String &= String($o_Object) Case "Bool" $s_JSON_String &= StringLower($o_Object) Case "Keyword" If IsKeyword($o_Object) = 2 Then $s_JSON_String &= "null" Case "Binary" $s_JSON_String &= '"' & __JSON_Base64Encode($o_Object) & '"' Case "Array" If UBound($o_Object, 0) = 2 Then $o_Object = __JSON_A2DToAinA($o_Object) If UBound($o_Object) = 0 Then $s_JSON_String &= "[]" Else $s_JSON_String &= "[" & $s_ArrDelEl For $o_Value In $o_Object $s_JSON_String &= _StringRepeat($s_ArrIndent, $i_Level + 1) _JSON_Generate($o_Value, $s_ObjIndent, $s_ObjDelEl, $s_ObjDelKey, $s_ObjDelVal, $s_ArrIndent, $s_ArrDelEl, $i_Level + 1) $s_JSON_String &= "," & $s_ArrDelEl Next $s_JSON_String = StringTrimRight($s_JSON_String, StringLen("," & $s_ArrDelEl)) & $s_ArrDelEl & _StringRepeat($s_ArrIndent, $i_Level) & "]" EndIf Case "Object" If ObjName($o_Object) = "Dictionary" Then Local $s_KeyTemp, $o_Value If $o_Object.Count() = 0 Then $s_JSON_String &= "{}" Else $s_JSON_String &= "{" & $s_ObjDelEl For $s_Key In $o_Object.Keys $s_KeyTemp = $s_Key $o_Value = $o_Object($s_Key) __JSON_FormatString($s_KeyTemp) $s_JSON_String &= _StringRepeat($s_ObjIndent, $i_Level + 1) & '"' & $s_KeyTemp & '"' & $s_ObjDelKey & ':' & $s_ObjDelVal _JSON_Generate($o_Value, $s_ObjIndent, $s_ObjDelEl, $s_ObjDelKey, $s_ObjDelVal, $s_ArrIndent, $s_ArrDelEl, $i_Level + 1) $s_JSON_String &= "," & $s_ObjDelEl Next $s_JSON_String = StringTrimRight($s_JSON_String, StringLen("," & $s_ObjDelEl)) & $s_ObjDelEl & _StringRepeat($s_ObjIndent, $i_Level) & "}" EndIf EndIf Case "Map" Local $s_KeyTemp, $o_Value If UBound($o_Object) = 0 Then $s_JSON_String &= "{}" Else $s_JSON_String &= "{" & $s_ObjDelEl For $s_Key In MapKeys($o_Object) $s_KeyTemp = $s_Key $o_Value = $o_Object[$s_Key] __JSON_FormatString($s_KeyTemp) $s_JSON_String &= _StringRepeat($s_ObjIndent, $i_Level + 1) & '"' & $s_KeyTemp & '"' & $s_ObjDelKey & ':' & $s_ObjDelVal _JSON_Generate($o_Value, $s_ObjIndent, $s_ObjDelEl, $s_ObjDelKey, $s_ObjDelVal, $s_ArrIndent, $s_ArrDelEl, $i_Level + 1) $s_JSON_String &= "," & $s_ObjDelEl Next $s_JSON_String = StringTrimRight($s_JSON_String, StringLen("," & $s_ObjDelEl)) & $s_ObjDelEl & _StringRepeat($s_ObjIndent, $i_Level) & "}" EndIf EndSwitch If $i_Level = 0 Then Local $s_Temp = $s_JSON_String $s_JSON_String = "" Return $s_Temp EndIf EndFunc ;==>_JSON_Generate ; #FUNCTION# ==================================================================================================================== ; Name ..........: _JSON_GenerateCompact ; Description ...: shorthand for _JSON_Generate()-parameters to produce a compact as possible JSON string ; Syntax ........: _JSON_GenerateCompact($o_Object) ; Parameters ....: $o_Object - [nested] AutoIt data structure ; Return values .: Success - Return a JSON formatted string ; Failure - Return "" ; Author ........: AspirinJunkie ; Modified ......: 2023-05-23 ; Related .......: _JSON_Generate ; =============================================================================================================================== Func _JSON_GenerateCompact($o_Object) Return _JSON_Generate($o_Object, "", "", "", "", "", "") EndFunc ;==>_JSON_GenerateCompact ; #FUNCTION# ==================================================================================================================== ; Name ..........: _JSON_Unminify ; Description ...: reads minified (compact) JSON file or string and converts to well readable JSON string ; Syntax ........: _JSON_Unminify($s_Input) ; Parameters ....: $s_Input - json file path/handle or json string ; Return values .: Success - Return a JSON formatted string ; Failure - Return "" and set @error to: ; @error = 1 - error during FileRead() - @extended = @error from FileRead() ; = 2 - no valid format for $s_Input ; Author ........: Sven Seyfert (SOLVE-SMART), AspirinJunkie ; Related .......: _JSON_Generate ; =============================================================================================================================== Func _JSON_Unminify($s_Input) ; read file if $sInput = file name or file handle If FileExists($s_Input) Or IsInt($s_Input) Then $s_Input = FileRead($s_Input) If @error Then Return SetError(1, @error, False) If Not IsString($s_Input) Then Return SetError(2, 0, False) Local Const $o_Object = _JSON_Parse($s_Input) Return _JSON_Generate($o_Object) EndFunc ;==>_JSON_Unminify ; #FUNCTION# ==================================================================================================================== ; Name ..........: _JSON_Minify ; Description ...: reads unminified (readable) JSON file or string and converts to minified (compact) JSON string ; Syntax ........: _JSON_Minify($s_Input) ; Parameters ....: $s_Input - json file path/handle or json string ; Return values .: Success - Return a JSON formatted string ; Failure - Return "" and set @error to: ; @error = 1 - error during FileRead() - @extended = @error from FileRead() ; = 2 - no valid format for $s_Input ; Author ........: Sven Seyfert (SOLVE-SMART), AspirinJunkie ; Related .......: _JSON_GenerateCompact ; =============================================================================================================================== Func _JSON_Minify($s_Input) ; read file if $sInput = file name or file handle If FileExists($s_Input) Or IsInt($s_Input) Then $s_Input = FileRead($s_Input) If @error Then Return SetError(1, @error, False) If Not IsString($s_Input) Then Return SetError(2, 0, False) Local Const $o_Object = _JSON_Parse($s_Input) Return _JSON_GenerateCompact($o_Object) EndFunc ;==>_JSON_Minify ; #FUNCTION# ====================================================================================== ; Name ..........: _JSON_Get ; Description ...: query nested AutoIt-datastructure with a simple query string with syntax: ; MapKey#1.MapKey#2.[ArrayIndex#1].MapKey#3... (points keynames can be achieved by "\.") ; multidimensional (2D or 3D only) array indices are separated through comma - e.g.: [2,3] ; Syntax ........: _JSON_Get(ByRef $o_Object, Const $s_Pattern) ; Parameters ....: $o_Object - a nested AutoIt datastructure (Arrays, Dictionaries, basic scalar types) ; $s_Pattern - query pattern like described above ; Return values .: Success - Return the queried object out of the nested datastructure ; Failure - Return "" and set @error to: ; @error = 1 - pattern is not correct ; = 2 - keyname query to none dictionary object ; = 3 - keyname queried not exists in dictionary ; = 4 - index query on none array object ; = 5 - index out of array range ; = 6 - number of subindices in index query not match array dimensions ; = 7 - more than 3 array dimensions are not supported ; Author ........: AspirinJunkie ; ================================================================================================= Func _JSON_Get(ByRef $o_Object, Const $s_Pattern) Local $o_Current = $o_Object, $d_Val Local $a_Tokens = StringRegExp($s_Pattern, '\[(\d+|[\d\h,]+)\]|((?>\\.|[^\.\[\]\\]+)+)', 4) If @error Then Return SetError(1, @error, "") For $a_CurToken In $a_Tokens If UBound($a_CurToken) = 3 Then ; KeyName $a_CurToken[2] = StringRegExpReplace($a_CurToken[2], '\\(.)', '$1') Switch VarGetType($o_Current) Case "Object" If Not IsObj($o_Current) Or ObjName($o_Current) <> "Dictionary" Then Return SetError(2, 0, "") If Not $o_Current.Exists($a_CurToken[2]) Then Return SetError(3, 0, "") $o_Current = $o_Current($a_CurToken[2]) Case "Map" If Not MapExists($o_Current, $a_CurToken[2]) Then Return SetError(3, 0, "") $o_Current = $o_Current[$a_CurToken[2]] EndSwitch ElseIf UBound($a_CurToken) = 2 Then ; ArrayIndex If (Not IsArray($o_Current)) Then Return SetError(4, UBound($o_Current, 0), "") ; multi dimensional array If StringInStr($a_CurToken[1], ',', 1) Then Local $aIndices = StringSplit($a_CurToken[1], ',', 3) If UBound($aIndices) <> UBound($o_Current, 0) Then Return SetError(6, UBound($o_Current, 0), "") ; get the indices and check their range Local $x = Int($aIndices[0]), $y = Int($aIndices[1]) If $x < 0 Or $x >= UBound($o_Current, 1) Then Return SetError(5, $x, "") If $y < 0 Or $y >= UBound($o_Current, 2) Then Return SetError(5, $y, "") Switch UBound($aIndices) Case 2 ; 2D array $o_Current = $o_Current[$x][$y] Case 3 ; 3D array Local $z = Int($aIndices[2]) If $z < 0 Or $z >= UBound($o_Current, 3) Then Return SetError(5, $z, "") $o_Current = $o_Current[$x][$y][$z] Case Else Return SetError(7, @error, "") EndSwitch ; 1D array Else If UBound($o_Current, 0) <> 1 Then Return SetError(6, UBound($o_Current, 0), "") $d_Val = Int($a_CurToken[1]) If $d_Val < 0 Or $d_Val >= UBound($o_Current) Then Return SetError(5, $d_Val, "") $o_Current = $o_Current[$d_Val] EndIf EndIf Next Return $o_Current EndFunc ;==>_JSON_Get ; #FUNCTION# ====================================================================================== ; Name ..........: _JSON_addChangeDelete ; Description ...: creates, modifies or deletes within nested AutoIt structures with a simple query string with syntax: ; MapKey#1.MapKey#2.[ArrayIndex#1].MapKey#3... (points keynames can be achieved by "\.") ; If the specified structure already exists, then the function overwrite the existing data. ; If the specified structure not exists, then the functions creates this structure. ; If $vVal = Default, then the function deletes this specific data point inside the structure. ; Syntax ........: _JSON_addChangeDelete(ByRef $oObject, Const $sPattern, Const $vVal = Default [, Const $iRecLevel = 0]) ; Parameters ....: $oObject - a nested AutoIt datastructure (Arrays, Maps, basic scalar types etc.) ; in which the structure is to be created or data is to be changed or deleted ; $sPattern - query pattern like described above ; $vVal - the value which should be written at the position in $sPattern ; - if $vVal = Default then the position in $sPattern is to be deleted ; $iRecLevel - don't touch! - only for internal purposes ; Return values .: Success - Return True ; Failure - Return False and set @error to: ; @error = 1 - pattern is not correct ; @error = 2 - wrong index for array element ; Author ........: AspirinJunkie ; ================================================================================================= Func _JSON_addChangeDelete(ByRef $oObject, Const $sPattern, Const $vVal = Default, Const $iRecLevel = 0) Local Static $aLevels[0] ; only on highest recursion level: process the selector string If $iRecLevel = 0 Then Local $aToken = StringRegExp($sPattern, '\[(\d+)\]|((?>\\.|[^\.\[\]\\]+)+)', 4) If @error Then Return SetError(1, @error, "") Local $aCurToken ReDim $aLevels[UBound($aToken) + 1][2] For $i = 0 To UBound($aToken) - 1 $aCurToken = $aToken[$i] If UBound($aCurToken) = 3 Then ; KeyName $aLevels[$i][0] = "Map" $aLevels[$i][1] = StringRegExpReplace($aCurToken[2], '\\(.)', '$1') Else ; Array Index $aLevels[$i][0] = "Array" $aLevels[$i][1] = Int($aCurToken[1]) EndIf Next $aLevels[UBound($aLevels) - 1][0] = "end" EndIf ; If data structure not exists already - build it as stated in the selector string: Local $sCurrenttype = $aLevels[$iRecLevel][0] If $sCurrenttype <> VarGetType($oObject) Then Switch $sCurrenttype Case "Map" Local $mTmp[] $oObject = $mTmp Case "Array" Local $aTmp[$aLevels[$iRecLevel][1] + 1] $oObject = $aTmp Case "end" Return $vVal EndSwitch EndIf ; special case treatment for arrays If $sCurrenttype = "Array" Then If UBound($oObject, 0) <> 1 Then Local $aTmp[$aLevels[$iRecLevel][1] + 1] $oObject = $aTmp ElseIf UBound($oObject) < ($aLevels[$iRecLevel][1] + 1) Then ReDim $oObject[$aLevels[$iRecLevel][1] + 1] EndIf EndIf ; create or change the objects in the next hierarchical level and use these as value for the current entry Local $vTmp = $oObject[$aLevels[$iRecLevel][1]], _ $oNext = _JSON_addChangeDelete($vTmp, $sPattern, $vVal, $iRecLevel + 1) If $oNext = Default Then ; delete the current level Switch $sCurrenttype Case "Map" MapRemove($oObject, $aLevels[$iRecLevel][1]) Case "Array" Local $iInd = $aLevels[$iRecLevel][1], $nElems = UBound($oObject) If $iInd < 0 Or $iInd >= $nElems Then Return SetError(2, @error, "") For $i = $iInd To $nElems - 2 $oObject[$i] = $oObject[$i + 1] Next ReDim $oObject[$nElems - 1] Case Else $oObject[$aLevels[$iRecLevel][1]] = "" For $j = UBound($oObject) - 1 To 0 Step -1 If $oObject[$j] <> "" Then ReDim $oObject[$j + 1] ExitLoop EndIf Next EndSwitch Else $oObject[$aLevels[$iRecLevel][1]] = $oNext EndIf If $iRecLevel > 0 Then Return $oObject Else ReDim $aLevels[0] ; clean Return True EndIf EndFunc ;==>_JSON_addChangeDelete ; helper function for converting a json formatted string into an AutoIt-string ; slower variant of __JSON_ParseString but also can handle large strings Func __JSON_ParseString(ByRef $s_String) Local $aB[5] Local $a_RE = StringRegExp($s_String, '\\\\(*SKIP)(*FAIL)|(\\["bf/]|\\u[[:xdigit:]]{4})', 3) If Not @error Then For $s_Esc In $a_RE Switch StringMid($s_Esc, 2, 1) Case "b" If $aB[0] Then ContinueLoop $s_String = StringRegExpReplace($s_String, '\\\\(*SKIP)(*FAIL)|\\b', Chr(8)) $aB[0] = True Case "f" If $aB[1] Then ContinueLoop $s_String = StringRegExpReplace($s_String, '\\\\(*SKIP)(*FAIL)|\\f', Chr(12)) $aB[1] = True Case "/" If $aB[2] Then ContinueLoop $s_String = StringRegExpReplace($s_String, '\\\\(*SKIP)(*FAIL)|\\/', "/") $aB[2] = True Case '"' If $aB[3] Then ContinueLoop $s_String = StringRegExpReplace($s_String, '\\\\(*SKIP)(*FAIL)|\\"', '"') $aB[3] = True Case "u" If $aB[4] Then ContinueLoop $a_RE = StringRegExp($s_String, '\\\\(*SKIP)(*FAIL)|\\u\K[[:xdigit:]]{4}', 3) If Not @error Then If UBound($a_RE) > 10 Then Local $mCodes[] For $s_Code In $a_RE If MapExists($mCodes, $s_Code) Then ContinueLoop $s_String = StringReplace($s_String, "\u" & $s_Code, ChrW(Dec($s_Code)), 0, 1) $mCodes[$s_Code] = "" Next Else For $s_Code In $a_RE $s_String = StringReplace($s_String, "\u" & $s_Code, ChrW(Dec($s_Code)), 0, 1) Next EndIf $aB[4] = True EndIf EndSwitch Next EndIf ; converts \n \r \t \\ implicit: Return StringFormat(StringReplace($s_String, "%", "%%", 0, 1)) EndFunc ;==>__JSON_ParseString ; helper function for converting a AutoIt-string into a json formatted string Func __JSON_FormatString(ByRef $s_String) $s_String = _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace($s_String, '\', '\\', 0, 1) _ , Chr(8), "\b", 0, 1) _ , Chr(12), "\f", 0, 1) _ , @CRLF, "\n", 0, 1) _ , @LF, "\n", 0, 1) _ , @CR, "\r", 0, 1) _ , @TAB, "\t", 0, 1) _ , '"', '\"', 0, 1) EndFunc ;==>__JSON_FormatString ; #FUNCTION# ====================================================================================== ; Name ..........: __JSON_Base64Encode ; Description ...: convert a binary- or string-Input into BASE64 (or optional base64url) format ; mainly a wrapper for the CryptBinaryToString API-function ; Syntax ........: __JSON_Base64Encode(Const ByRef $s_Input, [Const $b_base64url = False]) ; Parameters ....: $s_Input - binary data or string which should be converted ; [$b_base64url] - If true the output is in base64url-format instead of base64 ; Return values .: Success - Return base64 (or base64url) formatted string ; Failure - Return "" and set @error to: ; @error = 1 - failure at the first run to calculate the output size ; = 2 - failure at the second run to calculate the output ; Author ........: AspirinJunkie ; Example .......: Yes ; $s_Base64String = __JSON_Base64Encode("This is my test") ; ================================================================================================= Func __JSON_Base64Encode(Const ByRef $s_Input, Const $b_base64url = False) Local $b_Input = IsBinary($s_Input) ? $s_Input : Binary($s_Input) Local $t_BinArray = DllStructCreate("BYTE[" & BinaryLen($s_Input) & "]") DllStructSetData($t_BinArray, 1, $b_Input) Local $h_DLL_Crypt32 = DllOpen("Crypt32.dll") ; first run to calculate needed size of output buffer Local $a_Ret = DllCall($h_DLL_Crypt32, "BOOLEAN", "CryptBinaryToString", _ "STRUCT*", $t_BinArray, _ ; *pbBinary "DWORD", DllStructGetSize($t_BinArray), _ ; cbBinary "DWORD", 1, _ ; dwFlags "PTR", Null, _ ; pszString "DWORD*", 0) If @error Or Not IsArray($a_Ret) Or $a_Ret[0] = 0 Then Return SetError(1, @error, DllClose($h_DLL_Crypt32)) ; second run to calculate base64-string: Local $t_Output = DllStructCreate("CHAR Out[" & $a_Ret[5] & "]") Local $a_Ret2 = DllCall($h_DLL_Crypt32, "BOOLEAN", "CryptBinaryToString", _ "STRUCT*", $t_BinArray, _ ; *pbBinary "DWORD", DllStructGetSize($t_BinArray), _ ; cbBinary "DWORD", 1, _ ; dwFlags "STRUCT*", $t_Output, _ ; pszString "DWORD*", $a_Ret[5]) If @error Or Not IsArray($a_Ret2) Or $a_Ret2[0] = 0 Then Return SetError(2, @error, DllClose($h_DLL_Crypt32)) Local $s_Output = $t_Output.Out If StringInStr($s_Output, "=", 1, 1) Then $s_Output = StringLeft($s_Output, StringInStr($s_Output, "=", 1, 1) - 1) If $b_base64url Then $s_Output = StringReplace(StringReplace($s_Output, "/", "_", 0, 1), "+", "-", 0, 1) DllClose($h_DLL_Crypt32) Return $s_Output EndFunc ;==>__JSON_Base64Encode ; #FUNCTION# ====================================================================================== ; Name ..........: __JSON_Base64Decode ; Description ...: decode data which is coded as a base64-string into binary form ; mainly a wrapper for the CryptStringToBinary API-function ; Syntax ........: __JSON_Base64Decode(Const ByRef $s_Input, [Const $b_base64url = False]) ; Parameters ....: $s_Input - string in base64-format ; [$b_base64url] - If true the output is in base64url-format instead of base64 ; Return values .: Success - Return base64 (or base64url) formatted string ; Failure - Return "" and set @error to: ; @error = 1 - failure at the first run to calculate the output size ; = 2 - failure at the second run to calculate the output ; Author ........: AspirinJunkie ; Example .......: Yes ; MsgBox(0, '', BinaryToString(__JSON_Base64Decode("VGVzdA"))) ; ================================================================================================= Func __JSON_Base64Decode(Const ByRef $s_Input, Const $b_base64url = False) Local $h_DLL_Crypt32 = DllOpen("Crypt32.dll") ; hier noch einen Reg-Ex zum testen ob String base64-codiert ist ; first run to calculate needed size of output buffer Local $a_Ret = DllCall($h_DLL_Crypt32, "BOOLEAN", "CryptStringToBinary", _ "STR", $s_Input, _ ; pszString "DWORD", 0, _ ; cchString "DWORD", 1, _ ; dwFlags "PTR", Null, _ ; pbBinary "DWORD*", 0, _ ; pcbBinary "PTR", Null, _ ; pdwSkip "PTR", Null) ; pdwFlags Local $t_Ret = DllStructCreate("BYTE Out[" & $a_Ret[5] & "]") If @error Or Not IsArray($a_Ret) Or $a_Ret[0] = 0 Then Return SetError(1, @error, DllClose($h_DLL_Crypt32)) ; second run to calculate the output data: Local $a_Ret2 = DllCall($h_DLL_Crypt32, "BOOLEAN", "CryptStringToBinary", _ "STR", $s_Input, _ ; pszString "DWORD", 0, _ ; cchString "DWORD", 1, _ ; dwFlags "STRUCT*", $t_Ret, _ ; pbBinary "DWORD*", $a_Ret[5], _ ; pcbBinary "PTR", Null, _ ; pdwSkip "PTR", Null) ; pdwFlags If @error Or Not IsArray($a_Ret2) Or $a_Ret2[0] = 0 Then Return SetError(2, @error, DllClose($h_DLL_Crypt32)) DllClose($h_DLL_Crypt32) Local $s_Output = $t_Ret.Out If $b_base64url Then $s_Output = StringReplace(StringReplace($s_Output, "_", "/", 0, 1), "-", "+", 0, 1) Return $s_Output EndFunc ;==>__JSON_Base64Decode ; #FUNCTION# ====================================================================================== ; Name ..........: __JSON_A2DToAinA() ; Description ...: Convert a 2D array into a Arrays in Array ; Syntax ........: __JSON_A2DToAinA(ByRef $A) ; Parameters ....: $A - the 2D-Array which should be converted ; Return values .: Success: a Arrays in Array build from the input array ; Failure: False ; @error = 1: $A is'nt an 2D array ; Author ........: AspirinJunkie ; ================================================================================================= Func __JSON_A2DToAinA(ByRef $A, $bTruncEmpty = True) If UBound($A, 0) <> 2 Then Return SetError(1, UBound($A, 0), False) Local $N = UBound($A), $u = UBound($A, 2) Local $a_Ret[$N] If $bTruncEmpty Then For $i = 0 To $N - 1 Local $x = $u - 1 While IsString($A[$i][$x]) And $A[$i][$x] = "" $x -= 1 WEnd Local $t[$x + 1] For $j = 0 To $x $t[$j] = $A[$i][$j] Next $a_Ret[$i] = $t Next Else For $i = 0 To $N - 1 Local $t[$u] For $j = 0 To $u - 1 $t[$j] = $A[$i][$j] Next $a_Ret[$i] = $t Next EndIf Return $a_Ret EndFunc ;==>__JSON_A2DToAinA ; #FUNCTION# ====================================================================================== ; Name ..........: __JSON_AinAToA2d() ; Description ...: Convert a Arrays in Array into a 2D array ; here useful if you want to recover 2D-arrays from a json-string ; (there exists only a array-in-array and no 2D-Arrays) ; Syntax ........: __JSON_AinAToA2d(ByRef $A) ; Parameters ....: $A - the arrays in array which should be converted ; Return values .: Success: a 2D Array build from the input array ; Failure: False ; @error = 1: $A is'nt an 1D array ; = 2: $A is empty ; = 3: first element isn't a array ; Author ........: AspirinJunkie ; ================================================================================================= Func __JSON_AinAToA2d(ByRef $A) If UBound($A, 0) <> 1 Then Return SetError(1, UBound($A, 0), False) Local $N = UBound($A) If $N < 1 Then Return SetError(2, $N, False) Local $u = UBound($A[0]) If $u < 1 Then Return SetError(3, $u, False) Local $a_Ret[$N][$u] For $i = 0 To $N - 1 Local $t = $A[$i] If UBound($t) > $u Then ReDim $a_Ret[$N][UBound($t)] For $j = 0 To UBound($t) - 1 $a_Ret[$i][$j] = $t[$j] Next Next Return $a_Ret EndFunc ;==>__JSON_AinAToA2d Edited May 11 by ioa747 I know that I know nothing
argumentum Posted May 11 Posted May 11 On 5/11/2025 at 9:36 PM, ioa747 said: ; helper function for converting a AutoIt-string into a json formatted string Func __JSON_FormatString(ByRef $s_String) $s_String = _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace($s_String, '\', '\\', 0, 1) _ , Chr(8), "\b", 0, 1) _ , Chr(12), "\f", 0, 1) _ , @CRLF, "\n", 0, 1) _ , @LF, "\n", 0, 1) _ , @CR, "\r", 0, 1) _ , @TAB, "\t", 0, 1) _ , '"', '\"', 0, 1) EndFunc ;==>__JSON_FormatString Expand and I ; helper function for converting a AutoIt-string into a json formatted string Func __JSON_FormatString(ByRef $sString) Return StringLen($sString) < 50 ? _ StringTrimRight(StringRegExpReplace($sString & '\\\b\f\n\r\t\"', '(?s)(?|\\(?=.*(\\\\))|[\b](?=.*(\\b))|\f(?=.*(\\f))|\r\n(?=.*(\\n))|\n(?=.*(\\n))|\r(?=.*(\\r))|\t(?=.*(\\t))|"(?=.*(\\")))', '\1'), 15) : _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace($sString, '\', '\\', 0, 1) _ , Chr(8), "\b", 0, 1) _ , Chr(12), "\f", 0, 1) _ , @CRLF, "\n", 0, 1) _ , @LF, "\n", 0, 1) _ , @CR, "\r", 0, 1) _ , @TAB, "\t", 0, 1) _ , '"', '\"', 0, 1) EndFunc hence the oops =/ Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
ioa747 Posted May 11 Author Posted May 11 (edited) and which is the right one? ; Version .......: 0.10 ? Edited May 11 by ioa747 I know that I know nothing
ioa747 Posted May 11 Author Posted May 11 (edited) On 5/11/2025 at 4:37 PM, ioa747 said: update to Version: 0.3 Expand Edited May 11 by ioa747 I know that I know nothing
argumentum Posted May 12 Posted May 12 On 5/11/2025 at 9:47 PM, ioa747 said: and which is the right one? ; Version .......: 0.10 ? Expand ..good question. https://github.com/Sylvan86/autoit-json-udf/blob/master/JSON.au3 claims to be "0.10" and "Last changed ..: 2023-04-29" but, was changed 2 month ago ( changed: _JSON_Parse(): removed Byref - direct input is now possible ). I guess the one that works is the answer ? 😅 <rant> That's why I rather have the files in the forum. Static. These git places are here today and changed or gone some other time </rant> <note>I'll have to use a git of sorts/providers, to work with modern/current technologies 😭 </note> Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
SOLVE-SMART Posted May 12 Posted May 12 On 5/12/2025 at 12:57 AM, argumentum said: https://github.com/Sylvan86/autoit-json-udf/blob/master/JSON.au3 claims to be "0.10" and "Last changed ..: 2023-04-29" but, was changed 2 month ago Expand Yes, version 0.10 is correct, but it should be 0.11.0 instead I would say. As you already mentioned @argumentum, @AspirinJunkie added few commits (changes) to the UDF which should lead to 0.11.0 from 2025-04-01. On 5/12/2025 at 12:57 AM, argumentum said: <rant> That's why I rather have the files in the forum. Static. These git places are here today and changed or gone some other time </rant> Expand I understand your point of view, but exactly for this situation the idea of forking a repository exists. Then you have your static version or you decide on your own when you want to pull new changes in your repository/fork. To be honest, to search within the forum is way harder then on GitHub (at least for me). Best regards Sven ==> AutoIt related: 🔗 GitHub, 🔗 Discord Server, 🔗 Cheat Sheet Reveal hidden contents 🌍 Au3Forums 🎲 AutoIt (en) Cheat Sheet 📊 AutoIt limits/defaults 💎 Code Katas: [...] (comming soon) 🎭 Collection of GitHub users with AutoIt projects 🐞 False-Positives 🔮 Me on GitHub 💬 Opinion about new forum sub category 📑 UDF wiki list ✂ VSCode-AutoItSnippets 📑 WebDriver FAQs 👨🏫 WebDriver Tutorial (coming soon)
argumentum Posted May 12 Posted May 12 On 5/12/2025 at 7:13 AM, SOLVE-SMART said: To be honest, to search within the forum is way harder then on GitHub (at least for me). Expand but what about the future user going to use it and have for breakfast that it ( the code ) don't work because one of the dependencies changed fundamentally and, ...suck it. I understand selfishness and still advocate for ethical behaviors that don't lead to forking. A letter R apart from the same trend of thought. And I do understand that you are just adjusted to the current way of developing and you have to do what you must ( at least for you ). I strongly disagree with this way of participation mainly because anyone trying to replicate what is claimed, is out of phase with time. The time at witch it was all put together because the forks are not what they were. Pardon my less than nice posture but it is just non-functional. How can one be expected to have forked 2 years ago something so today ( because it was posed 1 day ago ) can not use what is supposed to be there as it was ? Even tho this chat is with you @SOLVE-SMART, is not necessarily personal. Is the way it is, and leads to these mishaps, hence the concept is wrong. And no, I can not change it ( the I fork what I need ) because it takes people to feel different, and people adjust for survival of the self over the survival of the group. That's all there is to it so, foRk it, I guess. SOLVE-SMART 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
genius257 Posted May 12 Posted May 12 @argumentum I am not sure i get if it's the platform, the repositories, the individual users or a combination you dislike? When it comes to git, keeping the version in the file seems wrong, in my opinion. Git tags and/or releases on some git platforms seems the best way to keep good track of the available versions of scripts/projects. In regards to the same code being available at a later date, unless they delete or change the visibility of the repository, you could keep a commit hash reference for a perma-link to the code you were able to access last time I personally prefer git (GitHub more specifically). Old files on this forum sometimes go poof, and sometimes no one can provide a replica (it's rare, i know). Both Git and this forum can be a time waster, if dependencies are not kept with the project, and you are forced to go on a treasure hunt to find the necessary files (happened once or twice to me 🫠). Personally i am working towards a package manager, using primarily git to automatically resolve and fetch dependencies of a project. If developers use the semver standard, patches should be pain free and allow upgrading dependencies using a single command I agree forking is not exactly a perfect solution, but is sometimes necessary, for example when dealing with abandoned projects or not agreeing on where a project is heading SOLVE-SMART and argumentum 2 To show your appreciation My highlighted topics: AutoIt Package Manager, AutoItObject Pure AutoIt, AutoIt extension for Visual Studio Code Github: AutoIt HTTP Server, AutoIt HTML Parser
argumentum Posted May 12 Posted May 12 On 5/12/2025 at 3:09 PM, genius257 said: you could keep a commit hash reference for a perma-link to the code you were able to access last time Expand Good to know. Since am not familiar with git, going to get "the file" and is not it, ..is frustrating. I code so I can debug it but those that expect the stuff to run ( because is stuff we/they discover, run it, and if it didn't, meh, it does not work, next... ) will miss in using it and participating with bugs or code or anything. On 5/12/2025 at 3:09 PM, genius257 said: Both Git and this forum can be a time waster, if dependencies are not kept with the project, and you are forced to go on a treasure hunt to find the necessary files (happened once or twice to me 🫠). Expand I've found myself uploading files for those occasions when I have them ( and I have them because I hoard them ). Maybe I went overboard in my rant, maybe. I should have advised to include all the external includes and that is a better solution genius257 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
argumentum Posted May 12 Posted May 12 On 5/12/2025 at 3:34 PM, argumentum said: I should have advised to include all the external includes and that is a better solution Expand ...but is a post, not a ZIP with all the files. I would have done the same, meaning to direct ( via a comment ) where to get the external UDF. Nah, ..it happens. Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
SOLVE-SMART Posted May 12 Posted May 12 Off topic Reveal hidden contents On 5/12/2025 at 3:34 PM, argumentum said: Maybe I went overboard in my rant, maybe. Expand I get your point(s) @argumentum, I am fine with your statements and I don't take it personally. I guess I am simply more used to work with Git and GitHub/GitLab. Although I'm all for making things as easy as possible for users and programmers, the world around AutoIt relies on > 90% of Git and GitHub usage (or other platforms). I'm adapting to this because it's common sense, and thousands of developers have chosen this path. Certainly not without reason. Anyhow, we can discuss such things in a separate thread or in the chat section, because I try not to hijack or disturb the original topic (again) 😇 . Best regards Sven argumentum 1 ==> AutoIt related: 🔗 GitHub, 🔗 Discord Server, 🔗 Cheat Sheet Reveal hidden contents 🌍 Au3Forums 🎲 AutoIt (en) Cheat Sheet 📊 AutoIt limits/defaults 💎 Code Katas: [...] (comming soon) 🎭 Collection of GitHub users with AutoIt projects 🐞 False-Positives 🔮 Me on GitHub 💬 Opinion about new forum sub category 📑 UDF wiki list ✂ VSCode-AutoItSnippets 📑 WebDriver FAQs 👨🏫 WebDriver Tutorial (coming soon)
argumentum Posted May 12 Posted May 12 On 5/12/2025 at 3:34 PM, argumentum said: Good to know. Since am not familiar with git, going to get "the file" and is not it, ..is frustrating. Expand I think then the reference link should be https://github.com/Sylvan86/autoit-json-udf/blob/8f326597f402c1576ef793b68552171472db62c9/JSON.au3 ( untested, just looking at it ) But it would be nice to fix just that function given that the file had many patches after that. Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now